14aaebc40Srrh #include	<stdio.h>
24aaebc40Srrh #include	<ctype.h>
34aaebc40Srrh #include	"pic.h"
44aaebc40Srrh #include	"y.tab.h"
54aaebc40Srrh 
64aaebc40Srrh extern	FILE	*yyin;
74aaebc40Srrh extern	int	lineno;
84aaebc40Srrh extern	char	*filename;
94aaebc40Srrh extern	int	synerr;
104aaebc40Srrh 
definition(s)114aaebc40Srrh definition(s)	/* collect definition for s and install */
124aaebc40Srrh 	char *s;	/* definitions picked up lexically */
134aaebc40Srrh {
14*7914cea4Srrh 	char buf[4000], *p, *tostring();
154aaebc40Srrh 	int c, delim;
164aaebc40Srrh 	struct symtab *stp;
174aaebc40Srrh 
184aaebc40Srrh 	while ((delim = input()) == ' ' || delim == '\t')
194aaebc40Srrh 		;
204aaebc40Srrh 	for (p = buf; (c = input()) != delim; ) {
214aaebc40Srrh 		if (p >= buf + sizeof(buf)) {
224aaebc40Srrh 			yyerror("definition of %s is too long", s);
234aaebc40Srrh 			exit(1);
244aaebc40Srrh 		}
254aaebc40Srrh 		if (c == EOF) {
264aaebc40Srrh 			yyerror("end of file while defining %s", s);
274aaebc40Srrh 			exit(1);
284aaebc40Srrh 		}
294aaebc40Srrh 		*p++ = c;
304aaebc40Srrh 	}
314aaebc40Srrh 	*p = '\0';
324aaebc40Srrh 	p = tostring(buf);
334aaebc40Srrh 	stp = lookup(s);
344aaebc40Srrh 	if (stp != NULL) {	/* it's there before */
354aaebc40Srrh 		if (stp->s_type != DEFNAME) {
364aaebc40Srrh 			yyerror("%s used as variable and definition\n", s);
374aaebc40Srrh 			return;
384aaebc40Srrh 		}
394aaebc40Srrh 		free(stp->s_val.p);
404aaebc40Srrh 		stp->s_val.p = p;
414aaebc40Srrh 	} else {
424aaebc40Srrh 		YYSTYPE u;
434aaebc40Srrh 		u.p = p;
444aaebc40Srrh 		makevar(tostring(s), DEFNAME, u);
454aaebc40Srrh 	}
464aaebc40Srrh 	dprintf("installing %s as `%s'\n", s, p);
474aaebc40Srrh }
484aaebc40Srrh 
494aaebc40Srrh char *argstk[10];	/* pointers to actual arguments in argval */
504aaebc40Srrh char argval[1000];	/* arguments stored here end to end */
514aaebc40Srrh char *argp;		/* current position in argval */
524aaebc40Srrh int argcnt;		/* number of arguments seen so far */
534aaebc40Srrh 
544aaebc40Srrh dodef(stp)	/* collect args and push back defn for name in table slot n */
554aaebc40Srrh 	struct symtab *stp;
564aaebc40Srrh {
574aaebc40Srrh 	int i, c, len;
584aaebc40Srrh 	char *p;
594aaebc40Srrh 
604aaebc40Srrh 	argcnt = 0;
614aaebc40Srrh 	if (input() != '(')
624aaebc40Srrh 		yyerror("disaster in dodef\n");
634aaebc40Srrh 	for (argp = argval; (len = getarg(argp)) != -1; argp += len) {
644aaebc40Srrh 		argstk[argcnt++] = argp;
654aaebc40Srrh 		if (input() == ')')
664aaebc40Srrh 			break;
674aaebc40Srrh 	}
684aaebc40Srrh 	for (i = argcnt; i < 10; i++)
694aaebc40Srrh 		argstk[i] = "";
704aaebc40Srrh 	if (dbg) {
714aaebc40Srrh 		for (i = 0; i < argcnt; i++)
724aaebc40Srrh 			printf("arg %d = %s\n", i, argstk[i]);
734aaebc40Srrh 	}
744aaebc40Srrh 
754aaebc40Srrh 	/* push them back */
764aaebc40Srrh 	for (p = stp->s_val.p; *p; p++)
774aaebc40Srrh 		;		/* find the end */
784aaebc40Srrh 	for (--p; p >= stp->s_val.p; p--) {
794aaebc40Srrh 		if (*(p-1) == '$') {
804aaebc40Srrh 			if (isdigit(*p)) {
814aaebc40Srrh 				pbstr(argstk[*p - '0' - 1]);
824aaebc40Srrh 				p--;
834aaebc40Srrh 			}
844aaebc40Srrh 			else
854aaebc40Srrh 				unput(*p);
864aaebc40Srrh 		} else {
874aaebc40Srrh 			unput(*p);
884aaebc40Srrh 		}
894aaebc40Srrh 	}
904aaebc40Srrh }
914aaebc40Srrh 
getarg(p)924aaebc40Srrh getarg(p)	/* pick up single argument, store in p, return length */
934aaebc40Srrh 	char *p;
944aaebc40Srrh {
954aaebc40Srrh 	int n, c, npar;
964aaebc40Srrh 
974aaebc40Srrh 	n = npar = 0;
984aaebc40Srrh 	for ( ;; ) {
994aaebc40Srrh 		c = input();
1004aaebc40Srrh 		if (c == EOF)
1014aaebc40Srrh 			yyerror("end of file in getarg!\n");
1024aaebc40Srrh 		if (npar == 0 && (c == ',' || c == ')'))
1034aaebc40Srrh 			break;
1044aaebc40Srrh 		if (c == '"')	/* copy quoted stuff intact */
1054aaebc40Srrh 			do {
1064aaebc40Srrh 				*p++ = c;
1074aaebc40Srrh 				n++;
1084aaebc40Srrh 			} while ((c = input()) != '"' && c != EOF);
1094aaebc40Srrh 		else if (c == '(')
1104aaebc40Srrh 			npar++;
1114aaebc40Srrh 		else if (c == ')')
1124aaebc40Srrh 			npar--;
1134aaebc40Srrh 		n++;
1144aaebc40Srrh 		*p++ = c;
1154aaebc40Srrh 	}
1164aaebc40Srrh 	*p = 0;
1174aaebc40Srrh 	unput(c);
1184aaebc40Srrh 	return(n + 1);
1194aaebc40Srrh }
1204aaebc40Srrh 
121*7914cea4Srrh #define	PBSIZE	4000
1224aaebc40Srrh char	pbuf[PBSIZE];		/* pushback buffer */
1234aaebc40Srrh char	*pb	= pbuf-1;	/* next pushed back character */
1244aaebc40Srrh 
1254aaebc40Srrh char	ebuf[200];		/* collect input here for error reporting */
1264aaebc40Srrh char	*ep	= ebuf;
1274aaebc40Srrh 
input()1284aaebc40Srrh input()
1294aaebc40Srrh {
1304aaebc40Srrh 	register int c;
1314aaebc40Srrh 
1324aaebc40Srrh 	if (pb >= pbuf) {
1334aaebc40Srrh 		c = *pb--;
1344aaebc40Srrh 	} else {
1354aaebc40Srrh 		c = getc(yyin);
1364aaebc40Srrh 		if (c == '\n')
1374aaebc40Srrh 			lineno++;
1384aaebc40Srrh 		else if (c == EOF) {
1394aaebc40Srrh 			yyerror("end of file inside .PS/.PE");
1404aaebc40Srrh 			exit(1);
1414aaebc40Srrh 		}
1424aaebc40Srrh 	}
1434aaebc40Srrh 	if (ep >= ebuf + sizeof ebuf)
1444aaebc40Srrh 		ep = ebuf;
1454aaebc40Srrh 	return (*ep++ = c);
1464aaebc40Srrh }
1474aaebc40Srrh 
unput(c)1484aaebc40Srrh unput(c)
1494aaebc40Srrh {
1504aaebc40Srrh 	if (++pb >= pbuf + sizeof pbuf) {
1514aaebc40Srrh 		yyerror("pushback overflow\n");
1524aaebc40Srrh 		exit(1);
1534aaebc40Srrh 	}
1544aaebc40Srrh 	if (--ep < ebuf)
1554aaebc40Srrh 		ep = ebuf + sizeof(ebuf) - 1;
1564aaebc40Srrh 	return(*pb = c);
1574aaebc40Srrh }
1584aaebc40Srrh 
pbstr(s)1594aaebc40Srrh pbstr(s)
1604aaebc40Srrh 	char *s;
1614aaebc40Srrh {
1624aaebc40Srrh 	int n;
1634aaebc40Srrh 
1644aaebc40Srrh 	n = strlen(s);
1654aaebc40Srrh 	while (--n >= 0)
1664aaebc40Srrh 		unput(s[n]);
1674aaebc40Srrh }
1684aaebc40Srrh 
yyerror(s,s1,s2,s3,s4)1694aaebc40Srrh yyerror(s, s1, s2, s3, s4)
1704aaebc40Srrh 	char *s, *s1, *s2, *s3, *s4;
1714aaebc40Srrh {
1724aaebc40Srrh 	if (synerr)
1734aaebc40Srrh 		return;
1744aaebc40Srrh 	fprintf(stderr, "pic: ");
1754aaebc40Srrh 	fprintf(stderr, s, s1, s2, s3, s4);
1764aaebc40Srrh 	fprintf(stderr, " near line %d, file %s\n", lineno, filename);
1774aaebc40Srrh 	eprint();
1784aaebc40Srrh 	synerr = 1;
1794aaebc40Srrh }
1804aaebc40Srrh 
eprint()1814aaebc40Srrh eprint()	/* try to print context around error */
1824aaebc40Srrh {
1834aaebc40Srrh 	char *p, *q;
1844aaebc40Srrh 	int c;
1854aaebc40Srrh 
1864aaebc40Srrh 	p = ep - 1;
1874aaebc40Srrh 	if (p > ebuf && *p == '\n')
1884aaebc40Srrh 		p--;
1894aaebc40Srrh 	for ( ; p >= ebuf && *p != '\n'; p--)
1904aaebc40Srrh 		;
1914aaebc40Srrh 	while (*p == '\n')
1924aaebc40Srrh 		p++;
1934aaebc40Srrh 	fprintf(stderr, " context is\n\t");
1944aaebc40Srrh 	while (p < ep)
1954aaebc40Srrh 		putc(*p++, stderr);
1964aaebc40Srrh 	fprintf(stderr, " ^ ");
1974aaebc40Srrh 	while (pb >= pbuf)
1984aaebc40Srrh 		putc(*pb--, stderr);
1994aaebc40Srrh 	fgets(ebuf, sizeof ebuf, yyin);
2004aaebc40Srrh 	fprintf(stderr, "%s", ebuf);
2014aaebc40Srrh 	pbstr(".PE\n");	/* safety first */
2024aaebc40Srrh 	ep = ebuf;
2034aaebc40Srrh }
2044aaebc40Srrh 
yywrap()2054aaebc40Srrh yywrap() {;}
206