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

Defined functions

Procblock defined in line 158; never used
Xsort defined in line 9; never used
trefcmp defined in line 158; used 2 times
tvalcmp defined in line 179; used 2 times
Last modified: 1984-11-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1232
Valid CSS Valid XHTML 1.0 Strict