|
|
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: fatal("inputs nested too deep");
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: fatal("pushed bad type %d\n", srcp->type);
45: }
46: }
47: }
48:
49: popsrc() /* restore an old one */
50: {
51: if (srcp <= src)
52: fatal("too many inputs popped");
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: fatal("pop weird input %d\n", srcp->type);
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: yyerror("%s used as variable and definition\n", s);
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: fatal("end of file in %s %c %.20s... %c", s, delim, buf, delim);
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: fatal("arguments too deep");
162: argcnt = 0;
163: if (input() != '(')
164: fatal("disaster in dodef\n");
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: fatal("end of file in getarg!\n");
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: fatal("argfp underflow");
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: fatal("end of file inside .G1/.G2");
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, n;
317: char *p;
318: Arg *ap;
319:
320: ap = argfp+1;
321: if (ap >= args+10)
322: fatal("arguments too deep");
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: ap->argstk[argcnt++] = p;
338: if (c == '"') {
339: do {
340: *p++ = c;
341: if ((c = nextchar()) == '\\') {
342: *p++ = c;
343: *p++ = nextchar();
344: c = nextchar();
345: }
346: } while (c != '"' && c != '\n' && c != EOF);
347: *p++ = '"';
348: if (c == '"')
349: c = nextchar();
350: } else {
351: do {
352: *p++ = c;
353: } while ((c = nextchar())!=' ' && c!='\t' && c!='\n' && c!=',' && c!=EOF);
354: if (c == ',')
355: c = nextchar();
356: }
357: *p++ = '\0';
358: }
359: if (c == EOF)
360: fatal("unexpected end of file in do_thru");
361: if (argcnt == 0) { /* ignore blank line */
362: pushsrc(Thru, (char *) 0);
363: return;
364: }
365: for (i = argcnt; i < MAXARGS; i++)
366: ap->argstk[i] = "";
367: if (dbg)
368: for (i = 0; i < argcnt; i++)
369: printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]);
370: if (strcmp(ap->argstk[0], ".G2") == 0) {
371: thru = 0;
372: thrudef = 0;
373: pushsrc(String, "\n.G2\n");
374: return;
375: }
376: if (untilstr && strcmp(ap->argstk[0], untilstr) == 0) {
377: thru = 0;
378: thrudef = 0;
379: free(untilstr);
380: untilstr = 0;
381: return;
382: }
383: pushsrc(Thru, (char *) 0);
384: dprintf("do_thru pushing back <%s>\n", thrudef->val);
385: argfp = ap;
386: pushsrc(Macro, thrudef->val);
387: }
388:
389: unput(c)
390: {
391: if (++pb >= pbuf + sizeof pbuf)
392: fatal("pushback overflow\n");
393: if (--ep < ebuf)
394: ep = ebuf + sizeof(ebuf) - 1;
395: *pb = c;
396: pushsrc(Char, pb);
397: return c;
398: }
399:
400: pbstr(s)
401: char *s;
402: {
403: pushsrc(String, s);
404: }
405:
406: double errcheck(x, s)
407: double x;
408: char *s;
409: {
410: extern int errno;
411:
412: if (errno == EDOM) {
413: errno = 0;
414: yyerror("%s argument out of domain", s);
415: } else if (errno == ERANGE) {
416: errno = 0;
417: yyerror("%s result out of range", s);
418: }
419: return x;
420: }
421:
422: fatal(s, s1, s2, s3, s4) /* should be a flag on yyerror */
423: char *s, *s1, *s2, *s3, *s4;
424: {
425: yyerror(s, s1, s2, s3, s4);
426: if (dbg)
427: abort();
428: else
429: onintr(); /* cleans up temporary */
430: }
431:
432: yyerror(s, s1, s2, s3, s4)
433: char *s, *s1, *s2, *s3, *s4;
434: {
435: extern char *cmdname, *sys_errlist[];
436: extern int errno, sys_nerr;
437:
438: if (synerr)
439: return;
440: fprintf(stderr, "%s: ", cmdname);
441: fprintf(stderr, s, s1, s2, s3, s4);
442: if (errno > 0 && errno < sys_nerr)
443: fprintf(stderr, " (%s)", sys_errlist[errno]);
444: fprintf(stderr, " near line %d, file %s\n",
445: curfile->lineno, curfile->fname);
446: eprint();
447: synerr = 1;
448: errno = 0;
449: }
450:
451: eprint() /* try to print context around error */
452: {
453: char *p, *q;
454: int c;
455:
456: p = ep - 1;
457: if (p > ebuf && *p == '\n')
458: p--;
459: for ( ; p >= ebuf && *p != '\n'; p--)
460: ;
461: while (*p == '\n')
462: p++;
463: fprintf(stderr, " context is\n\t");
464: for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
465: ;
466: while (p < q)
467: putc(*p++, stderr);
468: fprintf(stderr, " >>> ");
469: while (p < ep)
470: putc(*p++, stderr);
471: fprintf(stderr, " <<< ");
472: while (pb >= pbuf)
473: putc(*pb--, stderr);
474: fgets(ebuf, sizeof ebuf, curfile->fin);
475: fprintf(stderr, "%s", ebuf);
476: pbstr("\n.G2\n"); /* safety first */
477: ep = ebuf;
478: }
479:
480: yywrap() {;}
481:
482: char *newfile = 0; /* filename for file copy */
483: char *untilstr = 0; /* string that terminates a thru */
484: int thru = 0; /* 1 if copying thru macro */
485: Obj *thrudef = 0; /* macro being used */
486:
487: copyfile(s) /* remember file to start reading from */
488: char *s;
489: {
490: newfile = s;
491: }
492:
493: copydef(p) /* remember macro Obj */
494: Obj *p;
495: {
496: thrudef = p;
497: }
498:
499: Obj *copythru(s) /* collect the macro name or body for thru */
500: char *s;
501: {
502: Obj *p;
503: char *q, *addnewline();
504:
505: p = lookup(s, 0);
506: if (p != NULL) {
507: if (p->type == DEFNAME) {
508: p->val = addnewline(p->val);
509: return p;
510: } else
511: fatal("%s used as define and name", s);
512: }
513: /* have to collect the definition */
514: pbstr(s); /* first char is the delimiter */
515: q = delimstr("thru body");
516: p = lookup("nameless", 1);
517: if (p != NULL)
518: if (p->val)
519: free(p->val);
520: p->type = DEFNAME;
521: p->val = q;
522: p->val = addnewline(p->val);
523: dprintf("installing nameless as `%s'\n", p->val);
524: return p;
525: }
526:
527: char *addnewline(p) /* add newline to end of p */
528: char *p;
529: {
530: int n;
531: extern char *realloc();
532:
533: n = strlen(p);
534: if (p[n-1] != '\n') {
535: p = realloc(p, n+2);
536: p[n] = '\n';
537: p[n+1] = '\0';
538: }
539: return p;
540: }
541:
542: copyuntil(s) /* string that terminates a thru */
543: char *s;
544: {
545: untilstr = s;
546: }
547:
548: copy() /* begin input from file, etc. */
549: {
550: FILE *fin;
551:
552: if (newfile) {
553: if ((fin = fopen(newfile, "r")) == NULL)
554: fatal("can't open file %s", newfile);
555: curfile++;
556: curfile->fin = fin;
557: curfile->fname = tostring(newfile);
558: curfile->lineno = 0;
559: printf(".lf 1 %s\n", curfile->fname);
560: pushsrc(File, curfile);
561: newfile = 0;
562: }
563: if (thrudef) {
564: thru = 1;
565: begin = 1; /* wrong place */
566: }
567: }
568:
569: char shellbuf[1000], *shellp;
570:
571: shell_init() /* set up to interpret a shell command */
572: {
573: fprintf(tfd, "# shell cmd...\n");
574: sprintf(shellbuf, "sh -c '");
575: shellp = shellbuf + strlen(shellbuf);
576: }
577:
578: shell_text(s) /* add string to command being collected */
579: char *s;
580: {
581: /* fprintf(tfd, "#add <%s> to <%s>\n", s, shellbuf); */
582: while (*s) {
583: if (*s == '\'') { /* protect interior quotes */
584: *shellp++ = '\'';
585: *shellp++ = '\\';
586: *shellp++ = '\'';
587: }
588: *shellp++ = *s++;
589: }
590: }
591:
592: shell_exec() /* do it */
593: {
594: /* fprintf(tfd, "# run <%s>\n", shellbuf); */
595: *shellp++ = '\'';
596: *shellp = '\0';
597: system(shellbuf);
598: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.