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