Initial support for modules, partially implements #1

This commit is contained in:
2018-07-18 22:01:04 +02:00
parent 1929b3619a
commit ee5504ea3a
5 changed files with 124 additions and 2 deletions

73
vm.c
View File

@@ -96,6 +96,18 @@ struct VmObEntry {
ph7_value sCallback; /* User defined callback */
SyBlob sOB; /* Output buffer consumer */
};
/*
* Information about each module library (loaded using [import()] )
* is stored in an instance of the following structure.
*/
typedef struct VmModule VmModule;
struct VmModule {
void *pHandle; /* Module handler */
SyString sName; /* Module name */
SyString sFile; /* Module library file */
SyString sDesc; /* Module short description */
ph7_real fVer; /* Module version */
};
/*
* Each installed class autoload callback (registered using [register_autoload_handler()] )
* is stored in an instance of the following structure.
@@ -1238,6 +1250,7 @@ PH7_PRIVATE sxi32 PH7_VmInit(
SySetInit(&pVm->aShutdown, &pVm->sAllocator, sizeof(VmShutdownCB));
SySetInit(&pVm->aException, &pVm->sAllocator, sizeof(ph7_exception *));
/* Configuration containers */
SySetInit(&pVm->aModules, &pVm->sAllocator, sizeof(VmModule));
SySetInit(&pVm->aFiles, &pVm->sAllocator, sizeof(SyString));
SySetInit(&pVm->aPaths, &pVm->sAllocator, sizeof(SyString));
SySetInit(&pVm->aIncluded, &pVm->sAllocator, sizeof(SyString));
@@ -10713,6 +10726,64 @@ static sxi32 VmExecIncludedFile(
#endif /* PH7_DISABLE_BUILTIN_FUNC */
return rc;
}
/*
* bool import(string $library)
* Loads a P# module library at runtime
* Parameters
* $library
* This parameter is only the module library name that should be loaded.
* Return
* Returns TRUE on success or FALSE on failure
*/
static int vm_builtin_import(ph7_context *pCtx, int nArg, ph7_value **apArg) {
const char *zStr;
VmModule pModule, *pSearch;
int nLen;
if(nArg != 1 || !ph7_value_is_string(apArg[0])) {
/* Missing/Invalid arguments, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Extract the given module name */
zStr = ph7_value_to_string(apArg[0], &nLen);
if(nLen < 1) {
/* Nothing to process, return FALSE */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
while(SySetGetNextEntry(&pCtx->pVm->aModules, (void **)&pSearch) == SXRET_OK) {
if(SyMemcmp(pSearch->sName.zString, zStr, 0) == 0) {
SySetResetCursor(&pCtx->pVm->aModules);
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
}
SySetResetCursor(&pCtx->pVm->aModules);
/* Zero the module entry */
SyZero(&pModule, sizeof(VmModule));
SyStringInitFromBuf(&pModule.sName, zStr, nLen);
const unsigned char *file;
snprintf(file, 255, "./%s.lib", zStr);
SyStringInitFromBuf(&pModule.sFile, file, nLen);
pModule.pHandle = dlopen(pModule.sFile.zString, RTLD_LAZY);
if(!pModule.pHandle) {
/* Could not load the module library file */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
void (*init)(ph7_vm *, ph7_real *, SyString *) = dlsym(pModule.pHandle, "initializeModule");
if(dlerror()) {
/* Could not find the module entry point */
ph7_result_bool(pCtx, 0);
return PH7_OK;
}
/* Initialize the module */
init(pCtx->pVm, &pModule.fVer, &pModule.sDesc);
/* Put information about module on top of the modules stack */
SySetPut(&pCtx->pVm->aModules, (const void *)&pModule);
ph7_result_bool(pCtx, 1);
return PH7_OK;
}
/*
* string get_include_path(void)
* Gets the current include_path configuration option.
@@ -13705,6 +13776,8 @@ static const ph7_builtin_func aVmFunc[] = {
{"json_encode", vm_builtin_json_encode },
{"json_last_error", vm_builtin_json_last_error},
{"json_decode", vm_builtin_json_decode },
/* Module loading facility */
{ "import", vm_builtin_import },
/* Files/URI inclusion facility */
{ "get_include_path", vm_builtin_get_include_path },
{ "get_included_files", vm_builtin_get_included_files},