1 /*	$NetBSD: fsi_lex.l,v 1.3 2009/03/20 20:30:52 christos Exp $	*/
2 
3 %{
4 /*
5  * Copyright (c) 1997-2009 Erez Zadok
6  * Copyright (c) 1989 Jan-Simon Pendry
7  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
8  * Copyright (c) 1989 The Regents of the University of California.
9  * All rights reserved.
10  *
11  * This code is derived from software contributed to Berkeley by
12  * Jan-Simon Pendry at Imperial College, London.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. All advertising materials mentioning features or use of this software
23  *    must display the following acknowledgment:
24  *      This product includes software developed by the University of
25  *      California, Berkeley and its contributors.
26  * 4. Neither the name of the University nor the names of its contributors
27  *    may be used to endorse or promote products derived from this software
28  *    without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40  * SUCH DAMAGE.
41  *
42  *
43  * File: am-utils/fsinfo/fsi_lex.l
44  *
45  */
46 
47 /*
48  * Lexical analyzer for fsinfo.
49  * TODO: Needs rewriting.
50  */
51 
52 static int ayylineno;
53 
54 #ifdef FLEX_SCANNER
55 # define INIT_STATE {				\
56 		switch ((yy_start - 1) / 2) {	\
57 		case 0:				\
58 			BEGIN F;		\
59 			break;			\
60 		}				\
61 }
62 
63 #else /* not FLEX_SCANNER */
64 
65 /*
66  * Using old lex...
67  */
68 # define	INIT_STATE {			\
69 		switch (yybgin - yysvec - 1) {	\
70 		case 0:				\
71 			BEGIN F;		\
72 			break;			\
73 		}				\
74 }
75 
76 #endif /* end FLEX_SCANNER */
77 
78 #ifdef HAVE_CONFIG_H
79 # include <config.h>
80 #endif /* HAVE_CONFIG_H */
81 /*
82  * Some systems include a definition for the macro ECHO in <sys/ioctl.h>,
83  * and their (bad) version of lex defines it too at the very beginning of
84  * the generated lex.yy.c file (before it can be easily undefined),
85  * resulting in a conflict.  So undefine it here before needed.
86  * Luckily, it does not appear that this macro is actually used in the rest
87  * of the generated lex.yy.c file.
88  */
89 #ifdef ECHO
90 # undef ECHO
91 #endif /* ECHO */
92 #include <am_defs.h>
93 #include <fsi_data.h>
94 #include <fsinfo.h>
95 #include <fsi_gram.h>
96 /* and once again undefine this, just in case */
97 #ifdef ECHO
98 # undef ECHO
99 #endif /* ECHO */
100 
101 /*
102  * There are some things that need to be defined only if using GNU flex.
103  * These must not be defined if using standard lex
104  */
105 #ifdef FLEX_SCANNER
106 # ifndef ECHO
107 #  define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
108 # endif /* not ECHO */
109 #endif /* FLEX_SCANNER */
110 
111 /*
112  * some systems such as DU-4.x have a different GNU flex in /usr/bin
113  * which automatically generates yywrap macros and symbols.  So I must
114  * distinguish between them and when yywrap is actually needed.
115  */
116 #if !defined(yywrap) || defined(yylex)
117 int yywrap(void);
118 #endif /* not yywrap or yylex */
119 
120 int yyerror(const char *, ...);
121 
122 YYSTYPE yylval;
123 static char *fsi_filename;
124 static char *optr;
125 static char ostr[1024];
126 static int find_resword(char *);
127 static int quoted;
128 
129 struct r {
130   char *rw;
131   int tok;
132 } rr[] = {
133   { "->", tEQ },
134   { "arch", tARCH },
135   { "as", tAS },
136   { "automount", tAUTOMOUNT },
137   { "cluster", tCLUSTER },
138   { "config", tCONFIG },
139   { "direct", tDIRECT },
140   { "dumpset", tDUMPSET },
141   { "exportfs", tEXPORTFS },
142   { "freq", tFREQ },
143   { "from", tFROM },
144   { "fs", tFS },
145   { "fstype", tFSTYPE },
146   { "host", tHOST },
147   { "hwaddr", tHWADDR },
148   { "inaddr", tINADDR },
149   { "localhost", tLOCALHOST },
150   { "log", tLOG },
151   { "mount", tMOUNT },
152   { "netif", tNETIF },
153   { "netmask", tNETMASK },
154   { "nfsalias", tNFSEQ },
155   { "opts", tOPTS },
156   { "os", tOS },
157   { "passno", tPASSNO },
158   { "sel", tSEL },
159   { "volname", tVOLNAME },
160   { NULL, 0 },
161 };
162 #define	NRES_WORDS (sizeof(rr)/sizeof(rr[0])-1)
163 
164 %}
165 
166 /* This option causes Solaris lex to fail.  Use flex.  See BUGS file */
167 /* no need to use yyunput() */
168 %option nounput
169 
170 /* allocate more output slots so lex scanners don't run out of mem */
171 %o 1024
172 
173 %start F Q
174 
175 %%
176 		INIT_STATE;	/* witchcraft */
177 
178 <F>[^ \t\n"={}]+	{ return find_resword(yytext); } /* dummy " */
179 <F>[ \t]		;
180 <F>"\n"			{ ayylineno++; }
181 <F>[={}]		{ return *yytext; }
182 
183 <F>\"			{ BEGIN Q; optr = ostr; quoted = 1; }
184 <Q>\n			{ ayylineno++; yyerror("\" expected"); BEGIN F; }
185 <Q>\\b			{ *optr++ = '\b'; /* escape */ }
186 <Q>\\t			{ *optr++ = '\t'; /* escape */ }
187 <Q>\\\"			{ *optr++ = '\"'; /* escape */ }
188 <Q>\\\\			{ *optr++ = '\\'; /* escape */ }
189 <Q>\\\n			{ ayylineno++; /* continue */ }
190 <Q>\\r			{ *optr++ = '\r'; /* escape */ }
191 <Q>\\n			{ *optr++ = '\n'; /* escape */ }
192 <Q>\\f			{ *optr++ = '\f'; /* escape */ }
193 <Q>"\\ "		{ *optr++ = ' '; /* force space */ }
194 <Q>\\.			{ yyerror("Unknown \\ sequence"); }
195 <Q>([ \t]|"\\\n"){2,}	{ char *p = (char *) yytext-1; while ((p = strchr(p+1, '\n'))) ayylineno++; }
196 <Q>\"			{ BEGIN F; quoted = 0;
197 				*optr = '\0';
198 				yylval.s = strdup(ostr);
199 				return tSTR;
200 			}
201 <Q>.			{ *optr++ = *yytext; }
202 
203 %%
204 
205 
206 static int
207 find_resword(char *s)
208 {
209   int tok = 0;
210   int l = 0, m = NRES_WORDS/2, h = NRES_WORDS-1;
211   int rc = 0;
212 
213   m = NRES_WORDS/2;
214 
215 #define FSTRCMP(p, q) ((*(p) == *(q)) ? strcmp((p)+1, (q)+1) : *(p) - *(q))
216 
217   while ((l <= h) && (rc = FSTRCMP(s, rr[m].rw))) {
218     if (rc < 0)
219       h = m - 1;
220     else
221       l = m + 1;
222     m = (h + l) / 2;
223   }
224 
225   if (rc == 0)
226     tok = rr[m].tok;
227 
228   switch (tok) {
229   case tLOCALHOST:
230     s = "${host}";
231     /* fall through... */
232   case 0:
233     yylval.s = strdup(s);
234     tok = tSTR;
235     /* fall through... */
236   default:
237     return tok;
238   }
239 }
240 
241 
242 int
243 yyerror(const char *fmt, ...)
244 {
245   va_list ap;
246 
247   va_start(ap, fmt);
248   col_cleanup(0);
249   fprintf(stderr, "%s:%d: ", fsi_filename ? fsi_filename : "/dev/stdin", ayylineno);
250   vfprintf(stderr, fmt, ap);
251   fputc('\n', stderr);
252   parse_errors++;
253   va_end(ap);
254   return 0;
255 }
256 
257 
258 ioloc *
259 current_location(void)
260 {
261   ioloc *ip = CALLOC(struct ioloc);
262   ip->i_line = ayylineno;
263   ip->i_file = fsi_filename;
264   return ip;
265 }
266 
267 
268 /*
269  * some systems such as DU-4.x have a different GNU flex in /usr/bin
270  * which automatically generates yywrap macros and symbols.  So I must
271  * distinguish between them and when yywrap is actually needed.
272  */
273 #if !defined(yywrap) || defined(yylex)
274 int yywrap(void)
275 {
276   return 1;
277 }
278 #endif /* not yywrap or yylex */
279