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