|
|
1.1 root 1: #include <stdio.h>
2: #include "efix.h"
3:
4: /* add casts to convert efl source into acceptable C */
5:
6: #define INCLMAX 4 /* max include depth */
7: #define INCLNAMX 128 /* max include pathname length */
8:
9: FILE *fopen(), *infile;
10:
11: char emsg[64], linebuf[4096], type[257];
12: char *adjnam, *eofmsg, *infname, *lastc = linebuf,
13: *nextc = linebuf, *progname, *tstart, **xargv;
14: char *linelist;
15: long lineno, linestart;
16: int adjval, eexit, inlevel, lineinc = 1, rc, untok, verbose;
17: struct Include {
18: FILE *infile;
19: char *infname;
20: long lineno, linestart;
21: } inclstak[INCLMAX+1];
22: char inclname[INCLMAX][INCLNAMX];
23: char **te_addr, *te_value;
24:
25: char *fgets(), *memset(), *strcpy();
26:
27: next(eof) /* return next input character */
28: /* eof == 0 ==> return Eof on end of file */
29: /* eof == 1, 2 ==> quit on end of file */
30: /* 1 ==> msg controlled by eofmsg; */
31: /* 2 ==> complaint of unexpected eof (mid-token) */
32: {
33:
34: if (nextc >= lastc) {
35: if (!fgets(linebuf, sizeof(linebuf), infile)
36: && !nextfile(1)) switch(eof) {
37: case 0:
38: return Eof;
39: case 1:
40: if (eofmsg) fprintf(stderr,
41: eofmsg, progname, infname);
42: exit(rc);
43: case 2:
44: squawk("unexpected end of file");
45: exit(rc);
46: }
47: linestart += nextc - linebuf;
48: nextc = linebuf;
49: lastc = linebuf + strlen(linebuf);
50: lineno += lineinc;
51: lineinc = lastc[-1] == '\n';
52: }
53: return *nextc++;
54: }
55:
56: #define unget(c) *--nextc = c
57:
58: where() /* report position of current token on stderr */
59: {
60: int toff = --tstart - linebuf;
61: fprintf(stderr, "%s, line %ld [char %ld] of %s:\n\t",
62: progname, lineno, linestart + toff, infname);
63: return toff;
64: }
65:
66: scream(msg)
67: char *msg;
68: {
69: eexit = 1;
70: squawk(msg);
71: }
72:
73: squawk(msg) /* print error message */
74: char *msg;
75: {
76: int toff = where();
77: fprintf(stderr, "%s\ncontext: %.*s >>> %.*s <<< %s", msg,
78: toff, linebuf, nextc-tstart, tstart, nextc);
79: rc |= 1;
80: if (eexit) exit(rc);
81: }
82:
83: options(n)
84: {
85: static char *opts[] = {
86: "-L {put out # line comments}",
87: "-e {exit at first error}",
88: "-v {verbose}",
89: 0};
90: char **o;
91:
92: fprintf(stderr, "usage: %s [-Lev] [file [file...]]\noptions:\n",
93: progname);
94: for(o = opts; *o; o++) fprintf(stderr, "\t%s\n", *o);
95: exit(n);
96: }
97:
98: nextfile(loop) /* start next file (implicitly cat input files) */
99: {
100: char *s;
101: struct Include *I;
102:
103: while(inlevel > 0) {
104: fclose(infile);
105: I = inclstak + --inlevel;
106: if (!inlevel)
107: *te_addr = te_value;
108: infile = I->infile;
109: infname = I->infname;
110: lineno = I->lineno;
111: linestart = I->linestart;
112: lineinc = 0;
113: if (fgets(linebuf, sizeof(linebuf), infile)) {
114: nextc = linebuf;
115: return 1;
116: }
117: }
118: for(;;) {
119: if (!(s = *++xargv)) {
120: if (infname) return 0;
121: s = "-";
122: --xargv;
123: }
124: if (*s == '-') switch(s[1]) {
125: case 0:
126: infile = stdin;
127: s = "/dev/stdin";
128: break;
129: case 'L':
130: linelist = "\n#\tline %d, file \"%s\"\n";
131: continue;
132: case 'e':
133: eexit = 1;
134: continue;
135: case 'v':
136: verbose = 1;
137: continue;
138: case '?':
139: options(0);
140: default:
141: fprintf(stderr, "\ninvalid option -%c\n", s[1]);
142: options(1);
143: }
144: else if (!(infile = fopen(s,"r"))) {
145: fprintf(stderr, "%s: can't open %s\n", progname, s);
146: exit(rc+2);
147: }
148: if (!loop || fgets(linebuf, sizeof(linebuf), infile)) break;
149: }
150: infname = s;
151: if (linelist) printf(linelist, 1, s);
152: linestart = 0;
153: nextc = linebuf;
154: return 1;
155: }
156:
157: void
158: inclopen(s)
159: char *s;
160: {
161: FILE *f;
162: struct Include *I;
163: char buf[INCLNAMX], *be = buf + sizeof(buf), *s1 = s;
164:
165: if (!(f = fopen(s,"r")) && *s != '/') {
166: s1 = buf;
167: adjoin(adjoin(buf,be,"/usr/include/"),be,s);
168: f = fopen(s1,"r");
169: }
170: if (!f) {
171: fprintf(stderr, "%s: can't open \"%s\"\n",
172: progname, s1);
173: scream("include failure");
174: }
175: I = inclstak + inlevel;
176: I->infile = infile;
177: I->infname = infname;
178: I->lineno = lineno + lineinc;
179: I->linestart = linestart + nextc - linebuf;
180: lineno = linestart = 0;
181: lineinc = 1;
182: infname = strcpy(inclname[inlevel++], s1);
183: infile = f;
184: }
185:
186: void
187: dumpwhite() /* kludge: dump #include white stuff */
188: {
189: struct Tok *T1;
190: if (inlevel == 1) {
191: for(T1 = T->next; T1 != T; T1 = T1->next)
192: if (!T1->inlevel) {
193: T1->inlevel = 1;
194: printf("%s%s", T1->white, T1->tok);
195: }
196: printf("%s", T1->white);
197: }
198: }
199:
200: token(eof) /* return code for next token; T->tok := its print value */
201: {
202: register c, ct;
203: register char *Type = type;
204: register char *t;
205: int c1, nlsquawk;
206: char *t1, *te;
207: struct Tok *T1;
208:
209: if (untok) {
210: c = untok;
211: untok = 0;
212: return c;
213: }
214: T = T1 = T->next;
215: if (!T1->inlevel)
216: printf("%s%s", T1->white, T1->tok);
217: t = T1->white;
218: te = t + sizeof(T1->white) - 1;
219:
220: /* kludge: allow restoration of te by nextfile() */
221: te_addr = &te;
222: te_value = te;
223:
224: if (inlevel)
225: te = t;
226: top:
227: for(;;){
228: for(;;) {
229: c = next(eof);
230: if (ct = Type[c]) break;
231: if (t < te) *t++ = c;
232: }
233: if (c == '/') { /* start of comment? */
234: if (next(2) != '*') { --nextc; break; }
235: if (t < te) *t++ = '/';
236: if (t < te) *t++ = '*';
237: for(;;) {
238: do {
239: c = next(2);
240: if (t < te) *t++ = c;
241: } while(c != '*');
242: do {
243: c = next(2);
244: if (t < te) *t++ = c;
245: if (c == '/') goto top;
246: } while(c == '*');
247: }
248: }
249: else if (c == '#') { /* look for include "..." */
250: if (t < te) *t++ = c;
251: do {
252: c = next(eof);
253: if (t < te) *t++ = c;
254: } while(!Type[c]);
255: if (c != 'i') goto eat_rest;
256: t1 = t;
257: do {
258: c = next(eof);
259: if (t < te) *t++ = c;
260: } while(Type[c] == SYMBOL);
261: if (strncmp(t1,"nclude",6))
262: goto eat_rest;
263:
264: if (inlevel >= INCLMAX)
265: scream("includes nested too deeply");
266: while(!Type[c]) {
267: c = next(eof);
268: if (t < te) *t++ = c;
269: }
270: switch(c) {
271: case '"':
272: c1 = c;
273: break;
274: case '<':
275: c1 = '>';
276: break;
277: default:
278: goto eat_rest;
279: }
280: t1 = t;
281: do {
282: c = next(2);
283: if (t < te) *t++ = c;
284: } while(c > ' ' && c != c1);
285: if (t >= te) {
286: eat_rest:
287: while(c != '\n') {
288: c = next(2);
289: if (t < te) *t++ = c;
290: }
291: continue;
292: }
293: tstart = nextc;
294: if (t - t1 > INCLNAMX)
295: scream("oversize include name");
296: *--t = 0;
297: /* open file, put stuff on include stack */
298: inclopen(t1);
299: *t++ = c1;
300: while(nextc < lastc) {
301: if (t < te) *t++ = *nextc;
302: ++nextc;
303: }
304: *t = 0;
305: dumpwhite();
306: te = t = T1->white;
307: nextc = lastc = linebuf;
308: }
309: else break;
310: }
311: *t = 0;
312: tstart = nextc;
313: t = T1->tok;
314: te = t + sizeof(T1->tok) - 1;
315: *t++ = c;
316: switch(ct) {
317:
318: case SYMBOL:
319: for(;; ++t) {
320: c = next(eof);
321: if (Type[c] != SYMBOL) { unget(c); break; }
322: if (t >= te) {
323: do c = next(eof);
324: while (Type[c] == SYMBOL);
325: unget(c);
326: squawk("truncating oversize symbol");
327: break;
328: }
329: *t = c;
330: }
331: break;
332:
333: case OPERATOR /* ()[],;*#<>+/:^~|&!%={}?. */:
334: ct = c;
335: break;
336:
337: case STRING /* " */:
338: nlsquawk = 1;
339: for(;;) {
340: c = next(2);
341: if (t < te) *t++ = c;
342: switch(c) {
343: case '\\':
344: c = next(2);
345: if (t < te) *t++ = c;
346: continue;
347: case '\n':
348: if (nlsquawk) {
349: squawk("newline within string");
350: nlsquawk = 0;
351: }
352: continue;
353: case '"':
354: goto break2;
355: }
356: }
357: break2:
358: if (t >= te) squawk("oversize string");
359: break;
360:
361: case CHARCONST /* ' */:
362: do {
363: c = next(2);
364: if (t < te) *t++ = c;
365: if (c == '\\') {
366: c = next(2);
367: if (t < te) *t++ = c;
368: c = next(2);
369: if (t < te) *t++ = c;
370: }
371: if (c == '\n') {
372: squawk("newline in char constant");
373: break;
374: }
375: } while(c != '\'');
376: *t = 0;
377: break;
378:
379: case ARROW /* - */:
380: c = next(2);
381: if (c == '>') {
382: if (t < te) *t++ = c;
383: }
384: else {
385: unget(c);
386: ct = '-';
387: }
388: break;
389:
390: case FEND:
391: t = T1->tok;
392: }
393: *t = 0;
394: T1->inlevel = inlevel;
395: return T1->type = ct;
396: }
397:
398: main(argc,argv)
399: int argc;
400: char **argv;
401: {
402: int c;
403: char *s;
404:
405: progname = *argv;
406: xargv = argv;
407:
408: /* set up translate tables */
409:
410: for(c = ' ' + 1; c < 0x7f; c++) type[c] = SYMBOL;
411: for(s = "()[],;*#<>+/:?^~|&!%={}?."; c = *s; s++) type[c] = OPERATOR;
412: type['"'] = STRING;
413: type['\''] = CHARCONST;
414: type['-'] = ARROW;
415: type[Eof] = FEND;
416:
417: if (!nextfile(0)) {
418: fprintf(stderr, "%s: no (nonempty) input\n");
419: options(1);
420: }
421:
422: /* run */
423: process();
424: return rc;
425: }
426:
427: char *
428: adjoin(t,te,s) /* string concatenation with error-check and */
429: /* pointer to null char at string's end returned */
430: register char *t, *te, *s;
431: {
432: for(;; ++s, ++t) {
433: if (t >= te) {
434: sprintf(emsg, "%s = %d is too small",
435: adjnam, adjval);
436: squawk(emsg);
437: exit(rc);
438: }
439: if (!(*t = *s)) break;
440: }
441: return t;
442: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.