summaryrefslogtreecommitdiffstats
path: root/grammar
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2012-09-28 14:45:34 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2012-09-28 14:45:34 +0200
commit04c0124eb7dee70be4abeeba5e10d363154c8b40 (patch)
treecf2939f86281d3bbfa86716ba85d70eada1da5fd /grammar
parent38cdf1abaddea47aa5e9d11d97fade6a2455b632 (diff)
downloadrsyslog-04c0124eb7dee70be4abeeba5e10d363154c8b40.tar.gz
rsyslog-04c0124eb7dee70be4abeeba5e10d363154c8b40.tar.xz
rsyslog-04c0124eb7dee70be4abeeba5e10d363154c8b40.zip
rainerscript: add basic plumbing for arrays
can be used in expressions, but always evaluate to the first element, only
Diffstat (limited to 'grammar')
-rw-r--r--grammar/grammar.y12
-rw-r--r--grammar/lexer.l13
-rw-r--r--grammar/rainerscript.c65
-rw-r--r--grammar/rainerscript.h9
4 files changed, 94 insertions, 5 deletions
diff --git a/grammar/grammar.y b/grammar/grammar.y
index fcb9119b..70f98c02 100644
--- a/grammar/grammar.y
+++ b/grammar/grammar.y
@@ -51,12 +51,12 @@ extern int yyerror(char*);
struct nvlst *nvlst;
struct objlst *objlst;
struct cnfexpr *expr;
+ struct cnfarray *arr;
struct cnffunc *func;
struct cnffparamlst *fparams;
}
%token <estr> NAME
-%token <estr> VALUE
%token <estr> FUNC
%token <objType> BEGINOBJ
%token ENDOBJ
@@ -94,6 +94,7 @@ extern int yyerror(char*);
%token CMP_STARTSWITH
%token CMP_STARTSWITHI
+%type <estr> value
%type <nvlst> nv nvlst
%type <obj> obj property constant
%type <objlst> propconst
@@ -108,6 +109,7 @@ extern int yyerror(char*);
%type <rule> scriptfilt
*/
%type <fparams> fparams
+%type <arr> array arrayelt
%left AND OR
%left CMP_EQ CMP_NE CMP_LE CMP_GE CMP_LT CMP_GT CMP_CONTAINS CMP_CONTAINSI CMP_STARTSWITH CMP_STARTSWITHI
@@ -147,7 +149,9 @@ property: BEGIN_PROPERTY nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_PROPERTY, $2); }
constant: BEGIN_CONSTANT nvlst ENDOBJ { $$ = cnfobjNew(CNFOBJ_CONSTANT, $2); }
nvlst: { $$ = NULL; }
| nvlst nv { $2->next = $1; $$ = $2; }
-nv: NAME '=' VALUE { $$ = nvlstNew($1, $3); }
+nv: NAME '=' value { $$ = nvlstNew($1, $3); }
+value: STRING { $$ = $1; }
+ | array { dbgprintf("DDDD: value array\n"); }
script: stmt { $$ = $1; }
| script stmt { $$ = scriptAddStmt($1, $2); }
stmt: actlst { $$ = $1; }
@@ -196,8 +200,12 @@ expr: expr AND expr { $$ = cnfexprNew(AND, $1, $3); }
| NUMBER { $$ = (struct cnfexpr*) cnfnumvalNew($1); }
| STRING { $$ = (struct cnfexpr*) cnfstringvalNew($1); }
| VAR { $$ = (struct cnfexpr*) cnfvarNew($1); }
+ | array { $$ = (struct cnfexpr*) $1; }
fparams: expr { $$ = cnffparamlstNew($1, NULL); }
| expr ',' fparams { $$ = cnffparamlstNew($1, $3); }
+array: '[' arrayelt ']' { $$ = $2; }
+arrayelt: STRING { $$ = cnfarrayNew($1); }
+ | arrayelt ',' STRING { $$ = cnfarrayAdd($1, $3); }
%%
/*
diff --git a/grammar/lexer.l b/grammar/lexer.l
index 0fc333e4..bc56d4e5 100644
--- a/grammar/lexer.l
+++ b/grammar/lexer.l
@@ -108,6 +108,8 @@ int fileno(FILE *stream);
<EXPR>"+" |
<EXPR>"&" |
<EXPR>"-" |
+<EXPR>"[" |
+<EXPR>"]" |
<EXPR>"(" |
<EXPR>")" { return yytext[0]; }
<EXPR>"==" { return CMP_EQ; }
@@ -188,10 +190,17 @@ int fileno(FILE *stream);
<INOBJ>")" { BEGIN INITIAL; return ENDOBJ; }
<INOBJ>[a-z][a-z0-9_\.]* { yylval.estr = es_newStrFromCStr(yytext, yyleng);
return NAME; }
+<INOBJ>"," |
+<INOBJ>"[" |
+<INOBJ>"]" |
<INOBJ>"=" { return(yytext[0]); }
<INOBJ>\"([^"\\]|\\['"?\\abfnrtv]|\\[0-7]{1,3})*\" {
- yylval.estr = es_newStrFromBuf(yytext+1, yyleng-2);
- return VALUE; }
+ yytext[yyleng-1] = '\0';
+ unescapeStr((uchar*)yytext+1, yyleng-2);
+ yylval.estr = es_newStrFromBuf(yytext+1, strlen(yytext)-1);
+ return STRING; }
+ /*yylval.estr = es_newStrFromBuf(yytext+1, yyleng-2);
+ return VALUE; }*/
"/*" { preCommentState = YY_START; BEGIN COMMENT; }
<EXPR>"/*" { preCommentState = YY_START; BEGIN COMMENT; }
<COMMENT>"*/" { BEGIN preCommentState; }
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index 4e484804..af51dbc2 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -1428,6 +1428,13 @@ cnfexprEval(struct cnfexpr *expr, struct var *ret, void* usrptr)
ret->datatype = 'S';
ret->d.estr = es_strdup(((struct cnfstringval*)expr)->estr);
break;
+ case S_ARRAY:
+ /* if an array is used with "normal" operations, it just evaluates
+ * to its first element.
+ */
+ ret->datatype = 'S';
+ ret->d.estr = es_strdup(((struct cnfarray*)expr)->arr[0]);
+ break;
case 'V':
evalVar((struct cnfvar*)expr, usrptr, ret);
break;
@@ -1475,6 +1482,17 @@ cnfexprEval(struct cnfexpr *expr, struct var *ret, void* usrptr)
//---------------------------------------------------------
static inline void
+cnfarrayDestruct(struct cnfarray *ar)
+{
+ unsigned short i;
+
+ for(i = 0 ; i < ar->nmemb ; ++i) {
+ es_deleteStr(ar->arr[i]);
+ }
+ free(ar->arr);
+}
+
+static inline void
cnffuncDestruct(struct cnffunc *func)
{
unsigned short i;
@@ -1538,6 +1556,9 @@ cnfexprDestruct(struct cnfexpr *expr)
case 'F':
cnffuncDestruct((struct cnffunc*)expr);
break;
+ case S_ARRAY:
+ cnfarrayDestruct((struct cnfarray*)expr);
+ break;
default:break;
}
free(expr);
@@ -1588,7 +1609,7 @@ cnfexprPrint(struct cnfexpr *expr, int indent)
struct cnffunc *func;
int i;
- //dbgprintf("expr %p, indent %d, type '%c'\n", expr, indent, expr->nodetype);
+ dbgprintf("expr %p, indent %d, type '%c'\n", expr, indent, expr->nodetype);
switch(expr->nodetype) {
case CMP_EQ:
cnfexprPrint(expr->l, indent+1);
@@ -1672,6 +1693,15 @@ cnfexprPrint(struct cnfexpr *expr, int indent)
cstrPrint("string '", ((struct cnfstringval*)expr)->estr);
dbgprintf("'\n");
break;
+ case S_ARRAY:
+dbgprintf("DDDD: %d members\n", ((struct cnfarray*)expr)->nmemb);
+ doIndent(indent); dbgprintf("ARRAY:\n");
+ for(i = 0 ; i < ((struct cnfarray*)expr)->nmemb ; ++i) {
+ doIndent(indent+1);
+ cstrPrint("string '", ((struct cnfarray*)expr)->arr[i]);
+ dbgprintf("'\n");
+ }
+ break;
case 'N':
doIndent(indent);
dbgprintf("%lld\n", ((struct cnfnumval*)expr)->val);
@@ -1813,6 +1843,39 @@ cnfstringvalNew(es_str_t *estr)
return strval;
}
+/* creates array AND adds first element to it */
+struct cnfarray*
+cnfarrayNew(es_str_t *val)
+{
+ struct cnfarray *ar;
+ if((ar = malloc(sizeof(struct cnfarray))) != NULL) {
+ ar->nodetype = S_ARRAY;
+ ar->nmemb = 1;
+ if((ar->arr = malloc(sizeof(es_str_t*))) == NULL) {
+ free(ar);
+ ar = NULL;
+ goto done;
+ }
+ ar->arr[0] = val;
+ }
+done: return ar;
+}
+
+/* creates array AND adds first element to it */
+struct cnfarray*
+cnfarrayAdd(struct cnfarray *ar, es_str_t *val)
+{
+ es_str_t **newptr;
+ if((newptr = realloc(ar->arr, (ar->nmemb+1)*sizeof(es_str_t*))) == NULL) {
+ DBGPRINTF("cnfarrayAdd: realloc failed, item ignored, ar->arr=%p\n", ar->arr);
+ goto done;
+ } else {
+ ar->arr = newptr;
+ ar->arr[ar->nmemb] = val;
+ ar->nmemb++;
+ }
+done: return ar;
+}
struct cnfvar*
cnfvarNew(char *name)
diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h
index 6bd1660a..974f2160 100644
--- a/grammar/rainerscript.h
+++ b/grammar/rainerscript.h
@@ -116,6 +116,7 @@ struct nvlst {
* V - var
* ... plus the S_* #define's below:
*/
+#define S_ARRAY 3000
#define S_STOP 4000
#define S_PRIFILT 4001
#define S_PROPFILT 4002
@@ -200,6 +201,12 @@ struct cnfvar {
char *name;
};
+struct cnfarray {
+ unsigned nodetype;
+ int nmemb;
+ es_str_t **arr;
+};
+
struct cnffparamlst {
unsigned nodetype; /* P */
struct cnffparamlst *next;
@@ -315,6 +322,8 @@ struct cnfstmt * cnfstmtNewSet(char *var, struct cnfexpr *expr);
struct cnfstmt * cnfstmtNewUnset(char *var);
void cnfstmtDestruct(struct cnfstmt *root);
void cnfstmtOptimize(struct cnfstmt *root);
+struct cnfarray* cnfarrayNew(es_str_t *val);
+struct cnfarray* cnfarrayAdd(struct cnfarray *ar, es_str_t *val);
char* getFIOPName(unsigned iFIOP);
rsRetVal initRainerscript(void);
void unescapeStr(uchar *s, int len);