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