From 37fd063042821dc328c88e1f7366543decdcb76f Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Mon, 7 Jul 2008 09:41:31 +0200 Subject: 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. --- runtime/var.c | 40 ++++++++++++++++++++++++++++++++++++++++ runtime/var.h | 1 + runtime/vmop.c | 37 +++++++++++++++++++++++++++++++++++-- runtime/vmop.h | 2 ++ runtime/vmprg.c | 40 ++++++++++++++++++++++++++++++++++++++-- runtime/vmprg.h | 3 ++- 6 files changed, 118 insertions(+), 5 deletions(-) (limited to 'runtime') 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 #include #include @@ -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 #include #include @@ -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 #include #include #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! */ -- cgit