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
22char	token[SSIZE];
23int	sp;
24#define	putbak(c)	*ip++ = c;
25#define	PUSHBACK	300	/* maximum pushback characters */
26char	ibuf[PUSHBACK+SSIZE];	/* pushback buffer for definitions, etc. */
27char	*ip	= ibuf;
28
29extern tbl *keytbl[];
30extern tbl *deftbl[];
31
32void define(int);
33void delim(void);
34void getstr(char *, int);
35void include(void);
36int openinfile(void);
37void pbstr(char *);
38void space(void);
39
40int
41gtc(void)
42{
43loop:
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 */
63int
64openinfile(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
76void
77pbstr(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
91int
92yylex(void)
93{
94	int c;
95	tbl *tp, *lookup();
96
97beg:
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
165void
166getstr(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
195int
196cstr(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
226void
227define(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
246char    *spaceval   = NULL;
247
248void
249space(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
259char *
260strsave(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
272void
273include(void)
274{
275	error(!FATAL, gettext("Include not yet implemented"));
276}
277
278void
279delim(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