Annotation of 43BSD/contrib/icon/functions/sort.c, revision 1.1.1.1

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:    }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.