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