|
|
1.1 ! root 1: /* ! 2: * File: fstruct.c ! 3: * Contents: delete, get, insert, member, pop, pull, push, put, sort ! 4: */ ! 5: ! 6: #include "../h/rt.h" ! 7: ! 8: /* ! 9: * delete(S,x) - delete element x from set S if it is there ! 10: * (always succeeds and returns S). ! 11: */ ! 12: ! 13: FncDcl(delete,2) ! 14: { ! 15: register struct descrip *pd; ! 16: int res ; ! 17: extern struct descrip *memb(); ! 18: ! 19: Arg0 = Arg1; ! 20: ! 21: if (Arg1.dword != D_Set) ! 22: runerr(119,&Arg1); ! 23: ! 24: /* ! 25: * The technique and philosophy here are the same ! 26: * as used in insert - see comment there. ! 27: */ ! 28: pd = memb((struct b_set *)BlkLoc(Arg1),&Arg2,hash(&Arg2),&res); ! 29: if (res == 1) { ! 30: /* ! 31: * The element is there so delete it. ! 32: */ ! 33: *pd = BlkLoc(*pd)->selem.clink; ! 34: (BlkLoc(Arg1)->set.size)--; ! 35: } ! 36: Return; ! 37: } ! 38: ! 39: ! 40: /* ! 41: * get(x) - get an element from end of list x. ! 42: * Identical to pop(x). ! 43: */ ! 44: ! 45: FncDcl(get,1) ! 46: { ! 47: register word i; ! 48: register struct b_list *hp; ! 49: register struct b_lelem *bp; ! 50: extern struct b_lelem *alclstb(); ! 51: ! 52: /* ! 53: * x must be a list. ! 54: */ ! 55: if (Arg1.dword != D_List) ! 56: runerr(108, &Arg1); ! 57: ! 58: /* ! 59: * Fail if the list is empty. ! 60: */ ! 61: hp = (struct b_list *) BlkLoc(Arg1); ! 62: if (hp->size <= 0) ! 63: Fail; ! 64: ! 65: /* ! 66: * Point bp at the first list block. If the first block has no ! 67: * elements in use, point bp at the next list block. ! 68: */ ! 69: bp = (struct b_lelem *) BlkLoc(hp->listhead); ! 70: if (bp->nused <= 0) { ! 71: bp = (struct b_lelem *) BlkLoc(bp->listnext); ! 72: BlkLoc(hp->listhead) = (union block *) bp; ! 73: bp->listprev = nulldesc; ! 74: } ! 75: /* ! 76: * Locate first element and assign it to Arg0 for return. ! 77: */ ! 78: i = bp->first; ! 79: Arg0 = bp->lslots[i]; ! 80: /* ! 81: * Set bp->first to new first element, or 0 if the block is now ! 82: * empty. Decrement the usage count for the block and the size ! 83: * of the list. ! 84: */ ! 85: if (++i >= bp->nelem) ! 86: i = 0; ! 87: bp->first = i; ! 88: bp->nused--; ! 89: hp->size--; ! 90: Return; ! 91: } ! 92: ! 93: ! 94: /* ! 95: * insert(S,x) - insert element x into set S if not already there ! 96: * (always succeeds and returns S). ! 97: */ ! 98: ! 99: FncDcl(insert,2) ! 100: { ! 101: register struct descrip *pd; ! 102: register word hn; ! 103: int res; ! 104: extern struct b_selem *alcselem(); ! 105: extern struct descrip *memb(); ! 106: ! 107: Arg0 = Arg1; ! 108: ! 109: if (Arg1.dword != D_Set) ! 110: runerr(119,&Arg1); ! 111: ! 112: /* ! 113: * We may need at most one new element. ! 114: */ ! 115: blkreq((word)sizeof(struct b_selem)); ! 116: hn = hash(&Arg2); ! 117: /* ! 118: * If Arg2 is a member of set Arg1 then res will have the ! 119: * value 1 and pd will have a pointer to the descriptor ! 120: * that points to that member. ! 121: * If Arg2 is not a member of the set then res will have ! 122: * the value 0 and pd will point to the descriptor ! 123: * which should point to the member - thus we know where ! 124: * to link in the new element without having to do any ! 125: * repetitive looking. ! 126: */ ! 127: pd = memb((struct b_set *)BlkLoc(Arg1),&Arg2,hn,&res); ! 128: if (res == 0) ! 129: /* ! 130: * The element is not in the set - insert it. ! 131: */ ! 132: addmem((struct b_set *)BlkLoc(Arg1),alcselem(&Arg2,hn),pd); ! 133: Return; ! 134: } ! 135: ! 136: ! 137: /* ! 138: * member(S,x) - returns x if x is a member of set S otherwise fails. ! 139: */ ! 140: ! 141: FncDcl(member,2) ! 142: { ! 143: int res; ! 144: extern struct descrip *memb(); ! 145: ! 146: if (Arg1.dword != D_Set) ! 147: runerr(119,&Arg1); /* S is not a set */ ! 148: ! 149: /* If Arg2 is a member of set Arg1 then "res" will have the ! 150: * value 1 otherwise it will have the value 0. ! 151: */ ! 152: memb((struct b_set *)BlkLoc(Arg1),&Arg2,hash(&Arg2),&res); ! 153: if (res == 1) { /* It is a member. */ ! 154: Arg0 = Arg2; /* Return the member if it is in Arg1. */ ! 155: Return; ! 156: } ! 157: Fail; ! 158: } ! 159: ! 160: ! 161: /* ! 162: * pop(x) - pop an element from beginning of list x. ! 163: */ ! 164: ! 165: /* >pop */ ! 166: FncDcl(pop,1) ! 167: { ! 168: register word i; ! 169: register struct b_list *hp; ! 170: register struct b_lelem *bp; ! 171: extern struct b_lelem *alclstb(); ! 172: ! 173: /* ! 174: * Arg1 must be a list. ! 175: */ ! 176: if (Arg1.dword != D_List) ! 177: runerr(108, &Arg1); ! 178: ! 179: /* ! 180: * Fail if the list is empty. ! 181: */ ! 182: hp = (struct b_list *) BlkLoc(Arg1); ! 183: if (hp->size <= 0) ! 184: Fail; ! 185: ! 186: /* ! 187: * Point bp to the first list block. If the first block has no ! 188: * elements in use, point bp at the next list block. ! 189: */ ! 190: bp = (struct b_lelem *) BlkLoc(hp->listhead); ! 191: if (bp->nused <= 0) { ! 192: bp = (struct b_lelem *) BlkLoc(bp->listnext); ! 193: BlkLoc(hp->listhead) = (union block *) bp; ! 194: bp->listprev = nulldesc; ! 195: } ! 196: /* ! 197: * Locate first element and assign it to Arg0 for return. ! 198: */ ! 199: i = bp->first; ! 200: Arg0 = bp->lslots[i]; ! 201: ! 202: /* ! 203: * Set bp->first to new first element, or 0 if the block is now ! 204: * empty. Decrement the usage count for the block and the size ! 205: * of the list. ! 206: */ ! 207: if (++i >= bp->nelem) ! 208: i = 0; ! 209: bp->first = i; ! 210: bp->nused--; ! 211: hp->size--; ! 212: Return; ! 213: } ! 214: /* <pop */ ! 215: ! 216: ! 217: /* ! 218: * pull(x) - pull an element from end of list x. ! 219: */ ! 220: ! 221: FncDcl(pull,1) ! 222: { ! 223: register word i; ! 224: register struct b_list *hp; ! 225: register struct b_lelem *bp; ! 226: extern struct b_lelem *alclstb(); ! 227: ! 228: /* ! 229: * x must be a list. ! 230: */ ! 231: if (Arg1.dword != D_List) ! 232: runerr(108, &Arg1); ! 233: ! 234: /* ! 235: * Point at list header block and fail if the list is empty. ! 236: */ ! 237: hp = (struct b_list *) BlkLoc(Arg1); ! 238: if (hp->size <= 0) ! 239: Fail; ! 240: /* ! 241: * Point bp at the last list element block. If the last block has no ! 242: * elements in use, point bp at the previous list element block. ! 243: */ ! 244: bp = (struct b_lelem *) BlkLoc(hp->listtail); ! 245: if (bp->nused <= 0) { ! 246: bp = (struct b_lelem *) BlkLoc(bp->listprev); ! 247: BlkLoc(hp->listtail) = (union block *) bp; ! 248: bp->listnext = nulldesc; ! 249: } ! 250: /* ! 251: * Set i to position of last element and assign the element to ! 252: * Arg0 for return. Decrement the usage count for the block ! 253: * and the size of the list. ! 254: */ ! 255: i = bp->first + bp->nused - 1; ! 256: if (i >= bp->nelem) ! 257: i -= bp->nelem; ! 258: Arg0 = bp->lslots[i]; ! 259: bp->nused--; ! 260: hp->size--; ! 261: Return; ! 262: } ! 263: ! 264: ! 265: /* ! 266: * push(x,val) - push val onto beginning of list x. ! 267: */ ! 268: FncDcl(push,2) ! 269: { ! 270: register word i; ! 271: register struct b_list *hp; ! 272: register struct b_lelem *bp; ! 273: extern struct b_lelem *alclstb(); ! 274: ! 275: /* ! 276: * x must be a list. ! 277: */ ! 278: if (Arg1.dword != D_List) ! 279: runerr(108, &Arg1); ! 280: ! 281: /* ! 282: * A new list element block might be needed, so ensure space for it. ! 283: */ ! 284: blkreq((word)sizeof(struct b_lelem)+MinListSlots*sizeof(struct descrip)); ! 285: ! 286: /* ! 287: * Point hp at the list header block and bp at the first ! 288: * list element block. ! 289: */ ! 290: hp = (struct b_list *) BlkLoc(Arg1); ! 291: bp = (struct b_lelem *) BlkLoc(hp->listhead); ! 292: /* ! 293: * If the first list element block is full, ! 294: * allocate a new list element block, make it the first list ! 295: * element block and make it the previous block of the ! 296: * former first list element block. ! 297: */ ! 298: if (bp->nused >= bp->nelem) { ! 299: bp = alclstb((word)MinListSlots, (word)0, (word)0); ! 300: BlkLoc(hp->listhead)->lelem.listprev.dword = D_Lelem; ! 301: BlkLoc(BlkLoc(hp->listhead)->lelem.listprev) = (union block *) bp; ! 302: bp->listnext = hp->listhead; ! 303: BlkLoc(hp->listhead) = (union block *) bp; ! 304: } ! 305: /* ! 306: * Set i to position of new first element and assign val (Arg2) to ! 307: * that element. ! 308: */ ! 309: i = bp->first - 1; ! 310: if (i < 0) ! 311: i = bp->nelem - 1; ! 312: bp->lslots[i] = Arg2; ! 313: /* ! 314: * Adjust value of location of first element, block usage count, ! 315: * and current list size. ! 316: */ ! 317: bp->first = i; ! 318: bp->nused++; ! 319: hp->size++; ! 320: /* ! 321: * Return the list. ! 322: */ ! 323: Arg0 = Arg1; ! 324: Return; ! 325: } ! 326: ! 327: ! 328: /* ! 329: * put(x,val) - put val onto end of list x. ! 330: */ ! 331: ! 332: FncDcl(put,2) ! 333: { ! 334: register word i; ! 335: register struct b_list *hp; ! 336: register struct b_lelem *bp; ! 337: extern struct b_lelem *alclstb(); ! 338: ! 339: /* ! 340: * Arg1 must be a list. ! 341: */ ! 342: if (Arg1.dword != D_List) ! 343: runerr(108, &Arg1); ! 344: ! 345: /* ! 346: * A new list element block might be needed, so ensure space for it. ! 347: */ ! 348: blkreq((word)sizeof(struct b_lelem)+MinListSlots*sizeof(struct descrip)); ! 349: ! 350: /* >put */ ! 351: /* ! 352: * Point hp to the list header block and bp to the last ! 353: * list element block. ! 354: */ ! 355: hp = (struct b_list *) BlkLoc(Arg1); ! 356: bp = (struct b_lelem *) BlkLoc(hp->listtail); ! 357: ! 358: /* ! 359: * If the last list element block is full, allocate a new ! 360: * list element block, make it the first list element block ! 361: * and it make it the next block of the former last list ! 362: * element block. ! 363: */ ! 364: if (bp->nused >= bp->nelem) { ! 365: bp = alclstb((word)MinListSlots, (word)0, (word)0); ! 366: BlkLoc(hp->listtail)->lelem.listnext.dword = D_Lelem; ! 367: BlkLoc(BlkLoc(hp->listtail)->lelem.listnext) = (union block *) bp; ! 368: bp->listprev = hp->listtail; ! 369: BlkLoc(hp->listtail) = (union block *) bp; ! 370: } ! 371: ! 372: /* ! 373: * Set i to position of new last element and assign Arg2 to ! 374: * that element. ! 375: */ ! 376: i = bp->first + bp->nused; ! 377: if (i >= bp->nelem) ! 378: i -= bp->nelem; ! 379: bp->lslots[i] = Arg2; ! 380: ! 381: /* ! 382: * Adjust block usage count and current list size. ! 383: */ ! 384: bp->nused++; ! 385: hp->size++; ! 386: ! 387: /* ! 388: * Return the list. ! 389: */ ! 390: Arg0 = Arg1; ! 391: Return; ! 392: } ! 393: /* <put */ ! 394: ! 395: ! 396: struct dpair { ! 397: struct descrip dr; ! 398: struct descrip dv; ! 399: }; ! 400: ! 401: /* ! 402: * sort(l) - sort list l. ! 403: * sort(S) - sort set S. ! 404: * sort(t,i) - sort table. ! 405: */ ! 406: ! 407: FncDcl(sort,2) ! 408: { ! 409: register struct descrip *d1; ! 410: register word size; ! 411: register int i; ! 412: word nelem; ! 413: struct b_list *lp, *tp; ! 414: union block *bp, *ep; ! 415: extern struct b_list *alclist(); ! 416: extern struct b_lelem *alclstb(); ! 417: extern anycmp(), trefcmp(), tvalcmp(), trcmp3(), tvcmp4(); ! 418: ! 419: if (Arg1.dword == D_List) { ! 420: /* ! 421: * Sort the list by copying it into a new list and then using ! 422: * qsort to sort the descriptors. (That was easy!) ! 423: */ ! 424: size = BlkLoc(Arg1)->list.size; ! 425: cplist(&Arg1, &Arg0, (word)1, size + 1); ! 426: qsort(BlkLoc(BlkLoc(Arg0)->list.listhead)->lelem.lslots, size, ! 427: sizeof(struct descrip), anycmp); ! 428: } ! 429: else if (Arg1.dword == D_Set) { ! 430: /* ! 431: * Create a list the size of the set (or at least ! 432: * MinListSlots), copy each element into the list, and ! 433: * then sort the list using qsort as in list sorting ! 434: * and return the sorted list. ! 435: */ ! 436: nelem = size = BlkLoc(Arg1)->set.size; ! 437: if(nelem < MinListSlots) ! 438: nelem = MinListSlots; ! 439: blkreq(sizeof(struct b_list) + sizeof(struct b_lelem) + ! 440: nelem * sizeof(struct descrip)); ! 441: ! 442: bp = BlkLoc(Arg1); ! 443: lp = alclist(size); ! 444: lp->listhead.dword = lp->listtail.dword = D_Lelem; ! 445: BlkLoc(lp->listtail) = (union block *) alclstb(nelem, (word)0, size); ! 446: BlkLoc(lp->listhead) = BlkLoc(lp->listtail); ! 447: if (size > 0) { /* only need to sort non-empty sets */ ! 448: d1 = BlkLoc(lp->listhead)->lelem.lslots; ! 449: for(i = 0; i < SSlots; i++) { ! 450: ep = BlkLoc(bp->set.sbucks[i]); ! 451: while (ep != NULL) { ! 452: *d1 = ep->selem.setmem; ! 453: d1++; ! 454: ep = BlkLoc(ep->selem.clink); ! 455: } ! 456: } ! 457: qsort(BlkLoc(lp->listhead)->lelem.lslots,size, ! 458: sizeof(struct descrip),anycmp); ! 459: } ! 460: Arg0.dword = D_List; ! 461: BlkLoc(Arg0) = (union block *) lp; ! 462: } ! 463: ! 464: else if (Arg1.dword == D_Table) { ! 465: /* ! 466: * Default i (the type of sort) to 1. ! 467: */ ! 468: defshort(&Arg2, 1); ! 469: switch (IntVal(Arg2)) { ! 470: ! 471: /* ! 472: * Cases 1 and 2 are as in standard Version 5. ! 473: */ ! 474: case 1: ! 475: case 2: ! 476: { ! 477: /* ! 478: * The list resulting from the sort will have as many elements as ! 479: * the table has, so get that value and also make a valid list ! 480: * block size out of it. ! 481: */ ! 482: nelem = size = BlkLoc(Arg1)->table.size; ! 483: if (nelem < MinListSlots) ! 484: nelem = MinListSlots; ! 485: /* ! 486: * Ensure space for: the list header block and a list element ! 487: * block for the list which is to be returned, ! 488: * a list header block and a list element block for each of the two ! 489: * element lists the sorted list is to contain. Note that the ! 490: * calculation might be better expressed as: ! 491: * list_header_size + list_block_size + nelem * descriptor_size + ! 492: * nelem * (list_header_size + list_block_size + 2*descriptor_size) ! 493: */ ! 494: blkreq(sizeof(struct b_list) + sizeof(struct b_lelem) + ! 495: nelem * (sizeof(struct b_list) + sizeof(struct b_lelem) + ! 496: 3 * sizeof(struct descrip))); ! 497: /* ! 498: * Point bp at the table header block of the table to be sorted ! 499: * and point lp at a newly allocated list ! 500: * that will hold the the result of sorting the table. ! 501: */ ! 502: bp = BlkLoc(Arg1); ! 503: lp = alclist(size); ! 504: lp->listhead.dword = lp->listtail.dword = D_Lelem; ! 505: BlkLoc(lp->listtail) = (union block *) alclstb(nelem, (word)0, size); ! 506: BlkLoc(lp->listhead) = BlkLoc(lp->listtail); ! 507: /* ! 508: * If the table is empty, there is no need to sort anything. ! 509: */ ! 510: if (size <= 0) ! 511: break; ! 512: /* ! 513: * Point d1 at the start of the list elements in the new list ! 514: * element block in preparation for use as an index into the list. ! 515: */ ! 516: d1 = BlkLoc(lp->listhead)->lelem.lslots; ! 517: /* ! 518: * Traverse the element chain for each table bucket. For each ! 519: * element, allocate a two-element list and put the table ! 520: * entry value in the first element and the assigned value in ! 521: * the second element. The two-element list is assigned to ! 522: * the descriptor that d1 points at. When this is done, the ! 523: * list of two-element lists is complete, but unsorted. ! 524: */ ! 525: for (i = 0; i < TSlots; i++) { ! 526: ep = BlkLoc(bp->table.buckets[i]); ! 527: while (ep != NULL) { ! 528: d1->dword = D_List; ! 529: tp = alclist((word)2); ! 530: BlkLoc(*d1) = (union block *) tp; ! 531: tp->listhead.dword = tp->listtail.dword = D_Lelem; ! 532: BlkLoc(tp->listtail) = (union block *) alclstb((word)2, (word)0, ! 533: (word)2); ! 534: BlkLoc(tp->listhead) = BlkLoc(tp->listtail); ! 535: BlkLoc(tp->listhead)->lelem.lslots[0] = ep->telem.tref; ! 536: BlkLoc(tp->listhead)->lelem.lslots[1] = ep->telem.tval; ! 537: d1++; ! 538: ep = BlkLoc(ep->telem.clink); ! 539: } ! 540: } ! 541: /* ! 542: * Sort the resulting two-element list using the sorting function ! 543: * determined by i. ! 544: */ ! 545: if (IntVal(Arg2) == 1) ! 546: qsort(BlkLoc(lp->listhead)->lelem.lslots, size, ! 547: sizeof(struct descrip), trefcmp); ! 548: else ! 549: qsort(BlkLoc(lp->listhead)->lelem.lslots, size, ! 550: sizeof(struct descrip), tvalcmp); ! 551: break; /* from cases 1 and 2 */ ! 552: } ! 553: /* ! 554: * Cases 3 and 4 were introduced in Version 5.10. ! 555: */ ! 556: case 3 : ! 557: case 4 : ! 558: { ! 559: /* ! 560: * The list resulting from the sort will have twice as many elements as ! 561: * the table has, so get that value and also make a valid list ! 562: * block size out of it. ! 563: */ ! 564: nelem = size = BlkLoc(Arg1)->table.size * 2; ! 565: if (nelem < MinListSlots) ! 566: nelem = MinListSlots; ! 567: /* ! 568: * Ensure space for: the list header block and a list element ! 569: * block for the list which is to be returned, and two descriptors for ! 570: * each table element. ! 571: */ ! 572: blkreq(sizeof(struct b_list) + Vsizeof(struct b_lelem) + ! 573: (nelem * sizeof(struct descrip))); ! 574: /* ! 575: * Point bp at the table header block of the table to be sorted ! 576: * and point lp at a newly allocated list ! 577: * that will hold the the result of sorting the table. ! 578: */ ! 579: bp = BlkLoc(Arg1); ! 580: lp = alclist(size); ! 581: lp->listhead.dword = lp->listtail.dword = D_Lelem; ! 582: BlkLoc(lp->listtail) = (union block *) alclstb(nelem, (word)0, size); ! 583: BlkLoc(lp->listhead) = BlkLoc(lp->listtail); ! 584: /* ! 585: * If the table is empty there's no need to sort anything. ! 586: */ ! 587: if (size <= 0) ! 588: break; ! 589: ! 590: /* ! 591: * Point d1 at the start of the list elements in the new list ! 592: * element block in preparation for use as an index into the list. ! 593: */ ! 594: d1 = BlkLoc(lp->listhead)->lelem.lslots; ! 595: /* ! 596: * Traverse the element chain for each table bucket. For each ! 597: * table element copy the the entry descriptor and the value ! 598: * descriptor into adjacent descriptors in the lslots array ! 599: * in the list element block. ! 600: * When this is done we now need to sort this list. ! 601: */ ! 602: for (i = 0; i < TSlots; i++) { ! 603: ep = BlkLoc(bp->table.buckets[i]); ! 604: while (ep != NULL) { ! 605: *d1 = ep->telem.tref; ! 606: d1++; ! 607: *d1 = ep->telem.tval; ! 608: d1++; ! 609: ep = BlkLoc(ep->telem.clink); ! 610: } ! 611: } ! 612: /* ! 613: * Sort the resulting two-element list using the sorting function ! 614: * determined by i. ! 615: */ ! 616: if (IntVal(Arg2) == 3) ! 617: qsort(BlkLoc(lp->listhead)->lelem.lslots, size / 2, ! 618: (2 * sizeof(struct descrip)), trcmp3); ! 619: else ! 620: qsort(BlkLoc(lp->listhead)->lelem.lslots, size / 2, ! 621: (2 * sizeof(struct descrip)), tvcmp4); ! 622: break; /* from case 3 or 4 */ ! 623: } ! 624: ! 625: default : runerr(205,&Arg2); ! 626: } /* end of switch statement */ ! 627: /* ! 628: * Make Arg0 point at the sorted list. ! 629: */ ! 630: Arg0.dword = D_List; ! 631: BlkLoc(Arg0) = (union block *) lp; ! 632: } ! 633: else /* Tried to sort something that wasn't a list or a table. */ ! 634: runerr(115, &Arg1); ! 635: Return; ! 636: } ! 637: ! 638: /* ! 639: * trefcmp(d1,d2) - compare two-element lists on first field. ! 640: */ ! 641: ! 642: trefcmp(d1,d2) ! 643: struct descrip *d1, *d2; ! 644: { ! 645: extern anycmp(); ! 646: ! 647: #ifdef Debug ! 648: if (d1->dword != D_List || d2->dword != D_List) ! 649: syserr("trefcmp: internal consistency check fails."); ! 650: #endif Debug ! 651: return (anycmp(&(BlkLoc(BlkLoc(*d1)->list.listhead)->lelem.lslots[0]), ! 652: &(BlkLoc(BlkLoc(*d2)->list.listhead)->lelem.lslots[0]))); ! 653: } ! 654: ! 655: /* ! 656: * tvalcmp(d1,d2) - compare two-element lists on second field. ! 657: */ ! 658: ! 659: tvalcmp(d1,d2) ! 660: struct descrip *d1, *d2; ! 661: { ! 662: extern anycmp(); ! 663: ! 664: #ifdef Debug ! 665: if (d1->dword != D_List || d2->dword != D_List) ! 666: syserr("tvalcmp: internal consistency check fails."); ! 667: #endif Debug ! 668: return (anycmp(&(BlkLoc(BlkLoc(*d1)->list.listhead)->lelem.lslots[1]), ! 669: &(BlkLoc(BlkLoc(*d2)->list.listhead)->lelem.lslots[1]))); ! 670: } ! 671: ! 672: /* ! 673: * The following two routines are used to compare descriptor pairs in the ! 674: * experimental table sort. ! 675: * ! 676: * trcmp3(dp1,dp2) ! 677: */ ! 678: ! 679: trcmp3(dp1,dp2) ! 680: struct dpair *dp1,*dp2; ! 681: { ! 682: extern anycmp(); ! 683: ! 684: return (anycmp(&((*dp1).dr),&((*dp2).dr))); ! 685: } ! 686: /* ! 687: * tvcmp4(dp1,dp2) ! 688: */ ! 689: ! 690: tvcmp4(dp1,dp2) ! 691: struct dpair *dp1,*dp2; ! 692: ! 693: { ! 694: extern anycmp(); ! 695: ! 696: return (anycmp(&((*dp1).dv),&((*dp2).dv))); ! 697: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.