/[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 158 - (hide annotations) (download) (as text)
Mon Jan 2 09:02:52 2006 UTC (18 years, 6 months ago) by johnpye
File MIME type: text/x-csrc
File size: 14684 byte(s)
Removed support for Ultrix, OSF, which seem to be dead. This
makes the ascDynaload.c file much smaller. Also removed unused DynamicLoad
function (use Asc_DynamicLoad instead). Please let me know if these changes
break anything for you.
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 158 Small changes made by Michael Moore (mdm@cis.ohio-state.edu)
29     December 24th, 1993.
30     The tcl sections ripped out by Kirk Abbott (ka0p@edrc.cmu.edu)
31     September 3rd, 1994.
32     Removed OSF, Ultrix sections from this file -- johnpye, Mon 2 Jan 2005
33 aw0a 1
34 johnpye 158 To date the architectures supported are:
35     sun - pure sunos, defines also handle MACH.
36     solaris,
37     hpux
38     sgi
39     Windows
40    
41     Remember that under most systems, profiling does not work
42     with dynamic libraries. !
43     */
44    
45 aw0a 1 #include <stdio.h>
46     #include <stdlib.h>
47 ben.allan 45 #include <stdarg.h>
48 aw0a 1 #include "utilities/ascConfig.h"
49     #include "utilities/ascPrint.h"
50 jds 103 #include "utilities/ascPanic.h"
51 ben.allan 16 #include "utilities/ascMalloc.h"
52 jds 103 #include "utilities/ascDynaLoad.h"
53 jds 59
54 johnpye 158 /*--------------------------------------
55     GENERIC STUFF
56     */
57    
58 aw0a 1 struct ascend_dlrecord {
59 jds 59 char *path; /* library name */
60 aw0a 1 void *dlreturn; /* return from dlopen */
61     struct ascend_dlrecord *next;
62     };
63    
64 jds 59 /* Linked list of library names & dlopen() return values. */
65 aw0a 1 static
66     struct ascend_dlrecord *g_ascend_dllist = NULL;
67    
68     /*
69 jds 59 * Adds a record of the path and handle to the list.
70     * If it fails to do this, returns 1, else 0.
71 aw0a 1 */
72     static
73     int AscAddRecord(void *dlreturn, CONST char *path)
74     {
75     struct ascend_dlrecord *new;
76     char *keeppath;
77     if (dlreturn == NULL || path == NULL) {
78     return 1;
79     }
80 jds 103 keeppath = ascstrdup((char *)path);
81 aw0a 1 if (keeppath==NULL) return 1;
82 jds 103 new = (struct ascend_dlrecord *)ascmalloc(sizeof(struct ascend_dlrecord));
83 aw0a 1 if (new==NULL) {
84 jds 103 ascfree(keeppath);
85 aw0a 1 return 1;
86     }
87     new->next = g_ascend_dllist; /* insert at head */
88     g_ascend_dllist = new;
89     new->path = keeppath;
90     new->dlreturn = dlreturn;
91     return 0;
92     }
93    
94     /*
95     * Finds a record of the path given and returns the associated handle.
96     * If it fails to do this, returns NULL.
97     */
98     static
99     void *AscFindDLRecord(CONST char *path)
100     {
101     struct ascend_dlrecord *new;
102     if (path == NULL) {
103     return NULL;
104     }
105     new = g_ascend_dllist;
106     while (new != NULL && strcmp(new->path,path) != 0) {
107     /* advance new until no more new or new with path found */
108     new = new->next;
109     }
110     return (new != NULL) ? new->dlreturn : NULL;
111     }
112    
113     /*
114     * Finds and returns the handle to path, if one matches, and
115 jds 59 * deletes the record from the list. Returns NULL if not found.
116 aw0a 1 */
117     static
118 jds 103 void *AscDeleteRecord(CONST char *path)
119 aw0a 1 {
120     struct ascend_dlrecord *nextptr, *lastptr, *old;
121     void *dlreturn = NULL;
122 jds 59
123 jds 61 if ((g_ascend_dllist == NULL) || (NULL == path)) return NULL;
124 jds 59
125 aw0a 1 if (strcmp(path,g_ascend_dllist->path)==0) {
126     /* head case */
127     old = g_ascend_dllist;
128     g_ascend_dllist = old->next;
129     dlreturn = old->dlreturn;
130 jds 103 ascfree(old->path);
131     ascfree(old);
132 aw0a 1 } else {
133     lastptr = g_ascend_dllist;
134     nextptr = lastptr->next;
135     while (nextptr != NULL && strcmp(nextptr->path,path) != 0) {
136     lastptr = nextptr;
137     nextptr = nextptr->next;
138     }
139     /* so either nextptr is NULL and not in list, or nextptr is
140     * what we want to delete and lastptr is the link to it.
141     */
142     if (nextptr != NULL) {
143     old = nextptr;
144     lastptr->next = nextptr->next;
145     dlreturn = old->dlreturn;
146 jds 103 ascfree(old->path);
147     ascfree(old);
148 aw0a 1 }
149     }
150     return dlreturn;
151     }
152    
153     /*
154 jds 59 * Checks the list for a conflicting handle so we can issue
155 aw0a 1 * a more helpful warning, if need be, than the standard message.
156     */
157 jds 59 static
158 aw0a 1 void AscCheckDuplicateLoad(CONST char *path)
159     {
160     struct ascend_dlrecord *r;
161 jds 59
162     if (NULL == path) {
163     FPRINTF(stderr,"Null path in AscCheckDuplicateLoad\n");
164     return;
165     }
166    
167 aw0a 1 r = g_ascend_dllist;
168     while (r != NULL) {
169     if (strcmp(path,r->path)==0) {
170     FPRINTF(stderr,"Attempt to load already loaded %s\n",path);
171     return;
172     }
173     r = r->next;
174     }
175     }
176    
177 johnpye 158 /*---------------------------------------
178     PLATFORM-SPECIFIC STUFF
179     */
180    
181 aw0a 1 #ifdef __WIN32__
182 johnpye 158 # include <windows.h>
183 johnpye 62 /*
184     WINDOWS
185     */
186 aw0a 1 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
187     {
188     #define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
189     HINSTANCE xlib;
190 jds 61 int (*install)() = NULL;
191 aw0a 1
192 jds 59 if (NULL == path) {
193     FPRINTF(stderr,"Asc_DynamicLoad failed: Null path\n");
194     return 1;
195     }
196    
197 aw0a 1 AscCheckDuplicateLoad(path); /* whine if we've see it before */
198     /*
199     * If the named library does not exist, if it's not loadable or if
200     * it does not define the named install proc, report an error
201     */
202    
203     xlib = LoadLibrary(path);
204     if (xlib == NULL) {
205     FPRINTF(stderr,"Asc_DynamicLoad: LoadLibrary failed\n");
206     return 1;
207     }
208 jds 59 if (NULL != initFun) {
209     install = (int (*)())GetProcAddress(xlib,initFun);
210     if (install == NULL) {
211     FPRINTF(stderr,"Asc_DynamicLoad: Required function %s not found\n", initFun);
212     (void)FreeLibrary(xlib);
213     return 1;
214 johnpye 62 }else{
215 johnpye 66 FPRINTF(ASCERR,"FOUND INITFCN %s AT %d\n",initFun,install);
216 johnpye 62 }
217 aw0a 1 }
218 jds 59 if (0 != AscAddRecord(xlib,path)) {
219     FPRINTF(stderr,"Asc_DynamicLoad failed to record library (%s)\n",path);
220 aw0a 1 }
221 jds 61 return (install == NULL) ? 0 : (*install)();
222 aw0a 1 }
223     #endif /* __WIN32__ */
224 jds 61
225 johnpye 62 /*
226     SOLARIS and LINUX
227     */
228 johnpye 158 /* NOTE, added defined(__unix__) here, not sure if that's a bad thing or not -- johnpye */
229 johnpye 62 /*
230 johnpye 158 From a quick Google, it appears that AIX 5.1 now provides dlfcn.h,
231     so I'll remove the code that was emulating it here. -- johnpye
232 johnpye 62 */
233 johnpye 158 #if defined(sun) || defined(linux) || defined(__unix__) || defined(solaris) || defined(_AIX) || defined(_SGI_SOURCE)
234     # ifndef MACH
235     # include <dlfcn.h>
236     # else
237     # error "MACH unsupported"
238     # endif
239 jds 59
240 aw0a 1 /*
241 johnpye 158 R.I.P. OSF
242     http://en.wikipedia.org/wiki/Open_Software_Foundation
243 johnpye 62 */
244 jds 59
245 johnpye 62 /*
246 johnpye 158 POSIX-type systems (see above)
247 johnpye 62 */
248 aw0a 1 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
249     {
250     #define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
251     void *xlib;
252 jds 61 int (*install)() = NULL;
253 jds 59
254     if (NULL == path) {
255     FPRINTF(stderr,"Asc_DynamicLoad failed: Null path\n");
256     return 1;
257     }
258    
259 aw0a 1 AscCheckDuplicateLoad(path); /* whine if we've see it before */
260    
261     /*
262     * If the named library does not exist, if it's not loadable or if
263     * it does not define the named install proc, report an error
264     */
265     xlib = dlopen(path, 1);
266 jds 61 if (xlib == NULL) {
267 aw0a 1 FPRINTF(stderr,"%s\n",(char *)dlerror());
268     return 1;
269     }
270 jds 61 if (NULL != initFun) {
271     install = (int (*)())dlsym(xlib, initFun);
272     if (install == NULL) {
273     FPRINTF(stderr,"%s\n",(char *)dlerror());
274     dlclose(xlib);
275     return 1;
276     }
277     }
278    
279 jds 59 if (0 != AscAddRecord(xlib,path)) {
280     FPRINTF(stderr,"Asc_DynamicLoad failed to record library (%s)\n",path);
281 aw0a 1 }
282 jds 61 return (install == NULL) ? 0 : (*install)();
283 aw0a 1 }
284    
285 johnpye 158 #endif /* posix: linux, unix, solaris,sgi */
286 aw0a 1
287     #ifdef __hpux
288     /*
289     * Modified to work with HP/UX 9.X Operating System.
290     * Michael Moore (mdm@cis.ohio-state.edu)
291     * December 24th, 1993.
292     * Further modified by Kirk Abbott (ka0p@edrc.cmu.edu)
293     * to fit in with the ASCEND system.
294     */
295    
296 johnpye 158 # include <dl.h>
297     # include <errno.h>
298 aw0a 1
299 johnpye 62 /*
300     HPUX
301     */
302 aw0a 1 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
303     {
304 johnpye 158 # define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
305 aw0a 1 shl_t xlib;
306 jds 61 int (*install)() = NULL;
307 aw0a 1 int i;
308 jds 59
309     if (NULL == path) {
310     FPRINTF(stderr,"Asc_DynamicLoad failed: Null path\n");
311     return 1;
312     }
313    
314 aw0a 1 AscCheckDuplicateLoad(path); /* whine if we've see it before */
315    
316     /*
317     * If the named library does not exist, if it's not loadable or if
318     * it does not define the named install proc, report an error
319     */
320     xlib = shl_load(path, BIND_IMMEDIATE | BIND_VERBOSE, 0L);
321     if (xlib == (shl_t) NULL) {
322     FPRINTF(stderr,"Unable to load shared library : %s\n",strerror(errno));
323     return 1;
324     }
325 jds 59 if (NULL != initFun) {
326     i = shl_findsym(&xlib, initFun, TYPE_PROCEDURE, &install);
327     if (i == -1) {
328     FPRINTF(stderr,"Unable to find needed symbol %s %s\n",
329     initFun, strerror(errno));
330     shl_unload(xlib); /* baa */
331     return 1;
332 aw0a 1 }
333 jds 59 if (install == NULL) {
334     FPRINTF(stderr,"Unable to find needed symbol %s\n",initFun);
335     FPRINTF(stderr,"Error type unknown\n");
336     shl_unload(xlib); /* baa */
337     return 1;
338     }
339 aw0a 1 }
340 jds 59 if (0 != AscAddRecord(xlib,path)) {
341     FPRINTF(stderr,"Asc_DynamicLoad failed to record library (%s)\n",path);
342 aw0a 1 }
343 jds 61 return (install == NULL) ? 0 : (*install)();
344 aw0a 1 }
345    
346     #endif /* __hpux */
347    
348 johnpye 158 /*
349     R.I.P. Ultrix
350     http://en.wikipedia.org/wiki/Ultrix
351 johnpye 62 */
352 aw0a 1
353     #ifndef ASCDL_OK
354 johnpye 158 # error "Unable to build ascDynaload.o. Turn off strict ansi cc options."
355 aw0a 1 #endif /* adlok */
356     #ifdef __hpux
357 johnpye 158 # define UNLOAD shl_unload
358     # define DLL_CAST (shl_t)
359     # define ASC_DLERRSTRING "NULL definition"
360     # define UNLOAD_SUCCESS 0
361 aw0a 1 #endif /* __hpux */
362     #ifdef __WIN32__
363 johnpye 158 # define UNLOAD FreeLibrary
364     # define DLLSYM GetProcAddress
365     # define DLL_CAST (HINSTANCE)
366     # define ASC_DLERRSTRING "unknown"
367     # define UNLOAD_SUCCESS TRUE
368 aw0a 1 #endif /* __WIN32__ */
369     #ifndef UNLOAD
370 johnpye 158 # define UNLOAD dlclose
371     # define DLLSYM dlsym
372     # define DLL_CAST (void *)
373     # define ASC_DLERRSTRING dlerror()
374     # define UNLOAD_SUCCESS 0
375 aw0a 1 #endif /* UNLOAD */
376    
377 johnpye 158 /*--------------------------------------
378     MORE MOSTLY-GENERIC STUFF
379     */
380    
381 jds 103 int Asc_DynamicUnLoad(CONST char *path)
382 aw0a 1 {
383     void *dlreturn;
384 jds 61 int retval;
385    
386 jds 59 if (NULL == path) {
387     FPRINTF(stderr, "Asc_DynamicUnLoad failed: Null path\n");
388     return -3;
389     }
390    
391 aw0a 1 dlreturn = AscDeleteRecord(path);
392     if (dlreturn == NULL) {
393 jds 59 FPRINTF(stderr, "Asc_DynamicUnLoad: unable to remember or unload %s\n", path);
394 aw0a 1 return -3;
395     }
396 jds 59 FPRINTF(stderr, "Asc_DynamicUnLoad: forgetting & unloading %s \n", path);
397 jds 61 /*
398     * dlclose() returns 0 on success, FreeLibrary() returns TRUE.
399     * A uniform convention is preferable, so trap and return 0 on success.
400     */
401     retval = UNLOAD(DLL_CAST dlreturn);
402     return (retval == UNLOAD_SUCCESS) ? 0 : retval;
403 aw0a 1 }
404    
405 jds 103
406     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     FPRINTF(stderr,"Asc_DynamicSymbol failed: Null libname\n");
416 aw0a 1 return NULL;
417     }
418 jds 59 if (symbol == NULL) {
419     FPRINTF(stderr,"Asc_DynamicSymbol failed: Null symbol\n");
420     return NULL;
421     }
422    
423 aw0a 1 dlreturn = AscFindDLRecord(libname);
424     if (dlreturn == NULL) {
425 jds 59 FPRINTF(stderr,"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 jds 59 FPRINTF(stderr,"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     * 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     * 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 jds 59 FPRINTF(stderr,"Asc_DynamicSymbol: Unable to find requested symbol %s in %s\n",symbol,libname);
454 aw0a 1 FPRINTF(stderr,"Error type %s\n",ASC_DLERRSTRING);
455     }
456     return symreturn;
457     }
458 jds 103
459    
460     DynamicF Asc_DynamicFunction(CONST char *libname, CONST char *symbol)
461     {
462     void *dlreturn;
463     DynamicF symreturn;
464     #ifdef __hpux
465     int i;
466     #endif
467    
468     if (libname == NULL) {
469     FPRINTF(stderr,"Asc_DynamicFunction failed: Null library name\n");
470     return NULL;
471     }
472     if (symbol == NULL) {
473     FPRINTF(stderr,"Asc_DynamicFunction failed: Null function name\n");
474     return NULL;
475     }
476    
477     dlreturn = AscFindDLRecord(libname);
478     if (dlreturn == NULL) {
479     FPRINTF(stderr,"Asc_DynamicFunction: Unable to find requested library %s\n", libname);
480     return NULL;
481     }
482     #ifdef __hpux
483     i = shl_findsym(&dlreturn, symbol, TYPE_UNDEFINED, &symreturn);
484     if (i == -1) {
485     FPRINTF(stderr,"Asc_DynamicFunction: Unable to find requested function %s in %s (%s)\n",
486     symbol, libname, strerror(errno));
487     symreturn = NULL;
488     }
489     #elif defined(__WIN32__)
490     /* no problem on Windows - GetProcAddress() returns a function pointer. */
491     symreturn = (DynamicF)GetProcAddress((HINSTANCE)dlreturn, symbol);
492     #else
493     /*
494     * Here's the corresponding bit of possibly-misdirected casting horror.
495     * ISO C forbids casting between function and data pointers, so, naturally,
496     * we cast between function and data pointers. Well, we don't have much
497     * choice. dlsym() returns a void* for both variables and functions so we
498     * have to do the cast for functions. This is ok on POSIX systems since the
499     * pointer types are compatible. Then, to avoid being reminded by the
500     * compiler that we're doing something illegal, we apply convoluted casting
501     * to shut it up. Oh, the crap you can find on the internet... JDS
502     */
503     *(void**)(&symreturn) = dlsym(dlreturn, symbol);
504     #endif
505     if (symreturn == NULL) {
506     FPRINTF(stderr,"Asc_DynamicFunction: Unable to find requested function %s in %s\n",symbol,libname);
507     FPRINTF(stderr,"Error type %s\n",ASC_DLERRSTRING);
508     }
509     return symreturn;
510     }

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