On Sat, Jun 02, 2018 at 10:33:11PM +0200, Denis Fondras wrote: > Applying otto@'s diff to ospfd. > Fixes an off-by-one line count when using include statements. > > Ok ?
I applied your diff and verified that the line number for errors in included files is now correct. ok remi@ > > Index: parse.y > =================================================================== > RCS file: /cvs/src/usr.sbin/ospfd/parse.y,v > retrieving revision 1.87 > diff -u -p -r1.87 parse.y > --- parse.y 26 Apr 2018 14:12:19 -0000 1.87 > +++ parse.y 2 Jun 2018 20:17:10 -0000 > @@ -48,6 +48,10 @@ static struct file { > TAILQ_ENTRY(file) entry; > FILE *stream; > char *name; > + size_t ungetpos; > + size_t ungetsize; > + u_char *ungetbuf; > + int eof_reached; > int lineno; > int errors; > } *file, *topfile; > @@ -61,8 +65,9 @@ int yyerror(const char *, ...) > __attribute__((__nonnull__ (1))); > int kw_cmp(const void *, const void *); > int lookup(char *); > +int igetc(void); > int lgetc(int); > -int lungetc(int); > +void lungetc(int); > int findeol(void); > > TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); > @@ -154,7 +159,8 @@ grammar : /* empty */ > include : INCLUDE STRING { > struct file *nfile; > > - if ((nfile = pushfile($2, 1)) == NULL) { > + if ((nfile = pushfile($2, > + !(conf->opts & OSPFD_OPT_NOACTION))) == NULL) { > yyerror("failed to include file %s", $2); > free($2); > YYERROR; > @@ -836,34 +842,39 @@ lookup(char *s) > return (STRING); > } > > -#define MAXPUSHBACK 128 > +#define START_EXPAND 1 > +#define DONE_EXPAND 2 > > -u_char *parsebuf; > -int parseindex; > -u_char pushback_buffer[MAXPUSHBACK]; > -int pushback_index = 0; > +static int expanding; > > int > -lgetc(int quotec) > +igetc(void) > { > - int c, next; > + int c; > > - if (parsebuf) { > - /* Read character from the parsebuffer instead of input. */ > - if (parseindex >= 0) { > - c = parsebuf[parseindex++]; > - if (c != '\0') > - return (c); > - parsebuf = NULL; > - } else > - parseindex++; > + while (1) { > + if (file->ungetpos > 0) > + c = file->ungetbuf[--file->ungetpos]; > + else > + c = getc(file->stream); > + > + if (c == START_EXPAND) > + expanding = 1; > + else if (c == DONE_EXPAND) > + expanding = 0; > + else > + break; > } > + return (c); > +} > > - if (pushback_index) > - return (pushback_buffer[--pushback_index]); > +int > +lgetc(int quotec) > +{ > + int c, next; > > if (quotec) { > - if ((c = getc(file->stream)) == EOF) { > + if ((c = igetc()) == EOF) { > yyerror("reached end of file while parsing " > "quoted string"); > if (file == topfile || popfile() == EOF) > @@ -873,8 +884,8 @@ lgetc(int quotec) > return (c); > } > > - while ((c = getc(file->stream)) == '\\') { > - next = getc(file->stream); > + while ((c = igetc()) == '\\') { > + next = igetc(); > if (next != '\n') { > c = next; > break; > @@ -883,28 +894,39 @@ lgetc(int quotec) > file->lineno++; > } > > - while (c == EOF) { > - if (file == topfile || popfile() == EOF) > - return (EOF); > - c = getc(file->stream); > + if (c == EOF) { > + /* > + * Fake EOL when hit EOF for the first time. This gets line > + * count right if last line in included file is syntactically > + * invalid and has no newline. > + */ > + if (file->eof_reached == 0) { > + file->eof_reached = 1; > + return ('\n'); > + } > + while (c == EOF) { > + if (file == topfile || popfile() == EOF) > + return (EOF); > + c = igetc(); > + } > } > return (c); > } > > -int > +void > lungetc(int c) > { > if (c == EOF) > - return (EOF); > - if (parsebuf) { > - parseindex--; > - if (parseindex >= 0) > - return (c); > + return; > + > + if (file->ungetpos >= file->ungetsize) { > + void *p = reallocarray(file->ungetbuf, file->ungetsize, 2); > + if (p == NULL) > + err(1, "lungetc"); > + file->ungetbuf = p; > + file->ungetsize *= 2; > } > - if (pushback_index < MAXPUSHBACK-1) > - return (pushback_buffer[pushback_index++] = c); > - else > - return (EOF); > + file->ungetbuf[file->ungetpos++] = c; > } > > int > @@ -912,14 +934,9 @@ findeol(void) > { > int c; > > - parsebuf = NULL; > - > /* skip to either EOF or the first real EOL */ > while (1) { > - if (pushback_index) > - c = pushback_buffer[--pushback_index]; > - else > - c = lgetc(0); > + c = lgetc(0); > if (c == '\n') { > file->lineno++; > break; > @@ -947,7 +964,7 @@ top: > if (c == '#') > while ((c = lgetc(0)) != '\n' && c != EOF) > ; /* nothing */ > - if (c == '$' && parsebuf == NULL) { > + if (c == '$' && !expanding) { > while (1) { > if ((c = lgetc(0)) == EOF) > return (0); > @@ -969,8 +986,13 @@ top: > yyerror("macro '%s' not defined", buf); > return (findeol()); > } > - parsebuf = val; > - parseindex = 0; > + p = val + strlen(val) - 1; > + lungetc(DONE_EXPAND); > + while (p >= val) { > + lungetc(*p); > + p--; > + } > + lungetc(START_EXPAND); > goto top; > } > > @@ -1125,7 +1147,16 @@ pushfile(const char *name, int secret) > free(nfile); > return (NULL); > } > - nfile->lineno = 1; > + nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0; > + nfile->ungetsize = 16; > + nfile->ungetbuf = malloc(nfile->ungetsize); > + if (nfile->ungetbuf == NULL) { > + log_warn("malloc"); > + fclose(nfile->stream); > + free(nfile->name); > + free(nfile); > + return (NULL); > + } > TAILQ_INSERT_TAIL(&files, nfile, entry); > return (nfile); > } > @@ -1141,6 +1172,7 @@ popfile(void) > TAILQ_REMOVE(&files, file, entry); > fclose(file->stream); > free(file->name); > + free(file->ungetbuf); > free(file); > file = prev; > return (file ? 0 : EOF);