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