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