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