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