Applying otto@'s diff to relayd.
Fixes an off-by-one line count when using include statements.

Ok ?

Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/parse.y,v
retrieving revision 1.223
diff -u -p -r1.223 parse.y
--- parse.y     26 Apr 2018 14:12:19 -0000      1.223
+++ parse.y     2 Jun 2018 18:55:33 -0000
@@ -63,6 +63,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;
@@ -74,8 +78,9 @@ int            yylex(void);
 int             yyerror(const char *, ...);
 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);
@@ -2327,34 +2332,39 @@ lookup(char *s)
                return (STRING);
 }
 
-#define MAXPUSHBACK    128
 
-u_char *parsebuf;
-int     parseindex;
-u_char  pushback_buffer[MAXPUSHBACK];
-int     pushback_index = 0;
+#define START_EXPAND   1
+#define DONE_EXPAND    2
+
+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)
@@ -2364,8 +2374,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;
@@ -2374,28 +2384,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
@@ -2403,14 +2424,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;
@@ -2438,7 +2454,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);
@@ -2460,8 +2476,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;
        }
 
@@ -2616,7 +2637,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("%s: malloc", __func__);
+               fclose(nfile->stream);
+               free(nfile->name);
+               free(nfile);
+               return (NULL);
+       }
        TAILQ_INSERT_TAIL(&files, nfile, entry);
        return (nfile);
 }
@@ -2632,6 +2662,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);
@@ -2658,7 +2689,8 @@ parse_config(const char *filename, struc
 
        yyparse();
        errors = file->errors;
-       popfile();
+       while (popfile() != EOF)
+               ;
 
        endservent();
        endprotoent();
@@ -2706,7 +2738,8 @@ load_config(const char *filename, struct
 
        yyparse();
        errors = file->errors;
-       popfile();
+       while (popfile() != EOF)
+               ;
 
        endservent();
        endprotoent();

Reply via email to