summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--vm.c136
-rw-r--r--vmstk.c26
-rw-r--r--vmstk.h1
3 files changed, 138 insertions, 25 deletions
diff --git a/vm.c b/vm.c
index fe6d9b59..7b933c39 100644
--- a/vm.c
+++ b/vm.c
@@ -29,6 +29,7 @@
#include "rsyslog.h"
#include "obj.h"
#include "vm.h"
+#include "stringbuf.h"
/* static data */
DEFobjStaticHelpers
@@ -56,6 +57,7 @@ DEFobjCurrIf(var)
BEGINop(name) /* remember to set the instruction also in the ENDop macro! */ \
var_t *operand1; \
var_t *operand2; \
+CODESTARTop(name) \
vmstk.PopBool(pThis->pStk, &operand1); \
vmstk.PopBool(pThis->pStk, &operand2); \
if(operand1->val.num OPERATION operand2->val.num) { \
@@ -67,38 +69,114 @@ BEGINop(name) /* remember to set the instruction also in the ENDop macro! */ \
var.Destruct(&operand2); /* no longer needed */ \
finalize_it: \
ENDop(name)
-
BOOLOP(OR, ||)
BOOLOP(AND, &&)
-
#undef BOOLOP
-#if 0
-BEGINop(OR) /* remember to set the instruction also in the ENDop macro! */
- // var_t *pVar[2];
- var_t *operand1;
- var_t *operand2;
-CODESTARTop(OR)
- vmstk.PopBool(pThis->pStk, &operand1);
- vmstk.PopBool(pThis->pStk, &operand2);
- if(operand1->val.num || operand2->val.num) {
- CHKiRet(var.SetNumber(operand1, 1));
- } else {
- CHKiRet(var.SetNumber(operand1, 0));
- }
- vmstk.Push(pThis->pStk, operand1); /* result */
- var.Destruct(operand2); /* no longer needed */
-ENDop(OR)
-BEGINop(AND) /* remember to set the instruction also in the ENDop macro! */
+
+/* code generator for compare operations */
+#define BEGINCMPOP(name) \
+BEGINop(name) \
+ var_t *operand1; \
+ var_t *operand2; \
+ int bRes; \
+CODESTARTop(name) \
+ CHKiRet(vmstk.Pop2CommOp(pThis->pStk, &operand1, &operand2)); \
+ /* data types are equal (so we look only at operand1), but we must \
+ * check which type we have to deal with... \
+ */ \
+ switch(operand1->varType) {
+#define ENDCMPOP(name) \
+ default: \
+ bRes = 0; /* we do not abort just so that we have a value. TODO: reconsider */ \
+ break; \
+ } \
+ \
+ /* we have a result, so let's push it */ \
+ var.SetNumber(operand1, bRes); \
+ vmstk.Push(pThis->pStk, operand1); /* result */ \
+ var.Destruct(&operand2); /* no longer needed */ \
+finalize_it: \
+ENDop(name)
+
+BEGINCMPOP(CMP_EQ) /* remember to change the name also in the END macro! */
+ case VARTYPE_NUMBER:
+ bRes = operand1->val.num == operand2->val.num;
+ break;
+ case VARTYPE_STR:
+ bRes = !rsCStrCStrCmp(operand1->val.pStr, operand2->val.pStr);
+ break;
+ENDCMPOP(CMP_EQ)
+
+BEGINCMPOP(CMP_NEQ) /* remember to change the name also in the END macro! */
+ case VARTYPE_NUMBER:
+ bRes = operand1->val.num != operand2->val.num;
+ break;
+ case VARTYPE_STR:
+ bRes = rsCStrCStrCmp(operand1->val.pStr, operand2->val.pStr);
+ break;
+ENDCMPOP(CMP_EQ)
+
+BEGINCMPOP(CMP_LT) /* remember to change the name also in the END macro! */
+ case VARTYPE_NUMBER:
+ bRes = operand1->val.num < operand2->val.num;
+ break;
+ case VARTYPE_STR:
+ bRes = rsCStrCStrCmp(operand1->val.pStr, operand2->val.pStr) < 0;
+ break;
+ENDCMPOP(CMP_LT)
+
+BEGINCMPOP(CMP_GT) /* remember to change the name also in the END macro! */
+ case VARTYPE_NUMBER:
+ bRes = operand1->val.num > operand2->val.num;
+ break;
+ case VARTYPE_STR:
+ bRes = rsCStrCStrCmp(operand1->val.pStr, operand2->val.pStr) > 0;
+ break;
+ENDCMPOP(CMP_GT)
+
+BEGINCMPOP(CMP_LTEQ) /* remember to change the name also in the END macro! */
+ case VARTYPE_NUMBER:
+ bRes = operand1->val.num <= operand2->val.num;
+ break;
+ case VARTYPE_STR:
+ bRes = rsCStrCStrCmp(operand1->val.pStr, operand2->val.pStr) <= 0;
+ break;
+ENDCMPOP(CMP_LTEQ)
+
+BEGINCMPOP(CMP_GTEQ) /* remember to change the name also in the END macro! */
+ case VARTYPE_NUMBER:
+ bRes = operand1->val.num >= operand2->val.num;
+ break;
+ case VARTYPE_STR:
+ bRes = rsCStrCStrCmp(operand1->val.pStr, operand2->val.pStr) >= 0;
+ break;
+ENDCMPOP(CMP_GTEQ)
+
+#undef BEGINCMPOP
+#undef ENDCMPOP
+/* end regular compare operations */
+
+/* comare operations that work on strings, only */
+BEGINop(CMP_CONTAINS) /* remember to set the instruction also in the ENDop macro! */
var_t *operand1;
var_t *operand2;
-CODESTARTop(AND)
- vmstk.Pop(pThis->pStk, &operand1);
- vmstk.Pop(pThis->pStk, &operand2);
- // TODO: implement
+ int bRes;
+CODESTARTop(CMP_CONTAINS)
+ /* operand2 is on top of stack, so needs to be popped first */
+ vmstk.PopString(pThis->pStk, &operand2);
+ vmstk.PopString(pThis->pStk, &operand1);
+ /* TODO: extend cstr class so that it supports location of cstr inside cstr */
+ bRes = (rsCStrLocateInSzStr(operand2->val.pStr, rsCStrGetSzStr(operand1->val.pStr)) == -1) ? 0 : 1;
+
+ /* we have a result, so let's push it */
+ var.SetNumber(operand1, bRes);
vmstk.Push(pThis->pStk, operand1); /* result */
-ENDop(AND)
-#endif
+ var.Destruct(&operand2); /* no longer needed */
+ENDop(CMP_CONTAINS)
+
+/* end comare operations that work on strings, only */
+
BEGINop(POP) /* remember to set the instruction also in the ENDop macro! */
CODESTARTop(POP)
@@ -162,6 +240,14 @@ execProg(vm_t *pThis, vmprg_t *pProg)
switch(pCurrOp->opcode) {
doOP(OR);
doOP(AND);
+ doOP(CMP_EQ);
+ doOP(CMP_NEQ);
+ doOP(CMP_LT);
+ doOP(CMP_GT);
+ doOP(CMP_LTEQ);
+ doOP(CMP_GTEQ);
+ doOP(CMP_CONTAINS);
+ // TODO: implement: doOP(CMP_STARTSWITH);
doOP(POP);
doOP(PUSHCONSTANT);
default:
diff --git a/vmstk.c b/vmstk.c
index 0e035543..6f8d36f6 100644
--- a/vmstk.c
+++ b/vmstk.c
@@ -160,6 +160,31 @@ finalize_it:
}
+/* pop two variables for a common operation, e.g. a compare. When this
+ * functions returns, both variables have the same type, but the type
+ * is not set to anything specific.
+ * The user is responsible for destructing the ppVar's returned.
+ * A quick note on the name: it means pop 2 variable for a common
+ * opertion - just in case you wonder (I don't really like the name,
+ * but I didn't come up with a better one...).
+ * rgerhards, 2008-02-25
+ */
+static rsRetVal
+pop2CommOp(vmstk_t *pThis, var_t **ppVar1, var_t **ppVar2)
+{
+ DEFiRet;
+
+ /* assertions are done in pop(), we do not duplicate here */
+ /* operand two must be popped first, because it is at the top of stack */
+ CHKiRet(pop(pThis, ppVar2));
+ CHKiRet(pop(pThis, ppVar1));
+ CHKiRet(var.ConvForOperation(*ppVar1, *ppVar2));
+
+finalize_it:
+ RETiRet;
+}
+
+
/* queryInterface function
* rgerhards, 2008-02-21
*/
@@ -185,6 +210,7 @@ CODESTARTobjQueryInterface(vmstk)
pIf->PopBool = popBool;
pIf->PopNumber = popNumber;
pIf->PopString = popString;
+ pIf->Pop2CommOp = pop2CommOp;
finalize_it:
ENDobjQueryInterface(vmstk)
diff --git a/vmstk.h b/vmstk.h
index 206c7070..2033ba83 100644
--- a/vmstk.h
+++ b/vmstk.h
@@ -44,6 +44,7 @@ BEGINinterface(vmstk) /* name must also be changed in ENDinterface macro! */
rsRetVal (*PopBool)(vmstk_t *pThis, var_t **ppVar);
rsRetVal (*PopNumber)(vmstk_t *pThis, var_t **ppVar);
rsRetVal (*PopString)(vmstk_t *pThis, var_t **ppVar);
+ rsRetVal (*Pop2CommOp)(vmstk_t *pThis, var_t **ppVar1, var_t **ppVar2);
ENDinterface(vmstk)
#define vmstkCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */