summaryrefslogtreecommitdiffstats
path: root/runtime/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/vm.c')
-rw-r--r--runtime/vm.c62
1 files changed, 59 insertions, 3 deletions
diff --git a/runtime/vm.c b/runtime/vm.c
index aaf3c879..84ba4bcf 100644
--- a/runtime/vm.c
+++ b/runtime/vm.c
@@ -34,6 +34,7 @@
#include "vm.h"
#include "sysvar.h"
#include "stringbuf.h"
+#include "unicode-helper.h"
/* static data */
DEFobjStaticHelpers
@@ -41,6 +42,8 @@ DEFobjCurrIf(vmstk)
DEFobjCurrIf(var)
DEFobjCurrIf(sysvar)
+static pthread_mutex_t mutGetenv; /* we need to make this global because otherwise we can not guarantee proper init! */
+
/* ------------------------------ function registry code and structures ------------------------------ */
/* we maintain a registry of known functions */
@@ -285,7 +288,7 @@ BEGINCMPOP(CMP_NEQ) /* remember to change the name also in the END macro! */
case VARTYPE_STR:
bRes = rsCStrCStrCmp(operand1->val.pStr, operand2->val.pStr);
break;
-ENDCMPOP(CMP_EQ)
+ENDCMPOP(CMP_NEQ)
BEGINCMPOP(CMP_LT) /* remember to change the name also in the END macro! */
case VARTYPE_NUMBER:
@@ -471,6 +474,15 @@ CODESTARTop(PUSHSYSVAR)
CHKiRet(sysvar.GetVar(pOp->operand.pVar->val.pStr, &pVal));
vmstk.Push(pThis->pStk, pVal);
finalize_it:
+ if(Debug && iRet != RS_RET_OK) {
+ if(iRet == RS_RET_SYSVAR_NOT_FOUND) {
+ DBGPRINTF("rainerscript: sysvar '%s' not found\n",
+ rsCStrGetSzStrNoNULL(pOp->operand.pVar->val.pStr));
+ } else {
+ DBGPRINTF("rainerscript: error %d trying to obtain sysvar '%s'\n",
+ iRet, rsCStrGetSzStrNoNULL(pOp->operand.pVar->val.pStr));
+ }
+ }
ENDop(PUSHSYSVAR)
/* The function call operation is only very roughly implemented. While the plumbing
@@ -542,6 +554,42 @@ finalize_it:
}
+/* The getenv function. Note that we guard the OS call by a mutex, as that
+ * function is not guaranteed to be thread-safe. This implementation here is far from
+ * being optimal, at least we should cache the result. This is left TODO for
+ * a later revision.
+ * rgerhards, 2009-11-03
+ */
+static rsRetVal
+rsf_getenv(vmstk_t *pStk, int numOperands)
+{
+ DEFiRet;
+ var_t *operand1;
+ char *envResult;
+ cstr_t *pCstr;
+
+ if(numOperands != 1)
+ ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS);
+
+ /* pop args and do operaton (trivial case here...) */
+ vmstk.PopString(pStk, &operand1);
+ d_pthread_mutex_lock(&mutGetenv);
+ envResult = getenv((char*) rsCStrGetSzStr(operand1->val.pStr));
+ DBGPRINTF("rsf_getenv(): envvar '%s', return '%s'\n", rsCStrGetSzStr(operand1->val.pStr),
+ envResult == NULL ? "(NULL)" : envResult);
+ iRet = rsCStrConstructFromszStr(&pCstr, (envResult == NULL) ? UCHAR_CONSTANT("") : (uchar*)envResult);
+ d_pthread_mutex_unlock(&mutGetenv);
+ if(iRet != RS_RET_OK)
+ FINALIZE; /* need to do this after mutex is unlocked! */
+
+ /* Store result and cleanup */
+ var.SetString(operand1, pCstr);
+ vmstk.Push(pStk, operand1);
+finalize_it:
+ RETiRet;
+}
+
+
/* The "tolower" function, which converts its sole argument to lower case.
* Quite honestly, currently this is primarily a test driver for me...
* rgerhards, 2009-04-06
@@ -627,9 +675,11 @@ execProg(vm_t *pThis, vmprg_t *pProg)
ISOBJ_TYPE_assert(pThis, vm);
ISOBJ_TYPE_assert(pProg, vmprg);
-#define doOP(OP) case opcode_##OP: CHKiRet(op##OP(pThis, pCurrOp)); break
+#define doOP(OP) case opcode_##OP: DBGPRINTF("rainerscript: opcode %s\n", #OP); \
+ CHKiRet(op##OP(pThis, pCurrOp)); break
pCurrOp = pProg->vmopRoot; /* TODO: do this via a method! */
while(pCurrOp != NULL && pCurrOp->opcode != opcode_END_PROG) {
+ DBGPRINTF("rainerscript: executing step, opcode %d...\n", pCurrOp->opcode);
switch(pCurrOp->opcode) {
doOP(OR);
doOP(AND);
@@ -656,8 +706,8 @@ execProg(vm_t *pThis, vmprg_t *pProg)
doOP(UNARY_MINUS);
doOP(FUNC_CALL);
default:
- ABORT_FINALIZE(RS_RET_INVALID_VMOP);
dbgoprint((obj_t*) pThis, "invalid instruction %d in vmprg\n", pCurrOp->opcode);
+ ABORT_FINALIZE(RS_RET_INVALID_VMOP);
break;
}
/* so far, we have plain sequential execution, so on to next... */
@@ -670,6 +720,7 @@ execProg(vm_t *pThis, vmprg_t *pProg)
*/
finalize_it:
+ DBGPRINTF("rainerscript: script execution terminated with state %d\n", iRet);
RETiRet;
}
@@ -759,6 +810,8 @@ BEGINObjClassExit(vm, OBJ_IS_CORE_MODULE) /* class, version */
objRelease(sysvar, CORE_COMPONENT);
objRelease(var, CORE_COMPONENT);
objRelease(vmstk, CORE_COMPONENT);
+
+ pthread_mutex_destroy(&mutGetenv);
ENDObjClassExit(vm)
@@ -779,6 +832,9 @@ BEGINObjClassInit(vm, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* register built-in functions // TODO: move to its own module */
CHKiRet(rsfrAddFunction((uchar*)"strlen", rsf_strlen));
CHKiRet(rsfrAddFunction((uchar*)"tolower", rsf_tolower));
+ CHKiRet(rsfrAddFunction((uchar*)"getenv", rsf_getenv));
+
+ pthread_mutex_init(&mutGetenv, NULL);
ENDObjClassInit(vm)