1 #ifndef lint
2 static char sccsid[] = "@(#)input.c 2.2 (CWI) 87/04/01";
3 #endif lint
4 #include <stdio.h>
5 #include <ctype.h>
6 #include <errno.h>
7 #include "e.h"
8 #include "y.tab.h"
9
10 Infile infile[10];
11 Infile *curfile = infile;
12
13 #define MAXSRC 50
14 Src src[MAXSRC]; /* input source stack */
15 Src *srcp = src;
16
pushsrc(type,ptr)17 pushsrc(type, ptr) /* new input source */
18 int type;
19 char *ptr;
20 {
21 if (++srcp >= src + MAXSRC)
22 fatal("inputs nested too deep");
23 srcp->type = type;
24 srcp->sp = ptr;
25 if (dbg > 1) {
26 printf("\n%3d ", srcp - src);
27 switch (srcp->type) {
28 case File:
29 printf("push file %s\n", ((Infile *)ptr)->fname);
30 break;
31 case Macro:
32 printf("push macro <%s>\n", ptr);
33 break;
34 case Char:
35 printf("push char <%c>\n", *ptr);
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
popsrc()49 popsrc() /* restore an old one */
50 {
51 if (srcp <= src)
52 fatal("too many inputs popped");
53 if (dbg > 1) {
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 String:
66 printf("pop string\n");
67 break;
68 case Free:
69 printf("pop free\n");
70 break;
71 default:
72 fatal("pop weird input %d\n", srcp->type);
73 }
74 }
75 srcp--;
76 }
77
78 Arg args[10]; /* argument frames */
79 Arg *argfp = args; /* frame pointer */
80 int argcnt; /* number of arguments seen so far */
81
dodef(stp)82 dodef(stp) /* collect args and switch input to defn */
83 tbl *stp;
84 {
85 int i, len;
86 char *p;
87 Arg *ap;
88
89 ap = argfp+1;
90 if (ap >= args+10)
91 fatal("arguments too deep");
92 argcnt = 0;
93 if (input() != '(')
94 fatal("disaster in dodef\n");
95 if (ap->argval == 0)
96 ap->argval = malloc(1000);
97 for (p = ap->argval; (len = getarg(p)) != -1; p += len) {
98 ap->argstk[argcnt++] = p;
99 if (input() == ')')
100 break;
101 }
102 for (i = argcnt; i < MAXARGS; i++)
103 ap->argstk[i] = "";
104 if (dbg)
105 for (i = 0; i < argcnt; i++)
106 printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]);
107 argfp = ap;
108 pushsrc(Macro, stp->defn);
109 }
110
getarg(p)111 getarg(p) /* pick up single argument, store in p, return length */
112 char *p;
113 {
114 int n, c, npar;
115
116 n = npar = 0;
117 for ( ;; ) {
118 c = input();
119 if (c == EOF)
120 fatal("end of file in getarg!\n");
121 if (npar == 0 && (c == ',' || c == ')'))
122 break;
123 if (c == '"') /* copy quoted stuff intact */
124 do {
125 *p++ = c;
126 n++;
127 } while ((c = input()) != '"' && c != EOF);
128 else if (c == '(')
129 npar++;
130 else if (c == ')')
131 npar--;
132 n++;
133 *p++ = c;
134 }
135 *p = 0;
136 unput(c);
137 return(n + 1);
138 }
139
140 #define PBSIZE 2000
141 char pbuf[PBSIZE]; /* pushback buffer */
142 char *pb = pbuf-1; /* next pushed back character */
143
144 char ebuf[200]; /* collect input here for error reporting */
145 char *ep = ebuf;
146
input()147 input()
148 {
149 register int c;
150
151 loop:
152 switch (srcp->type) {
153 case File:
154 c = getc(curfile->fin);
155 if (c == EOF) {
156 if (curfile == infile)
157 break;
158 if (curfile->fin != stdin) {
159 fclose(curfile->fin);
160 free(curfile->fname); /* assumes allocated */
161 }
162 curfile--;
163 printf(".lf %d %s\n", curfile->lineno, curfile->fname);
164 popsrc();
165 goto loop;
166 }
167 if (c == '\n')
168 curfile->lineno++;
169 break;
170 case Char:
171 if (pb >= pbuf) {
172 c = *pb--;
173 popsrc();
174 break;
175 } else { /* can't happen? */
176 popsrc();
177 goto loop;
178 }
179 case String:
180 c = *srcp->sp++;
181 if (c == '\0') {
182 popsrc();
183 goto loop;
184 } else {
185 if (*srcp->sp == '\0') /* empty, so pop */
186 popsrc();
187 break;
188 }
189 case Macro:
190 c = *srcp->sp++;
191 if (c == '\0') {
192 if (--argfp < args)
193 fatal("argfp underflow");
194 popsrc();
195 goto loop;
196 } else if (c == '$' && isdigit(*srcp->sp)) {
197 int n = 0;
198 while (isdigit(*srcp->sp))
199 n = 10 * n + *srcp->sp++ - '0';
200 if (n > 0 && n <= MAXARGS)
201 pushsrc(String, argfp->argstk[n-1]);
202 goto loop;
203 }
204 break;
205 case Free: /* free string */
206 free(srcp->sp);
207 popsrc();
208 goto loop;
209 }
210 if (ep >= ebuf + sizeof ebuf)
211 ep = ebuf;
212 *ep++ = c;
213 return c;
214 }
215
216
unput(c)217 unput(c)
218 {
219 if (++pb >= pbuf + sizeof pbuf)
220 fatal("pushback overflow\n");
221 if (--ep < ebuf)
222 ep = ebuf + sizeof(ebuf) - 1;
223 *pb = c;
224 pushsrc(Char, pb);
225 return c;
226 }
227
pbstr(s)228 pbstr(s)
229 char *s;
230 {
231 pushsrc(String, s);
232 }
233
fatal(s,s1,s2,s3,s4)234 fatal(s, s1, s2, s3, s4) /* should be a flag on error */
235 char *s, *s1, *s2, *s3, *s4;
236 {
237 error(FATAL, s, s1, s2, s3, s4);
238 }
239
error(die,s,s1,s2,s3,s4)240 error(die, s, s1, s2, s3, s4)
241 int die;
242 char *s, *s1, *s2, *s3, *s4;
243 {
244 extern char *cmdname, *sys_errlist[];
245 extern int errno, sys_nerr;
246
247 if (synerr)
248 return;
249 fprintf(stderr, "%s: ", cmdname);
250 fprintf(stderr, s, s1, s2, s3, s4);
251 if (errno > 0 && errno < sys_nerr)
252 fprintf(stderr, " (%s)", sys_errlist[errno]);
253 if (curfile->fin)
254 fprintf(stderr, " near line %d, file %s",
255 curfile->lineno, curfile->fname);
256 fprintf(stderr, "\n");
257 eprint();
258 synerr = 1;
259 errno = 0;
260 if (die) {
261 if (dbg)
262 abort();
263 else
264 exit(1);
265 }
266 }
267
yyerror()268 yyerror() {;}
269
eprint()270 eprint() /* try to print context around error */
271 {
272 char *p, *q;
273 int c;
274
275 if (ep == ebuf)
276 return; /* no context */
277 p = ep - 1;
278 if (p > ebuf && *p == '\n')
279 p--;
280 for ( ; p >= ebuf && *p != '\n'; p--)
281 ;
282 while (*p == '\n')
283 p++;
284 fprintf(stderr, " context is\n\t");
285 for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
286 ;
287 while (p < q)
288 putc(*p++, stderr);
289 fprintf(stderr, " >>> ");
290 while (p < ep)
291 putc(*p++, stderr);
292 fprintf(stderr, " <<< ");
293 while (pb >= pbuf)
294 putc(*pb--, stderr);
295 if (curfile->fin)
296 fgets(ebuf, sizeof ebuf, curfile->fin);
297 fprintf(stderr, "%s", ebuf);
298 pbstr("\n.EN\n"); /* safety first */
299 ep = ebuf;
300 }
301