diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2011-07-08 09:13:39 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2011-07-08 09:13:39 +0200 |
commit | d9ea755214ab75afa039a4df89f828d4b8b30ef0 (patch) | |
tree | 38a342665c206fef93ba230567c9f0f8051feaea | |
parent | 834fe024b4e53f65d9622a176116f232e212e326 (diff) | |
download | rsyslog-d9ea755214ab75afa039a4df89f828d4b8b30ef0.tar.gz rsyslog-d9ea755214ab75afa039a4df89f828d4b8b30ef0.tar.xz rsyslog-d9ea755214ab75afa039a4df89f828d4b8b30ef0.zip |
milestone/[PARTWORK]: implemented comparison operations
-rw-r--r-- | grammar/lexer.l | 3 | ||||
-rw-r--r-- | grammar/rainerscript.c | 252 | ||||
-rw-r--r-- | runtime/Makefile.am | 20 | ||||
-rw-r--r-- | runtime/rsconf.c | 3 | ||||
-rw-r--r-- | runtime/rsyslog.c | 4 | ||||
-rw-r--r-- | runtime/rule.c | 11 | ||||
-rw-r--r-- | tools/syslogd.c | 1 |
7 files changed, 236 insertions, 58 deletions
diff --git a/grammar/lexer.l b/grammar/lexer.l index d761003a..347a2a7a 100644 --- a/grammar/lexer.l +++ b/grammar/lexer.l @@ -72,6 +72,7 @@ struct bufstack { YY_BUFFER_STATE bs; int lineno; char *fn; + es_str_t *estr; } *currbs = NULL; char *currfn; /* name of currently processed file */ @@ -228,6 +229,7 @@ cnfSetLexFile(char *fname) bs->prev = currbs; bs->fn = strdup(fname == NULL ? "stdin" : fname); bs->bs = yy_scan_buffer((char*)es_getBufAddr(str), es_strlen(str)); + bs->estr = str; /* needed so we can free it later */ currbs = bs; currfn = bs->fn; yylineno = 1; @@ -253,6 +255,7 @@ popfile(void) /* delte current entry */ yy_delete_buffer(bs->bs); free(bs->fn); + free(bs->estr); /* switch back to previous */ currbs = bs->prev; diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index bcc73af0..0def9653 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -286,14 +286,17 @@ done: } /* ensure that retval is a number; if string is no number, - * emit error message and set number to 0. + * try to convert it to one. The semantics from es_str2num() + * are used (bSuccess tells if the conversion went well or not). */ static inline long long -exprret2Number(struct exprret *r) +exprret2Number(struct exprret *r, int *bSuccess) { long long n; if(r->datatype == 'S') { - n = es_str2num(r->d.estr); + n = es_str2num(r->d.estr, bSuccess); + } else { + *bSuccess = 1; } return r->d.n; } @@ -316,7 +319,17 @@ exprret2String(struct exprret *r, int *bMustFree) cnfexprEval(expr->l, &l, usrptr); \ cnfexprEval(expr->r, &r, usrptr); \ ret->datatype = 'N'; \ - ret->d.n = exprret2Number(&l) x exprret2Number(&r) + ret->d.n = exprret2Number(&l, &convok_l) x exprret2Number(&r, &convok_r) + +#define PREP_TWO_STRINGS \ + cnfexprEval(expr->l, &l, usrptr); \ + cnfexprEval(expr->r, &r, usrptr); \ + estr_r = exprret2String(&r, &bMustFree); \ + estr_l = exprret2String(&l, &bMustFree2) + +#define FREE_TWO_STRINGS \ + if(bMustFree) es_deleteStr(estr_r); \ + if(bMustFree2) es_deleteStr(estr_l) /* evaluate an expression. * Note that we try to avoid malloc whenever possible (because of @@ -333,67 +346,239 @@ cnfexprEval(struct cnfexpr *expr, struct exprret *ret, void* usrptr) { struct exprret r, l; /* memory for subexpression results */ es_str_t *estr_r, *estr_l; - int bMustFree; - int bMustFree2; + int convok_r, convok_l; + int bMustFree, bMustFree2; + long long n_r, n_l; //dbgprintf("eval expr %p, type '%c'(%u)\n", expr, expr->nodetype, expr->nodetype); switch(expr->nodetype) { + /* note: comparison operations are extremely similar. The code can be copyied, only + * places flagged with "CMP" need to be changed. + */ case CMP_EQ: cnfexprEval(expr->l, &l, usrptr); cnfexprEval(expr->r, &r, usrptr); ret->datatype = 'N'; if(l.datatype == 'S') { if(r.datatype == 'S') { - ret->d.n = !es_strcmp(l.d.estr, r.d.estr); + ret->d.n = !es_strcmp(l.d.estr, r.d.estr); /*CMP*/ } else { - estr_r = exprret2String(&r, &bMustFree); - ret->d.n = !es_strcmp(l.d.estr, estr_r); - if(bMustFree) es_deleteStr(estr_r); + n_l = exprret2Number(&l, &convok_l); + if(convok_l) { + ret->d.n = (n_l == r.d.n); /*CMP*/ + } else { + estr_r = exprret2String(&r, &bMustFree); + ret->d.n = !es_strcmp(l.d.estr, estr_r); /*CMP*/ + if(bMustFree) es_deleteStr(estr_r); + } } } else { if(r.datatype == 'S') { - estr_l = exprret2String(&l, &bMustFree); - ret->d.n = !es_strcmp(r.d.estr, estr_l); - if(bMustFree) es_deleteStr(estr_l); + n_r = exprret2Number(&r, &convok_r); + if(convok_r) { + ret->d.n = (l.d.n == n_r); /*CMP*/ + } else { + estr_l = exprret2String(&l, &bMustFree); + ret->d.n = !es_strcmp(r.d.estr, estr_l); /*CMP*/ + if(bMustFree) es_deleteStr(estr_l); + } } else { - ret->d.n = (l.d.n == r.d.n); + ret->d.n = (l.d.n == r.d.n); /*CMP*/ } } break; case CMP_NE: - COMP_NUM_BINOP(!=); + cnfexprEval(expr->l, &l, usrptr); + cnfexprEval(expr->r, &r, usrptr); + ret->datatype = 'N'; + if(l.datatype == 'S') { + if(r.datatype == 'S') { + ret->d.n = es_strcmp(l.d.estr, r.d.estr); /*CMP*/ + } else { + n_l = exprret2Number(&l, &convok_l); + if(convok_l) { + ret->d.n = (n_l != r.d.n); /*CMP*/ + } else { + estr_r = exprret2String(&r, &bMustFree); + ret->d.n = es_strcmp(l.d.estr, estr_r); /*CMP*/ + if(bMustFree) es_deleteStr(estr_r); + } + } + } else { + if(r.datatype == 'S') { + n_r = exprret2Number(&r, &convok_r); + if(convok_r) { + ret->d.n = (l.d.n != n_r); /*CMP*/ + } else { + estr_l = exprret2String(&l, &bMustFree); + ret->d.n = es_strcmp(r.d.estr, estr_l); /*CMP*/ + if(bMustFree) es_deleteStr(estr_l); + } + } else { + ret->d.n = (l.d.n != r.d.n); /*CMP*/ + } + } break; case CMP_LE: - COMP_NUM_BINOP(<=); + cnfexprEval(expr->l, &l, usrptr); + cnfexprEval(expr->r, &r, usrptr); + ret->datatype = 'N'; + if(l.datatype == 'S') { + if(r.datatype == 'S') { + ret->d.n = es_strcmp(l.d.estr, r.d.estr) <= 0; /*CMP*/ + } else { + n_l = exprret2Number(&l, &convok_l); + if(convok_l) { + ret->d.n = (n_l <= r.d.n); /*CMP*/ + } else { + estr_r = exprret2String(&r, &bMustFree); + ret->d.n = es_strcmp(l.d.estr, estr_r) <= 0; /*CMP*/ + if(bMustFree) es_deleteStr(estr_r); + } + } + } else { + if(r.datatype == 'S') { + n_r = exprret2Number(&r, &convok_r); + if(convok_r) { + ret->d.n = (l.d.n <= n_r); /*CMP*/ + } else { + estr_l = exprret2String(&l, &bMustFree); + ret->d.n = es_strcmp(r.d.estr, estr_l) <= 0; /*CMP*/ + if(bMustFree) es_deleteStr(estr_l); + } + } else { + ret->d.n = (l.d.n <= r.d.n); /*CMP*/ + } + } break; case CMP_GE: - COMP_NUM_BINOP(>=); + cnfexprEval(expr->l, &l, usrptr); + cnfexprEval(expr->r, &r, usrptr); + ret->datatype = 'N'; + if(l.datatype == 'S') { + if(r.datatype == 'S') { + ret->d.n = es_strcmp(l.d.estr, r.d.estr) >= 0; /*CMP*/ + } else { + n_l = exprret2Number(&l, &convok_l); + if(convok_l) { + ret->d.n = (n_l >= r.d.n); /*CMP*/ + } else { + estr_r = exprret2String(&r, &bMustFree); + ret->d.n = es_strcmp(l.d.estr, estr_r) >= 0; /*CMP*/ + if(bMustFree) es_deleteStr(estr_r); + } + } + } else { + if(r.datatype == 'S') { + n_r = exprret2Number(&r, &convok_r); + if(convok_r) { + ret->d.n = (l.d.n >= n_r); /*CMP*/ + } else { + estr_l = exprret2String(&l, &bMustFree); + ret->d.n = es_strcmp(r.d.estr, estr_l) >= 0; /*CMP*/ + if(bMustFree) es_deleteStr(estr_l); + } + } else { + ret->d.n = (l.d.n >= r.d.n); /*CMP*/ + } + } break; case CMP_LT: - COMP_NUM_BINOP(<); + cnfexprEval(expr->l, &l, usrptr); + cnfexprEval(expr->r, &r, usrptr); + ret->datatype = 'N'; + if(l.datatype == 'S') { + if(r.datatype == 'S') { + ret->d.n = es_strcmp(l.d.estr, r.d.estr) < 0; /*CMP*/ + } else { + n_l = exprret2Number(&l, &convok_l); + if(convok_l) { + ret->d.n = (n_l < r.d.n); /*CMP*/ + } else { + estr_r = exprret2String(&r, &bMustFree); + ret->d.n = es_strcmp(l.d.estr, estr_r) < 0; /*CMP*/ + if(bMustFree) es_deleteStr(estr_r); + } + } + } else { + if(r.datatype == 'S') { + n_r = exprret2Number(&r, &convok_r); + if(convok_r) { + ret->d.n = (l.d.n < n_r); /*CMP*/ + } else { + estr_l = exprret2String(&l, &bMustFree); + ret->d.n = es_strcmp(r.d.estr, estr_l) < 0; /*CMP*/ + if(bMustFree) es_deleteStr(estr_l); + } + } else { + ret->d.n = (l.d.n < r.d.n); /*CMP*/ + } + } break; case CMP_GT: - COMP_NUM_BINOP(>); - break; - case CMP_CONTAINS: cnfexprEval(expr->l, &l, usrptr); cnfexprEval(expr->r, &r, usrptr); - estr_r = exprret2String(&r, &bMustFree); - estr_l = exprret2String(&l, &bMustFree2); ret->datatype = 'N'; -dbgprintf("ZZZZ: contains ret %d\n", es_strContains(estr_l, estr_r)); + if(l.datatype == 'S') { + if(r.datatype == 'S') { + ret->d.n = es_strcmp(l.d.estr, r.d.estr) > 0; /*CMP*/ + } else { + n_l = exprret2Number(&l, &convok_l); + if(convok_l) { + ret->d.n = (n_l > r.d.n); /*CMP*/ + } else { + estr_r = exprret2String(&r, &bMustFree); + ret->d.n = es_strcmp(l.d.estr, estr_r) > 0; /*CMP*/ + if(bMustFree) es_deleteStr(estr_r); + } + } + } else { + if(r.datatype == 'S') { + n_r = exprret2Number(&r, &convok_r); + if(convok_r) { + ret->d.n = (l.d.n > n_r); /*CMP*/ + } else { + estr_l = exprret2String(&l, &bMustFree); + ret->d.n = es_strcmp(r.d.estr, estr_l) > 0; /*CMP*/ + if(bMustFree) es_deleteStr(estr_l); + } + } else { + ret->d.n = (l.d.n > r.d.n); /*CMP*/ + } + } + break; + case CMP_STARTSWITH: + PREP_TWO_STRINGS; + ret->datatype = 'N'; + ret->d.n = es_strncmp(estr_l, estr_r, estr_r->lenStr) == 0; + FREE_TWO_STRINGS; + break; + case CMP_STARTSWITHI: + PREP_TWO_STRINGS; + ret->datatype = 'N'; + ret->d.n = es_strncasecmp(estr_l, estr_r, estr_r->lenStr) == 0; + FREE_TWO_STRINGS; + break; + case CMP_CONTAINS: + PREP_TWO_STRINGS; + ret->datatype = 'N'; ret->d.n = es_strContains(estr_l, estr_r) != -1; - if(bMustFree) es_deleteStr(estr_r); - if(bMustFree2) es_deleteStr(estr_l); + FREE_TWO_STRINGS; + break; + case CMP_CONTAINSI: + PREP_TWO_STRINGS; + ret->datatype = 'N'; + ret->d.n = es_strCaseContains(estr_l, estr_r) != -1; + FREE_TWO_STRINGS; break; case OR: cnfexprEval(expr->l, &l, usrptr); ret->datatype = 'N'; - if(exprret2Number(&l)) { + if(exprret2Number(&l, &convok_l)) { ret->d.n = 1ll; } else { cnfexprEval(expr->r, &r, usrptr); - if(exprret2Number(&r)) + if(exprret2Number(&r, &convok_r)) ret->d.n = 1ll; else ret->d.n = 0ll; @@ -402,9 +587,9 @@ dbgprintf("ZZZZ: contains ret %d\n", es_strContains(estr_l, estr_r)); case AND: cnfexprEval(expr->l, &l, usrptr); ret->datatype = 'N'; - if(exprret2Number(&l)) { + if(exprret2Number(&l, &convok_l)) { cnfexprEval(expr->r, &r, usrptr); - if(exprret2Number(&r)) + if(exprret2Number(&r, &convok_r)) ret->d.n = 1ll; else ret->d.n = 0ll; @@ -415,7 +600,7 @@ dbgprintf("ZZZZ: contains ret %d\n", es_strContains(estr_l, estr_r)); case NOT: cnfexprEval(expr->r, &r, usrptr); ret->datatype = 'N'; - ret->d.n = !exprret2Number(&r); + ret->d.n = !exprret2Number(&r, &convok_r); break; case 'N': ret->datatype = 'N'; @@ -447,7 +632,7 @@ dbgprintf("ZZZZ: contains ret %d\n", es_strContains(estr_l, estr_r)); case 'M': cnfexprEval(expr->r, &r, usrptr); ret->datatype = 'N'; - ret->d.n = -exprret2Number(&r); + ret->d.n = -exprret2Number(&r, &convok_r); break; default: ret->datatype = 'N'; @@ -465,9 +650,10 @@ dbgprintf("ZZZZ: contains ret %d\n", es_strContains(estr_l, estr_r)); int cnfexprEvalBool(struct cnfexpr *expr, void *usrptr) { + int convok; struct exprret ret; cnfexprEval(expr, &ret, usrptr); - return exprret2Number(&ret); + return exprret2Number(&ret, &convok); } inline static void diff --git a/runtime/Makefile.am b/runtime/Makefile.am index 7c3d18ef..c6c860ea 100644 --- a/runtime/Makefile.am +++ b/runtime/Makefile.am @@ -5,6 +5,16 @@ pkglib_LTLIBRARIES = #pkglib_LTLIBRARIES = librsyslog.la librsyslog_la_SOURCES = \ + expr.c \ + expr.h \ + vm.c \ + vm.h \ + vmstk.c \ + vmstk.h \ + vmprg.c \ + vmprg.h \ + vmop.c \ + vmop.h \ rsyslog.c \ rsyslog.h \ typedefs.h \ @@ -55,8 +65,6 @@ librsyslog_la_SOURCES = \ statsobj.h \ sync.c \ sync.h \ - expr.c \ - expr.h \ ctok.c \ ctok.h \ ctok_token.c \ @@ -71,14 +79,6 @@ librsyslog_la_SOURCES = \ wti.h \ sysvar.c \ sysvar.h \ - vm.c \ - vm.h \ - vmstk.c \ - vmstk.h \ - vmprg.c \ - vmprg.h \ - vmop.c \ - vmop.h \ queue.c \ queue.h \ ruleset.c \ diff --git a/runtime/rsconf.c b/runtime/rsconf.c index 0d3c940a..c1bc3b72 100644 --- a/runtime/rsconf.c +++ b/runtime/rsconf.c @@ -1152,11 +1152,8 @@ ourConf = loadConf; // TODO: remove, once ourConf is gone! CHKiRet(initLegacyConf()); /* open the configuration file */ - dbgprintf("ZZZZZ: calling cnfSetLexFile(%s)\n", confFile); r = cnfSetLexFile((char*)confFile); - dbgprintf("ZZZZZ: cnfSetLexFile returns %d, calling yyparse()\n", r); r = yyparse(); - dbgprintf("ZZZZZ: yyparse returns %d\n", r); //localRet = conf.processConfFile(loadConf, confFile); CHKiRet(conf.GetNbrActActions(loadConf, &iNbrActions)); diff --git a/runtime/rsyslog.c b/runtime/rsyslog.c index 2b8f2b64..d71fe88a 100644 --- a/runtime/rsyslog.c +++ b/runtime/rsyslog.c @@ -182,10 +182,13 @@ rsrtInit(char **ppErrObj, obj_if_t *pObjIF) CHKiRet(ctok_tokenClassInit(NULL)); if(ppErrObj != NULL) *ppErrObj = "ctok"; CHKiRet(ctokClassInit(NULL)); +#if 1 if(ppErrObj != NULL) *ppErrObj = "vmstk"; CHKiRet(vmstkClassInit(NULL)); +#endif if(ppErrObj != NULL) *ppErrObj = "sysvar"; CHKiRet(sysvarClassInit(NULL)); +#if 1 if(ppErrObj != NULL) *ppErrObj = "vm"; CHKiRet(vmClassInit(NULL)); if(ppErrObj != NULL) *ppErrObj = "vmop"; @@ -194,6 +197,7 @@ rsrtInit(char **ppErrObj, obj_if_t *pObjIF) CHKiRet(vmprgClassInit(NULL)); if(ppErrObj != NULL) *ppErrObj = "expr"; CHKiRet(exprClassInit(NULL)); +#endif if(ppErrObj != NULL) *ppErrObj = "rule"; CHKiRet(ruleClassInit(NULL)); if(ppErrObj != NULL) *ppErrObj = "ruleset"; diff --git a/runtime/rule.c b/runtime/rule.c index 67ef8650..0b4b48a2 100644 --- a/runtime/rule.c +++ b/runtime/rule.c @@ -36,7 +36,6 @@ #include "action.h" #include "rule.h" #include "errmsg.h" -#include "vm.h" #include "var.h" #include "srUtils.h" #include "batch.h" @@ -46,9 +45,7 @@ /* static data */ DEFobjStaticHelpers DEFobjCurrIf(errmsg) -DEFobjCurrIf(expr) DEFobjCurrIf(var) -DEFobjCurrIf(vm) /* support for simple textual representation of FIOP names @@ -124,7 +121,6 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, sbool *bProcessMsg) uchar *pszPropVal; int bRet = 0; size_t propLen; - vm_t *pVM = NULL; var_t *pResult = NULL; ISOBJ_TYPE_assert(pRule, rule); @@ -276,9 +272,6 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, sbool *bProcessMsg) finalize_it: /* destruct in any case, not just on error, but it makes error handling much easier */ - if(pVM != NULL) - vm.Destruct(&pVM); - if(pResult != NULL) var.Destruct(&pResult); @@ -482,9 +475,7 @@ ENDobjQueryInterface(rule) */ BEGINObjClassExit(rule, OBJ_IS_CORE_MODULE) /* class, version */ objRelease(errmsg, CORE_COMPONENT); - objRelease(expr, CORE_COMPONENT); objRelease(var, CORE_COMPONENT); - objRelease(vm, CORE_COMPONENT); ENDObjClassExit(rule) @@ -495,9 +486,7 @@ ENDObjClassExit(rule) BEGINObjClassInit(rule, 1, OBJ_IS_CORE_MODULE) /* class, version */ /* request objects we use */ CHKiRet(objUse(errmsg, CORE_COMPONENT)); - CHKiRet(objUse(expr, CORE_COMPONENT)); CHKiRet(objUse(var, CORE_COMPONENT)); - CHKiRet(objUse(vm, CORE_COMPONENT)); /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, ruleDebugPrint); diff --git a/tools/syslogd.c b/tools/syslogd.c index 79bf0c8a..f623b398 100644 --- a/tools/syslogd.c +++ b/tools/syslogd.c @@ -1602,7 +1602,6 @@ GlobalClassExit(void) objRelease(ruleset, CORE_COMPONENT); objRelease(rule, CORE_COMPONENT); objRelease(expr, CORE_COMPONENT); - vmClassExit(); /* this is hack, currently core_modules do not get this automatically called */ parserClassExit(); /* this is hack, currently core_modules do not get this automatically called */ rsconfClassExit(); /* this is hack, currently core_modules do not get this automatically called */ objRelease(datetime, CORE_COMPONENT); |