1 /* Bison file for rsyslog config format v2 (RainerScript). 2 * Please note: this file introduces the new config format, but maintains 3 * backward compatibility. In order to do so, the grammar is not 100% clean, 4 * but IMHO still sufficiently easy both to understand for programmers 5 * maitaining the code as well as users writing the config file. Users are, 6 * of course, encouraged to use new constructs only. But it needs to be noted 7 * that some of the legacy constructs (specifically the in-front-of-action 8 * PRI filter) are very hard to beat in ease of use, at least for simpler 9 * cases. 10 * 11 * Copyright 2011-2020 Rainer Gerhards and Adiscon GmbH. 12 * 13 * This file is part of the rsyslog runtime library. 14 * 15 * Licensed under the Apache License, Version 2.0 (the "License"); 16 * you may not use this file except in compliance with the License. 17 * You may obtain a copy of the License at 18 * 19 * http://www.apache.org/licenses/LICENSE-2.0 20 * -or- 21 * see COPYING.ASL20 in the source distribution 22 * 23 * Unless required by applicable law or agreed to in writing, software 24 * distributed under the License is distributed on an "AS IS" BASIS, 25 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 26 * See the License for the specific language governing permissions and 27 * limitations under the License. 28 */ 29 %{ 30 #define IN_GRAMMAR_Y /* tell parserif.h not to redefine things! */ 31 32 #include "config.h" 33 #include <stdio.h> 34 #include <libestr.h> 35 #include "rainerscript.h" 36 #include "parserif.h" 37 #define YYDEBUG 1 38 extern int yylineno; 39 extern char *yytext; 40 41 /* keep compile rule clean of errors */ 42 extern int yylex(void); 43 extern int yyerror(const char*); 44 %} 45 46 %union { 47 char *s; 48 long long n; 49 es_str_t *estr; 50 enum cnfobjType objType; 51 struct cnfobj *obj; 52 struct cnfstmt *stmt; 53 struct nvlst *nvlst; 54 struct objlst *objlst; 55 struct cnfexpr *expr; 56 struct cnfarray *arr; 57 struct cnffunc *func; 58 struct cnffuncexists *exists; 59 struct cnffparamlst *fparams; 60 struct cnfitr *itr; 61 } 62 63 %token <estr> NAME 64 %token <estr> FUNC 65 %token <objType> BEGINOBJ 66 %token ENDOBJ 67 %token BEGIN_INCLUDE 68 %token BEGIN_ACTION 69 %token BEGIN_PROPERTY 70 %token BEGIN_CONSTANT 71 %token BEGIN_TPL 72 %token BEGIN_RULESET 73 %token STOP 74 %token SET 75 %token RESET 76 %token UNSET 77 %token CONTINUE 78 %token EXISTS 79 %token <cnfstmt> CALL 80 %token <cnfstmt> CALL_INDIRECT 81 %token <s> LEGACY_ACTION 82 %token <s> LEGACY_RULESET 83 %token <s> PRIFILT 84 %token <s> PROPFILT 85 %token <s> BSD_TAG_SELECTOR 86 %token <s> BSD_HOST_SELECTOR 87 %token <s> RELOAD_LOOKUP_TABLE_PROCEDURE 88 %token IF 89 %token THEN 90 %token ELSE 91 %token FOREACH 92 %token ITERATOR_ASSIGNMENT 93 %token DO 94 %token OR 95 %token AND 96 %token NOT 97 %token <s> VAR 98 %token <estr> STRING 99 %token <n> NUMBER 100 %token CMP_EQ 101 %token CMP_NE 102 %token CMP_LE 103 %token CMP_GE 104 %token CMP_LT 105 %token CMP_GT 106 %token CMP_CONTAINS 107 %token CMP_CONTAINSI 108 %token CMP_STARTSWITH 109 %token CMP_STARTSWITHI 110 111 %type <nvlst> nv nvlst value 112 %type <obj> obj property constant 113 %type <objlst> propconst 114 %type <expr> expr 115 %type <stmt> stmt s_act actlst block script 116 %type <itr> iterator_decl 117 %type <fparams> fparams 118 %type <arr> array arrayelt 119 120 %left AND OR 121 %left CMP_EQ CMP_NE CMP_LE CMP_GE CMP_LT CMP_GT CMP_CONTAINS CMP_CONTAINSI CMP_STARTSWITH CMP_STARTSWITHI 122 %left '+' '-' '&' 123 %left '*' '/' '%' 124 %nonassoc UMINUS NOT 125 126 %expect 1 /* dangling else */ 127 /* If more erors show up, Use "bison -v grammar.y" if more conflicts arise and 128 * check grammar.output for were exactly these conflicts exits. 129 */ 130 %% 131 /* note: we use left recursion below, because that saves stack space AND 132 * offers the right sequence so that we can submit the top-layer objects 133 * one by one. 134 */ 135 conf: /* empty (to end recursion) */ 136 | conf obj { cnfDoObj($2); } 137 | conf stmt { cnfDoScript($2); } 138 | conf LEGACY_RULESET { cnfDoCfsysline($2); } 139 | conf BSD_TAG_SELECTOR { cnfDoBSDTag($2); } 140 | conf BSD_HOST_SELECTOR { cnfDoBSDHost($2); } 141 include: BEGIN_INCLUDE nvlst ENDOBJ { includeProcessCnf($2); } 142 obj: BEGINOBJ nvlst ENDOBJ { $$ = cnfobjNew($1, $2); } 143 | BEGIN_TPL nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_TPL, $2); } 144 | BEGIN_TPL nvlst ENDOBJ '{' propconst '}' 145 { $$ = cnfobjNew(CNFOBJ_TPL, $2); 146 $$->subobjs = $5; 147 } 148 | BEGIN_RULESET nvlst ENDOBJ '{' script '}' 149 { $$ = cnfobjNew(CNFOBJ_RULESET, $2); 150 $$->script = $5; 151 } 152 | BEGIN_RULESET nvlst ENDOBJ '{' '}' 153 { $$ = cnfobjNew(CNFOBJ_RULESET, $2); 154 $$->script = NULL; 155 } 156 propconst: { $$ = NULL; } 157 | propconst property { $$ = objlstAdd($1, $2); } 158 | propconst constant { $$ = objlstAdd($1, $2); } 159 property: BEGIN_PROPERTY nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_PROPERTY, $2); } 160 constant: BEGIN_CONSTANT nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_CONSTANT, $2); } 161 nvlst: { $$ = NULL; } 162 | nvlst nv { $2->next = $1; $$ = $2; } 163 nv: NAME '=' value { $$ = nvlstSetName($3, $1); } 164 value: STRING { $$ = nvlstNewStr($1); } 165 | array { $$ = nvlstNewArray($1); } 166 script: stmt { $$ = $1; } 167 | script stmt { $$ = scriptAddStmt($1, $2); } 168 stmt: actlst { $$ = $1; } 169 | IF expr THEN block { $$ = cnfstmtNew(S_IF); 170 $$->d.s_if.expr = $2; 171 $$->d.s_if.t_then = $4; 172 $$->d.s_if.t_else = NULL; } 173 | IF expr THEN block ELSE block { $$ = cnfstmtNew(S_IF); 174 $$->d.s_if.expr = $2; 175 $$->d.s_if.t_then = $4; 176 $$->d.s_if.t_else = $6; } 177 | FOREACH iterator_decl DO block { $$ = cnfstmtNew(S_FOREACH); 178 $$->d.s_foreach.iter = $2; 179 $$->d.s_foreach.body = $4;} 180 | RESET VAR '=' expr ';' { $$ = cnfstmtNewSet($2, $4, 1); } 181 | SET VAR '=' expr ';' { $$ = cnfstmtNewSet($2, $4, 0); } 182 | UNSET VAR ';' { $$ = cnfstmtNewUnset($2); } 183 | PRIFILT block { $$ = cnfstmtNewPRIFILT($1, $2); } 184 | PROPFILT block { $$ = cnfstmtNewPROPFILT($1, $2); } 185 | RELOAD_LOOKUP_TABLE_PROCEDURE '(' fparams ')' { $$ = cnfstmtNewReloadLookupTable($3);} 186 | include { $$ = NULL; } 187 | BEGINOBJ { $$ = NULL; parser_errmsg("declarative object '%s' not permitted in action block [stmt]", yytext);} 188 block: stmt { $$ = $1; } 189 | '{' script '}' { $$ = $2; } 190 actlst: s_act { $$ = $1; } 191 | actlst '&' s_act { $$ = scriptAddStmt($1, $3); } 192 /* s_act are actions and action-like statements */ 193 s_act: BEGIN_ACTION nvlst ENDOBJ { $$ = cnfstmtNewAct($2); } 194 | LEGACY_ACTION { $$ = cnfstmtNewLegaAct($1); } 195 | STOP { $$ = cnfstmtNew(S_STOP); } 196 | CALL NAME { $$ = cnfstmtNewCall($2); } 197 | CALL_INDIRECT expr ';' { $$ = cnfstmtNew(S_CALL_INDIRECT); 198 $$->d.s_call_ind.expr = $2; 199 } 200 | CONTINUE { $$ = cnfstmtNewContinue(); } 201 expr: expr AND expr { $$ = cnfexprNew(AND, $1, $3); } 202 | expr OR expr { $$ = cnfexprNew(OR, $1, $3); } 203 | NOT expr { $$ = cnfexprNew(NOT, NULL, $2); } 204 | expr CMP_EQ expr { $$ = cnfexprNew(CMP_EQ, $1, $3); } 205 | expr CMP_NE expr { $$ = cnfexprNew(CMP_NE, $1, $3); } 206 | expr CMP_LE expr { $$ = cnfexprNew(CMP_LE, $1, $3); } 207 | expr CMP_GE expr { $$ = cnfexprNew(CMP_GE, $1, $3); } 208 | expr CMP_LT expr { $$ = cnfexprNew(CMP_LT, $1, $3); } 209 | expr CMP_GT expr { $$ = cnfexprNew(CMP_GT, $1, $3); } 210 | expr CMP_CONTAINS expr { $$ = cnfexprNew(CMP_CONTAINS, $1, $3); } 211 | expr CMP_CONTAINSI expr { $$ = cnfexprNew(CMP_CONTAINSI, $1, $3); } 212 | expr CMP_STARTSWITH expr { $$ = cnfexprNew(CMP_STARTSWITH, $1, $3); } 213 | expr CMP_STARTSWITHI expr { $$ = cnfexprNew(CMP_STARTSWITHI, $1, $3); } 214 | expr '&' expr { $$ = cnfexprNew('&', $1, $3); } 215 | expr '+' expr { $$ = cnfexprNew('+', $1, $3); } 216 | expr '-' expr { $$ = cnfexprNew('-', $1, $3); } 217 | expr '*' expr { $$ = cnfexprNew('*', $1, $3); } 218 | expr '/' expr { $$ = cnfexprNew('/', $1, $3); } 219 | expr '%' expr { $$ = cnfexprNew('%', $1, $3); } 220 | '(' expr ')' { $$ = $2; } 221 | '-' expr %prec UMINUS { $$ = cnfexprNew('M', NULL, $2); } 222 | EXISTS '(' VAR ')' { $$ = (struct cnfexpr*) cnffuncexistsNew($3); } 223 | FUNC '(' ')' { $$ = (struct cnfexpr*) cnffuncNew($1, NULL); } 224 | FUNC '(' fparams ')' { $$ = (struct cnfexpr*) cnffuncNew($1, $3); } 225 | NUMBER { $$ = (struct cnfexpr*) cnfnumvalNew($1); } 226 | STRING { $$ = (struct cnfexpr*) cnfstringvalNew($1); } 227 | VAR { $$ = (struct cnfexpr*) cnfvarNew($1); } 228 | array { $$ = (struct cnfexpr*) $1; } 229 fparams: expr { $$ = cnffparamlstNew($1, NULL); } 230 | expr ',' fparams { $$ = cnffparamlstNew($1, $3); } 231 array: '[' arrayelt ']' { $$ = $2; } 232 iterator_decl: '(' VAR ITERATOR_ASSIGNMENT expr ')' { $$ = cnfNewIterator($2, $4); } 233 arrayelt: STRING { $$ = cnfarrayNew($1); } 234 | arrayelt ',' STRING { $$ = cnfarrayAdd($1, $3); } 235 236 %% 237 /* 238 int yyerror(char *s) 239 { 240 printf("parse failure on or before line %d: %s\n", yylineno, s); 241 return 0; 242 } 243 */ 244