summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-02-25 08:14:12 +0000
committerRainer Gerhards <rgerhards@adiscon.com>2008-02-25 08:14:12 +0000
commitb7f58acb515b102547976cc02bc3fcfcef18dd0c (patch)
tree09b39f5584577e921cc9b7510b324e5365a353d8
parent965c09147c8f87e4ed6ece46b9d54e612e35cf11 (diff)
downloadrsyslog-b7f58acb515b102547976cc02bc3fcfcef18dd0c.tar.gz
rsyslog-b7f58acb515b102547976cc02bc3fcfcef18dd0c.tar.xz
rsyslog-b7f58acb515b102547976cc02bc3fcfcef18dd0c.zip
implemented data type conversion
-rwxr-xr-xsrUtils.c10
-rw-r--r--var.c40
-rw-r--r--var.h3
-rw-r--r--vm.c64
-rw-r--r--vmstk.c55
-rw-r--r--vmstk.h3
6 files changed, 131 insertions, 44 deletions
diff --git a/srUtils.c b/srUtils.c
index 652ae5c8..d20f1174 100755
--- a/srUtils.c
+++ b/srUtils.c
@@ -28,7 +28,7 @@
*/
#include "config.h"
-#include "rsyslog.h" /* THIS IS A MODIFICATION FOR RSYSLOG! 2004-11-18 rgerards */
+#include "rsyslog.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -39,7 +39,7 @@
#include <assert.h>
#include <sys/wait.h>
#include <ctype.h>
-#include "liblogging-stub.h" /* THIS IS A MODIFICATION FOR RSYSLOG! 2004-11-18 rgerards */
+#include "liblogging-stub.h"
#define TRUE 1
#define FALSE 0
#include "srUtils.h"
@@ -392,14 +392,8 @@ timeoutVal(struct timespec *pt)
assert(pt != NULL);
/* compute timeout */
clock_gettime(CLOCK_REALTIME, &t);
-//RUNLOG_VAR("%ld", pt->tv_sec);
-//RUNLOG_VAR("%ld", t.tv_sec);
-//RUNLOG_VAR("%ld", pt->tv_nsec);
-//RUNLOG_VAR("%ld", t.tv_nsec);
iTimeout = (pt->tv_nsec - t.tv_nsec) / 1000000;
-//RUNLOG_VAR("%ld", iTimeout);
iTimeout += (pt->tv_sec - t.tv_sec) * 1000;
-//RUNLOG_VAR("%ld", iTimeout);
if(iTimeout < 0)
iTimeout = 0;
diff --git a/var.c b/var.c
index 6910986e..8b5a8dd0 100644
--- a/var.c
+++ b/var.c
@@ -33,6 +33,7 @@
#include "rsyslog.h"
#include "obj.h"
+#include "srUtils.h"
#include "var.h"
/* static data */
@@ -176,13 +177,13 @@ rsRetVal
ConvToString(var_t *pThis)
{
DEFiRet;
+ uchar szNumBuf[64];
if(pThis->varType == VARTYPE_STR) {
FINALIZE;
} else if(pThis->varType == VARTYPE_NUMBER) {
- //CHKiRet(rsCStrConvertToNumber(pThis->val.pStr, &n));
- //pThis->val.num = n;
- // TODO: ADD CODE!!!!
+ CHKiRet(srUtilItoA((char*)szNumBuf, sizeof(szNumBuf)/sizeof(uchar), pThis->val.num));
+ CHKiRet(rsCStrConstructFromszStr(&pThis->val.pStr, szNumBuf));
pThis->varType = VARTYPE_STR;
}
@@ -191,9 +192,32 @@ finalize_it:
}
+/* convert (if necessary) the value to a boolean. In essence, this means the
+ * value must be a number, but in case of a string special logic is used as
+ * some string-values may represent a boolean (e.g. "true").
+ * rgerhards, 2008-02-25
+ */
+rsRetVal
+ConvToBool(var_t *pThis)
+{
+ DEFiRet;
+ number_t n;
+
+ if(pThis->varType == VARTYPE_NUMBER) {
+ FINALIZE;
+ } else if(pThis->varType == VARTYPE_STR) {
+ CHKiRet(rsCStrConvertToBool(pThis->val.pStr, &n));
+ pThis->val.num = n;
+ pThis->varType = VARTYPE_NUMBER;
+ }
+
+finalize_it:
+ RETiRet;
+}
+
/* This function is used to prepare two var_t objects for a common operation,
- * e.g before they are added, multiplied or compared. The function looks at
+ * e.g before they are added, compared. The function looks at
* the data types of both operands and finds the best data type suitable for
* the operation (in respect to current types). Then, it converts those
* operands that need conversion. Please note that the passed-in var objects
@@ -229,7 +253,6 @@ static rsRetVal
ConvForOperation(var_t *pThis, var_t *pOther)
{
DEFiRet;
- varType_t commonType;
if(pThis->varType == VARTYPE_NONE || pOther->varType == VARTYPE_NONE)
ABORT_FINALIZE(RS_RET_INVALID_VAR);
@@ -244,7 +267,7 @@ ConvForOperation(var_t *pThis, var_t *pOther)
ABORT_FINALIZE(RS_RET_INVALID_VAR);
break;
case VARTYPE_STR:
- /* two strings, we are all set */
+ FINALIZE; /* two strings, we are all set */
break;
case VARTYPE_NUMBER:
/* check if we can convert pThis to a number, if so use number format. */
@@ -274,7 +297,7 @@ ConvForOperation(var_t *pThis, var_t *pOther)
}
break;
case VARTYPE_NUMBER:
- commonType = VARTYPE_NUMBER;
+ FINALIZE; /* two numbers, so we are all set */
break;
case VARTYPE_SYSLOGTIME:
ABORT_FINALIZE(RS_RET_NOT_IMPLEMENTED);
@@ -314,6 +337,9 @@ CODESTARTobjQueryInterface(var)
pIf->SetNumber = varSetNumber;
pIf->SetString = varSetString;
pIf->ConvForOperation = ConvForOperation;
+ pIf->ConvToNumber = ConvToNumber;
+ pIf->ConvToBool = ConvToBool;
+ pIf->ConvToString = ConvToString;
finalize_it:
ENDobjQueryInterface(var)
diff --git a/var.h b/var.h
index 77ccb8c6..3ebc1021 100644
--- a/var.h
+++ b/var.h
@@ -55,6 +55,9 @@ BEGINinterface(var) /* name must also be changed in ENDinterface macro! */
rsRetVal (*SetNumber)(var_t *pThis, number_t iVal);
rsRetVal (*SetString)(var_t *pThis, cstr_t *pCStr);
rsRetVal (*ConvForOperation)(var_t *pThis, var_t *pOther);
+ rsRetVal (*ConvToNumber)(var_t *pThis);
+ rsRetVal (*ConvToBool)(var_t *pThis);
+ rsRetVal (*ConvToString)(var_t *pThis);
ENDinterface(var)
#define varCURR_IF_VERSION 1 /* increment whenever you change the interface above! */
diff --git a/vm.c b/vm.c
index 93c0d5f6..fe6d9b59 100644
--- a/vm.c
+++ b/vm.c
@@ -33,56 +33,60 @@
/* static data */
DEFobjStaticHelpers
DEFobjCurrIf(vmstk)
+DEFobjCurrIf(var)
/* ------------------------------ instruction set implementation ------------------------------ *
* The following functions implement the VM's instruction set.
*/
#define BEGINop(instruction) \
- static rsRetVal op##instruction(vm_t *pThis, vmop_t *pOp) \
+ static rsRetVal op##instruction(vm_t *pThis, __attribute__((unused)) vmop_t *pOp) \
{ \
DEFiRet;
#define CODESTARTop(instruction) \
- ISOBJ_TYPE_assert(pThis, vm); \
- ISOBJ_TYPE_assert(pOp, vmop);
+ ISOBJ_TYPE_assert(pThis, vm);
#define ENDop(instruction) \
RETiRet; \
}
+/* code generator for boolean operations */
+#define BOOLOP(name, OPERATION) \
+BEGINop(name) /* remember to set the instruction also in the ENDop macro! */ \
+ var_t *operand1; \
+ var_t *operand2; \
+ vmstk.PopBool(pThis->pStk, &operand1); \
+ vmstk.PopBool(pThis->pStk, &operand2); \
+ if(operand1->val.num OPERATION 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 */ \
+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)
- // Pop(2, &pVar); --> should also do the conversion outlined below
- vmstk.Pop(pThis->pStk, &operand1);
- vmstk.Pop(pThis->pStk, &operand2);
- // TODO: implement
- /* We must check data types and find out on which data type the
- * operation needs to be performed. This may result in some data types
- * being converted.
- *
- * Current school of thought:
- * op1 op2 operation data type
- * string string string
- * string number number if op1 can be converted to number, string else
- * date string date if op1 can be converted to date, string else
- * number number number
- * date number string (maybe we can do better?)
- * date date date
- *
- * If a boolean value is required, we need to have a number inside the
- * operand. If it is not, conversion rules to number apply. Once we
- * have a number, things get easy: 0 is false, anything else is true.
- * Please note that due to this conversion rules, "0" becomes false
- * while "-4712" becomes true. Using a date as boolen is not a good
- * idea. Depending on the ultimate conversion rules, it may always
- * become true or false. As such, using dates as booleans is
- * prohibited and the result defined to be undefined.
- */
+ 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! */
@@ -94,6 +98,7 @@ CODESTARTop(AND)
// TODO: implement
vmstk.Push(pThis->pStk, operand1); /* result */
ENDop(AND)
+#endif
BEGINop(POP) /* remember to set the instruction also in the ENDop macro! */
CODESTARTop(POP)
@@ -211,6 +216,7 @@ ENDobjQueryInterface(vm)
BEGINObjClassInit(vm, 1) /* class, version */
/* request objects we use */
CHKiRet(objUse(vmstk));
+ CHKiRet(objUse(var));
/* set our own handlers */
OBJSetMethodHandler(objMethod_DEBUGPRINT, vmDebugPrint);
diff --git a/vmstk.c b/vmstk.c
index 6944b6f9..0e035543 100644
--- a/vmstk.c
+++ b/vmstk.c
@@ -109,6 +109,57 @@ finalize_it:
}
+/* pop a boolean value from the stack
+ * The user is responsible for destructing the ppVar returned.
+ */
+static rsRetVal
+popBool(vmstk_t *pThis, var_t **ppVar)
+{
+ DEFiRet;
+
+ /* assertions are done in pop(), we do not duplicate here */
+ CHKiRet(pop(pThis, ppVar));
+ CHKiRet(var.ConvToBool(*ppVar));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* pop a number value from the stack
+ * The user is responsible for destructing the ppVar returned.
+ */
+static rsRetVal
+popNumber(vmstk_t *pThis, var_t **ppVar)
+{
+ DEFiRet;
+
+ /* assertions are done in pop(), we do not duplicate here */
+ CHKiRet(pop(pThis, ppVar));
+ CHKiRet(var.ConvToNumber(*ppVar));
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* pop a number value from the stack
+ * The user is responsible for destructing the ppVar returned.
+ */
+static rsRetVal
+popString(vmstk_t *pThis, var_t **ppVar)
+{
+ DEFiRet;
+
+ /* assertions are done in pop(), we do not duplicate here */
+ CHKiRet(pop(pThis, ppVar));
+ CHKiRet(var.ConvToString(*ppVar));
+
+finalize_it:
+ RETiRet;
+}
+
+
/* queryInterface function
* rgerhards, 2008-02-21
*/
@@ -131,6 +182,10 @@ CODESTARTobjQueryInterface(vmstk)
pIf->DebugPrint = vmstkDebugPrint;
pIf->Push = push;
pIf->Pop = pop;
+ pIf->PopBool = popBool;
+ pIf->PopNumber = popNumber;
+ pIf->PopString = popString;
+
finalize_it:
ENDobjQueryInterface(vmstk)
diff --git a/vmstk.h b/vmstk.h
index 30bb9009..206c7070 100644
--- a/vmstk.h
+++ b/vmstk.h
@@ -41,6 +41,9 @@ BEGINinterface(vmstk) /* name must also be changed in ENDinterface macro! */
rsRetVal (*Destruct)(vmstk_t **ppThis);
rsRetVal (*Push)(vmstk_t *pThis, var_t *pVar);
rsRetVal (*Pop)(vmstk_t *pThis, var_t **ppVar);
+ rsRetVal (*PopBool)(vmstk_t *pThis, var_t **ppVar);
+ rsRetVal (*PopNumber)(vmstk_t *pThis, var_t **ppVar);
+ rsRetVal (*PopString)(vmstk_t *pThis, var_t **ppVar);
ENDinterface(vmstk)
#define vmstkCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */