1
/****************************************************************************
4
* CONTENT: Generic (cross platform) named primitive support
6
* AUTHOR: Andreas Raab (ar)
7
* ADDRESS: Walt Disney Imagineering, Glendale, CA
8
* EMAIL: Andreas.Raab@disney.com
9
* RCSID: $Id: sqNamedPrims.c 2158 2010-03-29 01:16:36Z johnmci $
13
*****************************************************************************/
20
void *primitiveAddress;
23
#include "sqNamedPrims.h"
28
#define dprintf(what) printf what
33
typedef struct ModuleEntry {
34
struct ModuleEntry *next;
41
static ModuleEntry *squeakModule = NULL;
42
static ModuleEntry *firstModule = NULL;
43
struct VirtualMachine *sqGetInterpreterProxy(void);
45
static void *findLoadedModule(char *pluginName)
48
if(!pluginName || !pluginName[0]) return squeakModule;
51
if(strcmp(module->name, pluginName) == 0) return module;
52
module = module->next;
57
static ModuleEntry *addToModuleList(char *pluginName, void* handle, sqInt ffiFlag)
61
module = (ModuleEntry*) calloc(1, sizeof(ModuleEntry) + strlen(pluginName));
62
strcpy(module->name, pluginName);
63
module->handle = handle;
64
module->ffiLoaded = ffiFlag;
65
module->next = firstModule;
72
Remove the given entry from the list of loaded modules.
75
static sqInt removeFromList(ModuleEntry *entry)
77
ModuleEntry *prevModule;
79
/* Unlink the entry from the module chain */
80
if(entry == firstModule) {
81
firstModule = entry->next;
83
prevModule = firstModule;
84
while(prevModule->next != entry)
85
prevModule = prevModule->next;
86
prevModule->next = entry->next;
92
findExternalFunctionIn:
93
Look up "pluginName_functionName" in the specified module through
94
the OS dependent call. NEVER used to search through the internal
97
static void *findExternalFunctionIn(char *functionName, ModuleEntry *module)
101
dprintf(("Looking (externally) for %s in %s... ", functionName,module->name));
103
result = ioFindExternalFunctionIn(functionName, module->handle);
106
dprintf(("%s\n", result ? "found" : "not found"));
111
findInternalFunctionIn:
112
Lookup the given "pluginName_functionName" in the internal
113
primitive table. If it can not be found try to look it up
114
by using the OS dependent mechanism (see comment below).
116
static void *findInternalFunctionIn(char *functionName, char *pluginName)
118
char *function, *plugin;
119
sqInt listIndex, index;
122
dprintf(("Looking (internally) for %s in %s ... ", functionName, (pluginName ? pluginName : "<intrinsic>")));
124
/* canonicalize functionName and pluginName to be NULL if not specified */
125
if(functionName && !functionName[0]) functionName = NULL;
126
if(pluginName && !pluginName[0]) pluginName = NULL;
127
for(listIndex=0;; listIndex++) {
128
exports = pluginExports[listIndex];
130
for(index=0;; index++) {
131
plugin = exports[index].pluginName;
132
function = exports[index].primitiveName;
133
/* canonicalize plugin and function to be NULL if not specified */
134
if(plugin && !plugin[0]) plugin = NULL;
135
if(function && !function[0]) function = NULL;
136
if(!plugin && !function) break; /* At end of table. */
137
/* check for module name match */
138
if((pluginName == NULL) != (plugin == NULL)) continue; /* one is missing */
139
if(plugin && strcmp(pluginName, plugin)) continue; /* name mismatch */
140
/* check for function name match */
141
if((functionName == NULL) != (function == NULL)) continue; /* one is missing */
142
if(function && strcmp(functionName, function)) continue; /* name mismatch */
145
dprintf(("found\n"));
146
return exports[index].primitiveAddress;
149
dprintf(("not found\n"));
155
static void *findFunctionIn(char *functionName, ModuleEntry *module)
157
if(module->handle == squeakModule->handle)
158
return findInternalFunctionIn(functionName, module->name);
160
return findExternalFunctionIn(functionName, module);
165
Call the required initializers in the given module.
166
The module has been loaded before so the task is to
167
call a) setInterpreter() and check it's return, and
168
b) initialiseModule (if defined) and check it's return
171
static sqInt callInitializersIn(ModuleEntry *module)
179
init0 = findFunctionIn("getModuleName", module);
180
init1 = findFunctionIn("setInterpreter", module);
181
init2 = findFunctionIn("initialiseModule", module);
184
/* Check the compiled name of the module */
185
moduleName = ((char* (*) (void))init0)();
187
dprintf(("ERROR: getModuleName() returned NULL\n"));
190
if(strncmp(moduleName, module->name, strlen(module->name)) != 0) {
191
dprintf(("ERROR: getModuleName returned %s (expected: %s)\n", moduleName, module->name));
195
/* Note: older plugins may not export the compiled module name */
196
dprintf(("WARNING: getModuleName() not found in %s\n", module->name));
199
dprintf(("ERROR: setInterpreter() not found\n"));
202
/* call setInterpreter */
203
okay = ((sqInt (*) (struct VirtualMachine*))init1)(sqGetInterpreterProxy());
205
dprintf(("ERROR: setInterpreter() returned false\n"));
209
okay = ((sqInt (*) (void)) init2)();
211
dprintf(("ERROR: initialiseModule() returned false\n"));
215
dprintf(("SUCCESS: Module %s is now initialized\n", module->name));
221
Find the module with the given name by,
222
* first looking it up in some (external) shared library
223
* then, by trying to find pluginName_setInterpreter.
224
If the module is found and the initialisers work, add it
225
to the list of loaded modules and return the new module.
226
If anything goes wrong make sure the module is unloaded
227
(WITHOUT calling shutdownModule()) and return NULL.
229
static ModuleEntry *findAndLoadModule(char *pluginName, sqInt ffiLoad)
234
dprintf(("Looking for plugin %s\n", (pluginName ? pluginName : "<intrinsic>")));
235
/* Try to load the module externally */
236
handle = ioLoadModule(pluginName);
238
/* When dealing with the FFI, don't attempt to mess around internally */
239
if(!handle) return NULL;
240
return addToModuleList(pluginName, handle, ffiLoad);
244
/* might be internal, so go looking for setInterpreter() */
245
if(findInternalFunctionIn("setInterpreter", pluginName))
246
handle = squeakModule->handle;
248
return NULL; /* PluginName_setInterpreter() not found */
250
module = addToModuleList(pluginName, handle, ffiLoad);
251
if(!callInitializersIn(module)) {
252
/* Initializers failed */
253
if(handle != squeakModule->handle) {
254
/* physically unload module */
255
ioFreeModule(handle);
257
removeFromList(module); /* remove list entry */
258
free(module); /* give back space */
265
Look if the given module is already loaded.
266
If so, return it's handle, otherwise try to load it.
268
static ModuleEntry *findOrLoadModule(char *pluginName, sqInt ffiLoad)
273
/* Load intrinsics (if possible) */
274
squeakModule = addToModuleList("", NULL, 1);
275
firstModule = NULL; /* drop off module list - will never be unloaded */
278
/* see if the module was already loaded */
279
module = findLoadedModule(pluginName);
281
/* if not try loading it */
282
module = findAndLoadModule(pluginName, ffiLoad);
284
return module; /* module not found */
287
/* ioLoadFunctionFrom:
288
Load and return the given function from the specified plugin.
289
Return the function address if successful, otherwise 0.
290
This entry point is called from the interpreter proxy.
292
void *ioLoadFunctionFrom(char *functionName, char *pluginName)
296
module = findOrLoadModule(pluginName, 0);
299
dprintf(("Failed to find %s (module %s was not loaded)\n", functionName, pluginName));
303
/* only the module was requested but not any specific function */
306
/* and load the actual function */
307
return findFunctionIn(functionName, module);
310
/* ioLoadExternalFunctionOfLengthFromModuleOfLength
311
Entry point for functions looked up through the VM.
313
void *ioLoadExternalFunctionOfLengthFromModuleOfLength(sqInt functionNameIndex, sqInt functionNameLength,
314
sqInt moduleNameIndex, sqInt moduleNameLength)
316
char *functionNamePointer= pointerForOop((usqInt)functionNameIndex);
317
char *moduleNamePointer= pointerForOop((usqInt)moduleNameIndex);
318
char functionName[256];
319
char moduleName[256];
322
if(functionNameLength > 255 || moduleNameLength > 255)
323
return 0; /* can't cope with those */
324
for(i=0; i< functionNameLength; i++)
325
functionName[i] = functionNamePointer[i];
326
functionName[functionNameLength] = 0;
327
for(i=0; i< moduleNameLength; i++)
328
moduleName[i] = moduleNamePointer[i];
329
moduleName[moduleNameLength] = 0;
330
return ioLoadFunctionFrom(functionName, moduleName);
333
/* ioLoadSymbolOfLengthFromModule
334
This entry point is exclusively for the FFI.
336
void *ioLoadSymbolOfLengthFromModule(sqInt functionNameIndex, sqInt functionNameLength, void *moduleHandle)
338
char *functionNamePointer= pointerForOop((usqInt)functionNameIndex);
339
char functionName[256];
342
if(functionNameLength > 255)
343
return 0; /* can't cope with those */
344
for(i=0; i< functionNameLength; i++)
345
functionName[i] = functionNamePointer[i];
346
functionName[functionNameLength] = 0;
348
return ioFindExternalFunctionIn(functionName, moduleHandle);
353
/* ioLoadModuleOfLength
354
This entry point is exclusively for the FFI.
355
It does *NOT* call any of the initializers nor
356
does it attempt to lookup stuff internally.
358
void *ioLoadModuleOfLength(sqInt moduleNameIndex, sqInt moduleNameLength)
361
char *moduleNamePointer= pointerForOop((usqInt)moduleNameIndex);
362
char moduleName[256];
365
if(moduleNameLength > 255) return 0; /* can't cope with those */
366
for(i=0; i< moduleNameLength; i++)
367
moduleName[i] = moduleNamePointer[i];
368
moduleName[moduleNameLength] = 0;
370
module = findOrLoadModule(moduleName, 1);
371
if(module) return module->handle;
377
Call the shutdown mechanism from the specified module.
379
static sqInt shutdownModule(ModuleEntry *module)
383
if(module->ffiLoaded) return 1; /* don't even attempt for ffi loaded modules */
385
/* load the actual function */
386
fn = findFunctionIn("shutdownModule", module);
387
if(fn) return ((sqInt (*) (void)) fn) ();
391
/* ioShutdownAllModules:
392
Call the shutdown mechanism for all loaded modules.
394
sqInt ioShutdownAllModules(void)
399
shutdownModule(entry);
406
Unload the module with the given name.
408
sqInt ioUnloadModule(char *moduleName)
410
ModuleEntry *entry, *temp;
412
if(!squeakModule) return 0; /* Nothing has been loaded */
413
if(!moduleName || !moduleName[0]) return 0; /* nope */
415
entry = findLoadedModule(moduleName);
416
if(!entry) return 1; /* module was never loaded */
418
/* Try to shutdown the module */
419
if(!shutdownModule(entry)) {
420
/* Could not shut down the module. Bail out. */
423
/* Notify all interested parties about the fact */
427
/* Lookup moduleUnloaded: from the plugin */
428
void *fn = findFunctionIn("moduleUnloaded", temp);
431
((sqInt (*) (char *))fn)(entry->name);
436
/* And actually unload it if it isn't just the VM... */
437
if(entry->handle != squeakModule->handle)
438
ioFreeModule(entry->handle);
439
removeFromList(entry);
440
free(entry); /* give back space */
444
/* ioUnloadModuleOfLength:
445
Entry point for the interpreter.
447
sqInt ioUnloadModuleOfLength(sqInt moduleNameIndex, sqInt moduleNameLength)
449
char *moduleNamePointer= pointerForOop((usqInt) moduleNameIndex);
450
char moduleName[256];
453
if(moduleNameLength > 255) return 0; /* can't cope with those */
454
for(i=0; i< moduleNameLength; i++)
455
moduleName[i] = moduleNamePointer[i];
456
moduleName[moduleNameLength] = 0;
457
return ioUnloadModule(moduleName);
460
/* ioListBuiltinModule:
461
Return the name of the n-th builtin module.
464
char *ioListBuiltinModule(sqInt moduleIndex)
466
sqInt index, listIndex;
471
for(listIndex=0;; listIndex++) {
472
exports = pluginExports[listIndex];
474
for(index=0;; index++) {
475
plugin = exports[index].pluginName;
476
function = exports[index].primitiveName;
477
if(!function && !plugin) break; /* no more plugins */
478
if(strcmp(function,"setInterpreter") == 0) {
480
if(--moduleIndex == 0) {
483
init0 = findInternalFunctionIn("getModuleName", plugin);
485
/* Check the compiled name of the module */
486
moduleName = ((char* (*) (void))init0)();
487
if(moduleName) { return moduleName;}
497
char *ioListLoadedModule(sqInt moduleIndex) {
503
if ( moduleIndex < 1) return (char*)NULL;
504
while(entry && index < moduleIndex) {
512
init0 = findFunctionIn("getModuleName", entry);
514
/* Check the compiled name of the module */
515
moduleName = ((char* (*) (void))init0)();
516
if(moduleName) { return moduleName;}
520
else return (char*)NULL;