diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2011-07-04 08:34:13 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2011-07-04 08:34:13 +0200 |
commit | 71003f146cc2dacfa8fc7c084404f3399812b64a (patch) | |
tree | 52a6d19c4a7e7658718542f897ab4489d4360dc3 /grammar/utils.c | |
parent | 849e4aa8e6437cbfb6efbc7379414fcf517e6db9 (diff) | |
download | rsyslog-71003f146cc2dacfa8fc7c084404f3399812b64a.tar.gz rsyslog-71003f146cc2dacfa8fc7c084404f3399812b64a.tar.bz2 rsyslog-71003f146cc2dacfa8fc7c084404f3399812b64a.zip |
milestone: added operations to expr, added evaluation
Diffstat (limited to 'grammar/utils.c')
-rw-r--r-- | grammar/utils.c | 187 |
1 files changed, 185 insertions, 2 deletions
diff --git a/grammar/utils.c b/grammar/utils.c index bc300aaf..4087bd81 100644 --- a/grammar/utils.c +++ b/grammar/utils.c @@ -4,6 +4,7 @@ #include <ctype.h> #include <libestr.h> #include "utils.h" +#include "rscript.tab.h" void readConfFile(FILE *fp, es_str_t **str) @@ -230,7 +231,7 @@ cnfactlstPrint(struct cnfactlst *actlst) } struct cnfexpr* -cnfexprNew(int nodetype, struct cnfexpr *l, struct cnfexpr *r) +cnfexprNew(unsigned nodetype, struct cnfexpr *l, struct cnfexpr *r) { struct cnfexpr *expr; @@ -250,6 +251,134 @@ done: return expr; } +/* ensure that retval is a number; if string is no number, + * emit error message and set number to 0. + */ +static inline long long +exprret2Number(struct exprret *r) +{ + if(r->datatype == 'S') { + printf("toNumber CONVERSION MISSING\n"); abort(); + } + return r->d.n; +} + +/* ensure that retval is a string; if string is no number, + * emit error message and set number to 0. + */ +static inline es_str_t * +exprret2String(struct exprret *r) +{ + if(r->datatype == 'N') { + printf("toString CONVERSION MISSING\n"); abort(); + } + return r->d.estr; +} + +#define COMP_NUM_BINOP(x) \ + cnfexprEval(expr->l, &l); \ + cnfexprEval(expr->r, &r); \ + ret->datatype = 'N'; \ + ret->d.n = exprret2Number(&l) x exprret2Number(&r) + +/* evaluate an expression. + * Note that we try to avoid malloc whenever possible (because on + * the large overhead it has, especially on highly threaded programs). + * As such, the each caller level must provide buffer space for the + * result on its stack during recursion. This permits the callee to store + * the return value without malloc. As the value is a somewhat larger + * struct, we could otherwise not return it without malloc. + * Note that we implement boolean shortcut operations. For our needs, there + * simply is no case where full evaluation would make any sense at all. + */ +void +cnfexprEval(struct cnfexpr *expr, struct exprret *ret) +{ + struct exprret r, l; /* memory for subexpression results */ + + printf("eval expr %p, type '%c'(%u)\n", expr, expr->nodetype, expr->nodetype); + switch(expr->nodetype) { + case CMP_EQ: + COMP_NUM_BINOP(==); + break; + case CMP_NE: + COMP_NUM_BINOP(!=); + break; + case CMP_LE: + COMP_NUM_BINOP(<=); + break; + case CMP_GE: + COMP_NUM_BINOP(>=); + break; + case CMP_LT: + COMP_NUM_BINOP(<); + break; + case CMP_GT: + COMP_NUM_BINOP(>); + break; + case OR: + cnfexprEval(expr->l, &l); + ret->datatype = 'N'; + if(exprret2Number(&l)) { + ret->d.n = 1ll; + } else { + cnfexprEval(expr->r, &r); + if(exprret2Number(&r)) + ret->d.n = 1ll; + else + ret->d.n = 0ll; + } + break; + case AND: + cnfexprEval(expr->l, &l); + ret->datatype = 'N'; + if(exprret2Number(&l)) { + cnfexprEval(expr->r, &r); + if(exprret2Number(&r)) + ret->d.n = 1ll; + else + ret->d.n = 0ll; + } else { + ret->d.n = 0ll; + } + break; + case NOT: + cnfexprEval(expr->r, &r); + ret->datatype = 'N'; + ret->d.n = !exprret2Number(&l); + break; + case 'N': + ret->datatype = 'N'; + ret->d.n = ((struct cnfnumval*)expr)->val; + break; + case '+': + COMP_NUM_BINOP(+); + break; + case '-': + COMP_NUM_BINOP(-); + break; + case '*': + COMP_NUM_BINOP(*); + break; + case '/': + COMP_NUM_BINOP(/); + break; + case '%': + COMP_NUM_BINOP(%); + break; + case 'M': + cnfexprEval(expr->r, &r); + ret->datatype = 'N'; + ret->d.n = -exprret2Number(&r); + break; + default: + ret->datatype = 'N'; + ret->d.n = 0ll; + printf("eval error: unknown nodetype %u\n", + (unsigned) expr->nodetype); + break; + } +} inline static void doIndent(indent) @@ -263,6 +392,59 @@ cnfexprPrint(struct cnfexpr *expr, int indent) { //printf("expr %p, indent %d, type '%c'\n", expr, indent, expr->nodetype); switch(expr->nodetype) { + case CMP_EQ: + cnfexprPrint(expr->l, indent+1); + doIndent(indent); + printf("==\n"); + cnfexprPrint(expr->r, indent+1); + break; + case CMP_NE: + cnfexprPrint(expr->l, indent+1); + doIndent(indent); + printf("!=\n"); + cnfexprPrint(expr->r, indent+1); + break; + case CMP_LE: + cnfexprPrint(expr->l, indent+1); + doIndent(indent); + printf("<=\n"); + cnfexprPrint(expr->r, indent+1); + break; + case CMP_GE: + cnfexprPrint(expr->l, indent+1); + doIndent(indent); + printf(">=\n"); + cnfexprPrint(expr->r, indent+1); + break; + case CMP_LT: + cnfexprPrint(expr->l, indent+1); + doIndent(indent); + printf("<\n"); + cnfexprPrint(expr->r, indent+1); + break; + case CMP_GT: + cnfexprPrint(expr->l, indent+1); + doIndent(indent); + printf(">\n"); + cnfexprPrint(expr->r, indent+1); + break; + case OR: + cnfexprPrint(expr->l, indent+1); + doIndent(indent); + printf("OR\n"); + cnfexprPrint(expr->r, indent+1); + break; + case AND: + cnfexprPrint(expr->l, indent+1); + doIndent(indent); + printf("AND\n"); + cnfexprPrint(expr->r, indent+1); + break; + case NOT: + doIndent(indent); + printf("NOT\n"); + cnfexprPrint(expr->r, indent+1); + break; case 'N': doIndent(indent); printf("%lld\n", ((struct cnfnumval*)expr)->val); @@ -280,7 +462,8 @@ cnfexprPrint(struct cnfexpr *expr, int indent) cnfexprPrint(expr->r, indent+1); break; default: - printf("error: unknown nodetype\n"); + printf("error: unknown nodetype %u\n", + (unsigned) expr->nodetype); break; } } |