1: static  char *sccsid = "@(#)sort.c	4.11 (Berkeley) 6/3/86";
   2: #include <stdio.h>
   3: #include <ctype.h>
   4: #include <signal.h>
   5: #include <sys/types.h>
   6: #include <sys/stat.h>
   7: 
   8: #define L   1024
   9: #define N   7
  10: #define C   20
  11: #ifndef pdp11
  12: #define MEM (128*2048)
  13: #else
  14: #define MEM (16*2048)
  15: #endif
  16: #define NF  10
  17: 
  18: #define rline(mp)   (fgets((mp)->l, L, (mp)->b) == NULL)
  19: 
  20: FILE    *is, *os;
  21: char    *dirtry[] = {"/usr/tmp", "/tmp", NULL};
  22: char    **dirs;
  23: char    file1[30];
  24: char    *file = file1;
  25: char    *filep;
  26: int nfiles;
  27: unsigned    nlines;
  28: unsigned    ntext;
  29: int *lspace;
  30: char    *tspace;
  31: int cmp(), cmpa();
  32: int (*compare)() = cmpa;
  33: char    *eol();
  34: int term();
  35: int     mflg;
  36: int cflg;
  37: int uflg;
  38: char    *outfil;
  39: int unsafeout;  /*kludge to assure -m -o works*/
  40: char    tabchar;
  41: int     eargc;
  42: char    **eargv;
  43: 
  44: char zero[256];
  45: 
  46: char    fold[256] = {
  47:     0200,0201,0202,0203,0204,0205,0206,0207,
  48:     0210,0211,0212,0213,0214,0215,0216,0217,
  49:     0220,0221,0222,0223,0224,0225,0226,0227,
  50:     0230,0231,0232,0233,0234,0235,0236,0237,
  51:     0240,0241,0242,0243,0244,0245,0246,0247,
  52:     0250,0251,0252,0253,0254,0255,0256,0257,
  53:     0260,0261,0262,0263,0264,0265,0266,0267,
  54:     0270,0271,0272,0273,0274,0275,0276,0277,
  55:     0300,0301,0302,0303,0304,0305,0306,0307,
  56:     0310,0311,0312,0313,0314,0315,0316,0317,
  57:     0320,0321,0322,0323,0324,0325,0326,0327,
  58:     0330,0331,0332,0333,0334,0335,0336,0337,
  59:     0340,0341,0342,0343,0344,0345,0346,0347,
  60:     0350,0351,0352,0353,0354,0355,0356,0357,
  61:     0360,0361,0362,0363,0364,0365,0366,0367,
  62:     0370,0371,0372,0373,0374,0375,0376,0377,
  63:     0000,0001,0002,0003,0004,0005,0006,0007,
  64:     0010,0011,0012,0013,0014,0015,0016,0017,
  65:     0020,0021,0022,0023,0024,0025,0026,0027,
  66:     0030,0031,0032,0033,0034,0035,0036,0037,
  67:     0040,0041,0042,0043,0044,0045,0046,0047,
  68:     0050,0051,0052,0053,0054,0055,0056,0057,
  69:     0060,0061,0062,0063,0064,0065,0066,0067,
  70:     0070,0071,0072,0073,0074,0075,0076,0077,
  71:     0100,0101,0102,0103,0104,0105,0106,0107,
  72:     0110,0111,0112,0113,0114,0115,0116,0117,
  73:     0120,0121,0122,0123,0124,0125,0126,0127,
  74:     0130,0131,0132,0133,0134,0135,0136,0137,
  75:     0140,0101,0102,0103,0104,0105,0106,0107,
  76:     0110,0111,0112,0113,0114,0115,0116,0117,
  77:     0120,0121,0122,0123,0124,0125,0126,0127,
  78:     0130,0131,0132,0173,0174,0175,0176,0177
  79: };
  80: char nofold[256] = {
  81:     0200,0201,0202,0203,0204,0205,0206,0207,
  82:     0210,0211,0212,0213,0214,0215,0216,0217,
  83:     0220,0221,0222,0223,0224,0225,0226,0227,
  84:     0230,0231,0232,0233,0234,0235,0236,0237,
  85:     0240,0241,0242,0243,0244,0245,0246,0247,
  86:     0250,0251,0252,0253,0254,0255,0256,0257,
  87:     0260,0261,0262,0263,0264,0265,0266,0267,
  88:     0270,0271,0272,0273,0274,0275,0276,0277,
  89:     0300,0301,0302,0303,0304,0305,0306,0307,
  90:     0310,0311,0312,0313,0314,0315,0316,0317,
  91:     0320,0321,0322,0323,0324,0325,0326,0327,
  92:     0330,0331,0332,0333,0334,0335,0336,0337,
  93:     0340,0341,0342,0343,0344,0345,0346,0347,
  94:     0350,0351,0352,0353,0354,0355,0356,0357,
  95:     0360,0361,0362,0363,0364,0365,0366,0367,
  96:     0370,0371,0372,0373,0374,0375,0376,0377,
  97:     0000,0001,0002,0003,0004,0005,0006,0007,
  98:     0010,0011,0012,0013,0014,0015,0016,0017,
  99:     0020,0021,0022,0023,0024,0025,0026,0027,
 100:     0030,0031,0032,0033,0034,0035,0036,0037,
 101:     0040,0041,0042,0043,0044,0045,0046,0047,
 102:     0050,0051,0052,0053,0054,0055,0056,0057,
 103:     0060,0061,0062,0063,0064,0065,0066,0067,
 104:     0070,0071,0072,0073,0074,0075,0076,0077,
 105:     0100,0101,0102,0103,0104,0105,0106,0107,
 106:     0110,0111,0112,0113,0114,0115,0116,0117,
 107:     0120,0121,0122,0123,0124,0125,0126,0127,
 108:     0130,0131,0132,0133,0134,0135,0136,0137,
 109:     0140,0141,0142,0143,0144,0145,0146,0147,
 110:     0150,0151,0152,0153,0154,0155,0156,0157,
 111:     0160,0161,0162,0163,0164,0165,0166,0167,
 112:     0170,0171,0172,0173,0174,0175,0176,0177
 113: };
 114: 
 115: char    nonprint[256] = {
 116:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 117:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 118:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 119:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 120:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 121:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 122:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 123:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 124:     1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,
 125:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 126:     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 127:     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 128:     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 129:     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 130:     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 131:     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
 132: };
 133: 
 134: char    dict[256] = {
 135:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 136:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 137:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 138:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 139:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 140:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 141:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 142:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 143:     1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,
 144:     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 145:     0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
 146:     0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,
 147:     1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 148:     0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,
 149:     1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 150:     0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1
 151: };
 152: 
 153: struct  field {
 154:     char *code;
 155:     char *ignore;
 156:     int nflg;
 157:     int rflg;
 158:     int bflg[2];
 159:     int m[2];
 160:     int n[2];
 161: }   fields[NF];
 162: struct field proto = {
 163:     nofold+128,
 164:     zero+128,
 165:     0,
 166:     1,
 167:     0,0,
 168:     0,-1,
 169:     0,0
 170: };
 171: int nfields;
 172: int     error = 1;
 173: char    *setfil();
 174: char    *sbrk();
 175: char    *brk();
 176: 
 177: #define blank(c)    ((c) == ' ' || (c) == '\t')
 178: 
 179: main(argc, argv)
 180: char **argv;
 181: {
 182:     register a;
 183:     extern char end[1];
 184:     char *ep;
 185:     char *arg;
 186:     struct field *p, *q;
 187:     int i;
 188: 
 189:     copyproto();
 190:     eargv = argv;
 191:     while (--argc > 0) {
 192:         if(**++argv == '-') for(arg = *argv;;) {
 193:             switch(*++arg) {
 194:             case '\0':
 195:                 if(arg[-1] == '-')
 196:                     eargv[eargc++] = "-";
 197:                 break;
 198: 
 199:             case 'o':
 200:                 if(--argc > 0)
 201:                     outfil = *++argv;
 202:                 continue;
 203: 
 204:             case 'T':
 205:                 if (--argc > 0)
 206:                     dirtry[0] = *++argv;
 207:                 continue;
 208: 
 209:             default:
 210:                 field(++*argv,nfields>0);
 211:                 break;
 212:             }
 213:             break;
 214:         } else if (**argv == '+') {
 215:             if(++nfields>=NF) {
 216:                 diag("too many keys","");
 217:                 exit(1);
 218:             }
 219:             copyproto();
 220:             field(++*argv,0);
 221:         } else
 222:             eargv[eargc++] = *argv;
 223:     }
 224:     q = &fields[0];
 225:     for(a=1; a<=nfields; a++) {
 226:         p = &fields[a];
 227:         if(p->code != proto.code) continue;
 228:         if(p->ignore != proto.ignore) continue;
 229:         if(p->nflg != proto.nflg) continue;
 230:         if(p->rflg != proto.rflg) continue;
 231:         if(p->bflg[0] != proto.bflg[0]) continue;
 232:         if(p->bflg[1] != proto.bflg[1]) continue;
 233:         p->code = q->code;
 234:         p->ignore = q->ignore;
 235:         p->nflg = q->nflg;
 236:         p->rflg = q->rflg;
 237:         p->bflg[0] = p->bflg[1] = q->bflg[0];
 238:     }
 239:     if(eargc == 0)
 240:         eargv[eargc++] = "-";
 241:     if(cflg && eargc>1) {
 242:         diag("can check only 1 file","");
 243:         exit(1);
 244:     }
 245:     safeoutfil();
 246: 
 247:     ep = end + MEM;
 248:     lspace = (int *)sbrk(0);
 249:     while((int)brk(ep) == -1)
 250:         ep -= 512;
 251: #ifndef vax
 252:     brk(ep -= 512); /* for recursion */
 253: #endif
 254:     a = ep - (char*)lspace;
 255:     nlines = (a-L);
 256:     nlines /= (5*(sizeof(char *)/sizeof(char)));
 257:     ntext = nlines * 4 * (sizeof(char *)/sizeof(char));
 258:     tspace = (char *)(lspace + nlines);
 259:     a = -1;
 260:     for(dirs=dirtry; *dirs; dirs++) {
 261:         sprintf(filep=file1, "%s/stm%05uaa", *dirs, getpid());
 262:         while (*filep)
 263:             filep++;
 264:         filep -= 2;
 265:         if ( (a=creat(file, 0600)) >=0)
 266:             break;
 267:     }
 268:     if(a < 0) {
 269:         diag("can't locate temp","");
 270:         exit(1);
 271:     }
 272:     close(a);
 273:     unlink(file);
 274:     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
 275:         signal(SIGHUP, term);
 276:     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
 277:         signal(SIGINT, term);
 278:     signal(SIGPIPE,term);
 279:     if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
 280:         signal(SIGTERM,term);
 281:     nfiles = eargc;
 282:     if(!mflg && !cflg) {
 283:         sort();
 284:         fclose(stdin);
 285:     }
 286:     for(a = mflg|cflg?0:eargc; a+N<nfiles || unsafeout&&a<eargc; a=i) {
 287:         i = a+N;
 288:         if(i>=nfiles)
 289:             i = nfiles;
 290:         newfile();
 291:         merge(a, i);
 292:     }
 293:     if(a != nfiles) {
 294:         oldfile();
 295:         merge(a, nfiles);
 296:     }
 297:     error = 0;
 298:     term();
 299: }
 300: 
 301: sort()
 302: {
 303:     register char *cp;
 304:     register char **lp;
 305:     register lines, text, len;
 306:     int done = 0;
 307:     int i = 0;
 308:     char *f;
 309:     char c;
 310: 
 311:     if((f = setfil(i++)) == NULL)
 312:         is = stdin;
 313:     else if((is = fopen(f, "r")) == NULL)
 314:         cant(f);
 315: 
 316:     do {
 317:         cp = tspace;
 318:         lp = (char **)lspace;
 319:         lines = nlines;
 320:         text = ntext;
 321:         while(lines > 0 && text > 0) {
 322:             if(fgets(cp, L, is) == NULL) {
 323:                 if(i >= eargc) {
 324:                     ++done;
 325:                     break;
 326:                 }
 327:                 fclose(is);
 328:                 if((f = setfil(i++)) == NULL)
 329:                     is = stdin;
 330:                 else if((is = fopen(f, "r")) == NULL)
 331:                     cant(f);
 332:                 continue;
 333:             }
 334:             *lp++ = cp;
 335:             len = strlen(cp) + 1; /* null terminate */
 336:             if(cp[len - 2] != '\n')
 337:                 if (len == L) {
 338:                     diag("line too long (skipped): ", cp);
 339:                     while((c=getc(is)) != EOF && c != '\n')
 340:                         /* throw it away */;
 341:                     --lp;
 342:                     continue;
 343:                 } else {
 344:                     diag("missing newline before EOF in ",
 345:                         f ? f : "standard input");
 346:                     /* be friendly, append a newline */
 347:                     ++len;
 348:                     cp[len - 2] = '\n';
 349:                     cp[len - 1] = '\0';
 350:                 }
 351:             cp += len;
 352:             --lines;
 353:             text -= len;
 354:         }
 355:         qsort((char **)lspace, lp);
 356:         if(done == 0 || nfiles != eargc)
 357:             newfile();
 358:         else
 359:             oldfile();
 360:         clearerr(os);
 361:         while(lp > (char **)lspace) {
 362:             cp = *--lp;
 363:             if(*cp)
 364:                 fputs(cp, os);
 365:             if (ferror(os)) {
 366:                 error = 1;
 367:                 term();
 368:             }
 369:         }
 370:         fclose(os);
 371:     } while(done == 0);
 372: }
 373: 
 374: struct merg
 375: {
 376:     char    l[L];
 377:     FILE    *b;
 378: } *ibuf[256];
 379: 
 380: merge(a,b)
 381: {
 382:     struct  merg    *p;
 383:     register char   *cp, *dp;
 384:     register    i;
 385:     struct merg **ip, *jp;
 386:     char    *f;
 387:     int j;
 388:     int k, l;
 389:     int muflg;
 390: 
 391:     p = (struct merg *)lspace;
 392:     j = 0;
 393:     for(i=a; i < b; i++) {
 394:         f = setfil(i);
 395:         if(f == 0)
 396:             p->b = stdin;
 397:         else if((p->b = fopen(f, "r")) == NULL)
 398:             cant(f);
 399:         ibuf[j] = p;
 400:         if(!rline(p))   j++;
 401:         p++;
 402:     }
 403: 
 404:     do {
 405:         i = j;
 406:         qsort((char **)ibuf, (char **)(ibuf+i));
 407:         l = 0;
 408:         while(i--) {
 409:             cp = ibuf[i]->l;
 410:             if(*cp == '\0') {
 411:                 l = 1;
 412:                 if(rline(ibuf[i])) {
 413:                     k = i;
 414:                     while(++k < j)
 415:                         ibuf[k-1] = ibuf[k];
 416:                     j--;
 417:                 }
 418:             }
 419:         }
 420:     } while(l);
 421: 
 422:     clearerr(os);
 423:     muflg = mflg & uflg | cflg;
 424:     i = j;
 425:     while(i > 0) {
 426:         cp = ibuf[i-1]->l;
 427:         if (!cflg && (uflg == 0 || muflg || i == 1 ||
 428:             (*compare)(ibuf[i-1]->l,ibuf[i-2]->l))) {
 429:             fputs(cp, os);
 430:             if (ferror(os)) {
 431:                 error = 1;
 432:                 term();
 433:             }
 434:         }
 435:         if(muflg){
 436:             cp = ibuf[i-1]->l;
 437:             dp = p->l;
 438:             do {
 439:             } while((*dp++ = *cp++) != '\n');
 440:         }
 441:         for(;;) {
 442:             if(rline(ibuf[i-1])) {
 443:                 i--;
 444:                 if(i == 0)
 445:                     break;
 446:                 if(i == 1)
 447:                     muflg = uflg;
 448:             }
 449:             ip = &ibuf[i];
 450:             while(--ip>ibuf&&(*compare)(ip[0]->l,ip[-1]->l)<0){
 451:                 jp = *ip;
 452:                 *ip = *(ip-1);
 453:                 *(ip-1) = jp;
 454:             }
 455:             if(!muflg)
 456:                 break;
 457:             j = (*compare)(ibuf[i-1]->l,p->l);
 458:             if(cflg) {
 459:                 if(j > 0)
 460:                     disorder("disorder:",ibuf[i-1]->l);
 461:                 else if(uflg && j==0)
 462:                     disorder("nonunique:",ibuf[i-1]->l);
 463:             } else if(j == 0)
 464:                 continue;
 465:             break;
 466:         }
 467:     }
 468:     p = (struct merg *)lspace;
 469:     for(i=a; i<b; i++) {
 470:         fclose(p->b);
 471:         p++;
 472:         if(i >= eargc)
 473:             unlink(setfil(i));
 474:     }
 475:     fclose(os);
 476: }
 477: 
 478: disorder(s,t)
 479: char *s, *t;
 480: {
 481:     register char *u;
 482:     for(u=t; *u!='\n';u++) ;
 483:     *u = 0;
 484:     diag(s,t);
 485:     term();
 486: }
 487: 
 488: newfile()
 489: {
 490:     register char *f;
 491: 
 492:     f = setfil(nfiles);
 493:     if((os=fopen(f, "w")) == NULL) {
 494:         diag("can't create ",f);
 495:         term();
 496:     }
 497:     nfiles++;
 498: }
 499: 
 500: char *
 501: setfil(i)
 502: {
 503: 
 504:     if(i < eargc)
 505:         if(eargv[i][0] == '-' && eargv[i][1] == '\0')
 506:             return(0);
 507:         else
 508:             return(eargv[i]);
 509:     i -= eargc;
 510:     filep[0] = i/26 + 'a';
 511:     filep[1] = i%26 + 'a';
 512:     return(file);
 513: }
 514: 
 515: oldfile()
 516: {
 517: 
 518:     if(outfil) {
 519:         if((os=fopen(outfil, "w")) == NULL) {
 520:             diag("can't create ",outfil);
 521:             term();
 522:         }
 523:     } else
 524:         os = stdout;
 525: }
 526: 
 527: safeoutfil()
 528: {
 529:     register int i;
 530:     struct stat obuf,ibuf;
 531: 
 532:     if(!mflg||outfil==0)
 533:         return;
 534:     if(stat(outfil,&obuf)==-1)
 535:         return;
 536:     for(i=eargc-N;i<eargc;i++) {    /*-N is suff., not nec.*/
 537:         if(stat(eargv[i],&ibuf)==-1)
 538:             continue;
 539:         if(obuf.st_dev==ibuf.st_dev&&
 540:            obuf.st_ino==ibuf.st_ino)
 541:             unsafeout++;
 542:     }
 543: }
 544: 
 545: cant(f)
 546: char *f;
 547: {
 548: 
 549:     perror(f);
 550:     term();
 551: }
 552: 
 553: diag(s,t)
 554: char *s, *t;
 555: {
 556:     fputs("sort: ",stderr);
 557:     fputs(s,stderr);
 558:     fputs(t,stderr);
 559:     fputs("\n",stderr);
 560: }
 561: 
 562: term()
 563: {
 564:     register i;
 565: 
 566:     signal(SIGINT, SIG_IGN);
 567:     signal(SIGHUP, SIG_IGN);
 568:     signal(SIGTERM, SIG_IGN);
 569:     if(nfiles == eargc)
 570:         nfiles++;
 571:     for(i=eargc; i<=nfiles; i++) {  /*<= in case of interrupt*/
 572:         unlink(setfil(i));  /*with nfiles not updated*/
 573:     }
 574:     _exit(error);
 575: }
 576: 
 577: cmp(i, j)
 578: char *i, *j;
 579: {
 580:     register char *pa, *pb;
 581:     char *skip();
 582:     char *code, *ignore;
 583:     int a, b;
 584:     int k;
 585:     char *la, *lb;
 586:     register int sa;
 587:     int sb;
 588:     char *ipa, *ipb, *jpa, *jpb;
 589:     struct field *fp;
 590: 
 591:     for(k = nfields>0; k<=nfields; k++) {
 592:         fp = &fields[k];
 593:         pa = i;
 594:         pb = j;
 595:         if(k) {
 596:             la = skip(pa, fp, 1);
 597:             pa = skip(pa, fp, 0);
 598:             lb = skip(pb, fp, 1);
 599:             pb = skip(pb, fp, 0);
 600:         } else {
 601:             la = eol(pa);
 602:             lb = eol(pb);
 603:         }
 604:         if(fp->nflg) {
 605:             if(tabchar) {
 606:                 if(pa<la&&*pa==tabchar)
 607:                     pa++;
 608:                 if(pb<lb&&*pb==tabchar)
 609:                     pb++;
 610:             }
 611:             while(blank(*pa))
 612:                 pa++;
 613:             while(blank(*pb))
 614:                 pb++;
 615:             sa = sb = fp->rflg;
 616:             if(*pa == '-') {
 617:                 pa++;
 618:                 sa = -sa;
 619:             }
 620:             if(*pb == '-') {
 621:                 pb++;
 622:                 sb = -sb;
 623:             }
 624:             for(ipa = pa; ipa<la&&isdigit(*ipa); ipa++) ;
 625:             for(ipb = pb; ipb<lb&&isdigit(*ipb); ipb++) ;
 626:             jpa = ipa;
 627:             jpb = ipb;
 628:             a = 0;
 629:             if(sa==sb)
 630:                 while(ipa > pa && ipb > pb)
 631:                     if(b = *--ipb - *--ipa)
 632:                         a = b;
 633:             while(ipa > pa)
 634:                 if(*--ipa != '0')
 635:                     return(-sa);
 636:             while(ipb > pb)
 637:                 if(*--ipb != '0')
 638:                     return(sb);
 639:             if(a) return(a*sa);
 640:             if(*(pa=jpa) == '.')
 641:                 pa++;
 642:             if(*(pb=jpb) == '.')
 643:                 pb++;
 644:             if(sa==sb)
 645:                 while(pa<la && isdigit(*pa)
 646:                    && pb<lb && isdigit(*pb))
 647:                     if(a = *pb++ - *pa++)
 648:                         return(a*sa);
 649:             while(pa<la && isdigit(*pa))
 650:                 if(*pa++ != '0')
 651:                     return(-sa);
 652:             while(pb<lb && isdigit(*pb))
 653:                 if(*pb++ != '0')
 654:                     return(sb);
 655:             continue;
 656:         }
 657:         code = fp->code;
 658:         ignore = fp->ignore;
 659: loop:
 660:         while(ignore[*pa])
 661:             pa++;
 662:         while(ignore[*pb])
 663:             pb++;
 664:         if(pa>=la || *pa=='\n')
 665:             if(pb<lb && *pb!='\n')
 666:                 return(fp->rflg);
 667:             else continue;
 668:         if(pb>=lb || *pb=='\n')
 669:             return(-fp->rflg);
 670:         if((sa = code[*pb++]-code[*pa++]) == 0)
 671:             goto loop;
 672:         return(sa*fp->rflg);
 673:     }
 674:     if(uflg)
 675:         return(0);
 676:     return(cmpa(i, j));
 677: }
 678: 
 679: cmpa(pa, pb)
 680: register char *pa, *pb;
 681: {
 682:     while(*pa == *pb) {
 683:         if(*pa++ == '\n')
 684:             return(0);
 685:         pb++;
 686:     }
 687:     return(
 688:         *pa == '\n' ? fields[0].rflg:
 689:         *pb == '\n' ?-fields[0].rflg:
 690:         *pb > *pa   ? fields[0].rflg:
 691:         -fields[0].rflg
 692:     );
 693: }
 694: 
 695: char *
 696: skip(pp, fp, j)
 697: struct field *fp;
 698: char *pp;
 699: {
 700:     register i;
 701:     register char *p;
 702: 
 703:     p = pp;
 704:     if( (i=fp->m[j]) < 0)
 705:         return(eol(p));
 706:     while(i-- > 0) {
 707:         if(tabchar != 0) {
 708:             while(*p != tabchar)
 709:                 if(*p != '\n')
 710:                     p++;
 711:                 else goto ret;
 712:             if(i>0||j==0)
 713:                 p++;
 714:         } else {
 715:             while(blank(*p))
 716:                 p++;
 717:             while(!blank(*p))
 718:                 if(*p != '\n')
 719:                     p++;
 720:                 else goto ret;
 721:         }
 722:     }
 723:     if(tabchar==0||fp->bflg[j])
 724:         while(blank(*p))
 725:             p++;
 726:     i = fp->n[j];
 727:     while(i-- > 0) {
 728:         if(*p != '\n')
 729:             p++;
 730:         else goto ret;
 731:     }
 732: ret:
 733:     return(p);
 734: }
 735: 
 736: char *
 737: eol(p)
 738: register char *p;
 739: {
 740:     while(*p != '\n') p++;
 741:     return(p);
 742: }
 743: 
 744: copyproto()
 745: {
 746:     register i;
 747:     register int *p, *q;
 748: 
 749:     p = (int *)&proto;
 750:     q = (int *)&fields[nfields];
 751:     for(i=0; i<sizeof(proto)/sizeof(*p); i++)
 752:         *q++ = *p++;
 753: }
 754: 
 755: field(s,k)
 756: char *s;
 757: {
 758:     register struct field *p;
 759:     register d;
 760:     p = &fields[nfields];
 761:     d = 0;
 762:     for(; *s!=0; s++) {
 763:         switch(*s) {
 764:         case '\0':
 765:             return;
 766: 
 767:         case 'b':
 768:             p->bflg[k]++;
 769:             break;
 770: 
 771:         case 'd':
 772:             p->ignore = dict+128;
 773:             break;
 774: 
 775:         case 'f':
 776:             p->code = fold+128;
 777:             break;
 778:         case 'i':
 779:             p->ignore = nonprint+128;
 780:             break;
 781: 
 782:         case 'c':
 783:             cflg = 1;
 784:             continue;
 785: 
 786:         case 'm':
 787:             mflg = 1;
 788:             continue;
 789: 
 790:         case 'n':
 791:             p->nflg++;
 792:             break;
 793:         case 't':
 794:             tabchar = *++s;
 795:             if(tabchar == 0) s--;
 796:             continue;
 797: 
 798:         case 'r':
 799:             p->rflg = -1;
 800:             continue;
 801:         case 'u':
 802:             uflg = 1;
 803:             break;
 804: 
 805:         case '.':
 806:             if(p->m[k] == -1)   /* -m.n with m missing */
 807:                 p->m[k] = 0;
 808:             d = &fields[0].n[0]-&fields[0].m[0];
 809: 
 810:         default:
 811:             p->m[k+d] = number(&s);
 812:         }
 813:         compare = cmp;
 814:     }
 815: }
 816: 
 817: number(ppa)
 818: char **ppa;
 819: {
 820:     int n;
 821:     register char *pa;
 822:     pa = *ppa;
 823:     n = 0;
 824:     while(isdigit(*pa)) {
 825:         n = n*10 + *pa - '0';
 826:         *ppa = pa++;
 827:     }
 828:     return(n);
 829: }
 830: 
 831: #define qsexc(p,q) t= *p;*p= *q;*q=t
 832: #define qstexc(p,q,r) t= *p;*p= *r;*r= *q;*q=t
 833: 
 834: qsort(a,l)
 835: char **a, **l;
 836: {
 837:     register char **i, **j;
 838:     char **k;
 839:     char **lp, **hp;
 840:     int c;
 841:     char *t;
 842:     unsigned n;
 843: 
 844: 
 845: 
 846: start:
 847:     if((n=l-a) <= 1)
 848:         return;
 849: 
 850: 
 851:     n /= 2;
 852:     hp = lp = a+n;
 853:     i = a;
 854:     j = l-1;
 855: 
 856: 
 857:     for(;;) {
 858:         if(i < lp) {
 859:             if((c = (*compare)(*i, *lp)) == 0) {
 860:                 --lp;
 861:                 qsexc(i, lp);
 862:                 continue;
 863:             }
 864:             if(c < 0) {
 865:                 ++i;
 866:                 continue;
 867:             }
 868:         }
 869: 
 870: loop:
 871:         if(j > hp) {
 872:             if((c = (*compare)(*hp, *j)) == 0) {
 873:                 ++hp;
 874:                 qsexc(hp, j);
 875:                 goto loop;
 876:             }
 877:             if(c > 0) {
 878:                 if(i == lp) {
 879:                     ++hp;
 880:                     qstexc(i, hp, j);
 881:                     i = ++lp;
 882:                     goto loop;
 883:                 }
 884:                 qsexc(i, j);
 885:                 --j;
 886:                 ++i;
 887:                 continue;
 888:             }
 889:             --j;
 890:             goto loop;
 891:         }
 892: 
 893: 
 894:         if(i == lp) {
 895:             if(uflg)
 896:                 for(k=lp+1; k<=hp;) **k++ = '\0';
 897:             if(lp-a >= l-hp) {
 898:                 qsort(hp+1, l);
 899:                 l = lp;
 900:             } else {
 901:                 qsort(a, lp);
 902:                 a = hp+1;
 903:             }
 904:             goto start;
 905:         }
 906: 
 907: 
 908:         --lp;
 909:         qstexc(j, lp, i);
 910:         j = --hp;
 911:     }
 912: }

Defined functions

cant defined in line 545; used 3 times
cmp defined in line 577; used 2 times
cmpa defined in line 679; used 3 times
copyproto defined in line 744; used 2 times
diag defined in line 553; used 8 times
disorder defined in line 478; used 2 times
eol defined in line 736; used 4 times
field defined in line 755; used 2 times
main defined in line 179; never used
merge defined in line 380; used 2 times
newfile defined in line 488; used 2 times
number defined in line 817; used 1 times
oldfile defined in line 515; used 2 times
qsort defined in line 834; used 5 times
safeoutfil defined in line 527; used 1 times
setfil defined in line 500; used 7 times
skip defined in line 695; used 5 times
sort defined in line 301; used 1 times
term defined in line 562; used 12 times

Defined variables

cflg defined in line 36; used 7 times
dict defined in line 134; used 1 times
dirs defined in line 22; used 4 times
dirtry defined in line 21; used 2 times
eargc defined in line 41; used 17 times
eargv defined in line 42; used 8 times
error defined in line 172; used 4 times
fields defined in line 161; used 11 times
file defined in line 24; used 3 times
file1 defined in line 23; used 2 times
filep defined in line 25; used 6 times
fold defined in line 46; used 1 times
ibuf defined in line 378; used 21 times
lspace defined in line 29; used 8 times
mflg defined in line 35; used 5 times
nfields defined in line 171; used 7 times
nfiles defined in line 26; used 12 times
nlines defined in line 27; used 5 times
nofold defined in line 80; used 1 times
nonprint defined in line 115; used 1 times
ntext defined in line 28; used 2 times
outfil defined in line 38; used 6 times
proto defined in line 162; used 8 times
sccsid defined in line 1; never used
tabchar defined in line 40; used 8 times
tspace defined in line 30; used 2 times
uflg defined in line 37; used 7 times
unsafeout defined in line 39; used 2 times
zero defined in line 44; used 1 times

Defined struct's

field defined in line 153; used 10 times
merg defined in line 374; used 8 times

Defined macros

C defined in line 10; never used
L defined in line 8; used 5 times
MEM defined in line 14; used 1 times
N defined in line 9; used 3 times
NF defined in line 16; used 2 times
blank defined in line 177; used 5 times
qsexc defined in line 831; used 3 times
qstexc defined in line 832; used 2 times
rline defined in line 18; used 3 times
Last modified: 1986-06-04
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2437
Valid CSS Valid XHTML 1.0 Strict