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