|
|
1.1 root 1: #include <stdio.h>
2: #include <stdlib.h>
3: #include <string.h>
4: #include <ctype.h>
5: #include <errno.h>
6: #include "grap.h"
7: #include "y.tab.h"
8:
9: Infile infile[10];
10: Infile *curfile = infile;
11:
12: #define MAXSRC 50
13: Src src[MAXSRC]; /* input source stack */
14: Src *srcp = src;
15:
16: void pushsrc(int type, char *ptr) /* new input source */
17: {
18: if (++srcp >= src + MAXSRC)
19: ERROR "inputs nested too deep" FATAL;
20: srcp->type = type;
21: srcp->sp = ptr;
22: if (dbg) {
23: printf("\n%3d ", srcp - src);
24: switch (srcp->type) {
25: case File:
26: printf("push file %s\n", ((Infile *)ptr)->fname);
27: break;
28: case Macro:
29: printf("push macro <%s>\n", ptr);
30: break;
31: case Char:
32: printf("push char <%c>\n", *ptr);
33: break;
34: case Thru:
35: printf("push thru\n");
36: break;
37: case String:
38: printf("push string <%s>\n", ptr);
39: break;
40: case Free:
41: printf("push free <%s>\n", ptr);
42: break;
43: default:
44: ERROR "pushed bad type %d", srcp->type FATAL;
45: }
46: }
47: }
48:
49: void popsrc(void) /* restore an old one */
50: {
51: if (srcp <= src)
52: ERROR "too many inputs popped" FATAL;
53: if (dbg) {
54: printf("%3d ", srcp - src);
55: switch (srcp->type) {
56: case File:
57: printf("pop file\n");
58: break;
59: case Macro:
60: printf("pop macro\n");
61: break;
62: case Char:
63: printf("pop char <%c>\n", *srcp->sp);
64: break;
65: case Thru:
66: printf("pop thru\n");
67: break;
68: case String:
69: printf("pop string\n");
70: break;
71: case Free:
72: printf("pop free\n");
73: break;
74: default:
75: ERROR "pop weird input %d", srcp->type FATAL;
76: }
77: }
78: srcp--;
79: }
80:
81: void definition(char *s) /* collect definition for s and install */
82: /* definitions picked up lexically */
83: {
84: char *p;
85: Obj *stp;
86:
87: p = delimstr("definition");
88: stp = lookup(s, 0);
89: if (stp != NULL) { /* it's there before */
90: if (stp->type != DEFNAME) {
91: ERROR "%s used as variable and definition", s WARNING;
92: return;
93: }
94: free(stp->val);
95: } else {
96: stp = lookup(s, 1);
97: stp->type = DEFNAME;
98: }
99: stp->val = p;
100: dprintf("installing %s as `%s'\n", s, p);
101: }
102:
103: char *delimstr(char *s) /* get body of X ... X */
104: /* message if too big */
105: {
106: int c, delim, rdelim, n, deep;
107: static char *buf = NULL;
108: static int nbuf = 0;
109: char *p;
110:
111: if (buf == NULL)
112: buf = grow(buf, "buf", nbuf += 1000, sizeof(buf[0]));
113: while ((delim = input()) == ' ' || delim == '\t' || delim == '\n')
114: ;
115: rdelim = baldelim(delim, "{}"); /* could be "(){}[]`'" */
116: deep = 1;
117: for (p = buf; ; ) {
118: c = input();
119: if (c == rdelim)
120: if (--deep == 0)
121: break;
122: if (c == delim)
123: deep++;
124: if (p >= buf + nbuf) {
125: n = p - buf;
126: buf = grow(buf, "buf", nbuf += 1000, sizeof(buf[0]));
127: p = buf + n;
128: }
129: if (c == EOF)
130: ERROR "end of file in %s %c %.20s... %c", s, delim, buf, delim FATAL;
131: *p++ = c;
132: }
133: *p = '\0';
134: dprintf("delimstr %s %c <%s> %c\n", s, delim, buf, delim);
135: return tostring(buf);
136: }
137:
138: baldelim(int c, char *s) /* replace c by balancing entry in s */
139: {
140: for ( ; *s; s += 2)
141: if (*s == c)
142: return s[1];
143: return c;
144: }
145:
146: Arg args[10]; /* argument frames */
147: Arg *argfp = args; /* frame pointer */
148: int argcnt; /* number of arguments seen so far */
149:
150: void dodef(Obj *stp) /* collect args and switch input to defn */
151: {
152: int i, len;
153: char *p;
154: Arg *ap;
155:
156: ap = argfp+1;
157: if (ap >= args+10)
158: ERROR "arguments too deep" FATAL;
159: argcnt = 0;
160: if (input() != '(')
161: ERROR "disaster in dodef" FATAL;
162: if (ap->argval == 0)
163: ap->argval = malloc(1000);
164: for (p = ap->argval; (len = getarg(p)) != -1; p += len) {
165: ap->argstk[argcnt++] = p;
166: if (input() == ')')
167: break;
168: }
169: for (i = argcnt; i < MAXARGS; i++)
170: ap->argstk[i] = "";
171: if (dbg)
172: for (i = 0; i < argcnt; i++)
173: printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]);
174: argfp = ap;
175: pushsrc(Macro, stp->val);
176: }
177:
178: getarg(char *p) /* pick up single argument, store in p, return length */
179: {
180: int n, c, npar;
181:
182: n = npar = 0;
183: for ( ;; ) {
184: c = input();
185: if (c == EOF)
186: ERROR "end of file in getarg!" FATAL;
187: if (npar == 0 && (c == ',' || c == ')'))
188: break;
189: if (c == '"') /* copy quoted stuff intact */
190: do {
191: *p++ = c;
192: n++;
193: } while ((c = input()) != '"' && c != EOF);
194: else if (c == '(')
195: npar++;
196: else if (c == ')')
197: npar--;
198: n++;
199: *p++ = c;
200: }
201: *p = 0;
202: unput(c);
203: return(n + 1);
204: }
205:
206: #define PBSIZE 2000
207: char pbuf[PBSIZE]; /* pushback buffer */
208: char *pb = pbuf-1; /* next pushed back character */
209:
210: char ebuf[200]; /* collect input here for error reporting */
211: char *ep = ebuf;
212:
213: int begin = 0;
214: extern int thru;
215: extern Obj *thrudef;
216: extern char *untilstr;
217:
218: input(void)
219: {
220: register int c;
221:
222: if (thru && begin) {
223: do_thru();
224: begin = 0;
225: }
226: c = nextchar();
227: dprintf(" <%c>", c);
228: if (ep >= ebuf + sizeof ebuf)
229: ep = ebuf;
230: return *ep++ = c;
231: }
232:
233: nextchar(void)
234: {
235: register int c;
236:
237: loop:
238: switch (srcp->type) {
239: case Free: /* free string */
240: free(srcp->sp);
241: popsrc();
242: goto loop;
243: case Thru: /* end of pushed back line */
244: begin = 1;
245: popsrc();
246: c = '\n';
247: break;
248: case Char:
249: if (pb >= pbuf) {
250: c = *pb--;
251: popsrc();
252: break;
253: } else { /* can't happen? */
254: popsrc();
255: goto loop;
256: }
257: case String:
258: c = *srcp->sp++;
259: if (c == '\0') {
260: popsrc();
261: goto loop;
262: } else {
263: if (*srcp->sp == '\0') /* empty, so pop */
264: popsrc();
265: break;
266: }
267: case Macro:
268: c = *srcp->sp++;
269: if (c == '\0') {
270: if (--argfp < args)
271: ERROR "argfp underflow" FATAL;
272: popsrc();
273: goto loop;
274: } else if (c == '$' && isdigit(*srcp->sp)) { /* $3 */
275: int n = 0;
276: while (isdigit(*srcp->sp))
277: n = 10 * n + *srcp->sp++ - '0';
278: if (n > 0 && n <= MAXARGS)
279: pushsrc(String, argfp->argstk[n-1]);
280: goto loop;
281: }
282: break;
283: case File:
284: c = getc(curfile->fin);
285: if (c == EOF) {
286: if (curfile == infile)
287: ERROR "end of file inside .G1/.G2" FATAL;
288: if (curfile->fin != stdin) {
289: fclose(curfile->fin);
290: free(curfile->fname); /* assumes allocated */
291: }
292: curfile--;
293: printf(".lf %d %s\n", curfile->lineno, curfile->fname);
294: popsrc();
295: thru = 0; /* chicken out */
296: thrudef = 0;
297: if (untilstr) {
298: free(untilstr);
299: untilstr = 0;
300: }
301: goto loop;
302: }
303: if (c == '\n')
304: curfile->lineno++;
305: break;
306: }
307: return c;
308: }
309:
310: void do_thru(void) /* read one line, make into a macro expansion */
311: {
312: int c, i;
313: char *p;
314: Arg *ap;
315:
316: ap = argfp+1;
317: if (ap >= args+10)
318: ERROR "arguments too deep" FATAL;
319: if (ap->argval == NULL)
320: ap->argval = malloc(1000);
321: p = ap->argval;
322: argcnt = 0;
323: c = nextchar();
324: if (thru == 0) { /* end of file was seen, so thru is done */
325: unput(c);
326: return;
327: }
328: for ( ; c != '\n' && c != EOF; ) {
329: if (c == ' ' || c == '\t') {
330: c = nextchar();
331: continue;
332: }
333: if (argcnt >= MAXARGS)
334: ERROR "too many fields on input line" FATAL;
335: ap->argstk[argcnt++] = p;
336: if (c == '"') {
337: do {
338: *p++ = c;
339: if ((c = nextchar()) == '\\') {
340: *p++ = c;
341: *p++ = nextchar();
342: c = nextchar();
343: }
344: } while (c != '"' && c != '\n' && c != EOF);
345: *p++ = '"';
346: if (c == '"')
347: c = nextchar();
348: } else {
349: do {
350: *p++ = c;
351: } while ((c = nextchar())!=' ' && c!='\t' && c!='\n' && c!=',' && c!=EOF);
352: if (c == ',')
353: c = nextchar();
354: }
355: *p++ = '\0';
356: }
357: if (c == EOF)
358: ERROR "unexpected end of file in do_thru" FATAL;
359: if (argcnt == 0) { /* ignore blank line */
360: pushsrc(Thru, (char *) 0);
361: return;
362: }
363: for (i = argcnt; i < MAXARGS; i++)
364: ap->argstk[i] = "";
365: if (dbg)
366: for (i = 0; i < argcnt; i++)
367: printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]);
368: if (strcmp(ap->argstk[0], ".G2") == 0) {
369: thru = 0;
370: thrudef = 0;
371: pushsrc(String, "\n.G2\n");
372: return;
373: }
374: if (untilstr && strcmp(ap->argstk[0], untilstr) == 0) {
375: thru = 0;
376: thrudef = 0;
377: free(untilstr);
378: untilstr = 0;
379: return;
380: }
381: pushsrc(Thru, (char *) 0);
382: dprintf("do_thru pushing back <%s>\n", thrudef->val);
383: argfp = ap;
384: pushsrc(Macro, thrudef->val);
385: }
386:
387: unput(int c)
388: {
389: if (++pb >= pbuf + sizeof pbuf)
390: ERROR "pushback overflow" FATAL;
391: if (--ep < ebuf)
392: ep = ebuf + sizeof(ebuf) - 1;
393: *pb = c;
394: pushsrc(Char, pb);
395: return c;
396: }
397:
398: void pbstr(char *s)
399: {
400: pushsrc(String, s);
401: }
402:
403: double errcheck(double x, char *s)
404: {
405: extern int errno;
406:
407: if (errno == EDOM) {
408: errno = 0;
409: ERROR "%s argument out of domain", s WARNING;
410: } else if (errno == ERANGE) {
411: errno = 0;
412: ERROR "%s result out of range", s WARNING;
413: }
414: return x;
415: }
416:
417: char errbuf[200];
418:
419: void yyerror(char *s)
420: {
421: extern char *cmdname;
422: int ern = errno; /* cause some libraries clobber it */
423:
424: if (synerr)
425: return;
426: fflush(stdout);
427: fprintf(stderr, "%s: %s", cmdname, s);
428: if (ern > 0) {
429: errno = ern;
430: perror("???");
431: }
432: fprintf(stderr, " near line %d, file %s\n",
433: curfile->lineno, curfile->fname);
434: eprint();
435: synerr = 1;
436: errno = 0;
437: }
438:
439: void eprint(void) /* try to print context around error */
440: {
441: char *p, *q;
442:
443: p = ep - 1;
444: if (p > ebuf && *p == '\n')
445: p--;
446: for ( ; p >= ebuf && *p != '\n'; p--)
447: ;
448: while (*p == '\n')
449: p++;
450: fprintf(stderr, " context is\n\t");
451: for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
452: ;
453: while (p < q)
454: putc(*p++, stderr);
455: fprintf(stderr, " >>> ");
456: while (p < ep)
457: putc(*p++, stderr);
458: fprintf(stderr, " <<< ");
459: while (pb >= pbuf)
460: putc(*pb--, stderr);
461: fgets(ebuf, sizeof ebuf, curfile->fin);
462: fprintf(stderr, "%s", ebuf);
463: pbstr("\n.G2\n"); /* safety first */
464: ep = ebuf;
465: }
466:
467: int yywrap(void) {return 1;}
468:
469: char *newfile = 0; /* filename for file copy */
470: char *untilstr = 0; /* string that terminates a thru */
471: int thru = 0; /* 1 if copying thru macro */
472: Obj *thrudef = 0; /* macro being used */
473:
474: void copyfile(char *s) /* remember file to start reading from */
475: {
476: newfile = s;
477: }
478:
479: void copydef(Obj *p) /* remember macro Obj */
480: {
481: thrudef = p;
482: }
483:
484: Obj *copythru(char *s) /* collect the macro name or body for thru */
485: {
486: Obj *p;
487: char *q;
488:
489: p = lookup(s, 0);
490: if (p != NULL) {
491: if (p->type == DEFNAME) {
492: p->val = addnewline(p->val);
493: return p;
494: } else
495: ERROR "%s used as define and name", s FATAL;
496: }
497: /* have to collect the definition */
498: pbstr(s); /* first char is the delimiter */
499: q = delimstr("thru body");
500: p = lookup("nameless", 1);
501: if (p != NULL)
502: if (p->val)
503: free(p->val);
504: p->type = DEFNAME;
505: p->val = q;
506: p->val = addnewline(p->val);
507: dprintf("installing nameless as `%s'\n", p->val);
508: return p;
509: }
510:
511: char *addnewline(char *p) /* add newline to end of p */
512: {
513: int n;
514:
515: n = strlen(p);
516: if (p[n-1] != '\n') {
517: p = realloc(p, n+2);
518: p[n] = '\n';
519: p[n+1] = '\0';
520: }
521: return p;
522: }
523:
524: void copyuntil(char *s) /* string that terminates a thru */
525: {
526: untilstr = s;
527: }
528:
529: void copy(void) /* begin input from file, etc. */
530: {
531: FILE *fin;
532:
533: if (newfile) {
534: if ((fin = fopen(newfile, "r")) == NULL)
535: ERROR "can't open file %s", newfile FATAL;
536: curfile++;
537: curfile->fin = fin;
538: curfile->fname = tostring(newfile);
539: curfile->lineno = 0;
540: printf(".lf 1 %s\n", curfile->fname);
541: pushsrc(File, curfile->fname);
542: newfile = 0;
543: }
544: if (thrudef) {
545: thru = 1;
546: begin = 1; /* wrong place */
547: }
548: }
549:
550: char shellbuf[1000], *shellp;
551:
552: void shell_init(void) /* set up to interpret a shell command */
553: {
554: fprintf(tfd, "# shell cmd...\n");
555: sprintf(shellbuf, "sh -c '");
556: shellp = shellbuf + strlen(shellbuf);
557: }
558:
559: void shell_text(char *s) /* add string to command being collected */
560: {
561: /* fprintf(tfd, "#add <%s> to <%s>\n", s, shellbuf); */
562: while (*s) {
563: if (*s == '\'') { /* protect interior quotes */
564: *shellp++ = '\'';
565: *shellp++ = '\\';
566: *shellp++ = '\'';
567: }
568: *shellp++ = *s++;
569: }
570: }
571:
572: void shell_exec(void) /* do it */
573: {
574: /* fprintf(tfd, "# run <%s>\n", shellbuf); */
575: *shellp++ = '\'';
576: *shellp = '\0';
577: system(shellbuf);
578: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.