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 1024 /* max line length increased for refer */ 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,0135,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: if ((putc(*cp, os) == EOF) && ferror(os)) { 338: perror("write"); 339: term(); 340: } 341: while(*cp++ != '\n'); 342: } 343: fclose(os); 344: } while(done == 0); 345: } 346: 347: struct merg 348: { 349: char l[L]; 350: FILE *b; 351: } *ibuf[256]; 352: 353: merge(a,b) 354: { 355: struct merg *p; 356: register char *cp, *dp; 357: register i; 358: struct merg **ip, *jp; 359: char *f; 360: int j; 361: int k, l; 362: int muflg; 363: 364: p = (struct merg *)lspace; 365: j = 0; 366: for(i=a; i < b; i++) { 367: f = setfil(i); 368: if(f == 0) 369: p->b = stdin; 370: else if((p->b = fopen(f, "r")) == NULL) 371: cant(f); 372: ibuf[j] = p; 373: if(!rline(p)) j++; 374: p++; 375: } 376: 377: do { 378: i = j; 379: qsort((char **)ibuf, (char **)(ibuf+i)); 380: l = 0; 381: while(i--) { 382: cp = ibuf[i]->l; 383: if(*cp == '\0') { 384: l = 1; 385: if(rline(ibuf[i])) { 386: k = i; 387: while(++k < j) 388: ibuf[k-1] = ibuf[k]; 389: j--; 390: } 391: } 392: } 393: } while(l); 394: 395: muflg = mflg & uflg | cflg; 396: i = j; 397: while(i > 0) { 398: cp = ibuf[i-1]->l; 399: if(!cflg && (uflg == 0 || muflg || 400: (*compare)(ibuf[i-1]->l,ibuf[i-2]->l))) 401: do 402: if ((putc(*cp, os) == EOF) && ferror(os)) { 403: perror("write"); 404: term(); 405: } 406: while(*cp++ != '\n'); 407: if(muflg){ 408: cp = ibuf[i-1]->l; 409: dp = p->l; 410: do { 411: } while((*dp++ = *cp++) != '\n'); 412: } 413: for(;;) { 414: if(rline(ibuf[i-1])) { 415: i--; 416: if(i == 0) 417: break; 418: if(i == 1) 419: muflg = uflg; 420: } 421: ip = &ibuf[i]; 422: while(--ip>ibuf&&(*compare)(ip[0]->l,ip[-1]->l)<0){ 423: jp = *ip; 424: *ip = *(ip-1); 425: *(ip-1) = jp; 426: } 427: if(!muflg) 428: break; 429: j = (*compare)(ibuf[i-1]->l,p->l); 430: if(cflg) { 431: if(j > 0) 432: disorder("disorder:",ibuf[i-1]->l); 433: else if(uflg && j==0) 434: disorder("nonunique:",ibuf[i-1]->l); 435: } else if(j == 0) 436: continue; 437: break; 438: } 439: } 440: p = (struct merg *)lspace; 441: for(i=a; i<b; i++) { 442: fclose(p->b); 443: p++; 444: if(i >= eargc) 445: unlink(setfil(i)); 446: } 447: fclose(os); 448: } 449: 450: rline(mp) 451: struct merg *mp; 452: { 453: register char *cp; 454: register char *ce; 455: FILE *bp; 456: register c; 457: 458: bp = mp->b; 459: cp = mp->l; 460: ce = cp+L; 461: do { 462: c = getc(bp); 463: if(c == EOF) 464: return(1); 465: if(cp>=ce) 466: cp--; 467: *cp++ = c; 468: } while(c!='\n'); 469: return(0); 470: } 471: 472: disorder(s,t) 473: char *s, *t; 474: { 475: register char *u; 476: for(u=t; *u!='\n';u++) ; 477: *u = 0; 478: diag(s,t); 479: term(); 480: } 481: 482: newfile() 483: { 484: register char *f; 485: 486: f = setfil(nfiles); 487: if((os=fopen(f, "w")) == NULL) { 488: diag("can't create ",f); 489: term(); 490: } 491: nfiles++; 492: } 493: 494: char * 495: setfil(i) 496: { 497: 498: if(i < eargc) 499: if(eargv[i][0] == '-' && eargv[i][1] == '\0') 500: return(0); 501: else 502: return(eargv[i]); 503: i -= eargc; 504: filep[0] = i/26 + 'a'; 505: filep[1] = i%26 + 'a'; 506: return(file); 507: } 508: 509: oldfile() 510: { 511: 512: if(outfil) { 513: if((os=fopen(outfil, "w")) == NULL) { 514: diag("can't create ",outfil); 515: term(); 516: } 517: } else 518: os = stdout; 519: } 520: 521: safeoutfil() 522: { 523: register int i; 524: struct stat obuf,ibuf; 525: 526: if(!mflg||outfil==0) 527: return; 528: if(stat(outfil,&obuf)==-1) 529: return; 530: for(i=eargc-N;i<eargc;i++) { /*-N is suff., not nec.*/ 531: if(stat(eargv[i],&ibuf)==-1) 532: continue; 533: if(obuf.st_dev==ibuf.st_dev&& 534: obuf.st_ino==ibuf.st_ino) 535: unsafeout++; 536: } 537: } 538: 539: cant(f) 540: char *f; 541: { 542: 543: diag("can't open ",f); 544: term(); 545: } 546: 547: diag(s,t) 548: char *s, *t; 549: { 550: fputs("sort: ",stderr); 551: fputs(s,stderr); 552: fputs(t,stderr); 553: fputs("\n",stderr); 554: } 555: 556: term() 557: { 558: register i; 559: 560: signal(SIGINT, SIG_IGN); 561: signal(SIGHUP, SIG_IGN); 562: signal(SIGTERM, SIG_IGN); 563: if(nfiles == eargc) 564: nfiles++; 565: for(i=eargc; i<=nfiles; i++) { /*<= in case of interrupt*/ 566: unlink(setfil(i)); /*with nfiles not updated*/ 567: } 568: exit(error); 569: } 570: 571: cmp(i, j) 572: char *i, *j; 573: { 574: register char *pa, *pb; 575: char *skip(); 576: char *code, *ignore; 577: int a, b; 578: int k; 579: char *la, *lb; 580: register int sa; 581: int sb; 582: char *ipa, *ipb, *jpa, *jpb; 583: struct field *fp; 584: 585: for(k = nfields>0; k<=nfields; k++) { 586: fp = &fields[k]; 587: pa = i; 588: pb = j; 589: if(k) { 590: la = skip(pa, fp, 1); 591: pa = skip(pa, fp, 0); 592: lb = skip(pb, fp, 1); 593: pb = skip(pb, fp, 0); 594: } else { 595: la = eol(pa); 596: lb = eol(pb); 597: } 598: if(fp->nflg) { 599: while(blank(*pa)) 600: pa++; 601: while(blank(*pb)) 602: pb++; 603: sa = sb = fp->rflg; 604: if(*pa == '-') { 605: pa++; 606: sa = -sa; 607: } 608: if(*pb == '-') { 609: pb++; 610: sb = -sb; 611: } 612: for(ipa = pa; ipa<la&&isdigit(*ipa); ipa++) ; 613: for(ipb = pb; ipb<lb&&isdigit(*ipb); ipb++) ; 614: jpa = ipa; 615: jpb = ipb; 616: a = 0; 617: if(sa==sb) 618: while(ipa > pa && ipb > pb) 619: if(b = *--ipb - *--ipa) 620: a = b; 621: while(ipa > pa) 622: if(*--ipa != '0') 623: return(-sa); 624: while(ipb > pb) 625: if(*--ipb != '0') 626: return(sb); 627: if(a) return(a*sa); 628: if(*(pa=jpa) == '.') 629: pa++; 630: if(*(pb=jpb) == '.') 631: pb++; 632: if(sa==sb) 633: while(pa<la && isdigit(*pa) 634: && pb<lb && isdigit(*pb)) 635: if(a = *pb++ - *pa++) 636: return(a*sa); 637: while(pa<la && isdigit(*pa)) 638: if(*pa++ != '0') 639: return(-sa); 640: while(pb<lb && isdigit(*pb)) 641: if(*pb++ != '0') 642: return(sb); 643: continue; 644: } 645: code = fp->code; 646: ignore = fp->ignore; 647: loop: 648: while(ignore[*pa]) 649: pa++; 650: while(ignore[*pb]) 651: pb++; 652: if(pa>=la || *pa=='\n') 653: if(pb<lb && *pb!='\n') 654: return(fp->rflg); 655: else continue; 656: if(pb>=lb || *pb=='\n') 657: return(-fp->rflg); 658: if((sa = code[*pb++]-code[*pa++]) == 0) 659: goto loop; 660: return(sa*fp->rflg); 661: } 662: if(uflg) 663: return(0); 664: return(cmpa(i, j)); 665: } 666: 667: cmpa(pa, pb) 668: register char *pa, *pb; 669: { 670: while(*pa == *pb) { 671: if(*pa++ == '\n') 672: return(0); 673: pb++; 674: } 675: return( 676: *pa == '\n' ? fields[0].rflg: 677: *pb == '\n' ?-fields[0].rflg: 678: *pb > *pa ? fields[0].rflg: 679: -fields[0].rflg 680: ); 681: } 682: 683: char * 684: skip(pp, fp, j) 685: struct field *fp; 686: char *pp; 687: { 688: register i; 689: register char *p; 690: 691: p = pp; 692: if( (i=fp->m[j]) < 0) 693: return(eol(p)); 694: while(i-- > 0) { 695: if(tabchar != 0) { 696: while(*p != tabchar) 697: if(*p != '\n') 698: p++; 699: else goto ret; 700: p++; 701: } else { 702: while(blank(*p)) 703: p++; 704: while(!blank(*p)) 705: if(*p != '\n') 706: p++; 707: else goto ret; 708: } 709: } 710: if(fp->bflg[j]) 711: while(blank(*p)) 712: p++; 713: i = fp->n[j]; 714: while(i-- > 0) { 715: if(*p != '\n') 716: p++; 717: else goto ret; 718: } 719: ret: 720: return(p); 721: } 722: 723: char * 724: eol(p) 725: register char *p; 726: { 727: while(*p != '\n') p++; 728: return(p); 729: } 730: 731: copyproto() 732: { 733: register i; 734: register int *p, *q; 735: 736: p = (int *)&proto; 737: q = (int *)&fields[nfields]; 738: for(i=0; i<sizeof(proto)/sizeof(*p); i++) 739: *q++ = *p++; 740: } 741: 742: field(s,k) 743: char *s; 744: { 745: register struct field *p; 746: register d; 747: p = &fields[nfields]; 748: d = 0; 749: for(; *s!=0; s++) { 750: switch(*s) { 751: case '\0': 752: return; 753: 754: case 'b': 755: p->bflg[k]++; 756: break; 757: 758: case 'd': 759: p->ignore = dict+128; 760: break; 761: 762: case 'f': 763: p->code = fold+128; 764: break; 765: case 'i': 766: p->ignore = nonprint+128; 767: break; 768: 769: case 'c': 770: cflg = 1; 771: continue; 772: 773: case 'm': 774: mflg = 1; 775: continue; 776: 777: case 'n': 778: p->nflg++; 779: break; 780: case 't': 781: tabchar = *++s; 782: if(tabchar == 0) s--; 783: continue; 784: 785: case 'r': 786: p->rflg = -1; 787: continue; 788: case 'u': 789: uflg = 1; 790: break; 791: 792: case '.': 793: if(p->m[k] == -1) /* -m.n with m missing */ 794: p->m[k] = 0; 795: d = &fields[0].n[0]-&fields[0].m[0]; 796: 797: default: 798: p->m[k+d] = number(&s); 799: } 800: compare = cmp; 801: } 802: } 803: 804: number(ppa) 805: char **ppa; 806: { 807: int n; 808: register char *pa; 809: pa = *ppa; 810: n = 0; 811: while(isdigit(*pa)) { 812: n = n*10 + *pa - '0'; 813: *ppa = pa++; 814: } 815: return(n); 816: } 817: 818: blank(c) 819: { 820: if(c==' ' || c=='\t') 821: return(1); 822: return(0); 823: } 824: 825: #define qsexc(p,q) t= *p;*p= *q;*q=t 826: #define qstexc(p,q,r) t= *p;*p= *r;*r= *q;*q=t 827: 828: qsort(a,l) 829: char **a, **l; 830: { 831: register char **i, **j; 832: char **k; 833: char **lp, **hp; 834: int c; 835: char *t; 836: unsigned n; 837: 838: 839: 840: start: 841: if((n=l-a) <= 1) 842: return; 843: 844: 845: n /= 2; 846: hp = lp = a+n; 847: i = a; 848: j = l-1; 849: 850: 851: for(;;) { 852: if(i < lp) { 853: if((c = (*compare)(*i, *lp)) == 0) { 854: --lp; 855: qsexc(i, lp); 856: continue; 857: } 858: if(c < 0) { 859: ++i; 860: continue; 861: } 862: } 863: 864: loop: 865: if(j > hp) { 866: if((c = (*compare)(*hp, *j)) == 0) { 867: ++hp; 868: qsexc(hp, j); 869: goto loop; 870: } 871: if(c > 0) { 872: if(i == lp) { 873: ++hp; 874: qstexc(i, hp, j); 875: i = ++lp; 876: goto loop; 877: } 878: qsexc(i, j); 879: --j; 880: ++i; 881: continue; 882: } 883: --j; 884: goto loop; 885: } 886: 887: 888: if(i == lp) { 889: if(uflg) 890: for(k=lp+1; k<=hp;) **k++ = '\0'; 891: if(lp-a >= l-hp) { 892: qsort(hp+1, l); 893: l = lp; 894: } else { 895: qsort(a, lp); 896: a = hp+1; 897: } 898: goto start; 899: } 900: 901: 902: --lp; 903: qstexc(j, lp, i); 904: j = --hp; 905: } 906: }