1 static char *sccsid = "@(#)sort.c 4.17 (Berkeley) 03/01/91"; 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 4096 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 void 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 void 568 term() 569 { 570 register i; 571 572 signal(SIGINT, SIG_IGN); 573 signal(SIGHUP, SIG_IGN); 574 signal(SIGTERM, SIG_IGN); 575 if(nfiles == eargc) 576 nfiles++; 577 for(i=eargc; i<=nfiles; i++) { /*<= in case of interrupt*/ 578 unlink(setfil(i)); /*with nfiles not updated*/ 579 } 580 _exit(error); 581 } 582 583 cmp(i, j) 584 char *i, *j; 585 { 586 register char *pa, *pb; 587 char *skip(); 588 char *code, *ignore; 589 int a, b; 590 int k; 591 char *la, *lb; 592 register int sa; 593 int sb; 594 char *ipa, *ipb, *jpa, *jpb; 595 struct field *fp; 596 597 for(k = nfields>0; k<=nfields; k++) { 598 fp = &fields[k]; 599 pa = i; 600 pb = j; 601 if(k) { 602 la = skip(pa, fp, 1); 603 pa = skip(pa, fp, 0); 604 lb = skip(pb, fp, 1); 605 pb = skip(pb, fp, 0); 606 } else { 607 la = eol(pa); 608 lb = eol(pb); 609 } 610 if(fp->nflg) { 611 if(tabchar) { 612 if(pa<la&&*pa==tabchar) 613 pa++; 614 if(pb<lb&&*pb==tabchar) 615 pb++; 616 } 617 while(blank(*pa)) 618 pa++; 619 while(blank(*pb)) 620 pb++; 621 sa = sb = fp->rflg; 622 if(*pa == '-') { 623 pa++; 624 sa = -sa; 625 } 626 if(*pb == '-') { 627 pb++; 628 sb = -sb; 629 } 630 for(ipa = pa; ipa<la&&isdigit(*ipa); ipa++) ; 631 for(ipb = pb; ipb<lb&&isdigit(*ipb); ipb++) ; 632 jpa = ipa; 633 jpb = ipb; 634 a = 0; 635 if(sa==sb) 636 while(ipa > pa && ipb > pb) 637 if(b = *--ipb - *--ipa) 638 a = b; 639 while(ipa > pa) 640 if(*--ipa != '0') 641 return(-sa); 642 while(ipb > pb) 643 if(*--ipb != '0') 644 return(sb); 645 if(a) return(a*sa); 646 if(*(pa=jpa) == '.') 647 pa++; 648 if(*(pb=jpb) == '.') 649 pb++; 650 if(sa==sb) 651 while(pa<la && isdigit(*pa) 652 && pb<lb && isdigit(*pb)) 653 if(a = *pb++ - *pa++) 654 return(a*sa); 655 while(pa<la && isdigit(*pa)) 656 if(*pa++ != '0') 657 return(-sa); 658 while(pb<lb && isdigit(*pb)) 659 if(*pb++ != '0') 660 return(sb); 661 continue; 662 } 663 code = fp->code; 664 ignore = fp->ignore; 665 loop: 666 while(ignore[*pa]) 667 pa++; 668 while(ignore[*pb]) 669 pb++; 670 if(pa>=la || *pa=='\n') 671 if(pb<lb && *pb!='\n') 672 return(fp->rflg); 673 else continue; 674 if(pb>=lb || *pb=='\n') 675 return(-fp->rflg); 676 if((sa = code[*pb++]-code[*pa++]) == 0) 677 goto loop; 678 return(sa*fp->rflg); 679 } 680 if(uflg) 681 return(0); 682 return(cmpa(i, j)); 683 } 684 685 cmpa(pa, pb) 686 register char *pa, *pb; 687 { 688 while(*pa == *pb) { 689 if(*pa++ == '\n') 690 return(0); 691 pb++; 692 } 693 return( 694 *pa == '\n' ? fields[0].rflg: 695 *pb == '\n' ?-fields[0].rflg: 696 *pb > *pa ? fields[0].rflg: 697 -fields[0].rflg 698 ); 699 } 700 701 char * 702 skip(pp, fp, j) 703 struct field *fp; 704 char *pp; 705 { 706 register i; 707 register char *p; 708 709 p = pp; 710 if( (i=fp->m[j]) < 0) 711 return(eol(p)); 712 while(i-- > 0) { 713 if(tabchar != 0) { 714 while(*p != tabchar) 715 if(*p != '\n') 716 p++; 717 else goto ret; 718 if(i>0||j==0) 719 p++; 720 } else { 721 while(blank(*p)) 722 p++; 723 while(!blank(*p)) 724 if(*p != '\n') 725 p++; 726 else goto ret; 727 } 728 } 729 if(tabchar==0||fp->bflg[j]) 730 while(blank(*p)) 731 p++; 732 i = fp->n[j]; 733 while(i-- > 0) { 734 if(*p != '\n') 735 p++; 736 else goto ret; 737 } 738 ret: 739 return(p); 740 } 741 742 char * 743 eol(p) 744 register char *p; 745 { 746 while(*p != '\n') p++; 747 return(p); 748 } 749 750 copyproto() 751 { 752 register i; 753 register int *p, *q; 754 755 p = (int *)&proto; 756 q = (int *)&fields[nfields]; 757 for(i=0; i<sizeof(proto)/sizeof(*p); i++) 758 *q++ = *p++; 759 } 760 761 field(s,k) 762 char *s; 763 { 764 register struct field *p; 765 register d; 766 p = &fields[nfields]; 767 d = 0; 768 for(; *s!=0; s++) { 769 switch(*s) { 770 case '\0': 771 return; 772 773 case 'b': 774 p->bflg[k]++; 775 break; 776 777 case 'd': 778 p->ignore = dict+128; 779 break; 780 781 case 'f': 782 p->code = fold+128; 783 break; 784 case 'i': 785 p->ignore = nonprint+128; 786 break; 787 788 case 'c': 789 cflg = 1; 790 continue; 791 792 case 'm': 793 mflg = 1; 794 continue; 795 796 case 'n': 797 p->nflg++; 798 break; 799 case 't': 800 tabchar = *++s; 801 if(tabchar == 0) s--; 802 continue; 803 804 case 'r': 805 p->rflg = -1; 806 continue; 807 case 'u': 808 uflg = 1; 809 break; 810 811 case '.': 812 if(p->m[k] == -1) /* -m.n with m missing */ 813 p->m[k] = 0; 814 d = &fields[0].n[0]-&fields[0].m[0]; 815 816 default: 817 p->m[k+d] = number(&s); 818 } 819 compare = cmp; 820 } 821 } 822 823 number(ppa) 824 char **ppa; 825 { 826 int n; 827 register char *pa; 828 pa = *ppa; 829 n = 0; 830 while(isdigit(*pa)) { 831 n = n*10 + *pa - '0'; 832 *ppa = pa++; 833 } 834 return(n); 835 } 836 837 #define qsexc(p,q) t= *p;*p= *q;*q=t 838 #define qstexc(p,q,r) t= *p;*p= *r;*r= *q;*q=t 839 840 qsort(a,l) 841 char **a, **l; 842 { 843 register char **i, **j; 844 char **k; 845 char **lp, **hp; 846 int c; 847 char *t; 848 unsigned n; 849 850 851 852 start: 853 if((n=l-a) <= 1) 854 return; 855 856 857 n /= 2; 858 hp = lp = a+n; 859 i = a; 860 j = l-1; 861 862 863 for(;;) { 864 if(i < lp) { 865 if((c = (*compare)(*i, *lp)) == 0) { 866 --lp; 867 qsexc(i, lp); 868 continue; 869 } 870 if(c < 0) { 871 ++i; 872 continue; 873 } 874 } 875 876 loop: 877 if(j > hp) { 878 if((c = (*compare)(*hp, *j)) == 0) { 879 ++hp; 880 qsexc(hp, j); 881 goto loop; 882 } 883 if(c > 0) { 884 if(i == lp) { 885 ++hp; 886 qstexc(i, hp, j); 887 i = ++lp; 888 goto loop; 889 } 890 qsexc(i, j); 891 --j; 892 ++i; 893 continue; 894 } 895 --j; 896 goto loop; 897 } 898 899 900 if(i == lp) { 901 if(uflg) 902 for(k=lp+1; k<=hp;) **k++ = '\0'; 903 if(lp-a >= l-hp) { 904 qsort(hp+1, l); 905 l = lp; 906 } else { 907 qsort(a, lp); 908 a = hp+1; 909 } 910 goto start; 911 } 912 913 914 --lp; 915 qstexc(j, lp, i); 916 j = --hp; 917 } 918 } 919 920