pic: use troff drawing commands for filling objects
[troff.git] / eqn / input.c
blob3b8656714a381fea23ca2dc8397c3cdb6d624c4d
1 #include "e.h"
2 #include "y.tab.h"
3 #include <ctype.h>
4 #include <errno.h>
6 Infile infile[10];
7 Infile *curfile = infile;
9 #define MAXSRC 50
10 Src src[MAXSRC]; /* input source stack */
11 Src *srcp = src;
13 extern int getarg(char *);
14 extern void eprint(void);
16 void pushsrc(int type, char *ptr) /* new input source */
18 if (++srcp >= src + MAXSRC)
19 ERROR "inputs nested too deep" FATAL;
20 srcp->type = type;
21 srcp->sp = ptr;
22 if (dbg > 1) {
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 String:
35 printf("push string <%s>\n", ptr);
36 break;
37 case Free:
38 printf("push free <%s>\n", ptr);
39 break;
40 default:
41 ERROR "pushed bad type %d\n", srcp->type FATAL;
46 void popsrc(void) /* restore an old one */
48 if (srcp <= src)
49 ERROR "too many inputs popped" FATAL;
50 if (dbg > 1) {
51 printf("%3d ", srcp - src);
52 switch (srcp->type) {
53 case File:
54 printf("pop file\n");
55 break;
56 case Macro:
57 printf("pop macro\n");
58 break;
59 case Char:
60 printf("pop char <%c>\n", *srcp->sp);
61 break;
62 case String:
63 printf("pop string\n");
64 break;
65 case Free:
66 printf("pop free\n");
67 break;
68 default:
69 ERROR "pop weird input %d\n", srcp->type FATAL;
72 srcp--;
75 Arg args[10]; /* argument frames */
76 Arg *argfp = args; /* frame pointer */
77 int argcnt; /* number of arguments seen so far */
79 void dodef(tbl *stp) /* collect args and switch input to defn */
81 int i, len;
82 char *p;
83 Arg *ap;
85 ap = argfp+1;
86 if (ap >= args+10)
87 ERROR "more than arguments\n" FATAL;
88 argcnt = 0;
89 if (input() != '(')
90 ERROR "disaster in dodef\n"FATAL;
91 if (ap->argval == 0)
92 ap->argval = malloc(1000);
93 for (p = ap->argval; (len = getarg(p)) != -1; p += len) {
94 ap->argstk[argcnt++] = p;
95 if (input() == ')')
96 break;
98 for (i = argcnt; i < MAXARGS; i++)
99 ap->argstk[i] = "";
100 if (dbg)
101 for (i = 0; i < argcnt; i++)
102 printf("arg %d.%d = <%s>\n", ap-args, i+1, ap->argstk[i]);
103 argfp = ap;
104 pushsrc(Macro, stp->cval);
107 getarg(char *p) /* pick up single argument, store in p, return length */
109 int n, c, npar;
111 n = npar = 0;
112 for ( ;; ) {
113 c = input();
114 if (c == EOF)
115 ERROR "end of file in getarg!\n" FATAL;
116 if (npar == 0 && (c == ',' || c == ')'))
117 break;
118 if (c == '"') /* copy quoted stuff intact */
119 do {
120 *p++ = c;
121 n++;
122 } while ((c = input()) != '"' && c != EOF);
123 else if (c == '(')
124 npar++;
125 else if (c == ')')
126 npar--;
127 n++;
128 *p++ = c;
130 *p = 0;
131 unput(c);
132 return(n + 1);
135 #define PBSIZE 2000
136 char pbuf[PBSIZE]; /* pushback buffer */
137 char *pb = pbuf-1; /* next pushed back character */
139 char ebuf[200]; /* collect input here for error reporting */
140 char *ep = ebuf;
142 input(void)
144 register int c = 0;
146 loop:
147 switch (srcp->type) {
148 case File:
149 c = getc(curfile->fin);
150 if (c == EOF) {
151 if (curfile == infile)
152 break;
153 if (curfile->fin != stdin) {
154 fclose(curfile->fin);
155 free(curfile->fname); /* assumes allocated */
157 curfile--;
158 printf(".lf %d %s\n", curfile->lineno, curfile->fname);
159 popsrc();
160 goto loop;
162 if (c == '\n')
163 curfile->lineno++;
164 break;
165 case Char:
166 if (pb >= pbuf) {
167 c = *pb--;
168 popsrc();
169 break;
170 } else { /* can't happen? */
171 popsrc();
172 goto loop;
174 case String:
175 c = *srcp->sp++;
176 if (c == '\0') {
177 popsrc();
178 goto loop;
179 } else {
180 if (*srcp->sp == '\0') /* empty, so pop */
181 popsrc();
182 break;
184 case Macro:
185 c = *srcp->sp++;
186 if (c == '\0') {
187 if (--argfp < args)
188 ERROR "argfp underflow" FATAL;
189 popsrc();
190 goto loop;
191 } else if (c == '$' && isdigit(*srcp->sp)) {
192 int n = 0;
193 while (isdigit(*srcp->sp))
194 n = 10 * n + *srcp->sp++ - '0';
195 if (n > 0 && n <= MAXARGS)
196 pushsrc(String, argfp->argstk[n-1]);
197 goto loop;
199 break;
200 case Free: /* free string */
201 free(srcp->sp);
202 popsrc();
203 goto loop;
205 if (ep >= ebuf + sizeof ebuf)
206 ep = ebuf;
207 *ep++ = c;
208 return c;
212 unput(int c)
214 if (++pb >= pbuf + sizeof pbuf)
215 ERROR "pushback overflow\n"FATAL;
216 if (--ep < ebuf)
217 ep = ebuf + sizeof(ebuf) - 1;
218 *pb = c;
219 pushsrc(Char, pb);
220 return c;
223 void pbstr(char *s)
225 pushsrc(String, s);
228 void error(int die, char *s)
230 extern char *cmdname;
232 if (synerr)
233 return;
234 fprintf(stderr, "%s: ", cmdname);
235 fprintf(stderr, s);
236 if (errno > 0)
237 perror("???");
238 if (curfile->fin)
239 fprintf(stderr, " near %s:%d",
240 curfile->fname, curfile->lineno+1);
241 fprintf(stderr, "\n");
242 eprint();
243 synerr = 1;
244 errno = 0;
245 if (die) {
246 if (dbg)
247 abort();
248 else
249 exit(1);
253 void yyerror(char *s)
255 error(0, s); /* temporary */
258 char errbuf[200];
260 void eprint(void) /* try to print context around error */
262 char *p, *q;
264 if (ep == ebuf)
265 return; /* no context */
266 p = ep - 1;
267 if (p > ebuf && *p == '\n')
268 p--;
269 for ( ; p >= ebuf && *p != '\n'; p--)
271 while (*p == '\n')
272 p++;
273 fprintf(stderr, " context is\n\t");
274 for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
276 while (p < q)
277 putc(*p++, stderr);
278 fprintf(stderr, " >>> ");
279 while (p < ep)
280 putc(*p++, stderr);
281 fprintf(stderr, " <<< ");
282 while (pb >= pbuf)
283 putc(*pb--, stderr);
284 if (curfile->fin)
285 fgets(ebuf, sizeof ebuf, curfile->fin);
286 fprintf(stderr, "%s", ebuf);
287 pbstr("\n.EN\n"); /* safety first */
288 ep = ebuf;