On Sat, Jun 02, 2018 at 10:33:07PM +0200, Denis Fondras wrote:
> Applying otto@'s diff to ospf6d.
> 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/ospf6d/parse.y,v
> retrieving revision 1.31
> diff -u -p -r1.31 parse.y
> --- parse.y   26 Apr 2018 14:12:19 -0000      1.31
> +++ parse.y   2 Jun 2018 20:18:24 -0000
> @@ -50,6 +50,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;
> @@ -63,8 +67,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);
> @@ -146,7 +151,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;
> @@ -591,34 +597,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)
> @@ -628,8 +639,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;
> @@ -638,28 +649,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
> @@ -667,14 +689,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;
> @@ -702,7 +719,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);
> @@ -724,8 +741,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;
>       }
>  
> @@ -880,7 +902,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);
>  }
> @@ -896,6 +927,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);

Reply via email to