cdbf3d9510359a34dd6719bac5fd260b2062d627
[imager.git] / dynaload.c
1 #include "dynaload.h"
2 #include "XSUB.h" /* so we can compile on threaded perls */
3
4 static symbol_table_t symbol_table={i_has_format,ICL_set_internal,ICL_info,
5                              i_img_new,i_img_empty,i_img_empty_ch,i_img_exorcise,
6                              i_img_info,i_img_setmask,i_img_getmask,
7                              i_box,i_draw,i_arc,i_copyto,i_copyto_trans,i_rubthru};
8
9
10 /* These functions are all shared - then comes platform dependant code */
11
12
13 int getstr(void *hv_t,char *key,char **store) {
14   SV** svpp;
15   HV* hv=(HV*)hv_t;
16
17   mm_log((1,"getstr(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
18
19   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
20
21   svpp=hv_fetch(hv, key, strlen(key), 0);
22   *store=SvPV(*svpp, PL_na );
23
24   return 1;
25 }
26
27 int getint(void *hv_t,char *key,int *store) {
28   SV** svpp;
29   HV* hv=(HV*)hv_t;  
30
31   mm_log((1,"getint(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
32
33   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
34
35   svpp=hv_fetch(hv, key, strlen(key), 0);
36   *store=(int)SvIV(*svpp);
37   return 1;
38 }
39
40 int getdouble(void *hv_t,char* key,double *store) {
41   SV** svpp;
42   HV* hv=(HV*)hv_t;
43
44   mm_log((1,"getdouble(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
45
46   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
47   svpp=hv_fetch(hv, key, strlen(key), 0);
48   *store=(float)SvNV(*svpp);
49   return 1;
50 }
51
52 int getvoid(void *hv_t,char* key,void **store) {
53   SV** svpp;
54   HV* hv=(HV*)hv_t;
55
56   mm_log((1,"getvoid(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
57
58   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
59
60   svpp=hv_fetch(hv, key, strlen(key), 0);
61   *store=(void*)SvIV(*svpp);
62
63   return 1;
64 }
65
66 int getobj(void *hv_t,char *key,char *type,void **store) {
67   SV** svpp;
68   HV* hv=(HV*)hv_t;
69
70   mm_log((1,"getobj(hv_t 0x%X, key %s,type %s, store 0x%X)\n",hv_t,key,type,store));
71
72   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
73
74   svpp=hv_fetch(hv, key, strlen(key), 0);
75
76   if (sv_derived_from(*svpp,type)) {
77     IV tmp = SvIV((SV*)SvRV(*svpp));
78     *store = (void*) tmp;
79   } else {
80     mm_log((1,"getobj: key exists in hash but is not of correct type"));
81     return 0;
82   }
83
84   return 1;
85 }
86
87
88 UTIL_table_t UTIL_table={getstr,getint,getdouble,getvoid,getobj};
89
90 /*
91   Dynamic loading works like this:
92   dynaload opens the shared object and
93   loads all the functions into an array of functions
94   it returns a string from the dynamic function that
95   can be supplied to the parser for evaling.
96 */
97
98 void
99 DSO_call(DSO_handle *handle,int func_index,HV* hv) {
100   mm_log((1,"DSO_call(handle 0x%X, func_index %d, hv 0x%X)\n",handle,func_index,hv));
101   (handle->function_list[func_index].iptr)((void*)hv);
102 }
103
104
105 #if defined( OS_hpux )
106
107 void*
108 DSO_open(char* file,char** evalstring) {
109   shl_t tt_handle;
110   void *d_handle,**plugin_symtab,**plugin_utiltab;
111   int  rc,*iptr, (*fptr)(int);
112   func_ptr *function_list;
113   DSO_handle *dso_handle;
114   void (*f)(void *s,void *u); /* these will just have to be void for now */
115   int i;
116
117   *evalstring=NULL;
118
119   mm_log( (1,"DSO_open(file '%s' (0x%08X), evalstring 0x%08X)\n",file,file,evalstring) );
120
121   if ( (tt_handle = shl_load(file, BIND_DEFERRED,0L)) == NULL) return NULL; 
122   if ( (shl_findsym(&tt_handle, I_EVALSTR,TYPE_UNDEFINED,(void*)evalstring))) return NULL;
123
124   /*
125   if ( (shl_findsym(&tt_handle, "symbol_table",TYPE_UNDEFINED,(void*)&plugin_symtab))) return NULL;
126   if ( (shl_findsym(&tt_handle, "util_table",TYPE_UNDEFINED,&plugin_utiltab))) return NULL;
127   (*plugin_symtab)=&symbol_table;
128   (*plugin_utiltab)=&UTIL_table;
129   */
130
131   if ( (shl_findsym(&tt_handle, I_INSTALL_TABLES ,TYPE_UNDEFINED, &f ))) return NULL; 
132  
133   mm_log( (1,"Calling install_tables\n") );
134   f(&symbol_table,&UTIL_table);
135   mm_log( (1,"Call ok.\n") ); 
136  
137   if ( (shl_findsym(&tt_handle, I_FUNCTION_LIST ,TYPE_UNDEFINED,(func_ptr*)&function_list))) return NULL; 
138   if ( (dso_handle=(DSO_handle*)malloc(sizeof(DSO_handle))) == NULL) return NULL;
139
140   dso_handle->handle=tt_handle; /* needed to close again */
141   dso_handle->function_list=function_list;
142   if ( (dso_handle->filename=(char*)malloc(strlen(file))) == NULL) { free(dso_handle); return NULL; }
143   strcpy(dso_handle->filename,file);
144
145   mm_log((1,"DSO_open <- (0x%X)\n",dso_handle));
146   return (void*)dso_handle;
147 }
148
149 undef_int
150 DSO_close(void *ptr) {
151   DSO_handle *handle=(DSO_handle*) ptr;
152   mm_log((1,"DSO_close(ptr 0x%X)\n",ptr));
153   return !shl_unload((handle->handle));
154 }
155
156 #elif defined(WIN32)
157
158 void *
159 DSO_open(char *file, char **evalstring) {
160   HMODULE d_handle;
161   func_ptr *function_list;
162   DSO_handle *dso_handle;
163   
164   void (*f)(void *s,void *u); /* these will just have to be void for now */
165
166   mm_log( (1,"DSO_open(file '%s' (0x%08X), evalstring 0x%08X)\n",file,file,evalstring) );
167
168   *evalstring = NULL;
169   if ((d_handle = LoadLibrary(file)) == NULL) {
170     mm_log((1, "DSO_open: LoadLibrary(%s) failed: %lu\n", file, GetLastError()));
171     return NULL;
172   }
173   if ( (*evalstring = (char *)GetProcAddress(d_handle, I_EVALSTR)) == NULL) {
174     mm_log((1,"DSO_open: GetProcAddress didn't fine '%s': %lu\n", I_EVALSTR, GetLastError()));
175     FreeLibrary(d_handle);
176     return NULL;
177   }
178   if ((f = (void (*)(void *, void*))GetProcAddress(d_handle, I_INSTALL_TABLES)) == NULL) {
179     mm_log((1, "DSO_open: GetProcAddress didn't find '%s': %lu\n", I_INSTALL_TABLES, GetLastError()));
180     FreeLibrary(d_handle);
181     return NULL;
182   }
183   mm_log((1, "Calling install tables\n"));
184   f(&symbol_table, &UTIL_table);
185   mm_log((1, "Call ok\n"));
186   
187   if ( (function_list = (func_ptr *)GetProcAddress(d_handle, I_FUNCTION_LIST)) == NULL) {
188     mm_log((1, "DSO_open: GetProcAddress didn't find '%s': %lu\n", I_FUNCTION_LIST, GetLastError()));
189     FreeLibrary(d_handle);
190     return NULL;
191   }
192   if ( (dso_handle = (DSO_handle*)malloc(sizeof(DSO_handle))) == NULL) {
193     mm_log( (1, "DSO_Open: out of memory\n") );
194     FreeLibrary(d_handle);
195     return NULL;
196   }
197   dso_handle->handle=d_handle; /* needed to close again */
198   dso_handle->function_list=function_list;
199   if ( (dso_handle->filename=(char*)malloc(strlen(file))) == NULL) { free(dso_handle); FreeLibrary(d_handle); return NULL; }
200   strcpy(dso_handle->filename,file);
201
202   mm_log( (1,"DSO_open <- 0x%X\n",dso_handle) );
203   return (void*)dso_handle;
204
205 }
206
207 undef_int
208 DSO_close(void *ptr) {
209   DSO_handle *handle = (DSO_handle *)ptr;
210   FreeLibrary(handle->handle);
211   free(handle->filename);
212   free(handle);
213 }
214
215 #else
216
217 /* OS/2 has no dlclose; Perl doesn't provide one. */
218 #ifdef __EMX__ /* OS/2 */
219 int
220 dlclose(minthandle_t h) {
221   return DosFreeModule(h) ? -1 : 0;
222 }
223 #endif /* __EMX__ */
224
225 #ifdef OS_darwin
226
227 #import <mach-o/dyld.h>
228
229 static char *dl_error = "unknown";
230
231 static char *dlopen(char *path, int mode /* mode is ignored */)
232 {
233   int dyld_result;
234   NSObjectFileImage ofile;
235   NSModule handle = NULL;
236
237
238
239   dyld_result = NSCreateObjectFileImageFromFile(path, &ofile);
240   if (dyld_result != NSObjectFileImageSuccess)
241     {
242      switch (dyld_result) {
243        case NSObjectFileImageFailure:
244            dl_error = "object file setup failure";
245            break;
246        case NSObjectFileImageInappropriateFile:
247            dl_error = "not a Mach-O MH_BUNDLE file type";
248            break;
249        case NSObjectFileImageArch:
250            dl_error = "no object for this architecture";
251            break;
252        case NSObjectFileImageFormat:
253            dl_error = "bad object file format";
254            break;
255        case NSObjectFileImageAccess:
256            dl_error = "can't read object file";
257            break;
258        default:
259            dl_error = "unknown error from NSCreateObjectFileImageFromFile()";
260            break;
261      }
262     }
263     else
264       {
265         // NSLinkModule will cause the run to abort on any link error's
266         // not very friendly but the error recovery functionality is limited.
267         handle = NSLinkModule(ofile, path, TRUE);
268       }
269
270   return handle;
271 }
272
273 static void *
274 dlsym(void *handle, char *symbol)
275 {
276   void *addr;
277
278   if (NSIsSymbolNameDefined(symbol))
279   {
280     addr = NSAddressOfSymbol(NSLookupAndBindSymbol(symbol));
281   }
282   else
283   {
284     dl_error = "cannot find symbol";
285     addr = NULL;
286   }
287
288   return addr;
289 }
290
291 static int dlclose(void *handle) /* stub only */
292 {
293   return 0;
294 }
295
296 static char *dlerror(void) /* stub only */
297 {
298   printf("Error occurred\n");
299   return dl_error; 
300 }
301
302 #define RTLD_LAZY 0
303
304 #endif 
305
306 void*
307 DSO_open(char* file,char** evalstring) {
308   void *d_handle;
309   func_ptr *function_list;
310   DSO_handle *dso_handle;
311
312   void (*f)(void *s,void *u); /* these will just have to be void for now */
313   
314   *evalstring=NULL;
315
316   mm_log( (1,"DSO_open(file '%s' (0x%08X), evalstring 0x%08X)\n",file,file,evalstring) );
317
318   if ( (d_handle = dlopen(file, RTLD_LAZY)) == NULL) {
319     mm_log( (1,"DSO_open: dlopen failed: %s.\n",dlerror()) );
320     return NULL;
321   }
322
323   if ( (*evalstring = (char *)dlsym(d_handle, I_EVALSTR)) == NULL) {
324     mm_log( (1,"DSO_open: dlsym didn't find '%s': %s.\n",I_EVALSTR,dlerror()) );
325     return NULL;
326   }
327
328   /*
329
330     I'll just leave this thing in here for now if I need it real soon
331
332    mm_log( (1,"DSO_open: going to dlsym '%s'\n", I_SYMBOL_TABLE ));
333    if ( (plugin_symtab = dlsym(d_handle, I_SYMBOL_TABLE)) == NULL) {
334      mm_log( (1,"DSO_open: dlsym didn't find '%s': %s.\n",I_SYMBOL_TABLE,dlerror()) );
335      return NULL;
336    }
337   
338    mm_log( (1,"DSO_open: going to dlsym '%s'\n", I_UTIL_TABLE ));
339     if ( (plugin_utiltab = dlsym(d_handle, I_UTIL_TABLE)) == NULL) {
340      mm_log( (1,"DSO_open: dlsym didn't find '%s': %s.\n",I_UTIL_TABLE,dlerror()) );
341      return NULL;
342    }
343
344   */
345
346   f = (void(*)(void *s,void *u))dlsym(d_handle, I_INSTALL_TABLES);
347   mm_log( (1,"DSO_open: going to dlsym '%s'\n", I_INSTALL_TABLES ));
348   if ( (f = (void(*)(void *s,void *u))dlsym(d_handle, I_INSTALL_TABLES)) == NULL) {
349     mm_log( (1,"DSO_open: dlsym didn't find '%s': %s.\n",I_INSTALL_TABLES,dlerror()) );
350     return NULL;
351   }
352
353   mm_log( (1,"Calling install_tables\n") );
354   f(&symbol_table,&UTIL_table);
355   mm_log( (1,"Call ok.\n") );
356
357   /* (*plugin_symtab)=&symbol_table;
358      (*plugin_utiltab)=&UTIL_table; */
359   
360   mm_log( (1,"DSO_open: going to dlsym '%s'\n", I_FUNCTION_LIST ));
361   if ( (function_list=(func_ptr *)dlsym(d_handle, I_FUNCTION_LIST)) == NULL) {
362     mm_log( (1,"DSO_open: dlsym didn't find '%s': %s.\n",I_FUNCTION_LIST,dlerror()) );
363     return NULL;
364   }
365   
366   if ( (dso_handle=(DSO_handle*)malloc(sizeof(DSO_handle))) == NULL) return NULL;
367   
368   dso_handle->handle=d_handle; /* needed to close again */
369   dso_handle->function_list=function_list;
370   if ( (dso_handle->filename=(char*)malloc(strlen(file))) == NULL) { free(dso_handle); return NULL; }
371   strcpy(dso_handle->filename,file);
372
373   mm_log( (1,"DSO_open <- 0x%X\n",dso_handle) );
374   return (void*)dso_handle;
375 }
376
377 undef_int
378 DSO_close(void *ptr) {
379   DSO_handle *handle;
380   mm_log((1,"DSO_close(ptr 0x%X)\n",ptr));
381   handle=(DSO_handle*) ptr;
382   return !dlclose(handle->handle);
383 }
384
385 #endif
386