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