xref: /plan9/sys/src/cmd/eqn/lex.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1*3e12c5d1SDavid du Colombier #include "e.h"
2*3e12c5d1SDavid du Colombier #include "y.tab.h"
3*3e12c5d1SDavid du Colombier #include <ctype.h>
4*3e12c5d1SDavid du Colombier 
5*3e12c5d1SDavid du Colombier #define	SSIZE	1000
6*3e12c5d1SDavid du Colombier char	token[SSIZE];
7*3e12c5d1SDavid du Colombier int	sp;
8*3e12c5d1SDavid du Colombier 
9*3e12c5d1SDavid du Colombier void	space(void);
10*3e12c5d1SDavid du Colombier void	dodef(tbl *);
11*3e12c5d1SDavid du Colombier void	define(int);
12*3e12c5d1SDavid du Colombier void	ifdef(void);
13*3e12c5d1SDavid du Colombier void	include(void);
14*3e12c5d1SDavid du Colombier void	delim(void);
15*3e12c5d1SDavid du Colombier 
yylex(void)16*3e12c5d1SDavid du Colombier yylex(void)
17*3e12c5d1SDavid du Colombier {
18*3e12c5d1SDavid du Colombier 	register int c;
19*3e12c5d1SDavid du Colombier 	tbl *tp;
20*3e12c5d1SDavid du Colombier 
21*3e12c5d1SDavid du Colombier   begin:
22*3e12c5d1SDavid du Colombier 	while ((c = input()) == ' ' || c == '\n' || c == '\t')
23*3e12c5d1SDavid du Colombier 		;
24*3e12c5d1SDavid du Colombier 	yylval = c;
25*3e12c5d1SDavid du Colombier 	switch (c) {
26*3e12c5d1SDavid du Colombier 	case EOF:
27*3e12c5d1SDavid du Colombier 		ERROR "unexpected end of input inside equation" WARNING;
28*3e12c5d1SDavid du Colombier 		return(EOF);
29*3e12c5d1SDavid du Colombier 	case '~':
30*3e12c5d1SDavid du Colombier 		return(SPACE);
31*3e12c5d1SDavid du Colombier 	case '^':
32*3e12c5d1SDavid du Colombier 		return(THIN);
33*3e12c5d1SDavid du Colombier 	/* case '\t':
34*3e12c5d1SDavid du Colombier 		return(TAB);
35*3e12c5d1SDavid du Colombier 	*/
36*3e12c5d1SDavid du Colombier 	case '{':
37*3e12c5d1SDavid du Colombier 		return('{');
38*3e12c5d1SDavid du Colombier 	case '}':
39*3e12c5d1SDavid du Colombier 		return('}');
40*3e12c5d1SDavid du Colombier 	case '"':
41*3e12c5d1SDavid du Colombier 		for (sp = 0; (c=input())!='"' && c != '\n'; ) {
42*3e12c5d1SDavid du Colombier 			if (c == '\\')
43*3e12c5d1SDavid du Colombier 				if ((c = input()) != '"')
44*3e12c5d1SDavid du Colombier 					token[sp++] = '\\';
45*3e12c5d1SDavid du Colombier 			token[sp++] = c;
46*3e12c5d1SDavid du Colombier 			if (sp >= SSIZE)
47*3e12c5d1SDavid du Colombier 				ERROR "quoted string %.20s... too long", token FATAL;
48*3e12c5d1SDavid du Colombier 		}
49*3e12c5d1SDavid du Colombier 		token[sp] = '\0';
50*3e12c5d1SDavid du Colombier 		yylval = (int) &token[0];
51*3e12c5d1SDavid du Colombier 		if (c == '\n')
52*3e12c5d1SDavid du Colombier 			ERROR "missing \" in %.20s", token WARNING;
53*3e12c5d1SDavid du Colombier 		return(QTEXT);
54*3e12c5d1SDavid du Colombier 	}
55*3e12c5d1SDavid du Colombier 	if (!display && c == righteq)
56*3e12c5d1SDavid du Colombier 		return(EOF);
57*3e12c5d1SDavid du Colombier 
58*3e12c5d1SDavid du Colombier 	unput(c);
59*3e12c5d1SDavid du Colombier 	getstr(token, SSIZE);
60*3e12c5d1SDavid du Colombier 	dprintf(".\tlex token = |%s|\n", token);
61*3e12c5d1SDavid du Colombier 	if ((tp = lookup(deftbl, token)) != NULL) {	/* defined term */
62*3e12c5d1SDavid du Colombier 		c = input();
63*3e12c5d1SDavid du Colombier 		unput(c);
64*3e12c5d1SDavid du Colombier 		if (c == '(')	/* macro with args */
65*3e12c5d1SDavid du Colombier 			dodef(tp);
66*3e12c5d1SDavid du Colombier 		else {		/* no args */
67*3e12c5d1SDavid du Colombier 			unput(' ');
68*3e12c5d1SDavid du Colombier 			pbstr(tp->cval);
69*3e12c5d1SDavid du Colombier 			dprintf(".\tfound %s|=%s|\n", token, tp->cval);
70*3e12c5d1SDavid du Colombier 		}
71*3e12c5d1SDavid du Colombier 		goto begin;
72*3e12c5d1SDavid du Colombier 	}
73*3e12c5d1SDavid du Colombier 
74*3e12c5d1SDavid du Colombier 	if ((tp = lookup(keytbl, token)) == NULL)	/* not a keyword */
75*3e12c5d1SDavid du Colombier 		return CONTIG;
76*3e12c5d1SDavid du Colombier 
77*3e12c5d1SDavid du Colombier 	switch (tp->ival) {		/* some kind of keyword */
78*3e12c5d1SDavid du Colombier 	case DEFINE: case TDEFINE: case NDEFINE:
79*3e12c5d1SDavid du Colombier 		define(tp->ival);
80*3e12c5d1SDavid du Colombier 		break;
81*3e12c5d1SDavid du Colombier 	case IFDEF:
82*3e12c5d1SDavid du Colombier 		ifdef();
83*3e12c5d1SDavid du Colombier 		break;
84*3e12c5d1SDavid du Colombier 	case DELIM:
85*3e12c5d1SDavid du Colombier 		delim();
86*3e12c5d1SDavid du Colombier 		break;
87*3e12c5d1SDavid du Colombier 	case GSIZE:
88*3e12c5d1SDavid du Colombier 		globsize();
89*3e12c5d1SDavid du Colombier 		break;
90*3e12c5d1SDavid du Colombier 	case GFONT:
91*3e12c5d1SDavid du Colombier 		globfont();
92*3e12c5d1SDavid du Colombier 		break;
93*3e12c5d1SDavid du Colombier 	case INCLUDE:
94*3e12c5d1SDavid du Colombier 		include();
95*3e12c5d1SDavid du Colombier 		break;
96*3e12c5d1SDavid du Colombier 	case SPACE:
97*3e12c5d1SDavid du Colombier 		space();
98*3e12c5d1SDavid du Colombier 		break;
99*3e12c5d1SDavid du Colombier 	case DOTEQ:
100*3e12c5d1SDavid du Colombier 			/* .EQ inside equation -- should warn if at bottom level */
101*3e12c5d1SDavid du Colombier 		break;
102*3e12c5d1SDavid du Colombier 	case DOTEN:
103*3e12c5d1SDavid du Colombier 		if (curfile == infile)
104*3e12c5d1SDavid du Colombier 			return EOF;
105*3e12c5d1SDavid du Colombier 		/* else ignore nested .EN */
106*3e12c5d1SDavid du Colombier 		break;
107*3e12c5d1SDavid du Colombier 	default:
108*3e12c5d1SDavid du Colombier 		return tp->ival;
109*3e12c5d1SDavid du Colombier 	}
110*3e12c5d1SDavid du Colombier 	goto begin;
111*3e12c5d1SDavid du Colombier }
112*3e12c5d1SDavid du Colombier 
getstr(char * s,int n)113*3e12c5d1SDavid du Colombier void getstr(char *s, int n)
114*3e12c5d1SDavid du Colombier {
115*3e12c5d1SDavid du Colombier 	register int c;
116*3e12c5d1SDavid du Colombier 	register char *p;
117*3e12c5d1SDavid du Colombier 
118*3e12c5d1SDavid du Colombier 	p = s;
119*3e12c5d1SDavid du Colombier 	while ((c = input()) == ' ' || c == '\n')
120*3e12c5d1SDavid du Colombier 		;
121*3e12c5d1SDavid du Colombier 	if (c == EOF) {
122*3e12c5d1SDavid du Colombier 		*s = 0;
123*3e12c5d1SDavid du Colombier 		return;
124*3e12c5d1SDavid du Colombier 	}
125*3e12c5d1SDavid du Colombier 	while (c != ' ' && c != '\t' && c != '\n' && c != '{' && c != '}'
126*3e12c5d1SDavid du Colombier 	    && c != '"' && c != '~' && c != '^') {
127*3e12c5d1SDavid du Colombier 		if (!display && c == righteq)
128*3e12c5d1SDavid du Colombier 			break;
129*3e12c5d1SDavid du Colombier 		if (c == '(' && p > s) {	/* might be defined(...) */
130*3e12c5d1SDavid du Colombier 			*p = '\0';
131*3e12c5d1SDavid du Colombier 			if (lookup(deftbl, s) != NULL)
132*3e12c5d1SDavid du Colombier 				break;
133*3e12c5d1SDavid du Colombier 		}
134*3e12c5d1SDavid du Colombier 		if (c == '\\')
135*3e12c5d1SDavid du Colombier 			if ((c = input()) != '"')
136*3e12c5d1SDavid du Colombier 				*p++ = '\\';
137*3e12c5d1SDavid du Colombier 		*p++ = c;
138*3e12c5d1SDavid du Colombier 		if (--n <= 0)
139*3e12c5d1SDavid du Colombier 			ERROR "token %.20s... too long", s FATAL;
140*3e12c5d1SDavid du Colombier 		c = input();
141*3e12c5d1SDavid du Colombier 	}
142*3e12c5d1SDavid du Colombier 	unput(c);
143*3e12c5d1SDavid du Colombier 	*p = '\0';
144*3e12c5d1SDavid du Colombier 	yylval = (int) s;
145*3e12c5d1SDavid du Colombier }
146*3e12c5d1SDavid du Colombier 
cstr(char * s,int quote,int maxs)147*3e12c5d1SDavid du Colombier cstr(char *s, int quote, int maxs)
148*3e12c5d1SDavid du Colombier {
149*3e12c5d1SDavid du Colombier 	int del, c, i;
150*3e12c5d1SDavid du Colombier 
151*3e12c5d1SDavid du Colombier 	s[0] = 0;
152*3e12c5d1SDavid du Colombier 	while ((del=input()) == ' ' || del == '\t')
153*3e12c5d1SDavid du Colombier 		;
154*3e12c5d1SDavid du Colombier 	if (quote)
155*3e12c5d1SDavid du Colombier 		for (i=0; (c=input()) != del && c != EOF;) {
156*3e12c5d1SDavid du Colombier 			s[i++] = c;
157*3e12c5d1SDavid du Colombier 			if (i >= maxs)
158*3e12c5d1SDavid du Colombier 				return(1);	/* disaster */
159*3e12c5d1SDavid du Colombier 		}
160*3e12c5d1SDavid du Colombier 	else {
161*3e12c5d1SDavid du Colombier 		if (del == '\n')
162*3e12c5d1SDavid du Colombier 			return(1);
163*3e12c5d1SDavid du Colombier 		s[0] = del;
164*3e12c5d1SDavid du Colombier 		for (i=1; (c=input())!=' ' && c!= '\t' && c!='\n' && c!=EOF;) {
165*3e12c5d1SDavid du Colombier 			s[i++] = c;
166*3e12c5d1SDavid du Colombier 			if (i >= maxs)
167*3e12c5d1SDavid du Colombier 				return(1);	/* disaster */
168*3e12c5d1SDavid du Colombier 		}
169*3e12c5d1SDavid du Colombier 	}
170*3e12c5d1SDavid du Colombier 	s[i] = '\0';
171*3e12c5d1SDavid du Colombier 	if (c == EOF)
172*3e12c5d1SDavid du Colombier 		ERROR "Unexpected end of input at %.20s", s FATAL;
173*3e12c5d1SDavid du Colombier 	return(0);
174*3e12c5d1SDavid du Colombier }
175*3e12c5d1SDavid du Colombier 
define(int type)176*3e12c5d1SDavid du Colombier void define(int type)
177*3e12c5d1SDavid du Colombier {
178*3e12c5d1SDavid du Colombier 	char *p1, *p2;
179*3e12c5d1SDavid du Colombier 	extern int ftune(char *, char *);
180*3e12c5d1SDavid du Colombier 
181*3e12c5d1SDavid du Colombier 	getstr(token, SSIZE);	/* get name */
182*3e12c5d1SDavid du Colombier 	if (type != DEFINE) {
183*3e12c5d1SDavid du Colombier 		cstr(token, 1, SSIZE);	/* skip the definition too */
184*3e12c5d1SDavid du Colombier 		return;
185*3e12c5d1SDavid du Colombier 	}
186*3e12c5d1SDavid du Colombier 	p1 = strsave(token);
187*3e12c5d1SDavid du Colombier 	if (cstr(token, 1, SSIZE))
188*3e12c5d1SDavid du Colombier 		ERROR "Unterminated definition at %.20s", token FATAL;
189*3e12c5d1SDavid du Colombier 	if (lookup(ftunetbl, p1) != NULL) {	/* double tuning param */
190*3e12c5d1SDavid du Colombier 		dprintf(".\ttune %s %s\n", p1, token);
191*3e12c5d1SDavid du Colombier 		ftune(p1, token);
192*3e12c5d1SDavid du Colombier 	} else {
193*3e12c5d1SDavid du Colombier 		p2 = strsave(token);
194*3e12c5d1SDavid du Colombier 		install(deftbl, p1, p2, 0);
195*3e12c5d1SDavid du Colombier 		dprintf(".\tname %s defined as %s\n", p1, p2);
196*3e12c5d1SDavid du Colombier 	}
197*3e12c5d1SDavid du Colombier }
198*3e12c5d1SDavid du Colombier 
ifdef(void)199*3e12c5d1SDavid du Colombier void ifdef(void)		/* do body if name is defined */
200*3e12c5d1SDavid du Colombier {
201*3e12c5d1SDavid du Colombier 	char name[100], *p;
202*3e12c5d1SDavid du Colombier 
203*3e12c5d1SDavid du Colombier 	getstr(name, sizeof(name));	/* get name */
204*3e12c5d1SDavid du Colombier 	cstr(token, 1, SSIZE);		/* and body */
205*3e12c5d1SDavid du Colombier 	if (lookup(deftbl, name) != NULL) {	/* found it */
206*3e12c5d1SDavid du Colombier 		p = strsave(token);
207*3e12c5d1SDavid du Colombier 		pushsrc(Free, p);
208*3e12c5d1SDavid du Colombier 		pushsrc(String, p);
209*3e12c5d1SDavid du Colombier 	}
210*3e12c5d1SDavid du Colombier }
211*3e12c5d1SDavid du Colombier 
212*3e12c5d1SDavid du Colombier char	*spaceval	= NULL;
213*3e12c5d1SDavid du Colombier 
space(void)214*3e12c5d1SDavid du Colombier void space(void)	/* collect line of form "space amt" to replace \x in output */
215*3e12c5d1SDavid du Colombier {
216*3e12c5d1SDavid du Colombier 	getstr(token, SSIZE);
217*3e12c5d1SDavid du Colombier 	spaceval = strsave(token);
218*3e12c5d1SDavid du Colombier 	dprintf(".\tsetting spaceval to %s\n", token);
219*3e12c5d1SDavid du Colombier }
220*3e12c5d1SDavid du Colombier 
strsave(char * s)221*3e12c5d1SDavid du Colombier char *strsave(char *s)
222*3e12c5d1SDavid du Colombier {
223*3e12c5d1SDavid du Colombier 	register char *q;
224*3e12c5d1SDavid du Colombier 
225*3e12c5d1SDavid du Colombier 	q = malloc(strlen(s)+1);
226*3e12c5d1SDavid du Colombier 	if (q == NULL)
227*3e12c5d1SDavid du Colombier 		ERROR "out of space in strsave on %s", s FATAL;
228*3e12c5d1SDavid du Colombier 	strcpy(q, s);
229*3e12c5d1SDavid du Colombier 	return(q);
230*3e12c5d1SDavid du Colombier }
231*3e12c5d1SDavid du Colombier 
include(void)232*3e12c5d1SDavid du Colombier void include(void)
233*3e12c5d1SDavid du Colombier {
234*3e12c5d1SDavid du Colombier 	char name[100];
235*3e12c5d1SDavid du Colombier 	FILE *fin;
236*3e12c5d1SDavid du Colombier 	int c;
237*3e12c5d1SDavid du Colombier 	extern int errno;
238*3e12c5d1SDavid du Colombier 
239*3e12c5d1SDavid du Colombier 	while ((c = input()) == ' ')
240*3e12c5d1SDavid du Colombier 		;
241*3e12c5d1SDavid du Colombier 	unput(c);
242*3e12c5d1SDavid du Colombier 	cstr(name, c == '"', sizeof(name));	/* gets it quoted or not */
243*3e12c5d1SDavid du Colombier 	if ((fin = fopen(name, "r")) == NULL)
244*3e12c5d1SDavid du Colombier 		ERROR "can't open file %s", name FATAL;
245*3e12c5d1SDavid du Colombier 	errno = 0;
246*3e12c5d1SDavid du Colombier 	curfile++;
247*3e12c5d1SDavid du Colombier 	curfile->fin = fin;
248*3e12c5d1SDavid du Colombier 	curfile->fname = strsave(name);
249*3e12c5d1SDavid du Colombier 	curfile->lineno = 0;
250*3e12c5d1SDavid du Colombier 	printf(".lf 1 %s\n", curfile->fname);
251*3e12c5d1SDavid du Colombier 	pushsrc(File, curfile->fname);
252*3e12c5d1SDavid du Colombier }
253*3e12c5d1SDavid du Colombier 
delim(void)254*3e12c5d1SDavid du Colombier void delim(void)
255*3e12c5d1SDavid du Colombier {
256*3e12c5d1SDavid du Colombier 	yyval = eqnreg = 0;
257*3e12c5d1SDavid du Colombier 	if (cstr(token, 0, SSIZE))
258*3e12c5d1SDavid du Colombier 		ERROR "Bizarre delimiters" FATAL;
259*3e12c5d1SDavid du Colombier 	lefteq = token[0];
260*3e12c5d1SDavid du Colombier 	righteq = token[1];
261*3e12c5d1SDavid du Colombier         if (!isprint(lefteq) || !isprint(righteq))
262*3e12c5d1SDavid du Colombier 		ERROR "Bizarre delimiters" FATAL;
263*3e12c5d1SDavid du Colombier 	if (lefteq == 'o' && righteq == 'f')
264*3e12c5d1SDavid du Colombier 		lefteq = righteq = '\0';
265*3e12c5d1SDavid du Colombier }
266