~drgeo-developers/drgeo/trunk

« back to all changes in this revision

Viewing changes to VMs/iPad/source/Cross/vm/sqNamedPrims.c

  • Committer: Hilaire Fernandes
  • Date: 2012-01-27 21:15:40 UTC
  • Revision ID: hilaire.fernandes@gmail.com-20120127211540-912spf97bhpx6mve
Initial additions

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
*   PROJECT: Squeak 
 
3
*   FILE:    sqNamedPrims.c
 
4
*   CONTENT: Generic (cross platform) named primitive support
 
5
*
 
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 $
 
10
*
 
11
*   NOTES:
 
12
*
 
13
*****************************************************************************/
 
14
#include "sq.h"
 
15
 
 
16
 
 
17
typedef struct {
 
18
  char *pluginName;
 
19
  char *primitiveName;
 
20
  void *primitiveAddress;
 
21
} sqExport;
 
22
 
 
23
#include "sqNamedPrims.h"
 
24
 
 
25
#undef DEBUG
 
26
 
 
27
#ifdef DEBUG
 
28
#define dprintf(what) printf what
 
29
#else
 
30
#define dprintf(what)
 
31
#endif
 
32
 
 
33
typedef struct ModuleEntry {
 
34
        struct ModuleEntry *next;
 
35
        void *handle;
 
36
        sqInt ffiLoaded;
 
37
        char name[1];
 
38
} ModuleEntry;
 
39
 
 
40
 
 
41
static ModuleEntry *squeakModule = NULL;
 
42
static ModuleEntry *firstModule = NULL;
 
43
struct VirtualMachine *sqGetInterpreterProxy(void);
 
44
 
 
45
static void *findLoadedModule(char *pluginName)
 
46
{
 
47
        ModuleEntry *module;
 
48
        if(!pluginName || !pluginName[0]) return squeakModule;
 
49
        module = firstModule;
 
50
        while(module) {
 
51
                if(strcmp(module->name, pluginName) == 0) return module;
 
52
                module = module->next;
 
53
        }
 
54
        return NULL;
 
55
}
 
56
 
 
57
static ModuleEntry *addToModuleList(char *pluginName, void* handle, sqInt ffiFlag)
 
58
{
 
59
        ModuleEntry *module;
 
60
 
 
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;
 
66
        firstModule = module;
 
67
        return firstModule;
 
68
}
 
69
 
 
70
/*
 
71
        removeFromList:
 
72
        Remove the given entry from the list of loaded modules.
 
73
        Do NOT free it yet.
 
74
*/
 
75
static sqInt removeFromList(ModuleEntry *entry)
 
76
{
 
77
        ModuleEntry *prevModule;
 
78
 
 
79
        /* Unlink the entry from the module chain */
 
80
        if(entry == firstModule) {
 
81
                firstModule = entry->next;
 
82
        } else {
 
83
                prevModule = firstModule;
 
84
                while(prevModule->next != entry)
 
85
                        prevModule = prevModule->next;
 
86
                prevModule->next = entry->next;
 
87
        }
 
88
        return 1;
 
89
}
 
90
 
 
91
/*
 
92
        findExternalFunctionIn:
 
93
        Look up "pluginName_functionName" in the specified module through
 
94
        the OS dependent call. NEVER used to search through the internal
 
95
        primitive table.
 
96
*/
 
97
static void *findExternalFunctionIn(char *functionName, ModuleEntry *module)
 
98
{
 
99
        void *result;
 
100
 
 
101
        dprintf(("Looking (externally) for %s in %s... ", functionName,module->name));
 
102
        if(module->handle)
 
103
                result = ioFindExternalFunctionIn(functionName, module->handle);
 
104
        else
 
105
                result = NULL;
 
106
        dprintf(("%s\n", result ? "found" : "not found"));
 
107
        return result;
 
108
}
 
109
 
 
110
/*
 
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).
 
115
*/
 
116
static void *findInternalFunctionIn(char *functionName, char *pluginName)
 
117
{
 
118
  char *function, *plugin;
 
119
  sqInt listIndex, index;
 
120
  sqExport *exports;
 
121
 
 
122
  dprintf(("Looking (internally) for %s in %s ... ", functionName, (pluginName ? pluginName : "<intrinsic>")));
 
123
 
 
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];
 
129
    if(!exports) break;
 
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 */
 
143
 
 
144
      /* match */
 
145
      dprintf(("found\n"));
 
146
      return exports[index].primitiveAddress;
 
147
    }
 
148
  }
 
149
  dprintf(("not found\n"));
 
150
  return NULL;
 
151
 
 
152
}
 
153
 
 
154
 
 
155
static void *findFunctionIn(char *functionName, ModuleEntry *module)
 
156
{
 
157
        if(module->handle == squeakModule->handle)
 
158
                return findInternalFunctionIn(functionName, module->name);
 
159
        else
 
160
                return findExternalFunctionIn(functionName, module);
 
161
}
 
162
 
 
163
/*
 
164
        callInitializersIn:
 
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
 
169
        as well.
 
170
*/
 
171
static sqInt callInitializersIn(ModuleEntry *module)
 
172
{
 
173
        void *init0;
 
174
        void *init1;
 
175
        void *init2;
 
176
        char *moduleName;
 
177
        sqInt okay;
 
178
 
 
179
        init0 = findFunctionIn("getModuleName", module);
 
180
        init1 = findFunctionIn("setInterpreter", module);
 
181
        init2 = findFunctionIn("initialiseModule", module);
 
182
 
 
183
        if(init0) {
 
184
                /* Check the compiled name of the module */
 
185
                moduleName = ((char* (*) (void))init0)();
 
186
                if(!moduleName) {
 
187
                        dprintf(("ERROR: getModuleName() returned NULL\n"));
 
188
                        return 0;
 
189
                }
 
190
                if(strncmp(moduleName, module->name, strlen(module->name)) != 0) {
 
191
                        dprintf(("ERROR: getModuleName returned %s (expected: %s)\n", moduleName, module->name));
 
192
                        return 0;
 
193
                }
 
194
        } else {
 
195
                /* Note: older plugins may not export the compiled module name */
 
196
                dprintf(("WARNING: getModuleName() not found in %s\n", module->name));
 
197
        }
 
198
        if(!init1) { 
 
199
                dprintf(("ERROR: setInterpreter() not found\n"));
 
200
                return 0;
 
201
        }
 
202
        /* call setInterpreter */
 
203
        okay = ((sqInt (*) (struct VirtualMachine*))init1)(sqGetInterpreterProxy());
 
204
        if(!okay) {
 
205
                dprintf(("ERROR: setInterpreter() returned false\n"));
 
206
                return 0;
 
207
        }
 
208
        if(init2) {
 
209
                okay = ((sqInt (*) (void)) init2)();
 
210
                if(!okay) {
 
211
                        dprintf(("ERROR: initialiseModule() returned false\n"));
 
212
                        return 0;
 
213
                }
 
214
        }
 
215
        dprintf(("SUCCESS: Module %s is now initialized\n", module->name));
 
216
        return 1;
 
217
}
 
218
 
 
219
/*
 
220
        findAndLoadModule:
 
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.
 
228
*/
 
229
static ModuleEntry *findAndLoadModule(char *pluginName, sqInt ffiLoad)
 
230
{
 
231
        void *handle;
 
232
        ModuleEntry *module;
 
233
 
 
234
        dprintf(("Looking for plugin %s\n", (pluginName ? pluginName : "<intrinsic>")));
 
235
        /* Try to load the module externally */
 
236
        handle = ioLoadModule(pluginName);
 
237
        if(ffiLoad) {
 
238
                /* When dealing with the FFI, don't attempt to mess around internally */
 
239
                if(!handle) return NULL;
 
240
                return addToModuleList(pluginName, handle, ffiLoad);
 
241
        }
 
242
        /* NOT ffiLoad */
 
243
        if(!handle) {
 
244
                /* might be internal, so go looking for setInterpreter() */
 
245
                if(findInternalFunctionIn("setInterpreter", pluginName))
 
246
                        handle = squeakModule->handle;
 
247
                else
 
248
                        return NULL; /* PluginName_setInterpreter() not found */
 
249
        }
 
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);
 
256
                }
 
257
                removeFromList(module); /* remove list entry */
 
258
                free(module); /* give back space */
 
259
                module = NULL;
 
260
        }
 
261
        return module;
 
262
}
 
263
 
 
264
/* findOrLoadModule:
 
265
        Look if the given module is already loaded. 
 
266
        If so, return it's handle, otherwise try to load it.
 
267
*/
 
268
static ModuleEntry *findOrLoadModule(char *pluginName, sqInt ffiLoad)
 
269
{
 
270
        ModuleEntry *module;
 
271
 
 
272
        if(!squeakModule) {
 
273
                /* Load intrinsics (if possible) */
 
274
                squeakModule = addToModuleList("", NULL, 1);
 
275
                firstModule = NULL; /* drop off module list - will never be unloaded */
 
276
        }
 
277
 
 
278
        /* see if the module was already loaded */
 
279
        module = findLoadedModule(pluginName);
 
280
        if(!module) {
 
281
                /* if not try loading it */
 
282
                module = findAndLoadModule(pluginName, ffiLoad);
 
283
        }
 
284
        return module; /* module not found */
 
285
}
 
286
 
 
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.
 
291
*/
 
292
void *ioLoadFunctionFrom(char *functionName, char *pluginName)
 
293
{
 
294
        ModuleEntry *module;
 
295
 
 
296
        module = findOrLoadModule(pluginName, 0);
 
297
        if(!module) {
 
298
                /* no module */
 
299
                dprintf(("Failed to find %s (module %s was not loaded)\n", functionName, pluginName));
 
300
                return 0;
 
301
        }
 
302
        if(!functionName) {
 
303
                /* only the module was requested but not any specific function */
 
304
          return (void *)1;
 
305
        }
 
306
        /* and load the actual function */
 
307
        return findFunctionIn(functionName, module);
 
308
}
 
309
 
 
310
/* ioLoadExternalFunctionOfLengthFromModuleOfLength
 
311
        Entry point for functions looked up through the VM.
 
312
*/
 
313
void *ioLoadExternalFunctionOfLengthFromModuleOfLength(sqInt functionNameIndex, sqInt functionNameLength,
 
314
                                                       sqInt moduleNameIndex,   sqInt moduleNameLength)
 
315
{
 
316
        char *functionNamePointer= pointerForOop((usqInt)functionNameIndex);
 
317
        char *moduleNamePointer= pointerForOop((usqInt)moduleNameIndex);
 
318
        char functionName[256];
 
319
        char moduleName[256];
 
320
        sqInt i;
 
321
 
 
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);
 
331
}
 
332
 
 
333
/* ioLoadSymbolOfLengthFromModule
 
334
        This entry point is exclusively for the FFI.
 
335
*/
 
336
void *ioLoadSymbolOfLengthFromModule(sqInt functionNameIndex, sqInt functionNameLength, void *moduleHandle)
 
337
{
 
338
        char *functionNamePointer= pointerForOop((usqInt)functionNameIndex);
 
339
        char functionName[256];
 
340
        sqInt i;
 
341
 
 
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;
 
347
        if(moduleHandle)
 
348
                return ioFindExternalFunctionIn(functionName, moduleHandle);
 
349
        else
 
350
                return 0;
 
351
}
 
352
 
 
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.
 
357
*/
 
358
void *ioLoadModuleOfLength(sqInt moduleNameIndex, sqInt moduleNameLength)
 
359
{
 
360
        ModuleEntry *module;
 
361
        char *moduleNamePointer= pointerForOop((usqInt)moduleNameIndex);
 
362
        char moduleName[256];
 
363
        sqInt i;
 
364
 
 
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;
 
369
 
 
370
        module = findOrLoadModule(moduleName, 1);
 
371
        if(module) return module->handle;
 
372
        return 0;
 
373
}
 
374
 
 
375
 
 
376
/* shutdownModule:
 
377
        Call the shutdown mechanism from the specified module.
 
378
*/
 
379
static sqInt shutdownModule(ModuleEntry *module)
 
380
{
 
381
        void* fn;
 
382
 
 
383
        if(module->ffiLoaded) return 1; /* don't even attempt for ffi loaded modules */
 
384
 
 
385
        /* load the actual function */
 
386
        fn = findFunctionIn("shutdownModule", module);
 
387
        if(fn) return ((sqInt (*) (void)) fn) ();
 
388
        return 1;
 
389
}
 
390
 
 
391
/* ioShutdownAllModules:
 
392
        Call the shutdown mechanism for all loaded modules.
 
393
*/
 
394
sqInt ioShutdownAllModules(void)
 
395
{
 
396
        ModuleEntry *entry;
 
397
        entry = firstModule;
 
398
        while(entry) {
 
399
                shutdownModule(entry);
 
400
                entry = entry->next;
 
401
        }
 
402
        return 1;
 
403
}
 
404
 
 
405
/* ioUnloadModule:
 
406
        Unload the module with the given name.
 
407
*/
 
408
sqInt ioUnloadModule(char *moduleName)
 
409
{
 
410
        ModuleEntry *entry, *temp;
 
411
 
 
412
        if(!squeakModule) return 0; /* Nothing has been loaded */
 
413
        if(!moduleName || !moduleName[0]) return 0; /* nope */
 
414
 
 
415
        entry = findLoadedModule(moduleName);
 
416
        if(!entry) return 1; /* module was never loaded */
 
417
 
 
418
        /* Try to shutdown the module */
 
419
        if(!shutdownModule(entry)) {
 
420
                /* Could not shut down the module. Bail out. */
 
421
                return 0;
 
422
        }
 
423
        /* Notify all interested parties about the fact */
 
424
        temp = firstModule;
 
425
        while(temp) {
 
426
                if(temp != entry) {
 
427
                        /* Lookup moduleUnloaded: from the plugin */
 
428
                        void *fn = findFunctionIn("moduleUnloaded", temp);
 
429
                        if(fn) {
 
430
                                /* call it */
 
431
                                ((sqInt (*) (char *))fn)(entry->name);
 
432
                        }
 
433
                }
 
434
                temp = temp->next;
 
435
        }
 
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 */
 
441
        return 1;
 
442
}
 
443
 
 
444
/* ioUnloadModuleOfLength:
 
445
        Entry point for the interpreter.
 
446
*/
 
447
sqInt ioUnloadModuleOfLength(sqInt moduleNameIndex, sqInt moduleNameLength)
 
448
{
 
449
        char *moduleNamePointer= pointerForOop((usqInt) moduleNameIndex);
 
450
        char moduleName[256];
 
451
        sqInt i;
 
452
 
 
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);
 
458
}
 
459
 
 
460
/* ioListBuiltinModule:
 
461
        Return the name of the n-th builtin module.
 
462
*/
 
463
 
 
464
char *ioListBuiltinModule(sqInt moduleIndex)
 
465
{
 
466
  sqInt index, listIndex;
 
467
  char *function;
 
468
  char *plugin;
 
469
  sqExport *exports;
 
470
 
 
471
  for(listIndex=0;; listIndex++) {
 
472
    exports = pluginExports[listIndex];
 
473
    if(!exports) break;
 
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) {
 
479
        /* new module */
 
480
        if(--moduleIndex == 0) {
 
481
          char *moduleName;
 
482
          void * init0;
 
483
          init0 = findInternalFunctionIn("getModuleName", plugin);
 
484
          if(init0) {
 
485
            /* Check the compiled name of the module */
 
486
            moduleName = ((char* (*) (void))init0)();
 
487
            if(moduleName) { return moduleName;}
 
488
          }
 
489
          return plugin;
 
490
        }
 
491
      }
 
492
    }
 
493
  }
 
494
  return NULL;
 
495
}
 
496
 
 
497
char *ioListLoadedModule(sqInt moduleIndex) {
 
498
        sqInt index = 1;
 
499
 
 
500
        ModuleEntry *entry;
 
501
        entry = firstModule;
 
502
 
 
503
        if ( moduleIndex < 1) return (char*)NULL;
 
504
        while(entry && index < moduleIndex) {
 
505
                entry = entry->next;
 
506
                index = index + 1;
 
507
        }
 
508
        if ( entry ) {
 
509
                char *moduleName;
 
510
                void * init0;
 
511
 
 
512
                init0 = findFunctionIn("getModuleName", entry);
 
513
                if(init0) {
 
514
                        /* Check the compiled name of the module */
 
515
                        moduleName = ((char* (*) (void))init0)();
 
516
                        if(moduleName) { return moduleName;}
 
517
                }
 
518
                return entry->name;
 
519
        }
 
520
        else return (char*)NULL;
 
521
}