diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-10-13 16:35:23 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-10-13 16:35:23 +0000 |
commit | 3bc6f4c74e1cc60c05a1ab152805af447144952a (patch) | |
tree | 4a68ea922315ee6f6d1396cafc87ae97f4d0d06f /bin/chio/parse.y | |
parent | 3270c1ab5c203bfd16890aaf55afd4c31904e523 (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.y | 148 |
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) { |