diff options
-rw-r--r-- | grammar/debian.conf | 2 | ||||
-rw-r--r-- | grammar/rscript.l | 98 | ||||
-rw-r--r-- | grammar/rscript.y | 1 | ||||
-rw-r--r-- | grammar/utils.c | 16 |
4 files changed, 106 insertions, 11 deletions
diff --git a/grammar/debian.conf b/grammar/debian.conf index e5e54fde..79c1f07d 100644 --- a/grammar/debian.conf +++ b/grammar/debian.conf @@ -43,7 +43,7 @@ $Umask 0022 # # Include all config files in /etc/rsyslog.d/ # -$IncludeConfig /etc/rsyslog.d/*.conf +#$IncludeConfig /etc/rsyslog.d/*.conf ############### diff --git a/grammar/rscript.l b/grammar/rscript.l index b7c3e521..7e7ab925 100644 --- a/grammar/rscript.l +++ b/grammar/rscript.l @@ -13,13 +13,17 @@ * Released under the GNU GPL v3. For details see LICENSE file. */ -%option noyywrap nodefault case-insensitive +%option noyywrap nodefault case-insensitive yylineno /*%option noyywrap nodefault case-insensitive */ %x INOBJ /* INOBJ is selected if we are inside an object (name/value pairs!) */ %x COMMENT /* COMMENT is "the usual trick" to handle C-style comments */ +%x INCL + /* INCL is in $IncludeConfig processing (skip to include file) */ +%x LINENO + /* LINENO: support for setting the linenumber */ %x EXPR /* EXPR is a bit ugly, but we need it to support pre v6-syntax. The problem * is that cfsysline statement start with $..., the same like variables in @@ -37,7 +41,16 @@ #include <libestr.h> #include "utils.h" #include "rscript.tab.h" -static int preCommentState; +static int preCommentState; /* save for lex state before a comment */ + +struct bufstack { + struct bufstack *prev; + YY_BUFFER_STATE bs; + int lineno; + char *fn; +} *currbs = NULL; + +char *currfn; /* name of currently processed file */ %} %% @@ -77,6 +90,23 @@ static int preCommentState; "{" { return '{'; } "}" { return '}'; } "ruleset" { printf("RULESET\n"); } + /* line number support because the "preprocessor" combines lines and so needs + * to tell us the real source line. + */ +"preprocfilelinenumber(" { BEGIN LINENO; } +<LINENO>[0-9]+ { printf("linno was %d, set to %d\n", yylineno, atoi(yytext) -1); + yylineno = atoi(yytext) - 1; } +<LINENO>")" { BEGIN INITIAL; } +<LINENO>.|\n + /* $IncludeConfig must be detected as part of CFSYSLINE, because this is + * always the longest match :-( + */ +<INCL>.|\n +<INCL>[^ \t\n]+ { if(cnfSetLexFile(yytext) != 0) + yyterminate(); + BEGIN INITIAL; + } + "global"[ \n\t]*"(" { yylval.objType = CNFOBJ_GLOBAL; BEGIN INOBJ; return BEGINOBJ; } @@ -107,28 +137,36 @@ static int preCommentState; <COMMENT>"*/" { BEGIN preCommentState; } <COMMENT>([^*]|\n)+|. -<INOBJ>#.*\n /* skip comments in input */ +<INOBJ>#.*$ /* skip comments in input */ <INOBJ>[ \n\t] <INOBJ>. { printf("INOBJ: invalid char '%s'\n", yytext); } /* CFSYSLINE is valid in all modes */ -\$[a-z]+.*$ { yylval.s = strdup(yytext); return CFSYSLINE; } +\$[a-z]+.*$ { /* see common on $IncludeConfig above */ + if(!strncasecmp(yytext, "$includeconfig ", 14)) { + yyless(14); + BEGIN INCL; + } else { + yylval.s = strdup(yytext); + return CFSYSLINE; + } + } \#.*\n /* skip comments in input */ [\n\t ] /* drop whitespace */ . { printf("invalid char: %s\n", yytext); } - /*<<EOF>> { printf("EOF reached\n"); }*/ +<<EOF>> { if(popfile() != 0) yyterminate(); } %% /* set a new buffers. Returns 0 on success, something else otherwise. */ int cnfSetLexFile(char *fname) { - es_str_t *str; - YY_BUFFER_STATE bp; + es_str_t *str = NULL; FILE *fp; int r = 0; + struct bufstack *bs; if(fname == NULL) { fp = stdin; @@ -141,9 +179,53 @@ int cnfSetLexFile(char *fname) readConfFile(fp, &str); if(fp != stdin) fclose(fp); - bp = yy_scan_buffer(es_getBufAddr(str), es_strlen(str)); + + /* maintain stack */ + if((bs = malloc(sizeof(struct bufstack))) == NULL) { + r = 1; + goto done; + } + + if(currbs != NULL) + currbs->lineno = yylineno; + bs->prev = currbs; + bs->fn = strdup(fname); + bs->bs = yy_scan_buffer(es_getBufAddr(str), es_strlen(str)); + currbs = bs; + currfn = bs->fn; yylineno = 1; done: + if(r != 0) { + if(str != NULL) + es_deleteStr(str); + } return r; } + + +/* returns 0 on success, something else otherwise */ +int +popfile(void) +{ + struct bufstack *bs = currbs; + + if(bs == NULL) + return 1; + + /* delte current entry */ + yy_delete_buffer(bs->bs); + free(bs->fn); + + /* switch back to previous */ + currbs = bs->prev; + free(bs); + + if(currbs == NULL) + return 1; /* all processed */ + + yy_switch_to_buffer(currbs->bs); + yylineno = currbs->lineno; + currfn = currbs->fn; + return 0; +} diff --git a/grammar/rscript.y b/grammar/rscript.y index 8bf0e55a..440a5525 100644 --- a/grammar/rscript.y +++ b/grammar/rscript.y @@ -4,6 +4,7 @@ #include <libestr.h> #include "utils.h" #define YYDEBUG 1 +extern int yylineno; %} %union { diff --git a/grammar/utils.c b/grammar/utils.c index d09a34a9..4e93c26c 100644 --- a/grammar/utils.c +++ b/grammar/utils.c @@ -11,13 +11,23 @@ void readConfFile(FILE *fp, es_str_t **str) { char ln[10240]; + char buf[512]; + int lenBuf; + int bWriteLineno = 0; int len, i; int start; /* start index of to be submitted text */ int bContLine = 0; + int lineno = 0; *str = es_newStr(4096); while(fgets(ln, sizeof(ln), fp) != NULL) { + ++lineno; + if(bWriteLineno) { + bWriteLineno = 0; + lenBuf = sprintf(buf, "PreprocFileLineNumber(%d)\n", lineno); + es_addBuf(str, buf, lenBuf); + } len = strlen(ln); /* if we are continuation line, we need to drop leading WS */ if(bContLine) { @@ -33,13 +43,15 @@ readConfFile(FILE *fp, es_str_t **str) --i; bContLine = 1; } else { + if(bContLine) /* write line number if we had cont line */ + bWriteLineno = 1; bContLine = 0; } /* add relevant data to buffer */ es_addBuf(str, ln+start, i+1 - start); - if(!bContLine) - es_addChar(str, '\n'); } + if(!bContLine) + es_addChar(str, '\n'); } /* indicate end of buffer to flex */ es_addChar(str, '\0'); |