summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-07-07 09:41:31 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2008-07-07 09:41:31 +0200
commit37fd063042821dc328c88e1f7366543decdcb76f (patch)
tree5f14f9144f7c4c9ad3a071535ccc8a4b48b40218
parent06001e951f5b5d0a7919c61057bc7a87b9eb8cba (diff)
downloadrsyslog-37fd063042821dc328c88e1f7366543decdcb76f.tar.gz
rsyslog-37fd063042821dc328c88e1f7366543decdcb76f.tar.xz
rsyslog-37fd063042821dc328c88e1f7366543decdcb76f.zip
added capability to create a printable string of a vmprg
This is needed so that we can create simple testbenches which will check the result of a test (a generated program) via a simple strcmp.
-rw-r--r--runtime/var.c40
-rw-r--r--runtime/var.h1
-rw-r--r--runtime/vmop.c37
-rw-r--r--runtime/vmop.h2
-rw-r--r--runtime/vmprg.c40
-rw-r--r--runtime/vmprg.h3
-rw-r--r--tests/rscript-parse.c16
7 files changed, 130 insertions, 9 deletions
diff --git a/runtime/var.c b/runtime/var.c
index 7e51fc6d..559bc56c 100644
--- a/runtime/var.c
+++ b/runtime/var.c
@@ -29,6 +29,7 @@
*/
#include "config.h"
+#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
@@ -89,6 +90,44 @@ CODESTARTobjDebugPrint(var)
ENDobjDebugPrint(var)
+/* This function is similar to DebugPrint, but does not send its output to
+ * the debug log but instead to a caller-provided string. The idea here is that
+ * we can use this string to get a textual representation of a variable.
+ * Among others, this is useful for creating testbenches, our first use case for
+ * it. Here, it enables simple comparison of the resulting program to a
+ * reference program by simple string compare.
+ * Note that the caller must initialize the string object. We always add
+ * data to it. So, it can be easily combined into a chain of methods
+ * to generate the final string.
+ * rgerhards, 2008-07-07
+ */
+static rsRetVal
+Obj2Str(var_t *pThis, cstr_t *pstrPrg)
+{
+ DEFiRet;
+ size_t lenBuf;
+ uchar szBuf[2048];
+
+ ISOBJ_TYPE_assert(pThis, var);
+ assert(pstrPrg != NULL);
+ switch(pThis->varType) {
+ case VARTYPE_STR:
+ lenBuf = snprintf((char*) szBuf, sizeof(szBuf), "%s[cstr]", rsCStrGetSzStr(pThis->val.pStr));
+ break;
+ case VARTYPE_NUMBER:
+ lenBuf = snprintf((char*) szBuf, sizeof(szBuf), "%lld[nbr]", pThis->val.num);
+ break;
+ default:
+ lenBuf = snprintf((char*) szBuf, sizeof(szBuf), "**UNKNOWN**[%d]", pThis->varType);
+ break;
+ }
+ CHKiRet(rsCStrAppendStrWithLen(pstrPrg, szBuf, lenBuf));
+
+finalize_it:
+ RETiRet;
+}
+
+
/* duplicates a var instance
* rgerhards, 2008-02-25
*/
@@ -387,6 +426,7 @@ CODESTARTobjQueryInterface(var)
pIf->ConstructFinalize = varConstructFinalize;
pIf->Destruct = varDestruct;
pIf->DebugPrint = varDebugPrint;
+ pIf->Obj2Str = Obj2Str;
pIf->SetNumber = varSetNumber;
pIf->SetString = varSetString;
pIf->ConvForOperation = ConvForOperation;
diff --git a/runtime/var.h b/runtime/var.h
index bbe7ba33..6d890ec9 100644
--- a/runtime/var.h
+++ b/runtime/var.h
@@ -59,6 +59,7 @@ BEGINinterface(var) /* name must also be changed in ENDinterface macro! */
rsRetVal (*ConvToNumber)(var_t *pThis);
rsRetVal (*ConvToBool)(var_t *pThis);
rsRetVal (*ConvToString)(var_t *pThis);
+ rsRetVal (*Obj2Str)(var_t *pThis, cstr_t*);
rsRetVal (*Duplicate)(var_t *pThis, var_t **ppNew);
ENDinterface(var)
#define varCURR_IF_VERSION 1 /* increment whenever you change the interface above! */
diff --git a/runtime/vmop.c b/runtime/vmop.c
index 219315c4..fcacb15b 100644
--- a/runtime/vmop.c
+++ b/runtime/vmop.c
@@ -25,6 +25,7 @@
*/
#include "config.h"
+#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
@@ -81,6 +82,39 @@ CODESTARTobjDebugPrint(vmop)
ENDobjDebugPrint(vmop)
+/* This function is similar to DebugPrint, but does not send its output to
+ * the debug log but instead to a caller-provided string. The idea here is that
+ * we can use this string to get a textual representation of an operation.
+ * Among others, this is useful for creating testbenches, our first use case for
+ * it. Here, it enables simple comparison of the resulting program to a
+ * reference program by simple string compare.
+ * Note that the caller must initialize the string object. We always add
+ * data to it. So, it can be easily combined into a chain of methods
+ * to generate the final string.
+ * rgerhards, 2008-07-04
+ */
+static rsRetVal
+Obj2Str(vmop_t *pThis, cstr_t *pstrPrg)
+{
+ uchar *pOpcodeName;
+ uchar szBuf[2048];
+ size_t lenBuf;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, vmop);
+ assert(pstrPrg != NULL);
+ vmopOpcode2Str(pThis, &pOpcodeName);
+ lenBuf = snprintf((char*) szBuf, sizeof(szBuf), "%s\t", pOpcodeName);
+ CHKiRet(rsCStrAppendStrWithLen(pstrPrg, szBuf, lenBuf));
+ if(pThis->operand.pVar != NULL)
+ CHKiRet(var.Obj2Str(pThis->operand.pVar, pstrPrg));
+ CHKiRet(rsCStrAppendChar(pstrPrg, '\n'));
+
+finalize_it:
+ RETiRet;
+}
+
+
/* set operand (variant case)
* rgerhards, 2008-02-20
*/
@@ -206,8 +240,6 @@ CODESTARTobjQueryInterface(vmop)
* work here (if we can support an older interface version - that,
* of course, also affects the "if" above).
*/
- //xxxpIf->oID = OBJvmop;
-
pIf->Construct = vmopConstruct;
pIf->ConstructFinalize = vmopConstructFinalize;
pIf->Destruct = vmopDestruct;
@@ -215,6 +247,7 @@ CODESTARTobjQueryInterface(vmop)
pIf->SetOpcode = vmopSetOpcode;
pIf->SetVar = vmopSetVar;
pIf->Opcode2Str = vmopOpcode2Str;
+ pIf->Obj2Str = Obj2Str;
finalize_it:
ENDobjQueryInterface(vmop)
diff --git a/runtime/vmop.h b/runtime/vmop.h
index 97f924d7..c3d5d5f4 100644
--- a/runtime/vmop.h
+++ b/runtime/vmop.h
@@ -26,6 +26,7 @@
#define INCLUDED_VMOP_H
#include "ctok_token.h"
+#include "stringbuf.h"
/* machine instructions types */
typedef enum { /* do NOT start at 0 to detect uninitialized types after calloc() */
@@ -83,6 +84,7 @@ BEGINinterface(vmop) /* name must also be changed in ENDinterface macro! */
rsRetVal (*SetOpcode)(vmop_t *pThis, opcode_t opcode);
rsRetVal (*SetVar)(vmop_t *pThis, var_t *pVar);
rsRetVal (*Opcode2Str)(vmop_t *pThis, uchar **ppName);
+ rsRetVal (*Obj2Str)(vmop_t *pThis, cstr_t *pstr);
ENDinterface(vmop)
#define vmopCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
diff --git a/runtime/vmprg.c b/runtime/vmprg.c
index a2b744d7..c7354fe4 100644
--- a/runtime/vmprg.c
+++ b/runtime/vmprg.c
@@ -24,12 +24,14 @@
*/
#include "config.h"
+#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "rsyslog.h"
#include "obj.h"
#include "vmprg.h"
+#include "stringbuf.h"
/* static data */
DEFobjStaticHelpers
@@ -79,6 +81,41 @@ CODESTARTobjDebugPrint(vmprg)
ENDobjDebugPrint(vmprg)
+/* This function is similar to DebugPrint, but does not send its output to
+ * the debug log but instead to a caller-provided string. The idea here is that
+ * we can use this string to get a textual representation of a bytecode program.
+ * Among others, this is useful for creating testbenches, our first use case for
+ * it. Here, it enables simple comparison of the resulting program to a
+ * reference program by simple string compare.
+ * Note that the caller must initialize the string object. We always add
+ * data to it. So, it can be easily combined into a chain of methods
+ * to generate the final string.
+ * rgerhards, 2008-07-04
+ */
+static rsRetVal
+Obj2Str(vmprg_t *pThis, cstr_t *pstrPrg)
+{
+ uchar szAddr[12];
+ vmop_t *pOp;
+ int i;
+ int lenAddr;
+ DEFiRet;
+
+ ISOBJ_TYPE_assert(pThis, vmprg);
+ assert(pstrPrg != NULL);
+ CHKiRet(rsCStrAppendStr(pstrPrg, (uchar*)"program contents:\n"));
+ i = 0; /* "program counter" */
+ for(pOp = pThis->vmopRoot ; pOp != NULL ; pOp = pOp->pNext) {
+ lenAddr = snprintf((char*)szAddr, sizeof(szAddr), "%8.8d: ", i++);
+ CHKiRet(rsCStrAppendStrWithLen(pstrPrg, szAddr, lenAddr));
+ vmop.Obj2Str(pOp, pstrPrg);
+ }
+
+finalize_it:
+ RETiRet;
+}
+
+
/* add an operation (instruction) to the end of the current program. This
* function is expected to be called while creating the program, but never
* again after this is done and it is being executed. Results are undefined if
@@ -146,12 +183,11 @@ CODESTARTobjQueryInterface(vmprg)
* work here (if we can support an older interface version - that,
* of course, also affects the "if" above).
*/
- //xxxpIf->oID = OBJvmprg;
-
pIf->Construct = vmprgConstruct;
pIf->ConstructFinalize = vmprgConstructFinalize;
pIf->Destruct = vmprgDestruct;
pIf->DebugPrint = vmprgDebugPrint;
+ pIf->Obj2Str = Obj2Str;
pIf->AddOperation = vmprgAddOperation;
pIf->AddVarOperation = vmprgAddVarOperation;
finalize_it:
diff --git a/runtime/vmprg.h b/runtime/vmprg.h
index db1f62f0..c1042f7d 100644
--- a/runtime/vmprg.h
+++ b/runtime/vmprg.h
@@ -38,7 +38,7 @@
#define INCLUDED_VMPRG_H
#include "vmop.h"
-
+#include "stringbuf.h"
/* the vmprg object */
typedef struct vmprg_s {
@@ -56,6 +56,7 @@ BEGINinterface(vmprg) /* name must also be changed in ENDinterface macro! */
rsRetVal (*Destruct)(vmprg_t **ppThis);
rsRetVal (*AddOperation)(vmprg_t *pThis, vmop_t *pOp);
rsRetVal (*AddVarOperation)(vmprg_t *pThis, opcode_t opcode, var_t *pVar);
+ rsRetVal (*Obj2Str)(vmprg_t *pThis, cstr_t *pstr);
ENDinterface(vmprg)
#define vmprgCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
diff --git a/tests/rscript-parse.c b/tests/rscript-parse.c
index 176f3f7e..01ddb7d1 100644
--- a/tests/rscript-parse.c
+++ b/tests/rscript-parse.c
@@ -21,6 +21,7 @@
*
* A copy of the GPL can be found in the file "COPYING" in this distribution.
*/
+#include "config.h"
#include <stdio.h>
#include "rsyslog.h"
@@ -33,12 +34,14 @@ MODULE_TYPE_TESTBENCH
DEFobjCurrIf(expr)
DEFobjCurrIf(ctok)
DEFobjCurrIf(ctok_token)
+DEFobjCurrIf(vmprg)
BEGINInit
CODESTARTInit
pErrObj = "expr"; CHKiRet(objUse(expr, CORE_COMPONENT));
pErrObj = "ctok"; CHKiRet(objUse(ctok, CORE_COMPONENT));
pErrObj = "ctok_token"; CHKiRet(objUse(ctok_token, CORE_COMPONENT));
+ pErrObj = "vmprg"; CHKiRet(objUse(vmprg, CORE_COMPONENT));
ENDInit
BEGINExit
@@ -46,13 +49,15 @@ CODESTARTExit
ENDExit
BEGINTest
+ cstr_t *pstrPrg;
ctok_t *tok;
ctok_token_t *pToken;
expr_t *pExpr;
/* the string below is an expression as defined up to 3.19.x - note that the
* then and the space after it MUST be present!
*/
- uchar szExpr[] = " $msg contains 'test' then ";
+ //uchar szExpr[] = " $msg contains 'test' then ";
+ uchar szExpr[] = "'test 1' <> $var or /* some comment */($SEVERITY == -4 +5 -(3 * - 2) and $fromhost == '127.0.0.1') then ";
/*uchar szSynErr[] = "$msg == 1 and syntaxerror ";*/
CODESTARTTest
/* we first need a tokenizer... */
@@ -77,16 +82,19 @@ CODESTARTTest
* Should anyone have any insight, I'd really appreciate if you drop me
* a line.
*/
-#if 0
CHKiRet(ctok.GetToken(tok, &pToken));
if(pToken->tok != ctok_THEN) {
-//printf("invalid token, probably due to invalid alignment between runtime lib and this program\n");
ctok_token.Destruct(&pToken);
ABORT_FINALIZE(RS_RET_SYNTAX_ERROR);
}
ctok_token.Destruct(&pToken); /* no longer needed */
-#endif
+
+ CHKiRet(rsCStrConstruct(&pstrPrg));
+ CHKiRet(vmprg.Obj2Str(pExpr->pVmprg, pstrPrg));
+
+ printf("string returned: '%s'\n", rsCStrGetSzStr(pstrPrg));
+ rsCStrDestruct(&pstrPrg);
/* we are done, so we now need to restore things */
CHKiRet(ctok.Destruct(&tok));