summaryrefslogtreecommitdiffstats
path: root/grammar
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2012-09-21 08:36:28 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2012-09-21 08:36:28 +0200
commitb16637ed74abee89d69e1e1cf0d7d9c9898e861e (patch)
treecf31a006a3875f154ff623cd1fcb72e62da76657 /grammar
parent7351fcc0e2635bf29c556b189190507c8c5202c9 (diff)
downloadrsyslog-b16637ed74abee89d69e1e1cf0d7d9c9898e861e.tar.gz
rsyslog-b16637ed74abee89d69e1e1cf0d7d9c9898e861e.tar.xz
rsyslog-b16637ed74abee89d69e1e1cf0d7d9c9898e861e.zip
Implement script optimizer basic constant folding & NOP removal
Diffstat (limited to 'grammar')
-rw-r--r--grammar/rainerscript.c195
1 files changed, 164 insertions, 31 deletions
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index d0a97f06..5db62abc 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -49,6 +49,8 @@
DEFobjCurrIf(obj)
DEFobjCurrIf(regexp)
+void cnfexprOptimize(struct cnfexpr *expr);
+
char*
getFIOPName(unsigned iFIOP)
{
@@ -168,16 +170,13 @@ struct cnfstmt*
scriptAddStmt(struct cnfstmt *root, struct cnfstmt *s)
{
struct cnfstmt *l;
-dbgprintf("RRRR: scriptAddStmt(%p, %p): ", root, s);
if(root == NULL) {
root = s;
-dbgprintf("root set to %p\n", s);
} else { /* find last, linear search ok, as only during config phase */
for(l = root ; l->next != NULL ; l = l->next)
;
l->next = s;
-dbgprintf("%p->next = %p\n", l, s);
}
return root;
}
@@ -1819,7 +1818,6 @@ cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then)
cnfstmt->d.s_propfilt.regex_cache = NULL;
cnfstmt->d.s_propfilt.pCSCompValue = NULL;
lRet = DecodePropFilter((uchar*)propfilt, cnfstmt);
-dbgprintf("AAAA: DecodePropFilter returns %d\n", lRet);
}
return cnfstmt;
}
@@ -1863,68 +1861,201 @@ done: return cnfstmt;
}
+/* returns 1 if the two expressions are constants, 0 otherwise
+ * if both are constants, the expression subtrees are destructed
+ * (this is an aid for constant folding optimizing)
+ */
+static int
+getConstNumber(struct cnfexpr *expr, long long *l, long long *r)
+{
+ int ret = 0;
+ cnfexprOptimize(expr->l);
+ cnfexprOptimize(expr->r);
+ if(expr->l->nodetype == 'N') {
+ if(expr->r->nodetype == 'N') {
+ ret = 1;
+ *l = ((struct cnfnumval*)expr->l)->val;
+ *r = ((struct cnfnumval*)expr->r)->val;
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ } else if(expr->r->nodetype == 'S') {
+ ret = 1;
+ *l = ((struct cnfnumval*)expr->l)->val;
+ *r = es_str2num(((struct cnfstringval*)expr->r)->estr, NULL);
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ }
+ } else if(expr->l->nodetype == 'S') {
+ if(expr->r->nodetype == 'N') {
+ ret = 1;
+ *l = es_str2num(((struct cnfstringval*)expr->l)->estr, NULL);
+ *r = ((struct cnfnumval*)expr->r)->val;
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ } else if(expr->r->nodetype == 'S') {
+ ret = 1;
+ *l = es_str2num(((struct cnfstringval*)expr->l)->estr, NULL);
+ *r = es_str2num(((struct cnfstringval*)expr->r)->estr, NULL);
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ }
+ }
+ return ret;
+}
+
+
+/* constant folding for string concatenation */
+static inline void
+constFoldConcat(struct cnfexpr *expr)
+{
+ es_str_t *estr;
+ cnfexprOptimize(expr->l);
+ cnfexprOptimize(expr->r);
+ if(expr->l->nodetype == 'S') {
+ if(expr->r->nodetype == 'S') {
+ estr = ((struct cnfstringval*)expr->l)->estr;
+ ((struct cnfstringval*)expr->l)->estr = NULL;
+ es_addStr(&estr, ((struct cnfstringval*)expr->r)->estr);
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ expr->nodetype = 'S';
+ ((struct cnfstringval*)expr)->estr = estr;
+ } else if(expr->r->nodetype == 'N') {
+ es_str_t *numstr;
+ estr = ((struct cnfstringval*)expr->l)->estr;
+ ((struct cnfstringval*)expr->l)->estr = NULL;
+ numstr = es_newStrFromNumber(((struct cnfnumval*)expr->r)->val);
+ es_addStr(&estr, numstr);
+ es_deleteStr(numstr);
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ expr->nodetype = 'S';
+ ((struct cnfstringval*)expr)->estr = estr;
+ }
+ } else if(expr->l->nodetype == 'N') {
+ if(expr->r->nodetype == 'S') {
+ estr = es_newStrFromNumber(((struct cnfnumval*)expr->l)->val);
+ es_addStr(&estr, ((struct cnfstringval*)expr->r)->estr);
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ expr->nodetype = 'S';
+ ((struct cnfstringval*)expr)->estr = estr;
+ } else if(expr->r->nodetype == 'S') {
+ es_str_t *numstr;
+ estr = es_newStrFromNumber(((struct cnfnumval*)expr->l)->val);
+ numstr = es_newStrFromNumber(((struct cnfnumval*)expr->r)->val);
+ es_addStr(&estr, numstr);
+ es_deleteStr(numstr);
+ cnfexprDestruct(expr->l);
+ cnfexprDestruct(expr->r);
+ expr->nodetype = 'S';
+ ((struct cnfstringval*)expr)->estr = estr;
+ }
+ }
+}
+
+
/* (recursively) optimize an expression */
void
cnfexprOptimize(struct cnfexpr *expr)
{
- struct var r, l; /* memory for subexpression results */
- es_str_t *estr_r, *estr_l;
- int convok_r, convok_l;
- int bMustFree, bMustFree2;
- long long n_r, n_l;
+ long long ln, rn;
dbgprintf("optimize expr %p, type '%c'(%u)\n", expr, expr->nodetype, expr->nodetype);
switch(expr->nodetype) {
case '&':
+ constFoldConcat(expr);
break;
case '+':
+ if(getConstNumber(expr, &ln, &rn)) {
+ expr->nodetype = 'N';
+ ((struct cnfnumval*)expr)->val = ln + rn;
+ }
break;
case '-':
+ if(getConstNumber(expr, &ln, &rn)) {
+ expr->nodetype = 'N';
+ ((struct cnfnumval*)expr)->val = ln - rn;
+ }
break;
case '*':
+ if(getConstNumber(expr, &ln, &rn)) {
+ expr->nodetype = 'N';
+ ((struct cnfnumval*)expr)->val = ln * rn;
+ }
break;
case '/':
+ if(getConstNumber(expr, &ln, &rn)) {
+ expr->nodetype = 'N';
+ ((struct cnfnumval*)expr)->val = ln / rn;
+ }
break;
case '%':
+ if(getConstNumber(expr, &ln, &rn)) {
+ expr->nodetype = 'N';
+ ((struct cnfnumval*)expr)->val = ln % rn;
+ }
break;
- default:DBGPRINTF("expr optimizer error: unknown nodetype %u['%c']\n",
- (unsigned) expr->nodetype, (char) expr->nodetype);
+ default:/* nodetype we cannot optimize */
break;
}
}
+/* removes NOPs from a statement list and returns the
+ * first non-NOP entry.
+ */
+static inline struct cnfstmt *
+removeNOPs(struct cnfstmt *root)
+{
+ struct cnfstmt *stmt, *toDel, *prevstmt = NULL;
+ struct cnfstmt *newRoot = NULL;
+
+ if(root == NULL) goto done;
+ stmt = root;
+ while(stmt != NULL) {
+dbgprintf("RRRR: removeNOPs: stmt %p, nodetype %u\n", stmt, stmt->nodetype);
+ if(stmt->nodetype == S_NOP) {
+ if(prevstmt != NULL)
+ /* end chain, is rebuild if more non-NOPs follow */
+ prevstmt->next = NULL;
+ toDel = stmt;
+ stmt = stmt->next;
+ cnfstmtDestruct(toDel);
+ } else {
+ if(newRoot == NULL)
+ newRoot = stmt;
+ if(prevstmt != NULL)
+ prevstmt->next = stmt;
+ prevstmt = stmt;
+ stmt = stmt->next;
+ }
+ }
+done: return newRoot;
+}
+
/* (recursively) optimize a statement */
void
cnfstmtOptimize(struct cnfstmt *root)
{
- struct cnfstmt *stmt, *prevstmt;
-
- prevstmt = NULL;
+ struct cnfstmt *stmt;
+ if(root == NULL) goto done;
for(stmt = root ; stmt != NULL ; stmt = stmt->next) {
dbgprintf("RRRR: stmtOptimize: stmt %p, nodetype %u\n", stmt, stmt->nodetype);
switch(stmt->nodetype) {
- case S_NOP:
- /* unchain NOPs, first NOP remains (TODO?) */
- if(prevstmt != NULL) {
- DBGPRINTF("removing NOP\n");
- prevstmt->next = stmt->next;
-#warning remove memleak, destruct
- }
- break;
case S_IF:
cnfexprOptimize(stmt->d.s_if.expr);
- if(stmt->d.s_if.t_then != NULL) {
- cnfstmtOptimize(stmt->d.s_if.t_then);
- }
- if(stmt->d.s_if.t_else != NULL) {
- cnfstmtOptimize(stmt->d.s_if.t_else);
- }
+ stmt->d.s_if.t_then = removeNOPs(stmt->d.s_if.t_then);
+ stmt->d.s_if.t_else = removeNOPs(stmt->d.s_if.t_else);
+ cnfstmtOptimize(stmt->d.s_if.t_then);
+ cnfstmtOptimize(stmt->d.s_if.t_else);
break;
case S_PRIFILT:
+ stmt->d.s_prifilt.t_then = removeNOPs(stmt->d.s_prifilt.t_then);
cnfstmtOptimize(stmt->d.s_prifilt.t_then);
break;
case S_PROPFILT:
+ stmt->d.s_propfilt.t_then = removeNOPs(stmt->d.s_propfilt.t_then);
cnfstmtOptimize(stmt->d.s_propfilt.t_then);
break;
case S_SET:
@@ -1932,16 +2063,18 @@ dbgprintf("RRRR: stmtOptimize: stmt %p, nodetype %u\n", stmt, stmt->nodetype);
break;
case S_STOP:
case S_UNSET:
- case S_ACT:
- /* nothing to do */
+ case S_ACT: /* nothing to do */
+ break;
+ case S_NOP:
+ DBGPRINTF("optimizer error: we see a NOP, how come?\n");
break;
default:
dbgprintf("error: unknown stmt type %u during optimizer run\n",
(unsigned) stmt->nodetype);
break;
}
- prevstmt = stmt;
}
+done: /*EMPTY*/;
}