From b30a9ec75bc3cb9246e1865458150d2256973b8a Mon Sep 17 00:00:00 2001 From: deraadt <> Date: Sat, 13 Oct 2007 16:35:21 +0000 Subject: [PATCH] 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. --- src/usr.sbin/ntpd/parse.y | 149 +++++++++++++++++++++++++------------- 1 file changed, 99 insertions(+), 50 deletions(-) diff --git a/src/usr.sbin/ntpd/parse.y b/src/usr.sbin/ntpd/parse.y index cbaaa3cd..f81341eb 100644 --- a/src/usr.sbin/ntpd/parse.y +++ b/src/usr.sbin/ntpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.36 2007/10/11 14:39:17 deraadt Exp $ */ +/* $OpenBSD: parse.y,v 1.37 2007/10/13 16:35:21 deraadt Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer @@ -36,20 +36,26 @@ #include "ntpd.h" -static struct ntpd_conf *conf; -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); +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 ntpd_conf *conf; struct opts { int weight; @@ -59,10 +65,10 @@ void opts_default(void); typedef struct { union { - int64_t number; + int64_t number; char *string; struct ntp_addr_wrap *addr; - struct opts opts; + struct opts opts; } v; int lineno; } YYSTYPE; @@ -83,11 +89,11 @@ typedef struct { grammar : /* empty */ | grammar '\n' - | grammar conf_main '\n' - | grammar error '\n' { errors++; } + | grammar main '\n' + | grammar error '\n' { file->errors++; } ; -conf_main : LISTEN ON address { +main : LISTEN ON address { struct listen_addr *la; struct ntp_addr *h, *next; @@ -279,9 +285,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) fatalx("yyerror asprintf"); vlog(LOG_CRIT, nfmt, ap); va_end(ap); @@ -327,10 +333,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. */ @@ -346,29 +351,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); } @@ -400,7 +415,7 @@ findeol(void) while (1) { c = lgetc(0); if (c == '\n') { - lineno++; + file->lineno++; break; } if (c == EOF) @@ -414,14 +429,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 */ @@ -429,21 +444,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; } @@ -517,33 +532,67 @@ 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); +} + int parse_config(const char *filename, struct ntpd_conf *xconf) { + int errors = 0; + conf = xconf; - lineno = 1; - errors = 0; TAILQ_INIT(&conf->listen_addrs); TAILQ_INIT(&conf->ntp_peers); TAILQ_INIT(&conf->ntp_conf_sensors); - if ((fin = fopen(filename, "r")) == NULL) { + if ((file = pushfile(filename)) == NULL) { log_warn("%s", filename); return (-1); } - infile = filename; yyparse(); - - fclose(fin); + errors = file->errors; + popfile(); return (errors ? -1 : 0); }