summaryrefslogtreecommitdiff
path: root/bin/chio/parse.y
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2007-10-13 16:35:23 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2007-10-13 16:35:23 +0000
commit3bc6f4c74e1cc60c05a1ab152805af447144952a (patch)
tree4a68ea922315ee6f6d1396cafc87ae97f4d0d06f /bin/chio/parse.y
parent3270c1ab5c203bfd16890aaf55afd4c31904e523 (diff)
in all these programs using the same pfctl-derived parse.y, re-unify the
yylex implementation and the code which interacts with yylex. this also brings the future potential for include support to all of the parsers. in the future please do not silly modifications to one of these files without checking if you are de-unifying the code. checked by developers in all these areas.
Diffstat (limited to 'bin/chio/parse.y')
-rw-r--r--bin/chio/parse.y148
1 files changed, 98 insertions, 50 deletions
diff --git a/bin/chio/parse.y b/bin/chio/parse.y
index a3000e8e39d..2f5dc35c3d3 100644
--- a/bin/chio/parse.y
+++ b/bin/chio/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.7 2007/10/11 14:39:15 deraadt Exp $ */
+/* $OpenBSD: parse.y,v 1.8 2007/10/13 16:35:16 deraadt Exp $ */
/*
* Copyright (c) 2006 Bob Beck <beck@openbsd.org>
@@ -33,6 +33,25 @@
#include <stdio.h>
#include <string.h>
+TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
+static struct file {
+ TAILQ_ENTRY(file) entry;
+ FILE *stream;
+ char *name;
+ int lineno;
+ int errors;
+} *file;
+struct file *pushfile(const char *);
+int popfile(void);
+int yyparse(void);
+int yylex(void);
+int yyerror(const char *, ...);
+int kw_cmp(const void *, const void *);
+int lookup(char *);
+int lgetc(int);
+int lungetc(int);
+int findeol(void);
+
struct changer {
TAILQ_ENTRY(changer) entry;
char *name;
@@ -42,20 +61,6 @@ struct changer {
TAILQ_HEAD(changers, changer) changers;
struct changer *curchanger;
-static FILE *fin = NULL;
-static int lineno = 1;
-static int errors = 0;
-const char *infile;
-
-int yyerror(const char *, ...);
-int yyparse(void);
-int kw_cmp(const void *, const void *);
-int lookup(char *);
-int lgetc(int);
-int lungetc(int);
-int findeol(void);
-int yylex(void);
-
typedef struct {
union {
int64_t number;
@@ -75,8 +80,8 @@ typedef struct {
grammar : /* empty */
| grammar '\n'
- | grammar changer '\n'
- | grammar error '\n' { errors++; }
+ | grammar main '\n'
+ | grammar error '\n' { file->errors++; }
;
optnl : '\n' optnl
@@ -86,7 +91,7 @@ optnl : '\n' optnl
nl : '\n' optnl
;
-changer : CHANGER STRING optnl '{' optnl {
+main : CHANGER STRING optnl '{' optnl {
curchanger = new_changer($2);
}
changeropts_l '}' {
@@ -132,9 +137,9 @@ yyerror(const char *fmt, ...)
va_list ap;
char *nfmt;
- errors = 1;
+ file->errors++;
va_start(ap, fmt);
- if (asprintf(&nfmt, "%s:%d: %s", infile, yylval.lineno, fmt) == -1)
+ if (asprintf(&nfmt, "%s:%d: %s", file->name, yylval.lineno, fmt) == -1)
err(1, "yyerror asprintf");
err(1, nfmt, ap);
va_end(ap);
@@ -175,10 +180,9 @@ char pushback_buffer[MAXPUSHBACK];
int pushback_index = 0;
int
-lgetc(int inquot)
+lgetc(int quotec)
{
- int c, next;
- FILE *f = fin;
+ int c, next;
if (parsebuf) {
/* Read character from the parsebuffer instead of input. */
@@ -194,29 +198,39 @@ lgetc(int inquot)
if (pushback_index)
return (pushback_buffer[--pushback_index]);
- if (inquot) {
- c = getc(f);
+ if (quotec) {
+ if ((c = getc(file->stream)) == EOF) {
+ yyerror("reached end of file while parsing quoted string");
+ if (popfile() == EOF)
+ return (EOF);
+ return (quotec);
+ }
return (c);
}
- while ((c = getc(f)) == '\\') {
- next = getc(f);
+ while ((c = getc(file->stream)) == '\\') {
+ next = getc(file->stream);
if (next != '\n') {
c = next;
break;
}
- yylval.lineno = lineno;
- lineno++;
+ yylval.lineno = file->lineno;
+ file->lineno++;
}
if (c == '\t' || c == ' ') {
/* Compress blanks to a single space. */
do {
- c = getc(f);
+ c = getc(file->stream);
} while (c == '\t' || c == ' ');
- ungetc(c, f);
+ ungetc(c, file->stream);
c = ' ';
}
+ while (c == EOF) {
+ if (popfile() == EOF)
+ return (EOF);
+ c = getc(file->stream);
+ }
return (c);
}
@@ -248,7 +262,7 @@ findeol(void)
while (1) {
c = lgetc(0);
if (c == '\n') {
- lineno++;
+ file->lineno++;
break;
}
if (c == EOF)
@@ -262,14 +276,14 @@ yylex(void)
{
char buf[8096];
char *p;
- int endc, next, c;
+ int quotec, next, c;
int token;
p = buf;
while ((c = lgetc(0)) == ' ')
; /* nothing */
- yylval.lineno = lineno;
+ yylval.lineno = file->lineno;
if (c == '#')
while ((c = lgetc(0)) != '\n' && c != EOF)
; /* nothing */
@@ -277,21 +291,21 @@ yylex(void)
switch (c) {
case '\'':
case '"':
- endc = c;
+ quotec = c;
while (1) {
- if ((c = lgetc(1)) == EOF)
+ if ((c = lgetc(quotec)) == EOF)
return (0);
if (c == '\n') {
- lineno++;
+ file->lineno++;
continue;
} else if (c == '\\') {
- if ((next = lgetc(1)) == EOF)
+ if ((next = lgetc(quotec)) == EOF)
return (0);
- if (next == endc)
+ if (next == quotec)
c = next;
else
lungetc(next);
- } else if (c == endc) {
+ } else if (c == quotec) {
*p = '\0';
break;
}
@@ -365,32 +379,66 @@ nodigits:
return (token);
}
if (c == '\n') {
- yylval.lineno = lineno;
- lineno++;
+ yylval.lineno = file->lineno;
+ file->lineno++;
}
if (c == EOF)
return (0);
return (c);
}
+struct file *
+pushfile(const char *name)
+{
+ struct file *nfile;
+
+ if ((nfile = calloc(1, sizeof(struct file))) == NULL ||
+ (nfile->name = strdup(name)) == NULL)
+ return (NULL);
+ if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
+ free(nfile->name);
+ free(nfile);
+ return (NULL);
+ }
+ nfile->lineno = 1;
+ TAILQ_INSERT_TAIL(&files, nfile, entry);
+ return (nfile);
+}
+
+int
+popfile(void)
+{
+ struct file *prev;
+
+ if ((prev = TAILQ_PREV(file, files, entry)) != NULL) {
+ prev->errors += file->errors;
+ TAILQ_REMOVE(&files, file, entry);
+ fclose(file->stream);
+ free(file->name);
+ free(file);
+ file = prev;
+ return (0);
+ }
+ return (EOF);
+}
+
char *
parse_tapedev(const char *filename, const char *changer, int drive)
{
struct changer *p;
- char *tapedev = NULL;
+ char *tapedev = NULL;
+ int errors = 0;
- lineno = 1;
- errors = 0;
TAILQ_INIT(&changers);
- if ((fin = fopen(filename, "r")) == NULL)
+ if ((file = pushfile(filename)) == NULL) {
+ warnx("cannot open the main config file!");
goto guess;
-
- infile = filename;
+ }
yyparse();
-
- fclose(fin);
+ errors = file->errors;
+ popfile();
TAILQ_FOREACH(p, &changers, entry) {
if (strcmp(basename(changer), p->name) == 0) {