NetBSD/usr.sbin/amd/fsinfo/fsi_lex.l

404 lines
9.1 KiB
Plaintext

%{
/*
* Copyright (c) 1989 Jan-Simon Pendry
* Copyright (c) 1989 Imperial College of Science, Technology & Medicine
* Copyright (c) 1989 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jan-Simon Pendry at Imperial College, London.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* %W% (Berkeley) %G%
*
* $Id: fsi_lex.l,v 1.1 1993/11/27 21:20:11 mycroft Exp $
*
*/
/*
* Lexical analyzer for fsinfo.
* TODO: Needs rewriting.
*/
static int xinput();
static void xunput();
#ifdef FLEX_SCANNER
static int yylineno;
/* Flex support with help from Vern Paxson <vern@helios.ee.lbl.gov> */
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
{ \
int i; \
for (i = 0; i < max_size; i++) { \
int ch = xinput(i == 0); \
if (ch == 0) \
break; \
buf[i] = ch; \
} \
result = i; \
}
#define INIT_STATE { \
switch ((yy_start - 1) / 2) { \
case 0: \
BEGIN F; \
break; \
} \
}
#else
/*
* Using old lex...
*/
#undef unput
#define unput(ch) xunput(ch)
#undef input
#define input() xinput(1)
#define INIT_STATE { \
switch (yybgin - yysvec - 1) { \
case 0: \
BEGIN F; \
break; \
} \
}
#endif /* FLEX_SCANNER */
#include "../fsinfo/fsinfo.h"
#include "fsi_gram.h"
#include <ctype.h>
static char *filename;
static char *optr;
static char ostr[1024];
static find_resword();
static unsigned char ibuf[64];
static unsigned char *iptr = ibuf;
static int quoted;
static int lastch, nextch = '\n';
YYSTYPE yylval;
struct r {
char *rw;
int tok;
} rr[] = {
{ "->", tEQ },
{ "arch", tARCH },
{ "as", tAS },
{ "automount", tAUTOMOUNT },
{ "cluster", tCLUSTER },
{ "config", tCONFIG },
{ "dumpset", tDUMPSET },
{ "exportfs", tEXPORTFS },
{ "freq", tFREQ },
{ "from", tFROM },
{ "fs", tFS },
{ "fstype", tFSTYPE },
{ "host", tHOST },
{ "hwaddr", tHWADDR },
{ "inaddr", tINADDR },
{ "localhost", tLOCALHOST },
{ "log", tLOG },
{ "mount", tMOUNT },
{ "netif", tNETIF },
{ "netmask", tNETMASK },
{ "opts", tOPTS },
{ "os", tOS },
{ "passno", tPASSNO },
{ "sel", tSEL },
{ "volname", tVOLNAME },
{ 0, 0 },
};
#define NRES_WORDS (sizeof(rr)/sizeof(rr[0])-1)
%}
%start F Q
%%
INIT_STATE; /* witchcraft */
<F>[^ \t\n"={}]+ { return find_resword(yytext); }
<F>[ \t] ;
<F>"\n" { yylineno++; }
<F>[={}] { return *yytext; }
<F>\" { BEGIN Q; optr = ostr; quoted = 1; }
<Q>\n { yylineno++; yyerror("\" expected"); BEGIN F; }
<Q>\\b { *optr++ = '\b'; /* escape */ }
<Q>\\t { *optr++ = '\t'; /* escape */ }
<Q>\\\" { *optr++ = '\"'; /* escape */ }
<Q>\\\\ { *optr++ = '\\'; /* escape */ }
<Q>\\\n { yylineno++; /* continue */ }
<Q>\\r { *optr++ = '\r'; /* escape */ }
<Q>\\n { *optr++ = '\n'; /* escape */ }
<Q>\\f { *optr++ = '\f'; /* escape */ }
<Q>\\. { yyerror("Unknown \\ sequence"); }
<Q>([ \t]|"\\\n"){2,} { char *p = yytext-1; while (p = strchr(p+1, '\n')) yylineno++; }
<Q>"\\ " { *optr++ = ' '; /* force space */ }
<Q>\" { BEGIN F; quoted = 0;
*optr = '\0';
yylval.s = strdup(ostr);
return tSTR;
}
<Q>. { *optr++ = *yytext; }
%%
static int find_resword(s)
char *s;
{
int tok = 0;
int l = 0, m = NRES_WORDS/2, h = NRES_WORDS-1;
int rc = 0;
m = NRES_WORDS/2;
#define FSTRCMP(p, q) ((*(p) == *(q)) ? strcmp((p)+1, (q)+1) : *(p) - *(q))
while ((l <= h) && (rc = FSTRCMP(s, rr[m].rw))) {
/*fprintf(stderr, "failed to cmp(%s, %s), %d, %d, %d\n", s, rr[m].rw, l, m, h);*/
if (rc < 0)
h = m - 1;
else
l = m + 1;
m = (h + l) / 2;
}
if (rc == 0)
tok = rr[m].tok;
switch (tok) {
case tLOCALHOST:
s = "${host}";
/* fall through... */
case 0:
yylval.s = strdup(s);
tok = tSTR;
/* fall through... */
default:
return tok;
}
}
int yyerror(s, s1, s2, s3, s4)
char *s;
char *s1, *s2, *s3, *s4;
{
col_cleanup(0);
fprintf(stderr, "%s:%d: ", filename ? filename : "/dev/stdin", yylineno);
fprintf(stderr, s, s1, s2, s3, s4);
fputc('\n', stderr);
parse_errors++;
}
ioloc *current_location()
{
ioloc *ip = ALLOC(ioloc);
ip->i_line = yylineno;
ip->i_file = filename;
return ip;
}
#ifdef FLEX_SCANNER
#undef yywrap
#endif
int yywrap()
{
static int first = 1;
if (first) {
char prog[16*1024];
strcpy(prog, "for file in ");
while (*++g_argv) {
if (access(*g_argv, 4) < 0) {
error("\"%s\": Cannot open for reading", *g_argv);
file_io_errors++;
} else {
strcat(prog, *g_argv);
strcat(prog, " ");
}
}
strcat(prog, "; do /lib/cpp ");
strcat(prog, idvbuf);
strcat(prog, " -DHOSTNAME=\'");
strcat(prog, hostname);
strcat(prog, "\' \"$file\"; done");
yyin = popen(prog, "r");
if (yyin) {
/*if (filename) free(filename);*/
filename = strdup("unknown");
yylineno = 1;
first = 0;
return 0;
} else {
perror(prog);
}
}
if (!first && yyin && pclose(yyin) != 0)
parse_errors++;
return 1;
}
#define xgetc(fp) ((iptr > ibuf) ? (*--iptr) : (lastch = nextch, nextch = getc(fp), (nextch == EOF ? nextch = lastch, EOF : nextch)))
static int xinput(need)
int need;
{
static int c_comment = 0;
int ch, ch2;
do {
ch = xgetc(yyin);
/* fprintf(stderr, "ch = %c, %#x, %d\n", ch, ibuf,iptr-ibuf); */
if (ch == EOF) return 0;
if (quoted)
return ch;
if (c_comment) {
ch2 = ch;
do {
if (ch2 == '\n') {
nextch = '\n';
return ch2;
}
/* C style comment */
do {
ch2 = getc(yyin);
if (ch2 == '\n') {
nextch = '\n';
return ch2;
}
} while (ch2 != '*' && ch2 != EOF);
while (ch2 == '*')
ch2 = getc(yyin);
} while (ch2 != '/' && ch2 != EOF);
c_comment = 0;
if (ch2 == EOF)
break;
continue;
}
if (ch == '#') {
/*log("lastch = '%c' (%#x)", lastch, lastch);*/
if (lastch == '\n') {
char fname[MAXPATHLEN];
char *fptr;
if (!need) {
xunput('#');
nextch = '\n';
return 0;
}
fname[0] = '\0';
/* Skip past space */
do {
ch2 = getc(yyin);
} while (ch2 != EOF && ch2 != '\n' && !isdigit(ch2));
if (isdigit(ch2)) {
/* Read in line number */
fptr = fname;
do {
*fptr++ = ch2;
ch2 = getc(yyin);
} while (isdigit(ch2));
*fptr = '\0';
if (fptr != fname)
yylineno = atoi(fname) - 1;
}
/* Skip past space */
while (ch2 != EOF && ch2 != '\"' && ch2 != '\n')
ch2 = getc(yyin);
if (ch2 == '\"') {
/* Read file name */
fptr = fname;
ch2 = getc(yyin);
while (ch2 != '\"' && ch2 != EOF && ch2 != EOF) {
*fptr++ = ch2;
ch2 = getc(yyin);
}
*fptr = '\0';
if (fname[0]) {
log("Setting filename to \"%s\"", fname);
/*if (filename) free(filename);*/
filename = strdup(fname);
}
}
while (ch2 != '\n' && ch2 != EOF)
ch2 = getc(yyin);
} else do {
ch2 = getc(yyin);
} while (ch2 != '\n' && ch2 != EOF);
if (ch2 == '\n') {
nextch = '\n';
return ch2;
}
} else if (ch == '/') {
ch2 = getc(yyin);
if (ch2 == '/') {
/* C++ style comment */
do {
ch2 = getc(yyin);
} while (ch2 != '\n' && ch2 != EOF);
if (ch2 == '\n') {
nextch = '\n';
return ch2;
}
} else if (ch2 == '*') {
c_comment = 1;
continue;
} else {
xunput(ch2);
return ch;
}
} else {
return ch;
}
} while (ch2 != EOF);
error("End of file within comment");
return 0;
}
static void xunput(c)
int c;
{
if (c && c != EOF) {
if (iptr == ibuf + sizeof(ibuf) - 1)
fatal("Out of space in lexical pushback");
*iptr++ = c;
}
}