summaryrefslogtreecommitdiffstats
path: root/grammar/rainerscript.c
diff options
context:
space:
mode:
Diffstat (limited to 'grammar/rainerscript.c')
-rw-r--r--grammar/rainerscript.c139
1 files changed, 80 insertions, 59 deletions
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index a7828839..a1de6442 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -854,7 +854,7 @@ nvlstGetParam(struct nvlst *valnode, struct cnfparamdescr *param,
r = doGetInt(valnode, param, val);
break;
case eCmdHdlrNonNegInt:
- r = doGetPositiveInt(valnode, param, val);
+ r = doGetNonNegInt(valnode, param, val);
break;
case eCmdHdlrPositiveInt:
r = doGetPositiveInt(valnode, param, val);
@@ -1259,7 +1259,7 @@ doFunc_re_extract(struct cnffunc *func, struct var *ret, void* usrptr)
str = (char*) var2CString(&r[0], &bMustFree);
matchnbr = (short) var2Number(&r[2], NULL);
submatchnbr = (size_t) var2Number(&r[3], NULL);
- if(submatchnbr > sizeof(pmatch)/sizeof(regmatch_t)) {
+ if(submatchnbr >= sizeof(pmatch)/sizeof(regmatch_t)) {
DBGPRINTF("re_extract() submatch %d is too large\n", submatchnbr);
bHadNoMatch = 1;
goto finalize_it;
@@ -1307,15 +1307,19 @@ doFunc_re_extract(struct cnffunc *func, struct var *ret, void* usrptr)
iLenBuf);
}
+finalize_it:
if(bMustFree) free(str);
if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr);
if(r[2].datatype == 'S') es_deleteStr(r[2].d.estr);
if(r[3].datatype == 'S') es_deleteStr(r[3].d.estr);
-finalize_it:
+
if(bHadNoMatch) {
cnfexprEval(func->expr[4], &r[4], usrptr);
estr = var2String(&r[4], &bMustFree);
- if(r[4].datatype == 'S') es_deleteStr(r[4].d.estr);
+ /* Note that we do NOT free the string that was returned/created
+ * for r[4]. We pass it to the caller, which in turn frees it.
+ * This saves us doing one unnecessary memory alloc & write.
+ */
}
ret->datatype = 'S';
ret->d.estr = estr;
@@ -1355,6 +1359,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr)
estr = var2String(&r[0], &bMustFree);
ret->d.n = es_strlen(estr);
if(bMustFree) es_deleteStr(estr);
+ if(r[0].datatype == 'S') es_deleteStr(r[0].d.estr);
}
ret->datatype = 'N';
break;
@@ -2279,7 +2284,8 @@ cnfstmtPrintOnly(struct cnfstmt *stmt, int indent, sbool subtree)
free(cstr);
break;
case S_ACT:
- doIndent(indent); dbgprintf("ACTION %p [%s]\n", stmt->d.act, stmt->printable);
+ doIndent(indent); dbgprintf("ACTION %p [%s:%s]\n", stmt->d.act,
+ modGetName(stmt->d.act->pMod), stmt->printable);
break;
case S_IF:
doIndent(indent); dbgprintf("IF\n");
@@ -2447,59 +2453,69 @@ cnfstmtNew(unsigned s_type)
return cnfstmt;
}
+void cnfstmtDestructLst(struct cnfstmt *root);
+
+/* delete a single stmt */
+static void
+cnfstmtDestruct(struct cnfstmt *stmt)
+{
+ switch(stmt->nodetype) {
+ case S_NOP:
+ case S_STOP:
+ break;
+ case S_CALL:
+ es_deleteStr(stmt->d.s_call.name);
+ break;
+ case S_ACT:
+ actionDestruct(stmt->d.act);
+ break;
+ case S_IF:
+ cnfexprDestruct(stmt->d.s_if.expr);
+ if(stmt->d.s_if.t_then != NULL) {
+ cnfstmtDestructLst(stmt->d.s_if.t_then);
+ }
+ if(stmt->d.s_if.t_else != NULL) {
+ cnfstmtDestructLst(stmt->d.s_if.t_else);
+ }
+ break;
+ case S_SET:
+ free(stmt->d.s_set.varname);
+ cnfexprDestruct(stmt->d.s_set.expr);
+ break;
+ case S_UNSET:
+ free(stmt->d.s_set.varname);
+ break;
+ case S_PRIFILT:
+ cnfstmtDestructLst(stmt->d.s_prifilt.t_then);
+ cnfstmtDestructLst(stmt->d.s_prifilt.t_else);
+ break;
+ case S_PROPFILT:
+ if(stmt->d.s_propfilt.propName != NULL)
+ es_deleteStr(stmt->d.s_propfilt.propName);
+ if(stmt->d.s_propfilt.regex_cache != NULL)
+ rsCStrRegexDestruct(&stmt->d.s_propfilt.regex_cache);
+ if(stmt->d.s_propfilt.pCSCompValue != NULL)
+ cstrDestruct(&stmt->d.s_propfilt.pCSCompValue);
+ cnfstmtDestructLst(stmt->d.s_propfilt.t_then);
+ break;
+ default:
+ dbgprintf("error: unknown stmt type during destruct %u\n",
+ (unsigned) stmt->nodetype);
+ break;
+ }
+ free(stmt->printable);
+ free(stmt);
+}
+
+/* delete a stmt and all others following it */
void
-cnfstmtDestruct(struct cnfstmt *root)
+cnfstmtDestructLst(struct cnfstmt *root)
{
struct cnfstmt *stmt, *todel;
for(stmt = root ; stmt != NULL ; ) {
- switch(stmt->nodetype) {
- case S_NOP:
- case S_STOP:
- break;
- case S_CALL:
- es_deleteStr(stmt->d.s_call.name);
- break;
- case S_ACT:
- actionDestruct(stmt->d.act);
- break;
- case S_IF:
- cnfexprDestruct(stmt->d.s_if.expr);
- if(stmt->d.s_if.t_then != NULL) {
- cnfstmtDestruct(stmt->d.s_if.t_then);
- }
- if(stmt->d.s_if.t_else != NULL) {
- cnfstmtDestruct(stmt->d.s_if.t_else);
- }
- break;
- case S_SET:
- free(stmt->d.s_set.varname);
- cnfexprDestruct(stmt->d.s_set.expr);
- break;
- case S_UNSET:
- free(stmt->d.s_set.varname);
- break;
- case S_PRIFILT:
- cnfstmtDestruct(stmt->d.s_prifilt.t_then);
- cnfstmtDestruct(stmt->d.s_prifilt.t_else);
- break;
- case S_PROPFILT:
- if(stmt->d.s_propfilt.propName != NULL)
- es_deleteStr(stmt->d.s_propfilt.propName);
- if(stmt->d.s_propfilt.regex_cache != NULL)
- rsCStrRegexDestruct(&stmt->d.s_propfilt.regex_cache);
- if(stmt->d.s_propfilt.pCSCompValue != NULL)
- cstrDestruct(&stmt->d.s_propfilt.pCSCompValue);
- cnfstmtDestruct(stmt->d.s_propfilt.t_then);
- break;
- default:
- dbgprintf("error: unknown stmt type during destruct %u\n",
- (unsigned) stmt->nodetype);
- break;
- }
- free(stmt->printable);
todel = stmt;
stmt = stmt->next;
- free(todel);
+ cnfstmtDestruct(todel);
}
}
@@ -2557,14 +2573,15 @@ struct cnfstmt *
cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then)
{
struct cnfstmt* cnfstmt;
- rsRetVal lRet;
if((cnfstmt = cnfstmtNew(S_PROPFILT)) != NULL) {
cnfstmt->printable = (uchar*)propfilt;
cnfstmt->d.s_propfilt.t_then = t_then;
cnfstmt->d.s_propfilt.propName = NULL;
cnfstmt->d.s_propfilt.regex_cache = NULL;
cnfstmt->d.s_propfilt.pCSCompValue = NULL;
- lRet = DecodePropFilter((uchar*)propfilt, cnfstmt);
+ if(DecodePropFilter((uchar*)propfilt, cnfstmt) != RS_RET_OK) {
+ cnfstmt->nodetype = S_NOP; /* disable action! */
+ }
}
return cnfstmt;
}
@@ -2769,7 +2786,7 @@ cnfexprOptimize_CMP_var(struct cnfexpr *expr)
parser_errmsg("invalid facility '%s', expression will always "
"evaluate to FALSE", cstr);
} else {
- /* we can acutally optimize! */
+ /* we can actually optimize! */
DBGPRINTF("optimizer: change comparison OP to FUNC prifilt()\n");
func = cnffuncNew_prifilt(fac);
if(expr->nodetype == CMP_NE)
@@ -2848,7 +2865,7 @@ cnfexprOptimize_AND_OR(struct cnfexpr *expr)
static inline void
cnfexprOptimize_CMPEQ_arr(struct cnfarray *arr)
{
- DBGPRINTF("optimizer: sorting array for CMP_EQ/NEQ comparison\n");
+ DBGPRINTF("optimizer: sorting array of %d members for CMP_EQ/NEQ comparison\n", arr->nmemb);
qsort(arr->arr, arr->nmemb, sizeof(es_str_t*), qs_arrcmp);
}
@@ -2910,10 +2927,14 @@ cnfexprOptimize(struct cnfexpr *expr)
expr->r = exprswap;
}
}
+ if(expr->r->nodetype == 'A') {
+ cnfexprOptimize_CMPEQ_arr((struct cnfarray *)expr->r);
+ }
+ /* This should be evaluated last because it may change expr
+ * to a function.
+ */
if(expr->l->nodetype == 'V') {
expr = cnfexprOptimize_CMP_var(expr);
- } else if(expr->r->nodetype == 'A') {
- cnfexprOptimize_CMPEQ_arr((struct cnfarray *)expr->r);
}
break;
case CMP_LE:
@@ -3050,7 +3071,7 @@ cnfstmtOptimizePRIFilt(struct cnfstmt *stmt)
DBGPRINTF("optimizer: removing always-true PRIFILT %p\n", stmt);
if(stmt->d.s_prifilt.t_else != NULL) {
parser_errmsg("error: always-true PRI filter has else part!\n");
- cnfstmtDestruct(stmt->d.s_prifilt.t_else);
+ cnfstmtDestructLst(stmt->d.s_prifilt.t_else);
}
free(stmt->printable);
stmt->printable = NULL;