|
|
1.1 root 1: #include <stdio.h>
2: #include <ctype.h>
3: #include <signal.h>
4: #include <sys/types.h>
5: #include <sys/stat.h>
6:
7: #define N 16
8: #define C 20
9: #define NF 10
10:
11: /*
12: * Memory administration
13: *
14: * Using a lot of memory is great when sorting a lot of data.
15: * Using a megabyte to sort the output of `who' loses big.
16: * MAXMEM, MINMEM and DEFMEM define the absolute maximum,
17: * minimum and default memory requirements. Administrators
18: * can override any or all of these via defines at compile time.
19: * Users can override the amount allocated (within the limits
20: * of MAXMEM and MINMEM) on the command line.
21: */
22:
23: #ifndef MAXMEM
24: #define MAXMEM 1048576 /* Megabyte maximum */
25: #endif
26:
27: #ifndef MINMEM
28: #define MINMEM 16384 /* 16K minimum */
29: #endif
30:
31: #ifndef DEFMEM
32: #define DEFMEM 131072 /* Same as old sort */
33: #endif
34:
35:
36: #define ASC 0
37: #define NUM 1
38: #define MON 2
39:
40: #define blank(c) ((c)==' ' || (c)=='\t')
41: FILE *is, *os;
42: char *dirtry[] = {"/usr/tmp", "/tmp", NULL};
43: char **dirs;
44: char file1[30];
45: char *file = file1;
46: char *filep;
47: int nfiles;
48: int *lspace;
49: unsigned alloc,tryfor;
50: char bufin[BUFSIZ], bufout[BUFSIZ]; /* Use setbuf's to avoid malloc calls.
51: ** Malloc seems to develope heartburn
52: ** when brk returns storage.
53: */
54: int maxrec;
55: int cmp(), cmpa();
56: int (*compare)() = cmpa;
57: char *eol();
58: int term();
59: int mflg;
60: int mphase;
61: int nway;
62: int cflg;
63: int uflg;
64: char *outfil;
65: int unsafeout; /*kludge to assure -m -o works*/
66: char tabchar;
67: int eargc;
68: char **eargv;
69:
70: char zero[256];
71:
72: char fold[256] = {
73: 0200,0201,0202,0203,0204,0205,0206,0207,
74: 0210,0211,0212,0213,0214,0215,0216,0217,
75: 0220,0221,0222,0223,0224,0225,0226,0227,
76: 0230,0231,0232,0233,0234,0235,0236,0237,
77: 0240,0241,0242,0243,0244,0245,0246,0247,
78: 0250,0251,0252,0253,0254,0255,0256,0257,
79: 0260,0261,0262,0263,0264,0265,0266,0267,
80: 0270,0271,0272,0273,0274,0275,0276,0277,
81: 0300,0301,0302,0303,0304,0305,0306,0307,
82: 0310,0311,0312,0313,0314,0315,0316,0317,
83: 0320,0321,0322,0323,0324,0325,0326,0327,
84: 0330,0331,0332,0333,0334,0335,0336,0337,
85: 0340,0341,0342,0343,0344,0345,0346,0347,
86: 0350,0351,0352,0353,0354,0355,0356,0357,
87: 0360,0361,0362,0363,0364,0365,0366,0367,
88: 0370,0371,0372,0373,0374,0375,0376,0377,
89: 0000,0001,0002,0003,0004,0005,0006,0007,
90: 0010,0011,0012,0013,0014,0015,0016,0017,
91: 0020,0021,0022,0023,0024,0025,0026,0027,
92: 0030,0031,0032,0033,0034,0035,0036,0037,
93: 0040,0041,0042,0043,0044,0045,0046,0047,
94: 0050,0051,0052,0053,0054,0055,0056,0057,
95: 0060,0061,0062,0063,0064,0065,0066,0067,
96: 0070,0071,0072,0073,0074,0075,0076,0077,
97: 0100,0101,0102,0103,0104,0105,0106,0107,
98: 0110,0111,0112,0113,0114,0115,0116,0117,
99: 0120,0121,0122,0123,0124,0125,0126,0127,
100: 0130,0131,0132,0133,0134,0134,0136,0137,
101: 0140,0101,0102,0103,0104,0105,0106,0107,
102: 0110,0111,0112,0113,0114,0115,0116,0117,
103: 0120,0121,0122,0123,0124,0125,0126,0127,
104: 0130,0131,0132,0173,0174,0175,0176,0177
105: };
106: char nofold[256] = {
107: 0200,0201,0202,0203,0204,0205,0206,0207,
108: 0210,0211,0212,0213,0214,0215,0216,0217,
109: 0220,0221,0222,0223,0224,0225,0226,0227,
110: 0230,0231,0232,0233,0234,0235,0236,0237,
111: 0240,0241,0242,0243,0244,0245,0246,0247,
112: 0250,0251,0252,0253,0254,0255,0256,0257,
113: 0260,0261,0262,0263,0264,0265,0266,0267,
114: 0270,0271,0272,0273,0274,0275,0276,0277,
115: 0300,0301,0302,0303,0304,0305,0306,0307,
116: 0310,0311,0312,0313,0314,0315,0316,0317,
117: 0320,0321,0322,0323,0324,0325,0326,0327,
118: 0330,0331,0332,0333,0334,0335,0336,0337,
119: 0340,0341,0342,0343,0344,0345,0346,0347,
120: 0350,0351,0352,0353,0354,0355,0356,0357,
121: 0360,0361,0362,0363,0364,0365,0366,0367,
122: 0370,0371,0372,0373,0374,0375,0376,0377,
123: 0000,0001,0002,0003,0004,0005,0006,0007,
124: 0010,0011,0012,0013,0014,0015,0016,0017,
125: 0020,0021,0022,0023,0024,0025,0026,0027,
126: 0030,0031,0032,0033,0034,0035,0036,0037,
127: 0040,0041,0042,0043,0044,0045,0046,0047,
128: 0050,0051,0052,0053,0054,0055,0056,0057,
129: 0060,0061,0062,0063,0064,0065,0066,0067,
130: 0070,0071,0072,0073,0074,0075,0076,0077,
131: 0100,0101,0102,0103,0104,0105,0106,0107,
132: 0110,0111,0112,0113,0114,0115,0116,0117,
133: 0120,0121,0122,0123,0124,0125,0126,0127,
134: 0130,0131,0132,0133,0134,0135,0136,0137,
135: 0140,0141,0142,0143,0144,0145,0146,0147,
136: 0150,0151,0152,0153,0154,0155,0156,0157,
137: 0160,0161,0162,0163,0164,0165,0166,0167,
138: 0170,0171,0172,0173,0174,0175,0176,0177
139: };
140:
141: char nonprint[256] = {
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,1,1,1,1,1,1,1,
147: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
148: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
149: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
150: 1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,
151: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
152: 0,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,0,0,0,0,0,
154: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
155: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
156: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
157: 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
158: };
159:
160: char dict[256] = {
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,1,1,1,1,1,1,1,
164: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
165: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
166: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
167: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
168: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
169: 1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,
170: 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
171: 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
172: 0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,
173: 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
174: 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,
175: 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
176: 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1
177: };
178:
179: struct field {
180: char *code;
181: char *ignore;
182: int fcmp;
183: int rflg;
184: int bflg[2];
185: int m[2];
186: int n[2];
187: } fields[NF];
188: struct field proto = {
189: nofold+128,
190: zero+128,
191: ASC,
192: 1,
193: 0,0,
194: 0,-1,
195: 0,0
196: };
197: int nfields;
198: int error = 1;
199: char *setfil();
200:
201: main(argc, argv)
202: char **argv;
203: {
204: register a;
205: char *arg;
206: struct field *p, *q;
207: int i;
208: long incr;
209: char *sbrk();
210: char *sp;
211:
212: copyproto();
213: eargv = argv;
214: tryfor = DEFMEM;
215: while (--argc > 0) {
216: if(**++argv == '-') for(arg = *argv;;) {
217: switch(*++arg) {
218: case '\0':
219: if(arg[-1] == '-')
220: eargv[eargc++] = "-";
221: break;
222:
223: case 'o':
224: if(--argc > 0)
225: outfil = *++argv;
226: continue;
227:
228: case 'T':
229: if (--argc > 0)
230: dirtry[0] = *++argv;
231: continue;
232:
233: default:
234: field(++*argv,nfields>0);
235: break;
236: }
237: break;
238: } else if (**argv == '+') {
239: if(++nfields>=NF) {
240: diag("too many keys","");
241: exit(1);
242: }
243: copyproto();
244: field(++*argv,0);
245: } else
246: eargv[eargc++] = *argv;
247: }
248: q = &fields[0];
249: for(a=1; a<=nfields; a++) {
250: p = &fields[a];
251: if(p->code != proto.code) continue;
252: if(p->ignore != proto.ignore) continue;
253: if(p->fcmp != proto.fcmp) continue;
254: if(p->rflg != proto.rflg) continue;
255: if(p->bflg[0] != proto.bflg[0]) continue;
256: if(p->bflg[1] != proto.bflg[1]) continue;
257: p->code = q->code;
258: p->ignore = q->ignore;
259: p->fcmp = q->fcmp;
260: p->rflg = q->rflg;
261: p->bflg[0] = p->bflg[1] = q->bflg[0];
262: }
263: if(eargc == 0)
264: eargv[eargc++] = "-";
265: if(cflg && eargc>1) {
266: diag("can check only 1 file","");
267: exit(1);
268: }
269:
270: safeoutfil();
271:
272: sp = sbrk(0);
273: lspace = (int *) sp;
274: if (!mflg && !cflg) {
275: if (tryfor < MINMEM) tryfor = MINMEM;
276: else if (tryfor > MAXMEM) tryfor = MAXMEM;
277: for (incr=tryfor; (sp + incr) <= sp; incr >>= 1);
278: do {
279: if ((long)alloc+incr <= tryfor && brk(sp+incr) == 0) {
280: sp += incr;
281: alloc += incr;
282: }
283: } while ( ( incr >>= 1 ) >= 512L );
284: alloc -= 512; /* for recursion? */
285: if ( brk((char *) lspace + alloc) != 0) {
286: diag("allocation error before sort", "");
287: exit(1);
288: }
289: }
290:
291: a = -1;
292: for(dirs=dirtry; *dirs; dirs++) {
293: (void) sprintf(filep=file1, "%s/stm%.5uaa", *dirs, getpid());
294: while (*filep)
295: filep++;
296: filep -= 2;
297: if ( (a=creat(file, 0600)) >=0)
298: break;
299: }
300: if(a < 0) {
301: diag("can't locate temp","");
302: exit(1);
303: }
304: (void) close(a);
305: (void) unlink(file);
306: if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
307: (void) signal(SIGHUP, term);
308: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
309: (void) signal(SIGINT, term);
310: (void) signal(SIGPIPE,term);
311: if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
312: (void) signal(SIGTERM,term);
313: nfiles = eargc;
314: if(!mflg && !cflg) {
315: sort();
316: if (ferror(stdin))
317: rderror("stdin");
318: (void) fclose(stdin);
319: }
320:
321: mphase = 1;
322: if (maxrec == 0) maxrec = 512;
323: alloc = (N + 1) * maxrec + N * BUFSIZ;
324: for (nway = N; nway >= 2; --nway) {
325: if (brk((char *)lspace + alloc) == 0) break;
326: alloc -= maxrec + BUFSIZ;
327: }
328: if (nway < 2) {
329: diag("allocation error before merge", "");
330: term();
331: }
332:
333: if (cflg) checksort();
334:
335: a = mflg || cflg ? 0 : eargc;
336: if ((i = nfiles - a) > nway) { /* Do leftovers early */
337: if ((i %= (nway - 1)) == 0)
338: i = nway - 1;
339: if (i != 1) {
340: newfile();
341: (void) setbuf(os, bufout);
342: merge(a,a+i);
343: a += i;
344: }
345: }
346: for(; a+nway<nfiles || unsafeout&&a<eargc; a=i) {
347: i = a+nway;
348: if(i>=nfiles)
349: i = nfiles;
350: newfile();
351: (void) setbuf(os, bufout);
352: merge(a, i);
353: }
354: if(a != nfiles) {
355: oldfile();
356: (void) setbuf(os, bufout);
357: merge(a, nfiles);
358: }
359: error = 0;
360: term();
361: }
362:
363: sort()
364: {
365: register char *cp;
366: register c;
367: register char **lp;
368: char *keep, *ekeep, *ep, **tp;
369: int done, i;
370: char *f;
371:
372: /*
373: ** Records are read in from the front of the buffer area.
374: ** Pointers to the records are allocated from the back of the buffer.
375: ** If a partially read record exhausts the buffer, it is saved and
376: ** then copied to the start of the buffer for processing with the
377: ** next coreload.
378: */
379: done = 0;
380: keep = 0;
381: i = 0;
382: c = EOF;
383: ep = (char *) lspace + alloc;
384: do {
385: lp = (char **)ep - 1;
386: cp = (char *) lspace;
387: if (keep != 0) { /* part of record from previous coreload */
388: *lp-- = cp;
389: for(; keep < ekeep; *cp++ = *keep++);
390: }
391: while (cp < (char *) lp) {
392: if (keep == 0) *lp-- = cp;
393: while (cp + 1 < (char *) lp && c != '\n') {
394: if(c != EOF) {
395: *cp++ = c;
396: c = getc(is);
397: continue;
398: } else if(is) {
399: if(ferror(is))
400: rderror(f);
401: (void) fclose(is);
402: }
403: if(i < eargc) {
404: if((f = setfil(i++)) == 0)
405: is = stdin;
406: else if((is = fopen(f, "r")) == NULL)
407: cant(f);
408: (void) setbuf(is, bufin);
409: c = getc(is);
410: } else
411: break;
412: }
413: if (c == '\n') {
414: *cp++ = '\n';
415: keep = 0;
416: }
417: else if (c != EOF) { /* save partial record */
418: lp++;
419: if (keep != 0) {
420: diag("whopper record won't fit", "");
421: term();
422: }
423: keep = *lp;
424: ekeep = cp;
425: break;
426: }
427: if(c == EOF) {
428: if(ferror(is))
429: rderror(f);
430: done++;
431: lp++;
432: break;
433: }
434: c = getc(is);
435: }
436: lp++;
437: qsort(lp, (char **) ep);
438: if(done == 0 || nfiles != eargc)
439: newfile();
440: else
441: oldfile();
442: (void) setbuf(os, bufout);
443: tp = (char **) ep;
444: while(tp > lp) {
445: cp = *--tp;
446: if(*cp) {
447: do
448: putc(*cp, os);
449: while(*cp++ != '\n');
450: }
451: }
452: if (ferror(os))
453: wterror("sorting");
454: (void) fclose(os);
455: } while(done == 0);
456: }
457:
458: char *heap[N];
459: int lowkid = 0; /*
460: ** Index of lesser subtree of heap, if known.
461: ** Useful if records are mostly ordered, with long runs of
462: ** records being written from the same input file before
463: ** the heap is really restructured.
464: */
465:
466:
467: # define EXC(a, b) t = a; a = b; b = t
468:
469: merge(a, b)
470: {
471: FILE *tfile[N];
472: char *buffer = (char *) lspace;
473: register int nf; /* number of merge files */
474: register int i;
475: int j;
476: register char *cp;
477: char *t, *f;
478: char *save,*iobuf;
479:
480: save = (char *) lspace + (nway * maxrec);
481: iobuf = save + maxrec;
482: for (nf=0, i=a; i < b; i++) {
483: f = setfil(i);
484: if (f == 0)
485: tfile[nf] = stdin;
486: else if ((tfile[nf] = fopen(f, "r")) == NULL)
487: cant(f);
488: heap[nf] = buffer + (nf * maxrec);
489: (void) setbuf(tfile[nf],iobuf);
490: iobuf += BUFSIZ;
491: if (rline(tfile[nf], heap[nf])==0)
492: nf++;
493: else {
494: if(ferror(tfile[nf]))
495: rderror(f);
496: (void) fclose(tfile[nf]);
497: }
498: }
499:
500: qsort(heap, (heap + nf));
501:
502: for (i=0, j=nf-1; i < j ; i++, --j ) { /* qsort is backwards */
503: EXC(heap[i], heap[j]);
504: }
505: lowkid = 1;
506:
507: while (nf > 0) {
508: cp = heap[0];
509: do
510: putc(*cp, os);
511: while (*cp++ != '\n');
512:
513: if (uflg) {
514: t = save;
515: cp = heap[0];
516: do
517: *t++ = *cp;
518: while (*cp++ != '\n');
519: }
520:
521: /* Get another record and reheap. Bypass repeats if uflg. */
522:
523: do {
524: i = (heap[0] - buffer) / maxrec;
525: if (rline(tfile[i], heap[0])) {
526: if (ferror(tfile[i]))
527: rderror(setfil(i+a));
528: (void) fclose(tfile[i]);
529: if (--nf <= 0) break;
530: heap[0] = heap[nf];
531: if (nf < 3) lowkid = 0;
532: }
533: reheap(nf);
534: } while (uflg && (*compare)(heap[0], save) == 0 );
535: }
536: for (i=a; i < b; i++) {
537: if (i >= eargc)
538: (void) unlink(setfil(i));
539: }
540: if (ferror(os))
541: wterror("merging");
542: (void) fclose(os);
543: }
544:
545:
546: reheap(ind)
547: register int ind;
548: {
549: register int i, j;
550: char *t;
551:
552: --ind; /* last legitimate index */
553: for (i=0; (j = 2*i + 1) <= ind; i = j) {
554: if (lowkid != 0)
555: j = lowkid;
556: else if ( (j < ind) && (*compare)(heap[j],heap[j+1]) <= 0 )
557: j++;
558: if ( (*compare)(heap[i], heap[j]) >= 0 ) {
559: if (i == 0) lowkid = j;
560: return;
561: }
562: EXC(heap[i], heap[j]);
563: lowkid = 0;
564: }
565: return;
566: }
567: rline(iop, s)
568: FILE *iop;
569: register char *s;
570: {
571: register char *ce;
572: register int c;
573:
574: ce = s + maxrec;
575: do {
576: c = getc(iop);
577: if (c == EOF)
578: return(1);
579: if (s >= ce)
580: --s;
581: *s++ = c;
582: } while (c != '\n');
583: return(0);
584: }
585:
586:
587: checksort()
588: {
589: char *f;
590: char *s[2];
591: register int i, j, r;
592:
593: f = setfil(0);
594: if (f == 0)
595: is = stdin;
596: else if ((is = fopen(f, "r")) == NULL)
597: cant(f);
598: (void) setbuf(is, bufin);
599:
600: i = 0; j = 1;
601: s[0] = (char *) lspace;
602: s[1] = s[0] + maxrec;
603: if ( rline(is, s[0]) ) {
604: if (ferror(is)) {
605: rderror(f);
606: }
607: (void) fclose(is);
608: exit(0);
609: }
610: while ( !rline(is, s[j]) ) {
611: r = (*compare)(s[i], s[j]);
612: if (r < 0)
613: disorder("disorder: ", s[j]);
614: if (r == 0 && uflg)
615: disorder("non-unique: ", s[j]);
616: r = i; i = j; j = r;
617: }
618: if (ferror(is))
619: rderror(f);
620: (void) fclose(is);
621: exit(0);
622: }
623:
624:
625: disorder(s,t)
626: char *s, *t;
627: {
628: register char *u;
629: for(u=t; *u!='\n';u++) ;
630: *u = 0;
631: diag(s,t);
632: term();
633: }
634:
635: newfile()
636: {
637: register char *f;
638:
639: f = setfil(nfiles);
640: if((os=fopen(f, "w")) == NULL) {
641: diag("can't create ",f);
642: term();
643: }
644: nfiles++;
645: }
646:
647: char *
648: setfil(i)
649: {
650:
651: if(i < eargc)
652: if(eargv[i][0] == '-' && eargv[i][1] == '\0')
653: return(0);
654: else
655: return(eargv[i]);
656: i -= eargc;
657: filep[0] = i/26 + 'a';
658: filep[1] = i%26 + 'a';
659: return(file);
660: }
661:
662: oldfile()
663: {
664:
665: if(outfil) {
666: if((os=fopen(outfil, "w")) == NULL) {
667: diag("can't create ",outfil);
668: term();
669: }
670: } else
671: os = stdout;
672: }
673:
674: safeoutfil()
675: {
676: register int i;
677: struct stat ostat,istat;
678:
679: if(!mflg||outfil==0)
680: return;
681: if(stat(outfil,&ostat)==-1)
682: return;
683: if ((i = eargc - N) < 0) i = 0; /*-N is suff., not nec. */
684: for (; i < eargc; i++) {
685: if(stat(eargv[i],&istat)==-1)
686: continue;
687: if(ostat.st_dev==istat.st_dev&&
688: ostat.st_ino==istat.st_ino)
689: unsafeout++;
690: }
691: }
692:
693: cant(f)
694: char *f;
695: {
696:
697: diag("can't open ",f);
698: term();
699: }
700:
701: diag(s,t)
702: char *s, *t;
703: {
704: (void) fputs("sort: ",stderr);
705: (void) fputs(s,stderr);
706: (void) fputs(t,stderr);
707: (void) fputs("\n",stderr);
708: }
709:
710: term()
711: {
712: register i;
713:
714: (void) signal(SIGINT, SIG_IGN);
715: (void) signal(SIGHUP, SIG_IGN);
716: (void) signal(SIGTERM, SIG_IGN);
717: if(nfiles == eargc)
718: nfiles++;
719: for(i=eargc; i<=nfiles; i++) { /*<= in case of interrupt*/
720: (void) unlink(setfil(i)); /*with nfiles not updated*/
721: }
722: exit(error);
723: }
724:
725: cmp(i, j)
726: char *i, *j;
727: {
728: register char *pa, *pb;
729: char *skip();
730: char *code, *ignore;
731: int a, b;
732: int k;
733: char *la, *lb;
734: register int sa;
735: int sb;
736: char *ipa, *ipb, *jpa, *jpb;
737: struct field *fp;
738:
739: for(k = nfields>0; k<=nfields; k++) {
740: fp = &fields[k];
741: pa = i;
742: pb = j;
743: if(k) {
744: la = skip(pa, fp, 1);
745: pa = skip(pa, fp, 0);
746: lb = skip(pb, fp, 1);
747: pb = skip(pb, fp, 0);
748: } else {
749: la = eol(pa);
750: lb = eol(pb);
751: }
752: if(fp->fcmp==NUM) {
753: sa = sb = fp->rflg;
754: while(blank(*pa))
755: pa++;
756: while(blank(*pb))
757: pb++;
758: if(*pa == '-') {
759: pa++;
760: sa = -sa;
761: }
762: if(*pb == '-') {
763: pb++;
764: sb = -sb;
765: }
766: for(ipa = pa; ipa<la&&isdigit(*ipa); ipa++) ;
767: for(ipb = pb; ipb<lb&&isdigit(*ipb); ipb++) ;
768: jpa = ipa;
769: jpb = ipb;
770: a = 0;
771: if(sa==sb)
772: while(ipa > pa && ipb > pb)
773: if(b = *--ipb - *--ipa)
774: a = b;
775: while(ipa > pa)
776: if(*--ipa != '0')
777: return(-sa);
778: while(ipb > pb)
779: if(*--ipb != '0')
780: return(sb);
781: if(a) return(a*sa);
782: if(*(pa=jpa) == '.')
783: pa++;
784: if(*(pb=jpb) == '.')
785: pb++;
786: if(sa==sb)
787: while(pa<la && isdigit(*pa)
788: && pb<lb && isdigit(*pb))
789: if(a = *pb++ - *pa++)
790: return(a*sa);
791: while(pa<la && isdigit(*pa))
792: if(*pa++ != '0')
793: return(-sa);
794: while(pb<lb && isdigit(*pb))
795: if(*pb++ != '0')
796: return(sb);
797: continue;
798: } else if(fp->fcmp==MON) {
799: sa = fp->rflg*(month(pb)-month(pa));
800: if(sa)
801: return(sa);
802: else
803: continue;
804: }
805: code = fp->code;
806: ignore = fp->ignore;
807: loop:
808: while(ignore[*pa])
809: pa++;
810: while(ignore[*pb])
811: pb++;
812: if(pa>=la || *pa=='\n')
813: if(pb<lb && *pb!='\n')
814: return(fp->rflg);
815: else continue;
816: if(pb>=lb || *pb=='\n')
817: return(-fp->rflg);
818: if((sa = code[*pb++]-code[*pa++]) == 0)
819: goto loop;
820: return(sa*fp->rflg);
821: }
822: if(uflg)
823: return(0);
824: return(cmpa(i, j));
825: }
826:
827: cmpa(pa, pb)
828: register char *pa, *pb;
829: {
830: while(*pa == *pb++)
831: if(*pa++ == '\n')
832: return(0);
833: return(
834: *pa == '\n' ? fields[0].rflg:
835: *--pb == '\n' ?-fields[0].rflg:
836: *pb > *pa ? fields[0].rflg:
837: -fields[0].rflg
838: );
839: }
840:
841: char *
842: skip(pp, fp, j)
843: struct field *fp;
844: char *pp;
845: {
846: register i;
847: register char *p;
848:
849: p = pp;
850: if( (i=fp->m[j]) < 0)
851: return(eol(p));
852: while(i-- > 0) {
853: if(tabchar != 0) {
854: while(*p != tabchar)
855: if(*p != '\n')
856: p++;
857: else goto ret;
858: p++;
859: } else {
860: while(blank(*p))
861: p++;
862: while(!blank(*p))
863: if(*p != '\n')
864: p++;
865: else goto ret;
866: }
867: }
868: if(fp->bflg[j])
869: while(blank(*p))
870: p++;
871: i = fp->n[j];
872: if(i==0 && j!=0 && fp->m[j]>0 && p[-1]==tabchar)
873: p--;
874: while((i-- > 0) && (*p != '\n'))
875: p++;
876: ret:
877: return(p);
878: }
879:
880: char *
881: eol(p)
882: register char *p;
883: {
884: while(*p != '\n') p++;
885: return(p);
886: }
887:
888: copyproto()
889: {
890: register i;
891: register int *p, *q;
892:
893: p = (int *)&proto;
894: q = (int *)&fields[nfields];
895: for(i=0; i<sizeof(proto)/sizeof(*p); i++)
896: *q++ = *p++;
897: }
898:
899: field(s,k)
900: char *s;
901: {
902: register struct field *p;
903: register d;
904: p = &fields[nfields];
905: d = 0;
906: for(; *s!=0; s++) {
907: switch(*s) {
908: case '\0':
909: return;
910:
911: case 'b':
912: p->bflg[k]++;
913: break;
914:
915: case 'd':
916: p->ignore = dict+128;
917: break;
918:
919: case 'f':
920: p->code = fold+128;
921: break;
922: case 'i':
923: p->ignore = nonprint+128;
924: break;
925:
926: case 'c':
927: cflg = 1;
928: continue;
929:
930: case 'm':
931: mflg = 1;
932: continue;
933:
934: case 'M':
935: p->fcmp = MON;
936: break;
937:
938: case 'n':
939: p->fcmp = NUM;
940: break;
941: case 't':
942: tabchar = *++s;
943: if(tabchar == 0) s--;
944: continue;
945:
946: case 'r':
947: p->rflg = -1;
948: continue;
949: case 'u':
950: uflg = 1;
951: continue;
952:
953: case 'y':
954: if ( *++s ) tryfor = number(&s);
955: else {
956: --s;
957: tryfor = MAXMEM;
958: }
959: continue;
960:
961: case 'z':
962: if ( *++s )
963: maxrec = number(&s);
964: else --s;
965: continue;
966:
967: case '.':
968: if(p->m[k] == -1) /* -m.n with m missing */
969: p->m[k] = 0;
970: d = &fields[0].n[0]-&fields[0].m[0];
971: if (*++s == '\0') {
972: --s;
973: p->m[k+d] = 0;
974: continue;
975: }
976:
977: default:
978: p->m[k+d] = number(&s);
979: }
980: compare = cmp;
981: }
982: }
983:
984: number(ppa)
985: char **ppa;
986: {
987: int n;
988: register char *pa;
989: pa = *ppa;
990: n = 0;
991: while(isdigit(*pa)) {
992: n = n*10 + *pa - '0';
993: *ppa = pa++;
994: }
995: return(n);
996: }
997:
998: #define qsexc(p,q) t= *p;*p= *q;*q=t
999: #define qstexc(p,q,r) t= *p;*p= *r;*r= *q;*q=t
1000:
1001: qsort(a,l)
1002: char **a, **l;
1003: {
1004: register char **i, **j;
1005: char **k;
1006: char **lp, **hp;
1007: int c;
1008: char *t;
1009: unsigned n;
1010:
1011:
1012: start:
1013: if((n=l-a) <= 1)
1014: return;
1015:
1016: n /= 2;
1017: hp = lp = a+n;
1018: i = a;
1019: j = l-1;
1020:
1021:
1022: for(;;) {
1023: if(i < lp) {
1024: if((c = (*compare)(*i, *lp)) == 0) {
1025: --lp;
1026: qsexc(i, lp);
1027: continue;
1028: }
1029: if(c < 0) {
1030: ++i;
1031: continue;
1032: }
1033: }
1034:
1035: loop:
1036: if(j > hp) {
1037: if((c = (*compare)(*hp, *j)) == 0) {
1038: ++hp;
1039: qsexc(hp, j);
1040: goto loop;
1041: }
1042: if(c > 0) {
1043: if(i == lp) {
1044: ++hp;
1045: qstexc(i, hp, j);
1046: i = ++lp;
1047: goto loop;
1048: }
1049: qsexc(i, j);
1050: --j;
1051: ++i;
1052: continue;
1053: }
1054: --j;
1055: goto loop;
1056: }
1057:
1058:
1059: if(i == lp) {
1060: if(uflg&&!mphase)
1061: for(k=lp+1; k<=hp;) **k++ = '\0';
1062: if(lp-a >= l-hp) {
1063: qsort(hp+1, l);
1064: l = lp;
1065: } else {
1066: qsort(a, lp);
1067: a = hp+1;
1068: }
1069: goto start;
1070: }
1071:
1072:
1073: --lp;
1074: qstexc(j, lp, i);
1075: j = --hp;
1076: }
1077: }
1078:
1079: char * months[] = {
1080: "jan",
1081: "feb",
1082: "mar",
1083: "apr",
1084: "may",
1085: "jun",
1086: "jul",
1087: "aug",
1088: "sep",
1089: "oct",
1090: "nov",
1091: "dec"
1092: };
1093: month(s)
1094: char *s;
1095: {
1096: register char *t, *u;
1097: register i;
1098: char *f = fold + 128;
1099:
1100: while(blank(*s))
1101: s++;
1102: for(i=0; i<sizeof(months)/sizeof(*months); i++) {
1103: for(t=s,u=months[i]; f[*t++]==f[*u++]; )
1104: if(*u==0)
1105: return(i);
1106: }
1107: return(-1);
1108: }
1109:
1110:
1111: rderror(s)
1112: char *s;
1113: {
1114: diag("read error on ", s == 0 ? "stdin" : s);
1115: term();
1116: }
1117:
1118: wterror(s)
1119: char *s;
1120: {
1121: diag("write error while ", s);
1122: term();
1123: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.