1 |
/* ASCEND modelling environment |
2 |
Copyright (C) 2006 Carnegie Mellon University |
3 |
|
4 |
This program is free software; you can redistribute it and/or modify |
5 |
it under the terms of the GNU General Public License as published by |
6 |
the Free Software Foundation; either version 2, or (at your option) |
7 |
any later version. |
8 |
|
9 |
This program is distributed in the hope that it will be useful, |
10 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 |
GNU General Public License for more details. |
13 |
|
14 |
You should have received a copy of the GNU General Public License |
15 |
along with this program; if not, write to the Free Software |
16 |
Foundation, Inc., 59 Temple Place - Suite 330, |
17 |
Boston, MA 02111-1307, USA. |
18 |
*//** |
19 |
@file |
20 |
|
21 |
This file *should* support unix/linux-style systems (dlfcn.h) |
22 |
and Windows. |
23 |
|
24 |
Note that under many systems, profiling does not work |
25 |
with dynamic libraries! |
26 |
*/ |
27 |
|
28 |
#include <stdio.h> |
29 |
#include <stdlib.h> |
30 |
#include <stdarg.h> |
31 |
#include "ascConfig.h" |
32 |
#include "error.h" |
33 |
#include "ascPrint.h" |
34 |
#include "ascPanic.h" |
35 |
#include "ascMalloc.h" |
36 |
#include "ascDynaLoad.h" |
37 |
|
38 |
#include <general/env.h> |
39 |
#include <general/ospath.h> |
40 |
#include <compiler/instance_enum.h> |
41 |
#include <general/list.h> |
42 |
#include <compiler/compiler.h> |
43 |
#include <compiler/extfunc.h> |
44 |
|
45 |
typedef int (*ExternalLibraryRegister_fptr_t)(void); |
46 |
|
47 |
/*-------------------------------------- |
48 |
GENERIC STUFF |
49 |
*/ |
50 |
|
51 |
struct ascend_dlrecord { |
52 |
char *path; /* library name */ |
53 |
void *dlreturn; /* return from dlopen */ |
54 |
struct ascend_dlrecord *next; |
55 |
}; |
56 |
|
57 |
/* Linked list of library names & dlopen() return values. */ |
58 |
static struct ascend_dlrecord *g_ascend_dllist = NULL; |
59 |
|
60 |
/* |
61 |
* Adds a record of the path and handle to the list. |
62 |
* If it fails to do this, returns 1, else 0. |
63 |
*/ |
64 |
static int AscAddRecord(void *dlreturn, CONST char *path){ |
65 |
struct ascend_dlrecord *new; |
66 |
char *keeppath; |
67 |
if (dlreturn == NULL || path == NULL) { |
68 |
return 1; |
69 |
} |
70 |
keeppath = ascstrdup((char *)path); |
71 |
if (keeppath==NULL) return 1; |
72 |
new = ASC_NEW(struct ascend_dlrecord); |
73 |
if (new==NULL) { |
74 |
ascfree(keeppath); |
75 |
return 1; |
76 |
} |
77 |
new->next = g_ascend_dllist; /* insert at head */ |
78 |
g_ascend_dllist = new; |
79 |
new->path = keeppath; |
80 |
new->dlreturn = dlreturn; |
81 |
return 0; |
82 |
} |
83 |
|
84 |
/* |
85 |
* Finds a record of the path given and returns the associated handle. |
86 |
* If it fails to do this, returns NULL. |
87 |
*/ |
88 |
static |
89 |
void *AscFindDLRecord(CONST char *path) |
90 |
{ |
91 |
struct ascend_dlrecord *new; |
92 |
if (path == NULL) { |
93 |
return NULL; |
94 |
} |
95 |
new = g_ascend_dllist; |
96 |
while (new != NULL && strcmp(new->path,path) != 0) { |
97 |
/* advance new until no more new or new with path found */ |
98 |
new = new->next; |
99 |
} |
100 |
return (new != NULL) ? new->dlreturn : NULL; |
101 |
} |
102 |
|
103 |
/* |
104 |
* Finds and returns the handle to path, if one matches, and |
105 |
* deletes the record from the list. Returns NULL if not found. |
106 |
*/ |
107 |
static |
108 |
void *AscDeleteRecord(CONST char *path) |
109 |
{ |
110 |
struct ascend_dlrecord *nextptr, *lastptr, *old; |
111 |
void *dlreturn = NULL; |
112 |
|
113 |
if ((g_ascend_dllist == NULL) || (NULL == path)) return NULL; |
114 |
|
115 |
if (strcmp(path,g_ascend_dllist->path)==0) { |
116 |
/* head case */ |
117 |
old = g_ascend_dllist; |
118 |
g_ascend_dllist = old->next; |
119 |
dlreturn = old->dlreturn; |
120 |
ascfree(old->path); |
121 |
ascfree(old); |
122 |
} else { |
123 |
lastptr = g_ascend_dllist; |
124 |
nextptr = lastptr->next; |
125 |
while (nextptr != NULL && strcmp(nextptr->path,path) != 0) { |
126 |
lastptr = nextptr; |
127 |
nextptr = nextptr->next; |
128 |
} |
129 |
/* so either nextptr is NULL and not in list, or nextptr is |
130 |
* what we want to delete and lastptr is the link to it. |
131 |
*/ |
132 |
if (nextptr != NULL) { |
133 |
old = nextptr; |
134 |
lastptr->next = nextptr->next; |
135 |
dlreturn = old->dlreturn; |
136 |
ascfree(old->path); |
137 |
ascfree(old); |
138 |
} |
139 |
} |
140 |
return dlreturn; |
141 |
} |
142 |
|
143 |
/* |
144 |
* Checks the list for a conflicting handle so we can issue |
145 |
* a more helpful warning, if need be, than the standard message. |
146 |
*/ |
147 |
static |
148 |
void AscCheckDuplicateLoad(CONST char *path) |
149 |
{ |
150 |
struct ascend_dlrecord *r; |
151 |
|
152 |
if (NULL == path) { |
153 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Null path"); |
154 |
return; |
155 |
} |
156 |
|
157 |
r = g_ascend_dllist; |
158 |
while (r != NULL) { |
159 |
if (strcmp(path,r->path)==0) { |
160 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Attempt to load already loaded '%s'.",path); |
161 |
return; |
162 |
} |
163 |
r = r->next; |
164 |
} |
165 |
} |
166 |
|
167 |
|
168 |
/*----------------------------------------------- |
169 |
WINDOWS |
170 |
*/ |
171 |
#if defined(__WIN32__) |
172 |
# include <windows.h> |
173 |
|
174 |
int Asc_DynamicLoad(CONST char *path, CONST char *initFun){ |
175 |
HINSTANCE xlib; |
176 |
ExternalLibraryRegister_fptr_t install = NULL; |
177 |
|
178 |
if (NULL == path) { |
179 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: Null path\n"); |
180 |
return 1; |
181 |
} |
182 |
|
183 |
AscCheckDuplicateLoad(path); /* whine if we've see it before */ |
184 |
/* |
185 |
* If the named library does not exist, if it's not loadable or if |
186 |
* it does not define the named install proc, report an error |
187 |
*/ |
188 |
|
189 |
xlib = LoadLibrary(path); |
190 |
if (xlib == NULL) { |
191 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"LoadLibrary failed\n'%s'",path); |
192 |
return 1; |
193 |
} |
194 |
ERROR_REPORTER_HERE(ASC_PROG_NOTE,"LoadLibrary succeeded, '%s'\n",path); |
195 |
|
196 |
if (NULL != initFun) { |
197 |
install = (int (*)(void))GetProcAddress(xlib,initFun); |
198 |
if (install == NULL) { |
199 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Required function '%s' not found", initFun); |
200 |
(void)FreeLibrary(xlib); |
201 |
return 1; |
202 |
}else{ |
203 |
FPRINTF(ASCERR,"FOUND INITFCN %s AT %d\n",initFun,install); |
204 |
} |
205 |
} |
206 |
if (0 != AscAddRecord(xlib,path)) { |
207 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed to record library (%s)\n",path); |
208 |
} |
209 |
return (install == NULL) ? 0 : (*install)(); |
210 |
} |
211 |
#define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */ |
212 |
|
213 |
# define UNLOAD FreeLibrary |
214 |
# define DLLSYM GetProcAddress |
215 |
# define DLL_CAST (HINSTANCE) |
216 |
# define ASC_DLERRSTRING "unknown" |
217 |
# define UNLOAD_SUCCESS TRUE |
218 |
|
219 |
#endif /* __WIN32__ */ |
220 |
|
221 |
/*----------------------------------------------- |
222 |
UNIX/LINUX |
223 |
*/ |
224 |
/* |
225 |
SOLARIS and LINUX |
226 |
*/ |
227 |
/* NOTE, added defined(__unix__) here, not sure if that's a bad thing or not -- johnpye */ |
228 |
/* |
229 |
From a quick Google, it appears that AIX 5.1 now provides dlfcn.h, |
230 |
so I'll remove the code that was emulating it here. -- johnpye |
231 |
*/ |
232 |
#if (defined(sun) || defined(linux) || defined(__unix__) || defined(solaris) || defined(_AIX) || defined(_SGI_SOURCE)) |
233 |
# ifndef MACH |
234 |
# include <dlfcn.h> |
235 |
# else |
236 |
# error "MACH unsupported" |
237 |
# endif /* mach */ |
238 |
|
239 |
int Asc_DynamicLoad(CONST char *path, CONST char *initFun) |
240 |
{ |
241 |
void *xlib; |
242 |
ExternalLibraryRegister_fptr_t install = NULL; |
243 |
|
244 |
if (NULL == path) { |
245 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: null path"); |
246 |
return 1; |
247 |
} |
248 |
|
249 |
AscCheckDuplicateLoad(path); /* whine if we've see it before */ |
250 |
|
251 |
/* |
252 |
* If the named library does not exist, if it's not loadable or if |
253 |
* it does not define the named install proc, report an error |
254 |
*/ |
255 |
xlib = dlopen(path, 1); |
256 |
if (xlib == NULL) { |
257 |
ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"%s",(char *)dlerror()); |
258 |
return 1; |
259 |
} |
260 |
if (NULL != initFun) { |
261 |
install = (int (*)())dlsym(xlib, initFun); |
262 |
if (install == NULL) { |
263 |
ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"%s",(char *)dlerror()); |
264 |
dlclose(xlib); |
265 |
return 1; |
266 |
} |
267 |
} |
268 |
|
269 |
if (0 != AscAddRecord(xlib,path)) { |
270 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed to record library (%s)",path); |
271 |
} |
272 |
return (install == NULL) ? 0 : (*install)(); |
273 |
} |
274 |
#define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */ |
275 |
|
276 |
# define UNLOAD dlclose |
277 |
# define DLLSYM dlsym |
278 |
# define DLL_CAST (void *) |
279 |
# define ASC_DLERRSTRING dlerror() |
280 |
# define UNLOAD_SUCCESS 0 |
281 |
|
282 |
#endif /* posix: linux, unix, solaris,sgi */ |
283 |
|
284 |
/*----------------------------------------------- |
285 |
HPUX |
286 |
*/ |
287 |
#ifdef __hpux |
288 |
/* |
289 |
Kirk Abbott last fiddled with the following, which was |
290 |
originally put in place my Michael Moore for an |
291 |
HP/UX 9.X Operating Sys back in 1993. Arrr. No idea if |
292 |
it still works. |
293 |
*/ |
294 |
|
295 |
# include <dl.h> |
296 |
# include <errno.h> |
297 |
|
298 |
int Asc_DynamicLoad(CONST char *path, CONST char *initFun) |
299 |
{ |
300 |
shl_t xlib; |
301 |
ExternalLibraryRegister_fptr_t install = NULL; |
302 |
int i; |
303 |
|
304 |
if (NULL == path) { |
305 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: Null path"); |
306 |
return 1; |
307 |
} |
308 |
|
309 |
AscCheckDuplicateLoad(path); /* whine if we've see it before */ |
310 |
|
311 |
/* |
312 |
* If the named library does not exist, if it's not loadable or if |
313 |
* it does not define the named install proc, report an error |
314 |
*/ |
315 |
xlib = shl_load(path, BIND_IMMEDIATE | BIND_VERBOSE, 0L); |
316 |
if (xlib == (shl_t) NULL) { |
317 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to load shared library: %s",strerror(errno)); |
318 |
return 1; |
319 |
} |
320 |
if (NULL != initFun) { |
321 |
i = shl_findsym(&xlib, initFun, TYPE_PROCEDURE, &install); |
322 |
if (i == -1) { |
323 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find needed symbol '%s': %s", |
324 |
initFun, strerror(errno)); |
325 |
shl_unload(xlib); /* baa */ |
326 |
return 1; |
327 |
} |
328 |
if(install == NULL) { |
329 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find needed symbol '%s'. Error type unknown",initFun); |
330 |
shl_unload(xlib); /* baa */ |
331 |
return 1; |
332 |
} |
333 |
} |
334 |
if (0 != AscAddRecord(xlib,path)) { |
335 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed to record library (%s)",path); |
336 |
} |
337 |
return (install == NULL) ? 0 : (*install)(); |
338 |
} |
339 |
# define ASCDL_OK /* this line should appear inside each Asc_DynamicLoad */ |
340 |
|
341 |
# define UNLOAD shl_unload |
342 |
# define DLL_CAST (shl_t) |
343 |
# define ASC_DLERRSTRING "NULL definition" |
344 |
# define UNLOAD_SUCCESS 0 |
345 |
|
346 |
#endif /* __hpux */ |
347 |
|
348 |
/*----------------------------------------------- |
349 |
Did we get something from the above? |
350 |
*/ |
351 |
|
352 |
#ifndef ASCDL_OK |
353 |
# error "Unable to define an Asc_DynamicLoad function. Check your compiler options and installed system libraries." |
354 |
#endif |
355 |
|
356 |
/**----------------------------------------------- |
357 |
DYNAMIC UNLOADING |
358 |
*/ |
359 |
|
360 |
int Asc_DynamicUnLoad(CONST char *path) |
361 |
{ |
362 |
void *dlreturn; |
363 |
int retval; |
364 |
|
365 |
if (NULL == path) { |
366 |
ERROR_REPORTER_HERE(ASC_PROG_ERR, "Failed: Null path"); |
367 |
return -3; |
368 |
} |
369 |
|
370 |
dlreturn = AscDeleteRecord(path); |
371 |
if (dlreturn == NULL) { |
372 |
ERROR_REPORTER_HERE(ASC_PROG_ERR, "Unable to remember or unload %s", path); |
373 |
return -3; |
374 |
} |
375 |
CONSOLE_DEBUG("Asc_DynamicUnLoad: forgetting & unloading %s", path); |
376 |
/* |
377 |
* dlclose() returns 0 on success, FreeLibrary() returns TRUE. |
378 |
* A uniform convention is preferable, so trap and return 0 on success. |
379 |
*/ |
380 |
retval = UNLOAD(DLL_CAST dlreturn); |
381 |
return (retval == UNLOAD_SUCCESS) ? 0 : retval; |
382 |
} |
383 |
|
384 |
/**----------------------------------------------- |
385 |
DYNAMIC VARIABLE LINKING |
386 |
*/ |
387 |
void *Asc_DynamicVariable(CONST char *libname, CONST char *symbol) |
388 |
{ |
389 |
void *dlreturn; |
390 |
void *symreturn; |
391 |
#ifdef __hpux |
392 |
int i; |
393 |
#endif |
394 |
|
395 |
if (libname == NULL) { |
396 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: Null libname"); |
397 |
return NULL; |
398 |
} |
399 |
if (symbol == NULL) { |
400 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: Null symbol"); |
401 |
return NULL; |
402 |
} |
403 |
|
404 |
dlreturn = AscFindDLRecord(libname); |
405 |
if (dlreturn == NULL) { |
406 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find requested library %s", libname); |
407 |
return NULL; |
408 |
} |
409 |
#ifdef __hpux |
410 |
i = shl_findsym(&dlreturn, symbol, TYPE_UNDEFINED, &symreturn); |
411 |
if (i == -1) { |
412 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find requested symbol '%s' in %s (%s)", |
413 |
symbol, libname, strerror(errno)); |
414 |
symreturn = NULL; |
415 |
} |
416 |
#elif defined(__WIN32__) |
417 |
/* |
418 |
* Here's a bit of possibly-misdirected casting horror. |
419 |
* ISO C forbids casting between function and data pointers, so, naturally, |
420 |
* we cast between function and data pointers. Well, we don't have much |
421 |
* choice. GetProcAddress() returns a function pointer for both functions |
422 |
* and variables so we have to do the cast for variables. This is ok on |
423 |
* 32 bit Windows since the pointers are compatible. Then, to avoid |
424 |
* being reminded by the compiler that we're doing something illegal, |
425 |
* we apply convoluted casting to shut it up. |
426 |
* Oh, the crap you can find on the internet... JDS |
427 |
*/ |
428 |
*(FARPROC*)(&symreturn) = GetProcAddress((HINSTANCE)dlreturn, symbol); |
429 |
#else |
430 |
/* no problem on POSIX systems - dlsym() returns a void *. */ |
431 |
symreturn = dlsym(dlreturn, symbol); |
432 |
#endif |
433 |
if (symreturn == NULL) { |
434 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find requested symbol '%s' in %s",symbol,libname); |
435 |
ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Error type: %s",ASC_DLERRSTRING); |
436 |
} |
437 |
return symreturn; |
438 |
} |
439 |
|
440 |
/**----------------------------------------------- |
441 |
DYNAMIC FUNCTION LINKING |
442 |
*/ |
443 |
DynamicF Asc_DynamicFunction(CONST char *libname, CONST char *symbol) |
444 |
{ |
445 |
void *dlreturn; |
446 |
DynamicF symreturn; |
447 |
#ifdef __hpux |
448 |
int i; |
449 |
#endif |
450 |
|
451 |
if (libname == NULL) { |
452 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: null library name"); |
453 |
return NULL; |
454 |
} |
455 |
if (symbol == NULL) { |
456 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Failed: null function name"); |
457 |
return NULL; |
458 |
} |
459 |
|
460 |
dlreturn = AscFindDLRecord(libname); |
461 |
if (dlreturn == NULL) { |
462 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find requested library %s", libname); |
463 |
return NULL; |
464 |
} |
465 |
#ifdef __hpux |
466 |
i = shl_findsym(&dlreturn, symbol, TYPE_UNDEFINED, &symreturn); |
467 |
if (i == -1) { |
468 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find requested function '%s' in %s (%s)", |
469 |
symbol, libname, strerror(errno)); |
470 |
symreturn = NULL; |
471 |
} |
472 |
#elif defined(__WIN32__) |
473 |
/* no problem on Windows - GetProcAddress() returns a function pointer. */ |
474 |
symreturn = (DynamicF)GetProcAddress((HINSTANCE)dlreturn, symbol); |
475 |
#else |
476 |
/* |
477 |
* Here's the corresponding bit of possibly-misdirected casting horror. |
478 |
* ISO C forbids casting between function and data pointers, so, naturally, |
479 |
* we cast between function and data pointers. Well, we don't have much |
480 |
* choice. dlsym() returns a void* for both variables and functions so we |
481 |
* have to do the cast for functions. This is ok on POSIX systems since the |
482 |
* pointer types are compatible. Then, to avoid being reminded by the |
483 |
* compiler that we're doing something illegal, we apply convoluted casting |
484 |
* to shut it up. Oh, the crap you can find on the internet... JDS |
485 |
*/ |
486 |
*(void**)(&symreturn) = dlsym(dlreturn, symbol); |
487 |
#endif |
488 |
if (symreturn == NULL) { |
489 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"Unable to find requested function '%s' in %s",symbol,libname); |
490 |
ERROR_REPORTER_NOLINE(ASC_PROG_ERR,"Error type: %s",ASC_DLERRSTRING); |
491 |
} |
492 |
return symreturn; |
493 |
} |
494 |
|
495 |
|
496 |
/*----------------------------------------------------------------------------- |
497 |
SEARCHING FOR LIBRARIES |
498 |
*/ |
499 |
|
500 |
/** |
501 |
A little structure to help with searching for libraries |
502 |
|
503 |
@see test_librarysearch |
504 |
*/ |
505 |
struct LibrarySearch{ |
506 |
struct FilePath *partialpath; |
507 |
char fullpath[PATH_MAX]; |
508 |
}; |
509 |
|
510 |
FilePathTestFn test_librarysearch; |
511 |
|
512 |
/** |
513 |
A 'test' function for passing to the ospath_searchpath_iterate function. |
514 |
This test function will return a match when a library having the required |
515 |
name is present in the fully resolved path. |
516 |
*/ |
517 |
int test_librarysearch(struct FilePath *path, void *userdata){ |
518 |
/* user data = the relative path, plus a place |
519 |
to store the full path when found */ |
520 |
FILE *f; |
521 |
struct LibrarySearch *ls; |
522 |
struct FilePath *fp; |
523 |
|
524 |
ls = (struct LibrarySearch *)userdata; |
525 |
fp = ospath_concat(path,ls->partialpath); |
526 |
if(fp==NULL){ |
527 |
char *tmp; |
528 |
tmp = ospath_str(path); |
529 |
CONSOLE_DEBUG("Unable to concatenate '%s'...",tmp); |
530 |
ospath_free_str(tmp); |
531 |
tmp = ospath_str(ls->partialpath); |
532 |
CONSOLE_DEBUG("... and '%s'...",tmp); |
533 |
ospath_free_str(tmp); |
534 |
return 0; |
535 |
} |
536 |
|
537 |
ospath_strncpy(fp,ls->fullpath,PATH_MAX); |
538 |
CONSOLE_DEBUG("SEARCHING FOR %s",ls->fullpath); |
539 |
|
540 |
f = ospath_fopen(fp,"r"); |
541 |
if(f==NULL){ |
542 |
ospath_free(fp); |
543 |
return 0; |
544 |
} |
545 |
fclose(f); |
546 |
|
547 |
/* ERROR_REPORTER_HERE(ASC_PROG_NOTE,"FOUND! %s\n",ls->fullpath); */ |
548 |
ospath_free(fp); |
549 |
return 1; |
550 |
} |
551 |
|
552 |
char *SearchArchiveLibraryPath(CONST char *name, char *dpath, char *envv){ |
553 |
struct FilePath *fp1, *fp2, *fp3; /* relative path */ |
554 |
char *s1; |
555 |
char buffer[PATH_MAX]; |
556 |
|
557 |
struct LibrarySearch ls; |
558 |
struct FilePath **sp; |
559 |
char *path, *foundpath; |
560 |
ospath_stat_t buf; |
561 |
FILE *f; |
562 |
|
563 |
fp1 = ospath_new_noclean(name); |
564 |
if(fp1==NULL){ |
565 |
ERROR_REPORTER_HERE(ASC_USER_ERROR,"Invalid partial path '%s'",name); |
566 |
ospath_free(fp1); |
567 |
return NULL; |
568 |
} |
569 |
|
570 |
s1 = ospath_getfilestem(fp1); |
571 |
if(s1==NULL){ |
572 |
/* not a file, so fail... */ |
573 |
return NULL; |
574 |
} |
575 |
|
576 |
fp2 = ospath_getdir(fp1); |
577 |
if(fp2==NULL){ |
578 |
ERROR_REPORTER_HERE(ASC_PROG_ERR,"unable to retrieve file dir"); |
579 |
return NULL; |
580 |
} |
581 |
|
582 |
/* CONSOLE_DEBUG("FILESTEM = '%s'",s1); */ |
583 |
|
584 |
# if defined(ASC_SHLIBSUFFIX) && defined(ASC_SHLIBPREFIX) |
585 |
/* |
586 |
this is the preferred operation: SCons reports what the local system |
587 |
uses as its shared library file extension. |
588 |
*/ |
589 |
snprintf(buffer,PATH_MAX,"%s%s%s",ASC_SHLIBPREFIX,s1,ASC_SHLIBSUFFIX); |
590 |
# else |
591 |
/** |
592 |
@DEPRECATED |
593 |
|
594 |
If we don't have ASC_SHLIB-SUFFIX and -PREFIX then we can do some |
595 |
system-specific stuff here, but it's not as general. |
596 |
*/ |
597 |
# ifdef __WIN32__ |
598 |
snprintf(buffer,PATH_MAX,"%s.dll",s1); |
599 |
# elif defined(linux) |
600 |
snprintf(buffer,PATH_MAX,"lib%s.so",s1); /* changed from .o to .so -- JP */ |
601 |
# elif defined(sun) || defined(solaris) |
602 |
snprintf(buffer,PATH_MAX,"%s.so.1.0",s1); |
603 |
# elif defined(__hpux) |
604 |
snprintf(buffer,PATH_MAX,"%s.sl",s1); |
605 |
# elif defined(_SGI_SOURCE) |
606 |
snprintf(buffer,PATH_MAX,"%s.so",s1); |
607 |
# else |
608 |
# error "Unknown system type (please define ASC_SHLIBSUFFIX and ASC_SHLIBPREFIX)" |
609 |
# endif |
610 |
# endif |
611 |
|
612 |
fp3 = ospath_new(buffer); |
613 |
ospath_free(fp1); |
614 |
fp1 = ospath_concat(fp2,fp3); |
615 |
ospath_free(fp2); |
616 |
ospath_free(fp3); |
617 |
ospath_free_str(s1); |
618 |
|
619 |
/* attempt to open "name" directly */ |
620 |
if(0==ospath_stat(fp1,&buf) && NULL!=(f = ospath_fopen(fp1,"r")) ){ |
621 |
char *tmp; |
622 |
tmp = ospath_str(fp1); |
623 |
CONSOLE_DEBUG("Library '%s' opened directly, without path search",tmp); |
624 |
ospath_free_str(tmp); |
625 |
fp2 = ospath_getabs(fp1); |
626 |
foundpath = ospath_str(fp2); |
627 |
ospath_free(fp2); |
628 |
fclose(f); |
629 |
}else{ |
630 |
|
631 |
ls.partialpath = fp1; |
632 |
|
633 |
path=Asc_GetEnv(envv); |
634 |
if(path==NULL){ |
635 |
/* CONSOLE_DEBUG("ENV VAR NOT FOUND, FALLING BACK TO DEFAULT SEARCH PATH = '%s'",dpath); */ |
636 |
path=dpath; |
637 |
} |
638 |
|
639 |
/* CONSOLE_DEBUG("SEARCHPATH IS %s",path); */ |
640 |
sp = ospath_searchpath_new(path); |
641 |
|
642 |
if(NULL==ospath_searchpath_iterate(sp,&test_librarysearch,&ls)){ |
643 |
ospath_free(fp1); |
644 |
ospath_searchpath_free(sp); |
645 |
return NULL; |
646 |
} |
647 |
|
648 |
foundpath = ASC_NEW_ARRAY(char,strlen(ls.fullpath)+1); |
649 |
strcpy(foundpath,ls.fullpath); |
650 |
ospath_searchpath_free(sp); |
651 |
} |
652 |
|
653 |
ospath_free(fp1); |
654 |
return foundpath; |
655 |
} |