summaryrefslogtreecommitdiffstats
path: root/runtime/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/vm.c')
-rw-r--r--runtime/vm.c56
1 files changed, 51 insertions, 5 deletions
diff --git a/runtime/vm.c b/runtime/vm.c
index 8cbf9e12..a1d992c3 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 */
@@ -82,6 +85,7 @@ rsfrAddFunction(uchar *szName, prsf_t rsf)
/* unique name, so add to head of list */
CHKmalloc(pEntry = calloc(1, sizeof(rsf_entry_t)));
CHKiRet(rsCStrConstructFromszStr(&pEntry->pName, szName));
+ CHKiRet(cstrFinalize(pEntry->pName));
pEntry->rsf = rsf;
pEntry->pNext = funcRegRoot;
funcRegRoot = pEntry;
@@ -167,7 +171,7 @@ rsfrRemoveAll(void)
while(pEntry != NULL) {
pEntryDel = pEntry;
pEntry = pEntry->pNext;
- rsCStrDestruct(&pEntryDel->pName);
+ cstrDestruct(&pEntryDel->pName);
free(pEntryDel);
}
funcRegRoot = NULL;
@@ -405,6 +409,7 @@ CODESTARTop(STRADD)
vmstk.PopString(pThis->pStk, &operand1);
CHKiRet(rsCStrAppendCStr(operand1->val.pStr, operand2->val.pStr));
+ CHKiRet(cstrFinalize(operand1->val.pStr));
/* we have a result, so let's push it */
vmstk.Push(pThis->pStk, operand1);
@@ -537,6 +542,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
@@ -554,12 +595,12 @@ rsf_tolower(vmstk_t *pStk, int numOperands)
ABORT_FINALIZE(RS_RET_INVLD_NBR_ARGUMENTS);
/* pop args and do operaton */
- CHKiRet(rsCStrConstruct(&pcstr));
+ CHKiRet(cstrConstruct(&pcstr));
vmstk.PopString(pStk, &operand1);
- pSrc = rsCStrGetSzStr(operand1->val.pStr);
- iStrlen = strlen((char*)pSrc);
+ pSrc = cstrGetSzStr(operand1->val.pStr);
+ iStrlen = strlen((char*)pSrc); // TODO: use count from string!
while(iStrlen--) {
- CHKiRet(rsCStrAppendChar(pcstr, tolower(*pSrc++)));
+ CHKiRet(cstrAppendChar(pcstr, tolower(*pSrc++)));
}
/* Store result and cleanup */
@@ -754,6 +795,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)
@@ -774,6 +817,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)