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