/[ascend]/trunk/base/generic/utilities/ascDynaLoad.c
ViewVC logotype

Annotation of /trunk/base/generic/utilities/ascDynaLoad.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 427 - (hide annotations) (download) (as text)
Tue Apr 4 04:13:34 2006 UTC (15 years, 9 months ago) by johnpye
File MIME type: text/x-csrc
File size: 15436 byte(s)
tentative: Disabled ascDynaload functions when DYNAMIC_PACKAGES is not defined. 
Altered error.[ch] so that MS VC++ variadic macros are used when available. 
Disabled Windows MessageBox in ascPanic, so that compilation of base engine is possible with the Platform SDK.
Added SConscript files to build FORTRAN components.
Removed some autoconf-related stuff from the pygtk/interface directory.
1 johnpye 158 /* What is the source of this file ?? -- johnpye */
2 aw0a 1 /*
3     * -----------------------------------------------------------------
4     * Copyright 1993 D.I.S. - Universita` di Pavia - Italy
5     * -----------------------------------------------------------------
6     *
7     * Permission to use, copy, modify, distribute this software
8 johnpye 158 * and its documentation for any purpose is hereby granted without
9 aw0a 1 * fee, provided that the above copyright notice appear in all
10     * copies and that both that copyright notice and this permission
11     * notice appear in supporting documentation, and that the name of
12     * D.I.S. not be used in advertising or publicity pertaining to
13     * distribution of the software without specific, written prior per-
14     * mission. D.I.S. makes no representations about the suitability
15     * of this software for any purpose. It is provided "as is" without
16     * express or implied warranty.
17     *
18     * D.I.S. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, IN-
19     * CLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
20     * NO EVENT SHALL D.I.S. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21     * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22     * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
23     * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNEC-
24     * TION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25     */
26    
27     /*
28 johnpye 427 This file *should* support unix/linux-style systems (dlfcn.h)
29     and Windows.
30 aw0a 1
31 johnpye 427 Note that under many systems, profiling does not work
32     with dynamic libraries!
33 johnpye 158 */
34    
35 johnpye 427
36    
37    
38     #ifdef DYNAMIC_PACKAGES
39    
40    
41    
42    
43 aw0a 1 #include <stdio.h>
44     #include <stdlib.h>
45 ben.allan 45 #include <stdarg.h>
46 johnpye 399 #include "ascConfig.h"
47     #include "error.h"
48     #include "ascPrint.h"
49     #include "ascPanic.h"
50     #include "ascMalloc.h"
51     #include "ascDynaLoad.h"
52 jds 59
53 johnpye 399 #include <compiler/instance_enum.h>
54     #include <general/list.h>
55     #include <compiler/compiler.h>
56     #include <compiler/extfunc.h>
57 johnpye 380
58     typedef int (*ExternalLibraryRegister_fptr_t)(
59     const CreateUserFunction_fptr_t
60     ,const ErrorReporter_fptr_t
61     );
62    
63 johnpye 158 /*--------------------------------------
64     GENERIC STUFF
65     */
66    
67 aw0a 1 struct ascend_dlrecord {
68 jds 59 char *path; /* library name */
69 aw0a 1 void *dlreturn; /* return from dlopen */
70     struct ascend_dlrecord *next;
71     };
72    
73 jds 59 /* Linked list of library names & dlopen() return values. */
74 aw0a 1 static
75     struct ascend_dlrecord *g_ascend_dllist = NULL;
76    
77     /*
78 jds 59 * Adds a record of the path and handle to the list.
79     * If it fails to do this, returns 1, else 0.
80 aw0a 1 */
81     static
82     int AscAddRecord(void *dlreturn, CONST char *path)
83     {
84     struct ascend_dlrecord *new;
85     char *keeppath;
86     if (dlreturn == NULL || path == NULL) {
87     return 1;
88     }
89 jds 103 keeppath = ascstrdup((char *)path);
90 aw0a 1 if (keeppath==NULL) return 1;
91 jds 103 new = (struct ascend_dlrecord *)ascmalloc(sizeof(struct ascend_dlrecord));
92 aw0a 1 if (new==NULL) {
93 jds 103 ascfree(keeppath);
94 aw0a 1 return 1;
95     }
96     new->next = g_ascend_dllist; /* insert at head */
97     g_ascend_dllist = new;
98     new->path = keeppath;
99     new->dlreturn = dlreturn;
100     return 0;
101     }
102    
103     /*
104     * Finds a record of the path given and returns the associated handle.
105     * If it fails to do this, returns NULL.
106     */
107     static
108     void *AscFindDLRecord(CONST char *path)
109     {
110     struct ascend_dlrecord *new;
111     if (path == NULL) {
112     return NULL;
113     }
114     new = g_ascend_dllist;
115     while (new != NULL && strcmp(new->path,path) != 0) {
116     /* advance new until no more new or new with path found */
117     new = new->next;
118     }
119     return (new != NULL) ? new->dlreturn : NULL;
120     }
121    
122     /*
123     * Finds and returns the handle to path, if one matches, and
124 jds 59 * deletes the record from the list. Returns NULL if not found.
125 aw0a 1 */
126     static
127 jds 103 void *AscDeleteRecord(CONST char *path)
128 aw0a 1 {
129     struct ascend_dlrecord *nextptr, *lastptr, *old;
130     void *dlreturn = NULL;
131 jds 59
132 jds 61 if ((g_ascend_dllist == NULL) || (NULL == path)) return NULL;
133 jds 59
134 aw0a 1 if (strcmp(path,g_ascend_dllist->path)==0) {
135     /* head case */
136     old = g_ascend_dllist;
137     g_ascend_dllist = old->next;
138     dlreturn = old->dlreturn;
139 jds 103 ascfree(old->path);
140     ascfree(old);
141 aw0a 1 } else {
142     lastptr = g_ascend_dllist;
143     nextptr = lastptr->next;
144     while (nextptr != NULL && strcmp(nextptr->path,path) != 0) {
145     lastptr = nextptr;
146     nextptr = nextptr->next;
147     }
148     /* so either nextptr is NULL and not in list, or nextptr is
149     * what we want to delete and lastptr is the link to it.
150     */
151     if (nextptr != NULL) {
152     old = nextptr;
153     lastptr->next = nextptr->next;
154     dlreturn = old->dlreturn;
155 jds 103 ascfree(old->path);
156     ascfree(old);
157 aw0a 1 }
158     }
159     return dlreturn;
160     }
161    
162     /*
163 jds 59 * Checks the list for a conflicting handle so we can issue
164 aw0a 1 * a more helpful warning, if need be, than the standard message.
165     */
166 jds 59 static
167 aw0a 1 void AscCheckDuplicateLoad(CONST char *path)
168     {
169     struct ascend_dlrecord *r;
170 jds 59
171     if (NULL == path) {
172 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Null path in AscCheckDuplicateLoad.");
173 jds 59 return;
174     }
175    
176 aw0a 1 r = g_ascend_dllist;
177     while (r != NULL) {
178     if (strcmp(path,r->path)==0) {
179 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Attempt to load already loaded '%s'.",path);
180 aw0a 1 return;
181     }
182     r = r->next;
183     }
184     }
185    
186 johnpye 427 /*-----------------------------------------------
187     WINDOWS
188 johnpye 158 */
189 johnpye 427 #if defined(__WIN32__)
190     # include <windows.h>
191 johnpye 158
192 aw0a 1 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
193     {
194     #define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
195     HINSTANCE xlib;
196 johnpye 380 ExternalLibraryRegister_fptr_t install = NULL;
197 aw0a 1
198 jds 59 if (NULL == path) {
199     FPRINTF(stderr,"Asc_DynamicLoad failed: Null path\n");
200     return 1;
201     }
202    
203 aw0a 1 AscCheckDuplicateLoad(path); /* whine if we've see it before */
204     /*
205     * If the named library does not exist, if it's not loadable or if
206     * it does not define the named install proc, report an error
207     */
208    
209     xlib = LoadLibrary(path);
210     if (xlib == NULL) {
211 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicLoad: LoadLibrary failed\n");
212 aw0a 1 return 1;
213     }
214 jds 59 if (NULL != initFun) {
215     install = (int (*)())GetProcAddress(xlib,initFun);
216     if (install == NULL) {
217 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicLoad: Required function %s not found\n", initFun);
218 jds 59 (void)FreeLibrary(xlib);
219     return 1;
220 johnpye 62 }else{
221 johnpye 66 FPRINTF(ASCERR,"FOUND INITFCN %s AT %d\n",initFun,install);
222 johnpye 62 }
223 aw0a 1 }
224 jds 59 if (0 != AscAddRecord(xlib,path)) {
225 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicLoad failed to record library (%s)\n",path);
226 aw0a 1 }
227 johnpye 380 return (install == NULL) ? 0 : (*install)(CreateUserFunction,error_reporter);
228 aw0a 1 }
229 johnpye 427
230     # define UNLOAD FreeLibrary
231     # define DLLSYM GetProcAddress
232     # define DLL_CAST (HINSTANCE)
233     # define ASC_DLERRSTRING "unknown"
234     # define UNLOAD_SUCCESS TRUE
235    
236 aw0a 1 #endif /* __WIN32__ */
237 jds 61
238 johnpye 427 /*-----------------------------------------------
239     UNIX/LINUX
240     */
241 johnpye 62 /*
242     SOLARIS and LINUX
243     */
244 johnpye 158 /* NOTE, added defined(__unix__) here, not sure if that's a bad thing or not -- johnpye */
245 johnpye 62 /*
246 johnpye 190 From a quick Google, it appears that AIX 5.1 now provides dlfcn.h,
247 johnpye 158 so I'll remove the code that was emulating it here. -- johnpye
248 johnpye 62 */
249 johnpye 427 #if defined(sun) || defined(linux) || defined(__unix__) \
250     || defined(solaris) || defined(_AIX) || defined(_SGI_SOURCE)
251 johnpye 158 # ifndef MACH
252     # include <dlfcn.h>
253     # else
254     # error "MACH unsupported"
255     # endif
256 jds 59
257 aw0a 1 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
258     {
259     #define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
260     void *xlib;
261 johnpye 380 ExternalLibraryRegister_fptr_t install = NULL;
262 jds 59
263     if (NULL == path) {
264 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicLoad failed: Null path\n");
265 jds 59 return 1;
266     }
267    
268 aw0a 1 AscCheckDuplicateLoad(path); /* whine if we've see it before */
269    
270     /*
271     * If the named library does not exist, if it's not loadable or if
272     * it does not define the named install proc, report an error
273     */
274     xlib = dlopen(path, 1);
275 jds 61 if (xlib == NULL) {
276 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"%s",(char *)dlerror());
277 aw0a 1 return 1;
278     }
279 jds 61 if (NULL != initFun) {
280     install = (int (*)())dlsym(xlib, initFun);
281     if (install == NULL) {
282 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"%s",(char *)dlerror());
283 jds 61 dlclose(xlib);
284     return 1;
285     }
286     }
287 johnpye 190
288 jds 59 if (0 != AscAddRecord(xlib,path)) {
289 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicLoad failed to record library (%s)\n",path);
290 aw0a 1 }
291 johnpye 380 return (install == NULL) ? 0 : (*install)(CreateUserFunction,error_reporter);
292 aw0a 1 }
293    
294 johnpye 427 # define UNLOAD dlclose
295     # define DLLSYM dlsym
296     # define DLL_CAST (void *)
297     # define ASC_DLERRSTRING dlerror()
298     # define UNLOAD_SUCCESS 0
299    
300 johnpye 158 #endif /* posix: linux, unix, solaris,sgi */
301 aw0a 1
302 johnpye 427 /*-----------------------------------------------
303     HPUX
304     */
305 aw0a 1 #ifdef __hpux
306     /*
307 johnpye 427 Kirk Abbott last fiddled with the following, which was
308     originally put in place my Michael Moore for an
309     HP/UX 9.X Operating Sys back in 1993. Arrr. No idea if
310     it still works.
311     */
312 aw0a 1
313 johnpye 158 # include <dl.h>
314     # include <errno.h>
315 aw0a 1
316     int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
317     {
318 johnpye 158 # define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
319 aw0a 1 shl_t xlib;
320 johnpye 380 ExternalLibraryRegister_fptr_t install = NULL;
321 aw0a 1 int i;
322 jds 59
323     if (NULL == path) {
324 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicLoad failed: Null path\n");
325 jds 59 return 1;
326     }
327    
328 aw0a 1 AscCheckDuplicateLoad(path); /* whine if we've see it before */
329    
330     /*
331     * If the named library does not exist, if it's not loadable or if
332     * it does not define the named install proc, report an error
333     */
334     xlib = shl_load(path, BIND_IMMEDIATE | BIND_VERBOSE, 0L);
335     if (xlib == (shl_t) NULL) {
336 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Unable to load shared library : %s\n",strerror(errno));
337 aw0a 1 return 1;
338     }
339 jds 59 if (NULL != initFun) {
340     i = shl_findsym(&xlib, initFun, TYPE_PROCEDURE, &install);
341     if (i == -1) {
342 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Unable to find needed symbol %s %s\n",
343 jds 59 initFun, strerror(errno));
344     shl_unload(xlib); /* baa */
345     return 1;
346 aw0a 1 }
347 jds 59 if (install == NULL) {
348 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Unable to find needed symbol %s\n",initFun);
349     ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Error type unknown\n");
350 jds 59 shl_unload(xlib); /* baa */
351     return 1;
352     }
353 aw0a 1 }
354 jds 59 if (0 != AscAddRecord(xlib,path)) {
355 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicLoad failed to record library (%s)\n",path);
356 aw0a 1 }
357 johnpye 380 return (install == NULL) ? 0 : (*install)(CreateUserFunction,error_reporter);
358 aw0a 1 }
359    
360 johnpye 158 # define UNLOAD shl_unload
361     # define DLL_CAST (shl_t)
362     # define ASC_DLERRSTRING "NULL definition"
363     # define UNLOAD_SUCCESS 0
364 johnpye 427
365 aw0a 1 #endif /* __hpux */
366    
367 johnpye 427 /*-----------------------------------------------
368     Did we get something from the above?
369 johnpye 158 */
370    
371 johnpye 427 #if !defined(ASCDL_OK)
372     # error "Unable to define an Asc_DynamicLoad function. Check your compiler options and installed system libraries."
373     #endif
374    
375     /**-----------------------------------------------
376     DYNAMIC UNLOADING
377     */
378    
379 jds 103 int Asc_DynamicUnLoad(CONST char *path)
380 aw0a 1 {
381     void *dlreturn;
382 jds 61 int retval;
383 johnpye 190
384 jds 59 if (NULL == path) {
385 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR, "Asc_DynamicUnLoad failed: Null path\n");
386 jds 59 return -3;
387     }
388    
389 aw0a 1 dlreturn = AscDeleteRecord(path);
390     if (dlreturn == NULL) {
391 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR, "Asc_DynamicUnLoad: unable to remember or unload %s\n", path);
392 aw0a 1 return -3;
393     }
394 johnpye 163 CONSOLE_DEBUG("Asc_DynamicUnLoad: forgetting & unloading %s \n", path);
395 johnpye 190 /*
396 jds 61 * dlclose() returns 0 on success, FreeLibrary() returns TRUE.
397     * A uniform convention is preferable, so trap and return 0 on success.
398     */
399     retval = UNLOAD(DLL_CAST dlreturn);
400     return (retval == UNLOAD_SUCCESS) ? 0 : retval;
401 aw0a 1 }
402    
403 johnpye 427 /**-----------------------------------------------
404     DYNAMIC VARIABLE LINKING
405     */
406 jds 103 void *Asc_DynamicVariable(CONST char *libname, CONST char *symbol)
407 aw0a 1 {
408     void *dlreturn;
409     void *symreturn;
410     #ifdef __hpux
411     int i;
412     #endif
413    
414 jds 59 if (libname == NULL) {
415 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicSymbol failed: Null libname\n");
416 aw0a 1 return NULL;
417     }
418 jds 59 if (symbol == NULL) {
419 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicSymbol failed: Null symbol\n");
420 jds 59 return NULL;
421     }
422    
423 aw0a 1 dlreturn = AscFindDLRecord(libname);
424     if (dlreturn == NULL) {
425 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicSymbol: Unable to find requested library %s\n", libname);
426 aw0a 1 return NULL;
427     }
428     #ifdef __hpux
429     i = shl_findsym(&dlreturn, symbol, TYPE_UNDEFINED, &symreturn);
430     if (i == -1) {
431 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicSymbol: Unable to find requested symbol %s in %s (%s)\n",
432 aw0a 1 symbol, libname, strerror(errno));
433     symreturn = NULL;
434     }
435 jds 103 #elif defined(__WIN32__)
436     /*
437     * Here's a bit of possibly-misdirected casting horror.
438     * ISO C forbids casting between function and data pointers, so, naturally,
439     * we cast between function and data pointers. Well, we don't have much
440     * choice. GetProcAddress() returns a function pointer for both functions
441 johnpye 190 * and variables so we have to do the cast for variables. This is ok on
442     * 32 bit Windows since the pointers are compatible. Then, to avoid
443     * being reminded by the compiler that we're doing something illegal,
444 jds 103 * we apply convoluted casting to shut it up.
445     * Oh, the crap you can find on the internet... JDS
446     */
447     *(FARPROC*)(&symreturn) = GetProcAddress((HINSTANCE)dlreturn, symbol);
448 aw0a 1 #else
449 jds 103 /* no problem on POSIX systems - dlsym() returns a void *. */
450     symreturn = dlsym(dlreturn, symbol);
451 aw0a 1 #endif
452     if (symreturn == NULL) {
453 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicSymbol: Unable to find requested symbol %s in %s\n",symbol,libname);
454     ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Error type %s\n",ASC_DLERRSTRING);
455 aw0a 1 }
456     return symreturn;
457     }
458 jds 103
459 johnpye 427 /**-----------------------------------------------
460     DYNAMIC FUNCTION LINKING
461     */
462 jds 103 DynamicF Asc_DynamicFunction(CONST char *libname, CONST char *symbol)
463     {
464     void *dlreturn;
465     DynamicF symreturn;
466     #ifdef __hpux
467     int i;
468     #endif
469    
470     if (libname == NULL) {
471 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicFunction failed: Null library name\n");
472 jds 103 return NULL;
473     }
474     if (symbol == NULL) {
475 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicFunction failed: Null function name\n");
476 jds 103 return NULL;
477     }
478    
479     dlreturn = AscFindDLRecord(libname);
480     if (dlreturn == NULL) {
481 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicFunction: Unable to find requested library %s\n", libname);
482 jds 103 return NULL;
483     }
484     #ifdef __hpux
485     i = shl_findsym(&dlreturn, symbol, TYPE_UNDEFINED, &symreturn);
486     if (i == -1) {
487 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicFunction: Unable to find requested function %s in %s (%s)\n",
488 jds 103 symbol, libname, strerror(errno));
489     symreturn = NULL;
490     }
491     #elif defined(__WIN32__)
492     /* no problem on Windows - GetProcAddress() returns a function pointer. */
493     symreturn = (DynamicF)GetProcAddress((HINSTANCE)dlreturn, symbol);
494     #else
495     /*
496     * Here's the corresponding bit of possibly-misdirected casting horror.
497     * ISO C forbids casting between function and data pointers, so, naturally,
498 johnpye 190 * we cast between function and data pointers. Well, we don't have much
499 jds 103 * choice. dlsym() returns a void* for both variables and functions so we
500 johnpye 190 * have to do the cast for functions. This is ok on POSIX systems since the
501     * pointer types are compatible. Then, to avoid being reminded by the
502     * compiler that we're doing something illegal, we apply convoluted casting
503 jds 103 * to shut it up. Oh, the crap you can find on the internet... JDS
504     */
505     *(void**)(&symreturn) = dlsym(dlreturn, symbol);
506     #endif
507     if (symreturn == NULL) {
508 johnpye 190 ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Asc_DynamicFunction: Unable to find requested function %s in %s\n",symbol,libname);
509     ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Error type %s\n",ASC_DLERRSTRING);
510 jds 103 }
511     return symreturn;
512     }
513 johnpye 427
514    
515    
516     #endif
517    
518    

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22