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