1 #include	<stdio.h>
2 #include	<ctype.h>
3 #include	"pic.h"
4 #include	"y.tab.h"
5 
6 extern	FILE	*yyin;
7 extern	int	lineno;
8 extern	char	*filename;
9 extern	int	synerr;
10 
definition(s)11 definition(s)	/* collect definition for s and install */
12 	char *s;	/* definitions picked up lexically */
13 {
14 	char buf[4000], *p, *tostring();
15 	int c, delim;
16 	struct symtab *stp;
17 
18 	while ((delim = input()) == ' ' || delim == '\t')
19 		;
20 	for (p = buf; (c = input()) != delim; ) {
21 		if (p >= buf + sizeof(buf)) {
22 			yyerror("definition of %s is too long", s);
23 			exit(1);
24 		}
25 		if (c == EOF) {
26 			yyerror("end of file while defining %s", s);
27 			exit(1);
28 		}
29 		*p++ = c;
30 	}
31 	*p = '\0';
32 	p = tostring(buf);
33 	stp = lookup(s);
34 	if (stp != NULL) {	/* it's there before */
35 		if (stp->s_type != DEFNAME) {
36 			yyerror("%s used as variable and definition\n", s);
37 			return;
38 		}
39 		free(stp->s_val.p);
40 		stp->s_val.p = p;
41 	} else {
42 		YYSTYPE u;
43 		u.p = p;
44 		makevar(tostring(s), DEFNAME, u);
45 	}
46 	dprintf("installing %s as `%s'\n", s, p);
47 }
48 
49 char *argstk[10];	/* pointers to actual arguments in argval */
50 char argval[1000];	/* arguments stored here end to end */
51 char *argp;		/* current position in argval */
52 int argcnt;		/* number of arguments seen so far */
53 
54 dodef(stp)	/* collect args and push back defn for name in table slot n */
55 	struct symtab *stp;
56 {
57 	int i, c, len;
58 	char *p;
59 
60 	argcnt = 0;
61 	if (input() != '(')
62 		yyerror("disaster in dodef\n");
63 	for (argp = argval; (len = getarg(argp)) != -1; argp += len) {
64 		argstk[argcnt++] = argp;
65 		if (input() == ')')
66 			break;
67 	}
68 	for (i = argcnt; i < 10; i++)
69 		argstk[i] = "";
70 	if (dbg) {
71 		for (i = 0; i < argcnt; i++)
72 			printf("arg %d = %s\n", i, argstk[i]);
73 	}
74 
75 	/* push them back */
76 	for (p = stp->s_val.p; *p; p++)
77 		;		/* find the end */
78 	for (--p; p >= stp->s_val.p; p--) {
79 		if (*(p-1) == '$') {
80 			if (isdigit(*p)) {
81 				pbstr(argstk[*p - '0' - 1]);
82 				p--;
83 			}
84 			else
85 				unput(*p);
86 		} else {
87 			unput(*p);
88 		}
89 	}
90 }
91 
getarg(p)92 getarg(p)	/* pick up single argument, store in p, return length */
93 	char *p;
94 {
95 	int n, c, npar;
96 
97 	n = npar = 0;
98 	for ( ;; ) {
99 		c = input();
100 		if (c == EOF)
101 			yyerror("end of file in getarg!\n");
102 		if (npar == 0 && (c == ',' || c == ')'))
103 			break;
104 		if (c == '"')	/* copy quoted stuff intact */
105 			do {
106 				*p++ = c;
107 				n++;
108 			} while ((c = input()) != '"' && c != EOF);
109 		else if (c == '(')
110 			npar++;
111 		else if (c == ')')
112 			npar--;
113 		n++;
114 		*p++ = c;
115 	}
116 	*p = 0;
117 	unput(c);
118 	return(n + 1);
119 }
120 
121 #define	PBSIZE	4000
122 char	pbuf[PBSIZE];		/* pushback buffer */
123 char	*pb	= pbuf-1;	/* next pushed back character */
124 
125 char	ebuf[200];		/* collect input here for error reporting */
126 char	*ep	= ebuf;
127 
input()128 input()
129 {
130 	register int c;
131 
132 	if (pb >= pbuf) {
133 		c = *pb--;
134 	} else {
135 		c = getc(yyin);
136 		if (c == '\n')
137 			lineno++;
138 		else if (c == EOF) {
139 			yyerror("end of file inside .PS/.PE");
140 			exit(1);
141 		}
142 	}
143 	if (ep >= ebuf + sizeof ebuf)
144 		ep = ebuf;
145 	return (*ep++ = c);
146 }
147 
unput(c)148 unput(c)
149 {
150 	if (++pb >= pbuf + sizeof pbuf) {
151 		yyerror("pushback overflow\n");
152 		exit(1);
153 	}
154 	if (--ep < ebuf)
155 		ep = ebuf + sizeof(ebuf) - 1;
156 	return(*pb = c);
157 }
158 
pbstr(s)159 pbstr(s)
160 	char *s;
161 {
162 	int n;
163 
164 	n = strlen(s);
165 	while (--n >= 0)
166 		unput(s[n]);
167 }
168 
yyerror(s,s1,s2,s3,s4)169 yyerror(s, s1, s2, s3, s4)
170 	char *s, *s1, *s2, *s3, *s4;
171 {
172 	if (synerr)
173 		return;
174 	fprintf(stderr, "pic: ");
175 	fprintf(stderr, s, s1, s2, s3, s4);
176 	fprintf(stderr, " near line %d, file %s\n", lineno, filename);
177 	eprint();
178 	synerr = 1;
179 }
180 
eprint()181 eprint()	/* try to print context around error */
182 {
183 	char *p, *q;
184 	int c;
185 
186 	p = ep - 1;
187 	if (p > ebuf && *p == '\n')
188 		p--;
189 	for ( ; p >= ebuf && *p != '\n'; p--)
190 		;
191 	while (*p == '\n')
192 		p++;
193 	fprintf(stderr, " context is\n\t");
194 	while (p < ep)
195 		putc(*p++, stderr);
196 	fprintf(stderr, " ^ ");
197 	while (pb >= pbuf)
198 		putc(*pb--, stderr);
199 	fgets(ebuf, sizeof ebuf, yyin);
200 	fprintf(stderr, "%s", ebuf);
201 	pbstr(".PE\n");	/* safety first */
202 	ep = ebuf;
203 }
204 
yywrap()205 yywrap() {;}
206