xref: /illumos-gate/usr/src/cmd/eqn/lex.c (revision b55148877d473978f0b46d593fd6213fa526fcc5)
1 /*
2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
7 /*	  All Rights Reserved  	*/
8 
9 /*
10  * Copyright (c) 1980 Regents of the University of California.
11  * All rights reserved. The Berkeley software License Agreement
12  * specifies the terms and conditions for redistribution.
13  */
14 
15 #pragma ident	"%Z%%M%	%I%	%E% SMI"
16 
17 #include "e.h"
18 #include "e.def"
19 #include <locale.h>
20 
21 #define	SSIZE	400
22 char	token[SSIZE];
23 int	sp;
24 #define	putbak(c)	*ip++ = c;
25 #define	PUSHBACK	300	/* maximum pushback characters */
26 char	ibuf[PUSHBACK+SSIZE];	/* pushback buffer for definitions, etc. */
27 char	*ip	= ibuf;
28 
29 void define(int);
30 void delim(void);
31 void getstr(char *, int);
32 void include(void);
33 int openinfile(void);
34 void pbstr(char *);
35 void space(void);
36 
37 int
38 gtc(void)
39 {
40 loop:
41 	if (ip > ibuf)
42 		return (*--ip);	/* already present */
43 	lastchar = getc(curfile);
44 	if (lastchar == '\n')
45 		linect++;
46 	if (lastchar != EOF)
47 		return (lastchar);
48 	if (++ifile > svargc) {
49 		return (EOF);
50 	}
51 	(void) fclose(curfile);
52 	linect = 1;
53 	if (openinfile() == 0)
54 		goto loop;
55 	return (EOF);
56 }
57 /*
58  *	open file indexed by ifile in svargv, return non zero if fail
59  */
60 int
61 openinfile(void)
62 {
63 	if (strcmp(svargv[ifile], "-") == 0) {
64 		curfile = stdin;
65 		return (0);
66 	} else if ((curfile = fopen(svargv[ifile], "r")) != NULL) {
67 		return (0);
68 	}
69 	error(FATAL, gettext("can't open file %s"), svargv[ifile]);
70 	return (1);
71 }
72 
73 void
74 pbstr(char *str)
75 {
76 	char *p;
77 
78 	p = str;
79 	while (*p++)
80 		;
81 	--p;
82 	if (ip >= &ibuf[PUSHBACK])
83 		error(FATAL, gettext("pushback overflow"));
84 	while (p > str)
85 		putbak(*--p);
86 }
87 
88 int
89 yylex(void)
90 {
91 	int c;
92 	tbl *tp, *lookup();
93 	extern tbl **keytbl, **deftbl;
94 
95 beg:
96 	while ((c = gtc()) == ' ' || c == '\n')
97 		;
98 	yylval = c;
99 	switch (c) {
100 
101 	case EOF:
102 		return (EOF);
103 	case '~':
104 		return (SPACE);
105 	case '^':
106 		return (THIN);
107 	case '\t':
108 		return (TAB);
109 	case '{':
110 		return ('{');
111 	case '}':
112 		return ('}');
113 	case '"':
114 		for (sp = 0; (c = gtc()) != '"' && c != '\n'; ) {
115 			if (c == '\\')
116 				if ((c = gtc()) != '"')
117 					token[sp++] = '\\';
118 			token[sp++] = c;
119 			if (sp >= SSIZE)
120 				error(FATAL, gettext(
121 				    "quoted string %.20s... too long"), token);
122 		}
123 		token[sp] = '\0';
124 		yylval = (int)&token[0];
125 		if (c == '\n')
126 			error(!FATAL, gettext("missing \" in %.20s"), token);
127 		return (QTEXT);
128 	}
129 	if (c == righteq)
130 		return (EOF);
131 
132 	putbak(c);
133 	getstr(token, SSIZE);
134 	if (dbg) printf(".\tlex token = |%s|\n", token);
135 	if ((tp = lookup(deftbl, token, NULL)) != NULL) {
136 		putbak(' ');
137 		pbstr(tp->defn);
138 		putbak(' ');
139 		if (dbg)
140 			printf(".\tfound %s|=%s|\n", token, tp->defn);
141 	} else if ((tp = lookup(keytbl, token, NULL)) == NULL) {
142 		if (dbg) printf(".\t%s is not a keyword\n", token);
143 		return (CONTIG);
144 	} else if (tp->defn == (char *)DEFINE ||
145 	    tp->defn == (char *)NDEFINE || tp->defn == (char *)TDEFINE)
146 		define((int)tp->defn);
147 	else if (tp->defn == (char *)DELIM)
148 		delim();
149 	else if (tp->defn == (char *)GSIZE)
150 		globsize();
151 	else if (tp->defn == (char *)GFONT)
152 		globfont();
153 	else if (tp->defn == (char *)INCLUDE)
154 		include();
155 	else if (tp->defn == (char *)SPACE)
156 		space();
157 	else {
158 		return ((int)tp->defn);
159 	}
160 	goto beg;
161 }
162 
163 void
164 getstr(char *s, int n)
165 {
166 	int c;
167 	char *p;
168 
169 	p = s;
170 	while ((c = gtc()) == ' ' || c == '\n')
171 		;
172 	if (c == EOF) {
173 		*s = 0;
174 		return;
175 	}
176 	while (c != ' ' && c != '\t' && c != '\n' && c != '{' && c != '}' &&
177 	    c != '"' && c != '~' && c != '^' && c != righteq) {
178 		if (c == '\\')
179 			if ((c = gtc()) != '"')
180 				*p++ = '\\';
181 		*p++ = c;
182 		if (--n <= 0)
183 			error(FATAL, gettext("token %.20s... too long"), s);
184 		c = gtc();
185 	}
186 	if (c == '{' || c == '}' || c == '"' || c == '~' || c == '^' ||
187 	    c == '\t' || c == righteq)
188 		putbak(c);
189 	*p = '\0';
190 	yylval = (int)s;
191 }
192 
193 int
194 cstr(char *s, int quote, int maxs)
195 {
196 	int del, c, i;
197 
198 	s[0] = 0;
199 	while ((del = gtc()) == ' ' || del == '\t')
200 		;
201 	if (quote) {
202 		for (i = 0; (c = gtc()) != del && c != EOF; ) {
203 			s[i++] = c;
204 			if (i >= maxs)
205 				return (1);	/* disaster */
206 		}
207 	} else {
208 		if (del == '\n')
209 			return (1);
210 		s[0] = del;
211 		for (i = 1; (c = gtc()) != ' ' && c != '\t' &&
212 		    c != '\n' && c != EOF; /* empty */) {
213 			s[i++] = c;
214 			if (i >= maxs)
215 				return (1);	/* disaster */
216 		}
217 	}
218 	s[i] = '\0';
219 	if (c == EOF)
220 		error(FATAL, gettext("Unexpected end of input at %.20s"), s);
221 	return (0);
222 }
223 
224 void
225 define(int type)
226 {
227 	char *strsave(), *p1, *p2;
228 	tbl *lookup();
229 	extern tbl **deftbl;
230 
231 	getstr(token, SSIZE);	/* get name */
232 	if (type != DEFINE) {
233 		(void) cstr(token, 1, SSIZE);	/* skip the definition too */
234 		return;
235 	}
236 	p1 = strsave(token);
237 	if (cstr(token, 1, SSIZE))
238 		error(FATAL, gettext(
239 		    "Unterminated definition at %.20s"), token);
240 	p2 = strsave(token);
241 	lookup(deftbl, p1, p2);
242 	if (dbg) printf(".\tname %s defined as %s\n", p1, p2);
243 }
244 
245 char    *spaceval   = NULL;
246 
247 void
248 space(void) /* collect line of form "space amt" to replace \x in output */
249 {
250 	char *strsave();
251 
252 	getstr(token, SSIZE);
253 	spaceval = strsave(token);
254 	if (dbg) printf(".\tsetting space to %s\n", token);
255 }
256 
257 
258 char *
259 strsave(char *s)
260 {
261 	char *malloc();
262 	char *q;
263 
264 	q = malloc(strlen(s)+1);
265 	if (q == NULL)
266 		error(FATAL, gettext("out of space in strsave on %s"), s);
267 	strcpy(q, s);
268 	return (q);
269 }
270 
271 void
272 include(void)
273 {
274 	error(!FATAL, gettext("Include not yet implemented"));
275 }
276 
277 void
278 delim(void)
279 {
280 	yyval = eqnreg = 0;
281 	if (cstr(token, 0, SSIZE))
282 		error(FATAL, gettext("Bizarre delimiters at %.20s"), token);
283 	lefteq = token[0];
284 	righteq = token[1];
285 	if (lefteq == 'o' && righteq == 'f')
286 		lefteq = righteq = '\0';
287 }
288