xref: /original-bsd/usr.sbin/amd/fsinfo/fsi_lex.l (revision f737e041)
1 %{
2 /*
3  * Copyright (c) 1989 Jan-Simon Pendry
4  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
5  * Copyright (c) 1989, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Jan-Simon Pendry at Imperial College, London.
10  *
11  * %sccs.include.redist.c%
12  *
13  *	@(#)fsi_lex.l	8.2 (Berkeley) 02/17/94
14  *
15  * $Id: fsi_lex.l,v 5.2.2.1 1992/02/09 15:09:36 jsp beta $
16  *
17  */
18 
19 /*
20  * Lexical analyzer for fsinfo.
21  * TODO: Needs rewriting.
22  */
23 
24 static int xinput();
25 static void xunput();
26 
27 #ifdef FLEX_SCANNER
28 static int yylineno;
29 /* Flex support with help from Vern Paxson <vern@helios.ee.lbl.gov> */
30 #undef YY_INPUT
31 #define YY_INPUT(buf,result,max_size)		\
32 {						\
33 	int i;					\
34 	for (i = 0; i < max_size; i++) {	\
35 		int ch = xinput(i == 0);	\
36 		if (ch == 0)			\
37 			break;			\
38 		buf[i] = ch;			\
39 	}					\
40 	result = i;				\
41 }
42 
43 #define	INIT_STATE {				\
44 		switch ((yy_start - 1) / 2) {	\
45 		case 0:				\
46 			BEGIN F;		\
47 			break;			\
48 		}				\
49 }
50 
51 
52 #else
53 /*
54  * Using old lex...
55  */
56 #undef unput
57 #define unput(ch) xunput(ch)
58 #undef input
59 #define input() xinput(1)
60 
61 #define	INIT_STATE {				\
62 		switch (yybgin - yysvec - 1) {	\
63 		case 0:				\
64 			BEGIN F;		\
65 			break;			\
66 		}				\
67 }
68 
69 #endif /* FLEX_SCANNER */
70 
71 #include "../fsinfo/fsinfo.h"
72 #include "fsi_gram.h"
73 #include <ctype.h>
74 
75 static char *filename;
76 static char *optr;
77 static char ostr[1024];
78 static find_resword();
79 static unsigned char ibuf[64];
80 static unsigned char *iptr = ibuf;
81 static int quoted;
82 static int lastch, nextch = '\n';
83 YYSTYPE yylval;
84 
85 struct r {
86 	char *rw;
87 	int tok;
88 } rr[] = {
89 	{ "->", tEQ },
90 	{ "arch", tARCH },
91 	{ "as", tAS },
92 	{ "automount", tAUTOMOUNT },
93 	{ "cluster", tCLUSTER },
94 	{ "config", tCONFIG },
95 	{ "dumpset", tDUMPSET },
96 	{ "exportfs", tEXPORTFS },
97 	{ "freq", tFREQ },
98 	{ "from", tFROM },
99 	{ "fs", tFS },
100 	{ "fstype", tFSTYPE },
101 	{ "host", tHOST },
102 	{ "hwaddr", tHWADDR },
103 	{ "inaddr", tINADDR },
104 	{ "localhost", tLOCALHOST },
105 	{ "log", tLOG },
106 	{ "mount", tMOUNT },
107 	{ "netif", tNETIF },
108 	{ "netmask", tNETMASK },
109 	{ "opts", tOPTS },
110 	{ "os", tOS },
111 	{ "passno", tPASSNO },
112 	{ "sel", tSEL },
113 	{ "volname", tVOLNAME },
114 	{ 0, 0 },
115 };
116 #define	NRES_WORDS (sizeof(rr)/sizeof(rr[0])-1)
117 
118 %}
119 
120 %start F Q
121 
122 %%
123 		INIT_STATE; /* witchcraft */
124 
125 <F>[^ \t\n"={}]+	{ return find_resword(yytext); }
126 <F>[ \t]		;
127 <F>"\n"			{ yylineno++; }
128 <F>[={}]		{ return *yytext; }
129 
130 <F>\"			{ BEGIN Q; optr = ostr; quoted = 1; }
131 <Q>\n			{ yylineno++; yyerror("\" expected"); BEGIN F; }
132 <Q>\\b			{ *optr++ = '\b'; /* escape */ }
133 <Q>\\t			{ *optr++ = '\t'; /* escape */ }
134 <Q>\\\"			{ *optr++ = '\"'; /* escape */ }
135 <Q>\\\\			{ *optr++ = '\\'; /* escape */ }
136 <Q>\\\n			{ yylineno++; /* continue */ }
137 <Q>\\r			{ *optr++ = '\r'; /* escape */ }
138 <Q>\\n			{ *optr++ = '\n'; /* escape */ }
139 <Q>\\f			{ *optr++ = '\f'; /* escape */ }
140 <Q>"\\ "		{ *optr++ = ' '; /* force space */ }
141 <Q>\\.			{ yyerror("Unknown \\ sequence"); }
142 <Q>([ \t]|"\\\n"){2,}	{ char *p = yytext-1; while (p = strchr(p+1, '\n')) yylineno++; }
143 <Q>\"			{ BEGIN F; quoted = 0;
144 				*optr = '\0';
145 				yylval.s = strdup(ostr);
146 				return tSTR;
147 			}
148 <Q>.			{ *optr++ = *yytext; }
149 
150 %%
151 
152 static int find_resword(s)
153 char *s;
154 {
155 	int tok = 0;
156 
157 	int l = 0, m = NRES_WORDS/2, h = NRES_WORDS-1;
158 	int rc = 0;
159 
160 	m = NRES_WORDS/2;
161 
162 #define FSTRCMP(p, q) ((*(p) == *(q)) ? strcmp((p)+1, (q)+1) : *(p) - *(q))
163 
164 	while ((l <= h) && (rc = FSTRCMP(s, rr[m].rw))) {
165 		/*fprintf(stderr, "failed to cmp(%s, %s), %d, %d, %d\n", s, rr[m].rw, l, m, h);*/
166 		if (rc < 0)
167 			h = m - 1;
168 		else
169 			l = m + 1;
170 		m = (h + l) / 2;
171 	}
172 
173 	if (rc == 0)
174 		tok = rr[m].tok;
175 
176 	switch (tok) {
177 	case tLOCALHOST:
178 		s = "${host}";
179 		/* fall through... */
180 	case 0:
181 		yylval.s = strdup(s);
182 		tok = tSTR;
183 		/* fall through... */
184 	default:
185 		return tok;
186 	}
187 
188 }
189 
190 int yyerror(s, s1, s2, s3, s4)
191 char *s;
192 char *s1, *s2, *s3, *s4;
193 {
194 	col_cleanup(0);
195 	fprintf(stderr, "%s:%d: ", filename ? filename : "/dev/stdin", yylineno);
196 	fprintf(stderr, s, s1, s2, s3, s4);
197 	fputc('\n', stderr);
198 	parse_errors++;
199 }
200 
201 ioloc *current_location()
202 {
203 	ioloc *ip = ALLOC(ioloc);
204 	ip->i_line = yylineno;
205 	ip->i_file = filename;
206 	return ip;
207 }
208 
209 #ifdef FLEX_SCANNER
210 #undef yywrap
211 #endif
212 
213 int yywrap()
214 {
215 static int first = 1;
216 	if (first) {
217 		char prog[16*1024];
218 		strcpy(prog, "for file in ");
219 		while (*++g_argv) {
220 			if (access(*g_argv, 4) < 0) {
221 				error("\"%s\": Cannot open for reading", *g_argv);
222 				file_io_errors++;
223 			} else {
224 				strcat(prog, *g_argv);
225 				strcat(prog, " ");
226 			}
227 		}
228 		strcat(prog, "; do /lib/cpp ");
229 		strcat(prog, idvbuf);
230 		strcat(prog, " -DHOSTNAME=\'");
231 		strcat(prog, hostname);
232 		strcat(prog, "\' \"$file\"; done");
233 		yyin = popen(prog, "r");
234 		if (yyin) {
235 			/*if (filename) free(filename);*/
236 			filename = strdup("unknown");
237 			yylineno = 1;
238 			first = 0;
239 			return 0;
240 		} else {
241 			perror(prog);
242 		}
243 	}
244 
245 	if (!first && yyin && pclose(yyin) != 0)
246 		parse_errors++;
247 
248 	return 1;
249 }
250 
251 #define xgetc(fp) ((iptr > ibuf) ? (*--iptr) : (lastch = nextch, nextch = getc(fp), (nextch == EOF ? nextch = lastch, EOF : nextch)))
252 
253 static int xinput(need)
254 int need;
255 {
256 static int c_comment = 0;
257 	int ch, ch2;
258 
259 	do {
260 		ch = xgetc(yyin);
261 		/* fprintf(stderr, "ch = %c, %#x, %d\n", ch, ibuf,iptr-ibuf); */
262 		if (ch == EOF) return 0;
263 		if (quoted)
264 			return ch;
265 		if (c_comment) {
266 			ch2 = ch;
267 			do {
268 				if (ch2 == '\n') {
269 					nextch = '\n';
270 					return ch2;
271 				}
272 				/* C style comment */
273 				do {
274 					ch2 = getc(yyin);
275 					if (ch2 == '\n') {
276 						nextch = '\n';
277 						return ch2;
278 					}
279 				} while (ch2 != '*' && ch2 != EOF);
280 
281 				while (ch2 == '*')
282 					ch2 = getc(yyin);
283 			} while (ch2 != '/' && ch2 != EOF);
284 			c_comment = 0;
285 			if (ch2 == EOF)
286 				break;
287 			continue;
288 		}
289 
290 		if (ch == '#') {
291 			/*log("lastch = '%c' (%#x)", lastch, lastch);*/
292 			if (lastch == '\n') {
293 				char fname[MAXPATHLEN];
294 				char *fptr;
295 				if (!need) {
296 					xunput('#');
297 					nextch = '\n';
298 					return 0;
299 				}
300 				fname[0] = '\0';
301 				/* Skip past space */
302 				do {
303 					ch2 = getc(yyin);
304 				} while (ch2 != EOF && ch2 != '\n' && !isdigit(ch2));
305 				if (isdigit(ch2)) {
306 					/* Read in line number */
307 					fptr = fname;
308 					do {
309 						*fptr++ = ch2;
310 						ch2 = getc(yyin);
311 					} while (isdigit(ch2));
312 					*fptr = '\0';
313 					if (fptr != fname)
314 						yylineno = atoi(fname) - 1;
315 				}
316 				/* Skip past space */
317 				while (ch2 != EOF && ch2 != '\"' && ch2 != '\n')
318 					ch2 = getc(yyin);
319 				if (ch2 == '\"') {
320 					/* Read file name */
321 					fptr = fname;
322 					ch2 = getc(yyin);
323 					while (ch2 != '\"' && ch2 != EOF && ch2 != EOF) {
324 						*fptr++ = ch2;
325 						ch2 = getc(yyin);
326 					}
327 					*fptr = '\0';
328 					if (fname[0]) {
329 						log("Setting filename to \"%s\"", fname);
330 						/*if (filename) free(filename);*/
331 						filename = strdup(fname);
332 					}
333 				}
334 				while (ch2 != '\n' && ch2 != EOF)
335 					ch2 = getc(yyin);
336 			} else do {
337 				ch2 = getc(yyin);
338 			} while (ch2 != '\n' && ch2 != EOF);
339 			if (ch2 == '\n') {
340 				nextch = '\n';
341 				return ch2;
342 			}
343 		} else if (ch == '/') {
344 			ch2 = getc(yyin);
345 			if (ch2 == '/') {
346 				/* C++ style comment */
347 				do {
348 					ch2 = getc(yyin);
349 				} while (ch2 != '\n' && ch2 != EOF);
350 				if (ch2 == '\n') {
351 					nextch = '\n';
352 					return ch2;
353 				}
354 			} else if (ch2 == '*') {
355 				c_comment = 1;
356 				continue;
357 			} else {
358 				xunput(ch2);
359 				return ch;
360 			}
361 		} else {
362 			return ch;
363 		}
364 	} while (ch2 != EOF);
365 	error("End of file within comment");
366 	return 0;
367 }
368 
369 static void xunput(c)
370 int c;
371 {
372 	if (c && c != EOF) {
373 		if (iptr == ibuf + sizeof(ibuf) - 1)
374 		 	fatal("Out of space in lexical pushback");
375 		*iptr++ = c;
376 	}
377 }
378