|
|
1.1 root 1: /* Copyright 1990, AT&T Bell Labs */
2: #include <stdlib.h>
3: #include <string.h>
4: #include <ctype.h>
5: #include "fsort.h"
6:
7: int mflag = 0;
8: int cflag = 0;
9: int keyed = 0;
10:
11: extern void readin(void);
12: extern void dumptotemp(void);
13: extern void sealstack(struct rec *p);
14: extern void filelist(int, char**);
15: extern int getopt(int, char*const*, const char*);
16: extern char *optarg;
17: extern int optind;
18:
19: FILE *input;
20: char *oname = "-";
21: char *tname[] = { "/usr/tmp"/*substitutable*/, "/usr/tmp", "/tmp", 0 };
22:
23: char **files;
24: int nfiles;
25: char *nofiles[] = { "-", 0 };
26:
27: main(int argc, char **argv)
28: {
29: int c, n;
30: static char s[3] = { '-' };
31: for(;;) {
32: if(optind<argc && argv[optind][0]=='+' &&
33: isdigit(argv[optind][1])) {
34: optind += fieldarg(argv[optind],
35: argv[optind+1]);
36: continue;
37: }
38: n = optind; /* for sake of case '?' */
39: c = getopt(argc,argv,"a:bcdfgik:mno:rst:uw:y:MT:");
40: switch(c) {
41: case '?':
42: fatal("bad option", argv[n], 0);
43: default:
44: fatal("implementation error 1","",0);
45: case 'b':
46: case 'd':
47: case 'f':
48: case 'g':
49: case 'i':
50: case 'n':
51: case 'M':
52: case 'r':
53: s[1] = c;
54: fieldarg(s, 0);
55: continue;
56: case 'c':
57: cflag++;
58: continue;
59: case 'm':
60: mflag++;
61: continue;
62: case 's':
63: sflag++;
64: continue;
65: case 'u':
66: uflag++;
67: sflag++;
68: continue;
69: case 'a':
70: aflag++;
71: uflag++;
72: sflag++;
73: optionk(optarg, accum, &naccum);
74: continue;
75: case 'k':
76: optionk(optarg, fields, &nfields);
77: continue;
78: case 'o':
79: oname = optarg;
80: continue;
81: case 'T':
82: tname[0] = optarg;
83: continue;
84: case 'w':
85: nmerge = atoi(optarg);
86: if(nmerge < 2)
87: fatal("-w too small","",0);
88: continue;
89: case 'y':
90: optiony(optarg);
91: continue;
92: case 't':
93: if(strlen(optarg) != 1)
94: fatal("bad argument for -t", "", 0);
95: tab = optarg[0];
96: continue;
97: case 'z':
98: warn("nonstandard option -z ignored","",0);
99: case -1:
100: break;
101: }
102: break;
103: }
104: filelist(argc, argv);
105: if(cflag)
106: aflag = 0;
107: fieldwrapup();
108: tabinit();
109: setsigs(cleanup);
110:
111: if(cflag) {
112: if(nfiles > 1)
113: fatal("-c takes just one file", "", 0);
114: check(files[0]);
115: return 0;
116: }
117: if(mflag) {
118: merge(0);
119: return 0;
120: }
121: for(n=0; n<nfiles; n++) {
122: input = fileopen(files[n], "r");
123: readin();
124: fileclose(input, files[n]);
125: }
126: if(stack->head==0 && nextfile==0) { /* empty input */
127: if(strcmp(oname,"-") != 0)
128: fileclose(fileopen(oname, "w"), oname);
129: return 0;
130: }
131: if(stack->head && stack->head->next)
132: sort(stack, 0);
133: if(nextfile > 0) {
134: if(stack->head)
135: dumptotemp();
136: tabfree();
137: merge(1);
138: } else {
139: FILE *f;
140: f = fileopen(oname, "w");
141: printout(stack->head, f, oname);
142: fileclose(f, oname);
143: }
144: return 0;
145: }
146:
147: void
148: filelist(int argc, char **argv)
149: {
150: int i, j;
151: files = nofiles;
152: nfiles = argc - optind;
153: if(nfiles != 0)
154: files = argv + optind;
155: else
156: nfiles = 1;
157: if(strcmp(argv[optind-1], "--") == 0)
158: return;
159: for(i=j=0; i<nfiles; i++) {
160: if(strncmp(files[i], "-o", 2) == 0) {
161: if(files[i][2] != 0)
162: oname = files[i] + 2;
163: else if(i < argc-1)
164: oname = files[++i];
165: else
166: fatal("incomplete -o", "", 0);
167: } else
168: files[j++] = files[i];
169: }
170: files[j] = 0;
171: nfiles = j;
172: }
173:
174: void
175: readin(void)
176: {
177: int n;
178: struct rec *new;
179: struct rec *p = stack->tail;
180: struct rec *r = p? succ(p): buffer;
181:
182: for(;;) {
183: if(bufmax-(uchar*)r < MINREC) {
184: sealstack(p);
185: dumptotemp();
186: p = 0;
187: r = buffer;
188: }
189: r->next = (struct rec*)bufmax;
190: new = getline(r, input);
191: recenter:
192: if(new == 0) {
193: r->next = 0;
194: if(p)
195: p->next = r;
196: p = r;
197: r = succ(r);
198: } else if(new == ENDFILE) {
199: sealstack(p);
200: return;
201: } else {
202: sealstack(p);
203: dumptotemp();
204: p = 0;
205: r = buffer;
206: n = data(new)-(uchar*)new+new->dlen+new->klen;
207: if((uchar*)r+n > bufmax)
208: fatal("monster record", "", 0);
209: memmove(r, new, n);
210: free(new);
211: new = 0;
212: goto recenter;
213: }
214: }
215: }
216:
217: void
218: sealstack(struct rec *p)
219: {
220: if(p == 0)
221: return;
222: p->next = 0;
223: if(stack->head == 0)
224: stack->head = buffer;
225: stack->tail = p;
226: }
227:
228: void
229: printout(struct rec *r, FILE *f, char *name)
230: {
231: int c, n;
232: uchar *dp, *ep;
233: for( ; r; r=r->next) {
234: dp = data(r);
235: n = r->dlen;
236: ep = dp + n++;
237: c = *ep;
238: *ep = '\n';
239: if(fwrite((char*)dp, 1, n, f) != n)
240: fatal("error writing", name, 0);
241: *ep = c;
242: }
243: }
244:
245: void
246: dumptotemp()
247: {
248: char *tempfile = filename(nextfile++);
249: FILE *temp = fileopen(tempfile,"w");
250:
251: if(stack->head == 0)
252: fatal("monster record", "", 0);
253: stack->tail->next = 0; /* for good measure */
254: sort(stack, 0);
255: printout(stack->head, temp, tempfile);
256: fileclose(temp, tempfile);
257: free(tempfile);
258: stack->head = stack->tail = 0;
259: return;
260: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.