|
|
1.1 ! root 1: #include "../h/rt.h" ! 2: ! 3: /* ! 4: * sort(l) - sort list l. ! 5: * sort(S) - sort set S. ! 6: * sort(t,i) - sort table on reference (i = 1) or value (i = 2) field. ! 7: */ ! 8: ! 9: Xsort(nargs, arg2, arg1, arg0) ! 10: int nargs; ! 11: struct descrip arg2, arg1, arg0; ! 12: { ! 13: register struct descrip *d1; ! 14: register int size, i; ! 15: int nelem; ! 16: struct b_list *lp, *tp; ! 17: union block *bp, *ep; ! 18: extern struct b_list *alclist(); ! 19: extern struct b_lelem *alclstb(); ! 20: extern anycmp(), trefcmp(), tvalcmp(); ! 21: ! 22: DeRef(arg1) ! 23: if (arg1.type == D_LIST) { ! 24: /* ! 25: * Sort the list by copying it into a new list and then using ! 26: * qsort to sort the descriptors. (That was easy!) ! 27: */ ! 28: size = BLKLOC(arg1)->list.cursize; ! 29: cplist(&arg1, &arg0, 1, size + 1); ! 30: qsort(BLKLOC(BLKLOC(arg0)->list.listhead)->lelem.lslots, size, ! 31: sizeof(struct descrip), anycmp); ! 32: } ! 33: #ifdef SETS ! 34: else if (arg1.type == D_SET) { ! 35: /* ! 36: * Create a list the size of the set (or at least ! 37: * LISTBLKSIZE), copy each element into the list, and ! 38: * then sort the list using qsort as in list sorting ! 39: * and return the sorted list. ! 40: */ ! 41: nelem = size = BLKLOC(arg1)->set.setsize; ! 42: if(nelem < LISTBLKSIZE) ! 43: nelem = LISTBLKSIZE; ! 44: hneed(sizeof(struct b_list) + sizeof(struct b_lelem) + ! 45: nelem * sizeof(struct descrip)); ! 46: ! 47: bp = BLKLOC(arg1); ! 48: lp = alclist(size); ! 49: lp->listhead.type = lp->listtail.type = D_LELEM; ! 50: BLKLOC(lp->listtail) = (union block *) alclstb(nelem,0,size); ! 51: BLKLOC(lp->listhead) = BLKLOC(lp->listtail); ! 52: if (size > 0) { /* only need to sort non-empty sets */ ! 53: d1 = BLKLOC(lp->listhead)->lelem.lslots; ! 54: for(i = 0; i < NBUCKETS; i++) { ! 55: ep = BLKLOC(bp->set.sbucks[i]); ! 56: while (ep != NULL) { ! 57: *d1 = ep->selem.setmem; ! 58: d1++; ! 59: ep = BLKLOC(ep->selem.sblink); ! 60: } ! 61: } ! 62: qsort(BLKLOC(lp->listhead)->lelem.lslots,size,sizeof(struct descrip),anycmp); ! 63: } ! 64: arg0.type = D_LIST; ! 65: BLKLOC(arg0) = (union block *) lp; ! 66: } ! 67: #endif SETS ! 68: ! 69: else if (arg1.type == D_TABLE) { ! 70: /* ! 71: * Default i (the type of sort) to 1, and be sure that it is ! 72: * either 1 or 2. ! 73: */ ! 74: defshort(&arg2, 1); ! 75: if (INTVAL(arg2) != 1 && INTVAL(arg2) != 2) ! 76: runerr(205, &arg2); ! 77: ! 78: /* ! 79: * The list resulting from the sort will have as many elements as ! 80: * the table has, so get that value and also make a valid list ! 81: * block size out of it. ! 82: */ ! 83: nelem = size = BLKLOC(arg1)->table.cursize; ! 84: if (nelem < LISTBLKSIZE) ! 85: nelem = LISTBLKSIZE; ! 86: /* ! 87: * Ensure space for: the list header block and a list element ! 88: * block for the list which is to be returned, ! 89: * a list header block and a list element block for each of the two ! 90: * element lists the sorted list is to contain. Note that the ! 91: * calculation might be better expressed as: ! 92: * list_header_size + list_block_size + nelem * descriptor_size + ! 93: * nelem * (list_header_size + list_block_size + 2*descriptor_size) ! 94: */ ! 95: hneed(sizeof(struct b_list) + sizeof(struct b_lelem) + ! 96: nelem * (sizeof(struct b_list) + sizeof(struct b_lelem) + ! 97: 3 * sizeof(struct descrip))); ! 98: /* ! 99: * Point bp at the table header block of the table to be sorted ! 100: * and point lp at a newly allocated list ! 101: * that will hold the the result of sorting the table. ! 102: */ ! 103: bp = BLKLOC(arg1); ! 104: lp = alclist(size); ! 105: lp->listhead.type = lp->listtail.type = D_LELEM; ! 106: BLKLOC(lp->listtail) = (union block *) alclstb(nelem, 0, size); ! 107: BLKLOC(lp->listhead) = BLKLOC(lp->listtail); ! 108: if (size > 0) { /* No need to sort the elements of an empty table */ ! 109: /* ! 110: * Point d1 at the start of the list elements in the new list ! 111: * element block in preparation for use as an index into the list. ! 112: */ ! 113: d1 = BLKLOC(lp->listhead)->lelem.lslots; ! 114: /* ! 115: * Traverse the element chain for each table bucket. For each ! 116: * element, allocate a two-element list and put the table ! 117: * entry value in the first element and the assigned value in ! 118: * the second element. The two-element list is assigned to ! 119: * the descriptor that d1 points at. When this is done, the ! 120: * list of two-element lists is complete, but unsorted. ! 121: */ ! 122: for (i = 0; i < NBUCKETS; i++) { ! 123: ep = BLKLOC(bp->table.buckets[i]); ! 124: while (ep != NULL) { ! 125: d1->type = D_LIST; ! 126: tp = alclist(2); ! 127: BLKLOC(*d1) = (union block *) tp; ! 128: tp->listhead.type = tp->listtail.type = D_LELEM; ! 129: BLKLOC(tp->listtail) = (union block *) alclstb(2, 0, 2); ! 130: BLKLOC(tp->listhead) = BLKLOC(tp->listtail); ! 131: BLKLOC(tp->listhead)->lelem.lslots[0] = ep->telem.tref; ! 132: BLKLOC(tp->listhead)->lelem.lslots[1] = ep->telem.tval; ! 133: d1++; ! 134: ep = BLKLOC(ep->telem.blink); ! 135: } ! 136: } ! 137: /* ! 138: * Sort the resulting two-element list using the sorting function ! 139: * determined by i. ! 140: */ ! 141: if (INTVAL(arg2) == 1) ! 142: qsort(BLKLOC(lp->listhead)->lelem.lslots, size, ! 143: sizeof(struct descrip), trefcmp); ! 144: else ! 145: qsort(BLKLOC(lp->listhead)->lelem.lslots, size, ! 146: sizeof(struct descrip), tvalcmp); ! 147: } ! 148: /* ! 149: * Make arg0 point at the sorted list. ! 150: */ ! 151: arg0.type = D_LIST; ! 152: BLKLOC(arg0) = (union block *) lp; ! 153: } ! 154: else /* Tried to sort something that wasn't a list or a table. */ ! 155: runerr(115, &arg1); ! 156: } ! 157: ! 158: Procblock(sort,2) ! 159: ! 160: /* ! 161: * trefcmp(d1,d2) - compare two-element lists on first field. ! 162: */ ! 163: ! 164: trefcmp(d1,d2) ! 165: struct descrip *d1, *d2; ! 166: { ! 167: extern anycmp(); ! 168: ! 169: if (d1->type != D_LIST || d2->type != D_LIST) ! 170: syserr("trefcmp: internal consistency check fails."); ! 171: return (anycmp(&(BLKLOC(BLKLOC(*d1)->list.listhead)->lelem.lslots[0]), ! 172: &(BLKLOC(BLKLOC(*d2)->list.listhead)->lelem.lslots[0]))); ! 173: } ! 174: ! 175: /* ! 176: * tvalcmp(d1,d2) - compare two-element lists on second field. ! 177: */ ! 178: ! 179: tvalcmp(d1,d2) ! 180: struct descrip *d1, *d2; ! 181: { ! 182: extern anycmp(); ! 183: ! 184: if (d1->type != D_LIST || d2->type != D_LIST) ! 185: syserr("tvalcmp: internal consistency check fails."); ! 186: return (anycmp(&(BLKLOC(BLKLOC(*d1)->list.listhead)->lelem.lslots[1]), ! 187: &(BLKLOC(BLKLOC(*d2)->list.listhead)->lelem.lslots[1]))); ! 188: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.