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