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