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