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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 163 - (show annotations) (download) (as text)
Tue Jan 3 07:17:41 2006 UTC (14 years, 9 months ago) by johnpye
File MIME type: text/x-csrc
File size: 15258 byte(s)
Fixed bug #198
1 /* What is the source of this file ?? -- johnpye */
2 /*
3 * -----------------------------------------------------------------
4 * Copyright 1993 D.I.S. - Universita` di Pavia - Italy
5 * -----------------------------------------------------------------
6 *
7 * Permission to use, copy, modify, distribute this software
8 * and its documentation for any purpose is hereby granted without
9 * 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 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
34 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 #include <stdio.h>
46 #include <stdlib.h>
47 #include <stdarg.h>
48 #include "utilities/ascConfig.h"
49 #include "utilities/ascPrint.h"
50 #include "utilities/ascPanic.h"
51 #include "utilities/ascMalloc.h"
52 #include "utilities/ascDynaLoad.h"
53
54 /*--------------------------------------
55 GENERIC STUFF
56 */
57
58 struct ascend_dlrecord {
59 char *path; /* library name */
60 void *dlreturn; /* return from dlopen */
61 struct ascend_dlrecord *next;
62 };
63
64 /* Linked list of library names & dlopen() return values. */
65 static
66 struct ascend_dlrecord *g_ascend_dllist = NULL;
67
68 /*
69 * Adds a record of the path and handle to the list.
70 * If it fails to do this, returns 1, else 0.
71 */
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 keeppath = ascstrdup((char *)path);
81 if (keeppath==NULL) return 1;
82 new = (struct ascend_dlrecord *)ascmalloc(sizeof(struct ascend_dlrecord));
83 if (new==NULL) {
84 ascfree(keeppath);
85 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 * deletes the record from the list. Returns NULL if not found.
116 */
117 static
118 void *AscDeleteRecord(CONST char *path)
119 {
120 struct ascend_dlrecord *nextptr, *lastptr, *old;
121 void *dlreturn = NULL;
122
123 if ((g_ascend_dllist == NULL) || (NULL == path)) return NULL;
124
125 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 ascfree(old->path);
131 ascfree(old);
132 } 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 ascfree(old->path);
147 ascfree(old);
148 }
149 }
150 return dlreturn;
151 }
152
153 /*
154 * Checks the list for a conflicting handle so we can issue
155 * a more helpful warning, if need be, than the standard message.
156 */
157 static
158 void AscCheckDuplicateLoad(CONST char *path)
159 {
160 struct ascend_dlrecord *r;
161
162 if (NULL == path) {
163 error_reporter(ASC_PROG_ERR,NULL,0,"Null path in AscCheckDuplicateLoad.");
164 return;
165 }
166
167 r = g_ascend_dllist;
168 while (r != NULL) {
169 if (strcmp(path,r->path)==0) {
170 error_reporter(ASC_PROG_ERR,NULL,0,"Attempt to load already loaded '%s'.",path);
171 return;
172 }
173 r = r->next;
174 }
175 }
176
177 /*---------------------------------------
178 PLATFORM-SPECIFIC STUFF
179 */
180
181 #ifdef __WIN32__
182 # include <windows.h>
183 /*
184 WINDOWS
185 */
186 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 int (*install)() = NULL;
191
192 if (NULL == path) {
193 FPRINTF(stderr,"Asc_DynamicLoad failed: Null path\n");
194 return 1;
195 }
196
197 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 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicLoad: LoadLibrary failed\n");
206 return 1;
207 }
208 if (NULL != initFun) {
209 install = (int (*)())GetProcAddress(xlib,initFun);
210 if (install == NULL) {
211 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicLoad: Required function %s not found\n", initFun);
212 (void)FreeLibrary(xlib);
213 return 1;
214 }else{
215 FPRINTF(ASCERR,"FOUND INITFCN %s AT %d\n",initFun,install);
216 }
217 }
218 if (0 != AscAddRecord(xlib,path)) {
219 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicLoad failed to record library (%s)\n",path);
220 }
221 return (install == NULL) ? 0 : (*install)();
222 }
223 #endif /* __WIN32__ */
224
225 /*
226 SOLARIS and LINUX
227 */
228 /* NOTE, added defined(__unix__) here, not sure if that's a bad thing or not -- johnpye */
229 /*
230 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 */
233 #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
240 /*
241 R.I.P. OSF
242 http://en.wikipedia.org/wiki/Open_Software_Foundation
243 */
244
245 /*
246 POSIX-type systems (see above)
247 */
248 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 int (*install)() = NULL;
253
254 if (NULL == path) {
255 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicLoad failed: Null path\n");
256 return 1;
257 }
258
259 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 if (xlib == NULL) {
267 error_reporter(ASC_PROG_ERR,NULL,0,"%s",(char *)dlerror());
268 return 1;
269 }
270 if (NULL != initFun) {
271 install = (int (*)())dlsym(xlib, initFun);
272 if (install == NULL) {
273 error_reporter(ASC_PROG_ERR,NULL,0,"%s",(char *)dlerror());
274 dlclose(xlib);
275 return 1;
276 }
277 }
278
279 if (0 != AscAddRecord(xlib,path)) {
280 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicLoad failed to record library (%s)\n",path);
281 }
282 return (install == NULL) ? 0 : (*install)();
283 }
284
285 #endif /* posix: linux, unix, solaris,sgi */
286
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 # include <dl.h>
297 # include <errno.h>
298
299 /*
300 HPUX
301 */
302 int Asc_DynamicLoad(CONST char *path, CONST char *initFun)
303 {
304 # define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */
305 shl_t xlib;
306 int (*install)() = NULL;
307 int i;
308
309 if (NULL == path) {
310 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicLoad failed: Null path\n");
311 return 1;
312 }
313
314 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 error_reporter(ASC_PROG_ERR,NULL,0,"Unable to load shared library : %s\n",strerror(errno));
323 return 1;
324 }
325 if (NULL != initFun) {
326 i = shl_findsym(&xlib, initFun, TYPE_PROCEDURE, &install);
327 if (i == -1) {
328 error_reporter(ASC_PROG_ERR,NULL,0,"Unable to find needed symbol %s %s\n",
329 initFun, strerror(errno));
330 shl_unload(xlib); /* baa */
331 return 1;
332 }
333 if (install == NULL) {
334 error_reporter(ASC_PROG_ERR,NULL,0,"Unable to find needed symbol %s\n",initFun);
335 error_reporter(ASC_PROG_ERR,NULL,0,"Error type unknown\n");
336 shl_unload(xlib); /* baa */
337 return 1;
338 }
339 }
340 if (0 != AscAddRecord(xlib,path)) {
341 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicLoad failed to record library (%s)\n",path);
342 }
343 return (install == NULL) ? 0 : (*install)();
344 }
345
346 #endif /* __hpux */
347
348 /*
349 R.I.P. Ultrix
350 http://en.wikipedia.org/wiki/Ultrix
351 */
352
353 #ifndef ASCDL_OK
354 # error "Unable to build ascDynaload.o. Turn off strict ansi cc options."
355 #endif /* adlok */
356 #ifdef __hpux
357 # define UNLOAD shl_unload
358 # define DLL_CAST (shl_t)
359 # define ASC_DLERRSTRING "NULL definition"
360 # define UNLOAD_SUCCESS 0
361 #endif /* __hpux */
362 #ifdef __WIN32__
363 # define UNLOAD FreeLibrary
364 # define DLLSYM GetProcAddress
365 # define DLL_CAST (HINSTANCE)
366 # define ASC_DLERRSTRING "unknown"
367 # define UNLOAD_SUCCESS TRUE
368 #endif /* __WIN32__ */
369 #ifndef UNLOAD
370 # define UNLOAD dlclose
371 # define DLLSYM dlsym
372 # define DLL_CAST (void *)
373 # define ASC_DLERRSTRING dlerror()
374 # define UNLOAD_SUCCESS 0
375 #endif /* UNLOAD */
376
377 /*--------------------------------------
378 MORE MOSTLY-GENERIC STUFF
379 */
380
381 int Asc_DynamicUnLoad(CONST char *path)
382 {
383 void *dlreturn;
384 int retval;
385
386 if (NULL == path) {
387 error_reporter(ASC_PROG_ERR,NULL,0, "Asc_DynamicUnLoad failed: Null path\n");
388 return -3;
389 }
390
391 dlreturn = AscDeleteRecord(path);
392 if (dlreturn == NULL) {
393 error_reporter(ASC_PROG_ERR,NULL,0, "Asc_DynamicUnLoad: unable to remember or unload %s\n", path);
394 return -3;
395 }
396 CONSOLE_DEBUG("Asc_DynamicUnLoad: forgetting & unloading %s \n", path);
397 /*
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 }
404
405
406 void *Asc_DynamicVariable(CONST char *libname, CONST char *symbol)
407 {
408 void *dlreturn;
409 void *symreturn;
410 #ifdef __hpux
411 int i;
412 #endif
413
414 if (libname == NULL) {
415 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicSymbol failed: Null libname\n");
416 return NULL;
417 }
418 if (symbol == NULL) {
419 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicSymbol failed: Null symbol\n");
420 return NULL;
421 }
422
423 dlreturn = AscFindDLRecord(libname);
424 if (dlreturn == NULL) {
425 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicSymbol: Unable to find requested library %s\n", libname);
426 return NULL;
427 }
428 #ifdef __hpux
429 i = shl_findsym(&dlreturn, symbol, TYPE_UNDEFINED, &symreturn);
430 if (i == -1) {
431 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicSymbol: Unable to find requested symbol %s in %s (%s)\n",
432 symbol, libname, strerror(errno));
433 symreturn = NULL;
434 }
435 #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 #else
449 /* no problem on POSIX systems - dlsym() returns a void *. */
450 symreturn = dlsym(dlreturn, symbol);
451 #endif
452 if (symreturn == NULL) {
453 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicSymbol: Unable to find requested symbol %s in %s\n",symbol,libname);
454 error_reporter(ASC_PROG_ERR,NULL,0,"Error type %s\n",ASC_DLERRSTRING);
455 }
456 return symreturn;
457 }
458
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 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicFunction failed: Null library name\n");
470 return NULL;
471 }
472 if (symbol == NULL) {
473 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicFunction failed: Null function name\n");
474 return NULL;
475 }
476
477 dlreturn = AscFindDLRecord(libname);
478 if (dlreturn == NULL) {
479 error_reporter(ASC_PROG_ERR,NULL,0,"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 error_reporter(ASC_PROG_ERR,NULL,0,"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 error_reporter(ASC_PROG_ERR,NULL,0,"Asc_DynamicFunction: Unable to find requested function %s in %s\n",symbol,libname);
507 error_reporter(ASC_PROG_ERR,NULL,0,"Error type %s\n",ASC_DLERRSTRING);
508 }
509 return symreturn;
510 }

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