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 - 1.87
> +++ parse.y 2 Jun 2018 20:17:10 -
> @@ -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_charpushback_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);
> -