1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* Support for dynamic loading of extension modules */
33 /* If no dynamic linking is supported, this file still generates some code! */
37 #ifdef HAVE_SYS_PARAM_H
38 /* osdefs.h will define MAXPATHLEN if it's not already defined. */
39 #include <sys/param.h>
44 /* Explanation of some of the the various #defines used by dynamic linking...
46 symbol -- defined for:
48 DYNAMIC_LINK -- any kind of dynamic linking
49 USE_RLD -- NeXT dynamic linking with FVM shlibs
50 USE_DYLD -- NeXT dynamic linking with frameworks
51 USE_DL -- Jack's dl for IRIX 4 or GNU dld with emulation for Jack's dl
52 USE_SHLIB -- SunOS or IRIX 5 (SVR4?) shared libraries
53 _AIX -- AIX style dynamic linking
54 MS_WIN32 -- Windows NT style dynamic linking (using DLLs)
55 MS_WIN16 -- Windows 16-bit dynamic linking (using DLLs)
56 PYOS_OS2 -- IBM OS/2 dynamic linking (using DLLs)
57 _DL_FUNCPTR_DEFINED -- if the typedef dl_funcptr has been defined
58 USE_MAC_DYNAMIC_LOADING -- Mac CFM shared libraries
59 SHORT_EXT -- short extension for dynamic module, e.g. ".so"
60 LONG_EXT -- long extension, e.g. "module.so"
61 hpux -- HP-UX Dynamic Linking - defined by the compiler
62 __NetBSD__ -- NetBSD shared libraries
63 (assuming dlerror() was introduced between 1.2 and 1.3)
64 __FreeBSD__ -- FreeBSD shared libraries
65 __BEOS__ -- BeOS shared libraries - defined by the compiler
67 (The other WITH_* symbols are used only once, to set the
71 /* Configure dynamic linking */
82 typedef void (*dl_funcptr
)();
83 #define _DL_FUNCPTR_DEFINED 1
84 #define SHORT_EXT ".sl"
85 #define LONG_EXT "module.sl"
90 #define INCL_DOSERRORS
91 #define INCL_DOSMODULEMGR
93 typedef int (* APIENTRY dl_funcptr
)();
94 #define _DL_FUNCPTR_DEFINED 1
95 #define SHORT_EXT ".pyd"
96 #define LONG_EXT ".dll"
99 #if defined(__NetBSD__) && (NetBSD < 199712)
103 #define dlerror() "error in dynamic linking"
106 #ifdef MS_WINDOWS /* i.e. MS_WIN32 or MS_WIN16 */
110 typedef FARPROC dl_funcptr
;
111 #define _DL_FUNCPTR_DEFINED
113 #define SHORT_EXT "_d.pyd"
114 #define LONG_EXT "_d.dll"
116 #define SHORT_EXT ".pyd"
117 #define LONG_EXT ".dll"
124 #define SHORT_EXT ".so"
125 #define LONG_EXT "module.so"
126 #define FUNCNAME_PATTERN "_init%.200s"
129 #if defined(NeXT) && !defined(DYNAMIC_LINK)
132 /* Define this to 1 if you want be able to load ObjC modules as well:
133 it switches between two different way of loading modules on the NeXT,
134 one that directly interfaces with the dynamic loader (rld_load(), which
135 does not correctly load ObjC object files), and another that uses the
136 ObjC runtime (objc_loadModules()) to do the job.
137 You'll have to add ``-ObjC'' to the compiler flags if you set this to 1.
139 #define HANDLE_OBJC_MODULES 1
140 #if HANDLE_OBJC_MODULES
141 #include <objc/Object.h>
142 #include <objc/objc-load.h>
144 #define SHORT_EXT ".so"
145 #define LONG_EXT "module.so"
158 #ifdef USE_MAC_DYNAMIC_LOADING
160 #define SHORT_EXT ".slb"
162 #define LONG_EXT ".CFM68K.slb"
164 #define LONG_EXT ".ppc.slb"
166 #ifndef _DL_FUNCPTR_DEFINED
167 typedef void (*dl_funcptr
)();
171 #if !defined(DYNAMIC_LINK) && (defined(HAVE_DLOPEN) || defined(M_UNIX))
177 #undef USE_SHLIB /* AIX 4.2 and higher have dlfcn.h but we don't want it */
179 #define SHORT_EXT ".so"
180 #define LONG_EXT "module.so"
182 typedef void (*dl_funcptr
)();
183 #define _DL_FUNCPTR_DEFINED
184 static int aix_getoldmodules(void **);
185 static int aix_bindnewmodule(void *, void *);
186 static void aix_loaderror(char *);
190 #undef USE_SHLIB /* probably not defined anyway */
192 #define SHORT_EXT ".so"
193 #define LONG_EXT "module.so"
194 typedef void (*dl_funcptr
)(void);
195 #define _DL_FUNCPTR_DEFINED
197 #if defined(MAXPATHLEN) && !defined(_SYS_PARAM_H)
201 #include <kernel/image.h>
202 #include <kernel/OS.h>
207 #include "pythread.h"
208 static PyThread_type_lock beos_dyn_lock
;
211 static PyObject
*beos_dyn_images
= NULL
;
213 static void beos_init_dyn( void );
214 static void beos_cleanup_dyn( void );
215 static void beos_nuke_dyn( PyObject
*item
);
216 static void beos_add_dyn( char *pathname
, image_id id
);
222 #include <sys/types.h>
223 #include <sys/stat.h>
224 #if defined(__NetBSD__) && (NetBSD < 199712)
232 #ifndef _DL_FUNCPTR_DEFINED
233 typedef void (*dl_funcptr
)();
238 #define SHORT_EXT ".so"
239 #define LONG_EXT "module.so"
240 #endif /* USE_SHLIB */
242 #if defined(USE_DL) || defined(hpux)
246 #ifdef USE_MAC_DYNAMIC_LOADING
248 #include <CodeFragments.h>
249 #ifdef SYMANTEC__CFM68K__ /* Really an older version of Universal Headers */
250 #define CFragConnectionID ConnectionID
251 #define kLoadCFrag 0x01
254 #include "TFileSpec.h" /* for Path2FSSpec() */
262 #include <mach-o/rld.h>
263 #ifndef _DL_FUNCPTR_DEFINED
264 typedef void (*dl_funcptr
)();
269 #include <mach-o/dyld.h>
270 #ifndef _DL_FUNCPTR_DEFINED
271 typedef void (*dl_funcptr
)();
273 #endif /* USE_DYLD */
275 extern char *Py_GetProgramName();
277 #ifndef FUNCNAME_PATTERN
278 #if defined(__hp9000s300) || (defined(__NetBSD__) || defined(__FreeBSD__)) && !defined(__ELF__) || defined(__OpenBSD__) || defined(__BORLANDC__) || defined(NeXT)
279 #define FUNCNAME_PATTERN "_init%.200s"
281 #define FUNCNAME_PATTERN "init%.200s"
285 #if !defined(SHORT_EXT) && !defined(LONG_EXT)
286 #define SHORT_EXT ".o"
287 #define LONG_EXT "module.o"
288 #endif /* !SHORT_EXT && !LONG_EXT */
290 #endif /* DYNAMIC_LINK */
292 struct filedescr _PyImport_Filetab
[] = {
294 {SHORT_EXT
, "rb", C_EXTENSION
},
295 #endif /* !SHORT_EXT */
297 {LONG_EXT
, "rb", C_EXTENSION
},
298 #endif /* !LONG_EXT */
299 {".py", "r", PY_SOURCE
},
300 {".pyc", "rb", PY_COMPILED
},
304 #ifdef NO_DYNAMIC_LINK
309 _PyImport_LoadDynamicModule(name
, pathname
, fp
)
315 PyErr_SetString(PyExc_ImportError
,
316 "dynamically linked modules not supported");
321 char *lastdot
, *shortname
, *packagecontext
;
329 static int nhandles
= 0;
331 if (strchr(pathname
, '/') == NULL
) {
332 /* Prefix bare filename with "./" */
333 sprintf(pathbuf
, "./%-.255s", pathname
);
337 if ((m
= _PyImport_FindExtension(name
, pathname
)) != NULL
) {
341 lastdot
= strrchr(name
, '.');
342 if (lastdot
== NULL
) {
343 packagecontext
= NULL
;
347 packagecontext
= name
;
348 shortname
= lastdot
+1;
350 sprintf(funcname
, FUNCNAME_PATTERN
, shortname
);
355 fstat(fileno(fp
), &statb
);
356 for (i
= 0; i
< nhandles
; i
++) {
357 if (statb
.st_dev
== handles
[i
].dev
&&
358 statb
.st_ino
== handles
[i
].ino
) {
359 p
= (dl_funcptr
) dlsym(handles
[i
].handle
,
364 if (nhandles
< 128) {
365 handles
[nhandles
].dev
= statb
.st_dev
;
366 handles
[nhandles
].ino
= statb
.st_ino
;
369 #endif /* USE_SHLIB */
370 #ifdef USE_MAC_DYNAMIC_LOADING
372 ** Dynamic loading of CFM shared libraries on the Mac. The
373 ** code has become more convoluted than it was, because we
374 ** want to be able to put multiple modules in a single
375 ** file. For this reason, we have to determine the fragment
376 ** name, and we cannot use the library entry point but we have
377 ** to locate the correct init routine "by hand".
381 CFragConnectionID connID
;
386 Boolean isfolder
, didsomething
;
391 CFragSymbolClass
class;
393 /* First resolve any aliases to find the real file */
395 err
= Path2FSSpec(pathname
, &libspec
);
397 (void)FSMakeFSSpec(0, 0, Pstring(pathname
), &libspec
);
398 err
= ResolveAliasFile(&libspec
, 1, &isfolder
, &didsomething
);
401 sprintf(buf
, "%.255s: %.200s",
402 pathname
, PyMac_StrError(err
));
403 PyErr_SetString(PyExc_ImportError
, buf
);
406 /* Next, determine the fragment name,
407 by stripping '.slb' and 'module' */
408 memcpy(fragname
+1, libspec
.name
+1, libspec
.name
[0]);
409 fragname
[0] = libspec
.name
[0];
410 if( strncmp((char *)(fragname
+1+fragname
[0]-4),
413 if ( strncmp((char *)(fragname
+1+fragname
[0]-6),
417 (or return the connID if it is already loaded */
418 err
= GetDiskFragment(&libspec
, 0, 0, fragname
,
419 kLoadCFrag
, &connID
, &mainAddr
,
422 sprintf(buf
, "%.*s: %.200s",
423 errMessage
[0], errMessage
+1,
424 PyMac_StrError(err
));
425 PyErr_SetString(PyExc_ImportError
, buf
);
428 /* Locate the address of the correct init function */
429 err
= FindSymbol(connID
, Pstring(funcname
), &symAddr
, &class);
431 sprintf(buf
, "%s: %.200s",
432 funcname
, PyMac_StrError(err
));
433 PyErr_SetString(PyExc_ImportError
, buf
);
436 p
= (dl_funcptr
)symAddr
;
438 #endif /* USE_MAC_DYNAMIC_LOADING */
442 /* RTLD_NOW: resolve externals now
443 (i.e. core dump now if some are missing) */
444 void *handle
= dlopen(pathname
, RTLD_NOW
);
448 printf("dlopen(\"%s\", %d);\n", pathname
,
450 handle
= dlopen(pathname
, RTLD_LAZY
);
451 #endif /* RTLD_NOW */
452 if (handle
== NULL
) {
453 PyErr_SetString(PyExc_ImportError
, dlerror());
456 if (fp
!= NULL
&& nhandles
< 128)
457 handles
[nhandles
++].handle
= handle
;
458 p
= (dl_funcptr
) dlsym(handle
, funcname
);
460 #endif /* USE_SHLIB */
463 -- Invoke load() with L_NOAUTODEFER leaving the imported symbols
464 -- of the shared module unresolved. Thus we have to resolve them
465 -- explicitely with loadbind. The new module is loaded, then we
466 -- resolve its symbols using the list of already loaded modules
467 -- (only those that belong to the python executable). Get these
468 -- with loadquery(L_GETINFO).
471 static void *staticmodlistptr
= NULL
;
473 if (!staticmodlistptr
)
474 if (aix_getoldmodules(&staticmodlistptr
) == -1)
476 p
= (dl_funcptr
) load(pathname
, L_NOAUTODEFER
, 0);
478 aix_loaderror(pathname
);
481 if (aix_bindnewmodule((void *)p
, staticmodlistptr
) == -1) {
482 aix_loaderror(pathname
);
491 if (strchr(pathname
, SEP
) == NULL
&&
492 strchr(pathname
, ALTSEP
) == NULL
)
494 /* Prefix bare filename with ".\" */
497 _getcwd(pathbuf
, sizeof pathbuf
);
498 if (*p
!= '\0' && p
[1] == ':')
500 sprintf(p
, ".\\%-.255s", pathname
);
503 /* Look for dependent DLLs in directory of pathname first */
504 /* XXX This call doesn't exist in Windows CE */
505 hDLL
= LoadLibraryEx(pathname
, NULL
,
506 LOAD_WITH_ALTERED_SEARCH_PATH
);
509 unsigned int errorCode
;
511 /* Get an error string from Win32 error code */
512 char theInfo
[256]; /* Pointer to error text
514 int theLength
; /* Length of error text */
516 errorCode
= GetLastError();
518 theLength
= FormatMessage(
519 FORMAT_MESSAGE_FROM_SYSTEM
, /* flags */
520 NULL
, /* message source */
521 errorCode
, /* the message (error) ID */
522 0, /* default language environment */
523 (LPTSTR
) theInfo
, /* the buffer */
524 sizeof(theInfo
), /* the buffer size */
525 NULL
); /* no additional format args. */
527 /* Problem: could not get the error message.
528 This should not happen if called correctly. */
529 if (theLength
== 0) {
531 "DLL load failed with error code %d",
535 /* For some reason a \r\n
536 is appended to the text */
537 if (theLength
>= 2 &&
538 theInfo
[theLength
-2] == '\r' &&
539 theInfo
[theLength
-1] == '\n') {
541 theInfo
[theLength
] = '\0';
543 strcpy(errBuf
, "DLL load failed: ");
544 len
= strlen(errBuf
);
545 strncpy(errBuf
+len
, theInfo
,
547 errBuf
[sizeof(errBuf
)-1] = '\0';
549 PyErr_SetString(PyExc_ImportError
, errBuf
);
552 p
= GetProcAddress(hDLL
, funcname
);
554 #endif /* MS_WIN32 */
559 if (strchr(pathname
, SEP
) == NULL
&&
560 strchr(pathname
, ALTSEP
) == NULL
)
562 /* Prefix bare filename with ".\" */
563 sprintf(pathbuf
, ".\\%-.13s", pathname
);
566 hDLL
= LoadLibrary(pathname
);
567 if (hDLL
< HINSTANCE_ERROR
){
570 "DLL load failed with error code %d", hDLL
);
571 PyErr_SetString(PyExc_ImportError
, errBuf
);
574 p
= GetProcAddress(hDLL
, funcname
);
576 #endif /* MS_WIN16 */
578 #if defined(PYOS_OS2)
582 char failreason
[256];
584 rc
= DosLoadModule(failreason
,
589 if (rc
!= NO_ERROR
) {
592 "DLL load failed, rc = %d, problem '%s': %s",
594 PyErr_SetString(PyExc_ImportError
, errBuf
);
598 rc
= DosQueryProcAddr(hDLL
, 0L, funcname
, &p
);
600 p
= NULL
; /* Signify Failure to Acquire Entrypoint */
602 #endif /* PYOS_OS2 */
605 p
= dl_loadmod(Py_GetProgramName(), pathname
, funcname
);
609 NXStream
*errorStream
;
610 struct mach_header
*new_header
;
611 const char *filenames
[2];
615 errorStream
= NXOpenMemory(NULL
, 0, NX_WRITEONLY
);
616 filenames
[0] = pathname
;
619 #if HANDLE_OBJC_MODULES
621 /* The following very bogus line of code ensures that
622 objc_msgSend, etc are linked into the binary. Without
623 it, dynamic loading of a module that includes objective-c
624 method calls will fail with "undefined symbol _objc_msgSend()".
625 This remains true even in the presence of the -ObjC flag
631 /* objc_loadModules() dynamically loads the object files
632 indicated by the paths in filenames. If there are any
633 errors generated during loading -- typically due to the
634 inability to find particular symbols -- an error message
635 will be written to errorStream.
636 It returns 0 if the module is successfully loaded, 1
640 ret
= !objc_loadModules(filenames
, errorStream
,
641 NULL
, &new_header
, NULL
);
643 #else /* !HANDLE_OBJC_MODULES */
645 ret
= rld_load(errorStream
, &new_header
,
648 #endif /* HANDLE_OBJC_MODULES */
650 /* extract the error messages for the exception */
655 NXPutc(errorStream
, (char)0);
657 NXGetMemoryBuffer(errorStream
,
658 &streamBuf
, &len
, &maxLen
);
659 PyErr_SetString(PyExc_ImportError
, streamBuf
);
662 if(ret
&& rld_lookup(errorStream
, funcname
, &ptr
))
663 p
= (dl_funcptr
) ptr
;
665 NXCloseMemory(errorStream
, NX_FREEBUFFER
);
672 /* This is also NeXT-specific. However, frameworks (the new style
673 of shared library) and rld() can't be used in the same program;
674 instead, you have to use dyld, which is mostly unimplemented. */
676 NSObjectFileImageReturnCode rc
;
677 NSObjectFileImage image
;
681 const char *errString
;
683 rc
= NSCreateObjectFileImageFromFile(pathname
, &image
);
686 case NSObjectFileImageFailure
:
687 NSObjectFileImageFormat
:
688 /* for these a message is printed on stderr by dyld */
689 errString
= "Can't create object file image";
691 case NSObjectFileImageSuccess
:
694 case NSObjectFileImageInappropriateFile
:
695 errString
= "Inappropriate file type for dynamic loading";
697 case NSObjectFileImageArch
:
698 errString
= "Wrong CPU type in object file";
700 NSObjectFileImageAccess
:
701 errString
= "Can't read object file (no access)";
704 if (errString
== NULL
) {
705 newModule
= NSLinkModule(image
, pathname
, TRUE
);
707 errString
= "Failure linking new module";
709 if (errString
!= NULL
) {
710 PyErr_SetString(PyExc_ImportError
, errString
);
713 if (!NSIsSymbolNameDefined(funcname
)) {
714 /* UnlinkModule() isn't implimented in current versions, but calling it does no harm */
715 NSUnLinkModule(newModule
, FALSE
);
716 PyErr_Format(PyExc_ImportError
, "Loaded module does not contain symbol %s", funcname
);
719 theSym
= NSLookupAndBindSymbol(funcname
);
720 p
= (dl_funcptr
)NSAddressOfSymbol(theSym
);
722 #endif /* USE_DYLD */
728 flags
= BIND_FIRST
| BIND_DEFERRED
;
729 if (Py_VerboseFlag
) {
730 flags
= DYNAMIC_PATH
| BIND_FIRST
| BIND_IMMEDIATE
|
731 BIND_NONFATAL
| BIND_VERBOSE
;
732 printf("shl_load %s\n",pathname
);
734 lib
= shl_load(pathname
, flags
, 0);
735 /* XXX Chuck Blake once wrote that 0 should be BIND_NOSTART? */
740 sprintf(buf
, "Failed to load %.200s", pathname
);
741 PyErr_SetString(PyExc_ImportError
, buf
);
745 printf("shl_findsym %s\n", funcname
);
746 shl_findsym(&lib
, funcname
, TYPE_UNDEFINED
, (void *) &p
);
747 if (p
== NULL
&& Py_VerboseFlag
)
755 char fullpath
[PATH_MAX
];
757 if( Py_VerboseFlag
) {
758 printf( "load_add_on( %s )\n", pathname
);
761 /* Hmm, this old bug appears to have regenerated itself; if the
762 * path isn't absolute, load_add_on() will fail. Reported to Be
765 if( pathname
[0] != '/' ) {
766 (void)getcwd( fullpath
, PATH_MAX
);
767 (void)strncat( fullpath
, "/", PATH_MAX
);
768 (void)strncat( fullpath
, pathname
, PATH_MAX
);
770 if( Py_VerboseFlag
) {
771 printf( "load_add_on( %s )\n", fullpath
);
774 (void)strcpy( fullpath
, pathname
);
777 the_id
= load_add_on( fullpath
);
778 if( the_id
< B_NO_ERROR
) {
779 /* It's too bad load_add_on() doesn't set errno or something...
781 char buff
[256]; /* hate hard-coded string sizes... */
783 if( Py_VerboseFlag
) {
784 printf( "load_add_on( %s ) failed", fullpath
);
789 sprintf( buff
, "BeOS: Failed to load %.200s", fullpath
);
792 sprintf( buff
, "Unknown error loading %.200s", fullpath
);
796 PyErr_SetString( PyExc_ImportError
, buff
);
800 if( Py_VerboseFlag
) {
801 printf( "get_image_symbol( %s )\n", funcname
);
804 retval
= get_image_symbol( the_id
, funcname
, B_SYMBOL_TYPE_TEXT
, &p
);
805 if( retval
!= B_NO_ERROR
|| p
== NULL
) {
806 /* That's bad, we can't find that symbol in the module...
808 char buff
[256]; /* hate hard-coded string sizes... */
810 if( Py_VerboseFlag
) {
811 printf( "get_image_symbol( %s ) failed", funcname
);
816 sprintf( buff
, "can't load init function for dynamic module: "
817 "Invalid image ID for %.180s", fullpath
);
820 sprintf( buff
, "can't load init function for dynamic module: "
821 "Bad index for %.180s", funcname
);
824 sprintf( buff
, "can't load init function for dynamic module: "
825 "Unknown error looking up %.180s", funcname
);
829 retval
= unload_add_on( the_id
);
831 PyErr_SetString( PyExc_ImportError
, buff
);
835 /* Save the module name and image ID for later so we can clean up
838 beos_add_dyn( name
, the_id
);
840 #endif /* __BEOS__ */
845 PyErr_Format(PyExc_ImportError
,
846 "dynamic module does not define init function (%.200s)",
850 _Py_PackageContext
= packagecontext
;
852 _Py_PackageContext
= NULL
;
853 if (PyErr_Occurred())
855 if (_PyImport_FixupExtension(name
, pathname
) == NULL
)
858 m
= PyDict_GetItemString(PyImport_GetModuleDict(), name
);
860 PyErr_SetString(PyExc_SystemError
,
861 "dynamic module not initialized properly");
864 /* Remember the filename as the __file__ attribute */
865 d
= PyModule_GetDict(m
);
866 s
= PyString_FromString(pathname
);
867 if (s
== NULL
|| PyDict_SetItemString(d
, "__file__", s
) != 0)
868 PyErr_Clear(); /* Not important enough to report */
872 "import %s # dynamically loaded from %s\n",
876 #endif /* DYNAMIC_LINK */
882 #include <ctype.h> /* for isdigit() */
883 #include <errno.h> /* for global errno */
884 #include <string.h> /* for strerror() */
885 #include <stdlib.h> /* for malloc(), free() */
887 typedef struct Module
{
890 } Module
, *ModulePtr
;
893 aix_getoldmodules(modlistptr
)
896 register ModulePtr modptr
, prevmodptr
;
897 register struct ld_info
*ldiptr
;
898 register char *ldibuf
;
899 register int errflag
, bufsize
= 1024;
900 register unsigned int offset
;
901 char *progname
= Py_GetProgramName();
904 -- Get the list of loaded modules into ld_info structures.
906 if ((ldibuf
= malloc(bufsize
)) == NULL
) {
907 PyErr_SetString(PyExc_ImportError
, strerror(errno
));
910 while ((errflag
= loadquery(L_GETINFO
, ldibuf
, bufsize
)) == -1
911 && errno
== ENOMEM
) {
914 if ((ldibuf
= malloc(bufsize
)) == NULL
) {
915 PyErr_SetString(PyExc_ImportError
, strerror(errno
));
920 PyErr_SetString(PyExc_ImportError
, strerror(errno
));
924 -- Make the modules list from the ld_info structures.
926 ldiptr
= (struct ld_info
*)ldibuf
;
929 if (strstr(progname
, ldiptr
->ldinfo_filename
) == NULL
&&
930 strstr(ldiptr
->ldinfo_filename
, "python") == NULL
) {
932 -- Extract only the modules belonging to the main
933 -- executable + those containing "python" as a
934 -- substring (like the "python[version]" binary or
935 -- "libpython[version].a" in case it's a shared lib).
937 offset
= (unsigned int)ldiptr
->ldinfo_next
;
938 ldiptr
= (struct ld_info
*)((unsigned int)
942 if ((modptr
= (ModulePtr
)malloc(sizeof(Module
))) == NULL
) {
943 PyErr_SetString(PyExc_ImportError
, strerror(errno
));
944 while (*modlistptr
) {
945 modptr
= (ModulePtr
)*modlistptr
;
946 *modlistptr
= (void *)modptr
->next
;
951 modptr
->entry
= ldiptr
->ldinfo_dataorg
;
953 if (prevmodptr
== NULL
)
954 *modlistptr
= (void *)modptr
;
956 prevmodptr
->next
= modptr
;
958 offset
= (unsigned int)ldiptr
->ldinfo_next
;
959 ldiptr
= (struct ld_info
*)((unsigned int)ldiptr
+ offset
);
966 aix_bindnewmodule(newmoduleptr
, modlistptr
)
970 register ModulePtr modptr
;
973 -- Bind the new module with the list of loaded modules.
975 for (modptr
= (ModulePtr
)modlistptr
; modptr
; modptr
= modptr
->next
)
976 if (loadbind(0, modptr
->entry
, newmoduleptr
) != 0)
982 aix_loaderror(pathname
)
986 char *message
[1024], errbuf
[1024];
993 {L_ERROR_TOOMANY
, "too many errors, rest skipped."},
994 {L_ERROR_NOLIB
, "can't load library:"},
995 {L_ERROR_UNDEF
, "can't find symbol in library:"},
997 "RLD index out of range or bad relocation type:"},
998 {L_ERROR_FORMAT
, "not a valid, executable xcoff file:"},
1000 "file not an archive or does not contain requested member:"},
1001 {L_ERROR_TYPE
, "symbol table mismatch:"},
1002 {L_ERROR_ALIGN
, "text alignment in file is wrong."},
1003 {L_ERROR_SYSTEM
, "System error:"},
1004 {L_ERROR_ERRNO
, NULL
}
1007 #define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
1008 #define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
1010 sprintf(errbuf
, "from module %.200s ", pathname
);
1012 if (!loadquery(L_GETMESSAGES
, &message
[0], sizeof(message
))) {
1013 ERRBUF_APPEND(strerror(errno
));
1014 ERRBUF_APPEND("\n");
1016 for(i
= 0; message
[i
] && *message
[i
]; i
++) {
1017 int nerr
= atoi(message
[i
]);
1018 for (j
=0; j
<LOAD_ERRTAB_LEN
; j
++) {
1019 if (nerr
== load_errtab
[j
].errNo
&& load_errtab
[j
].errstr
)
1020 ERRBUF_APPEND(load_errtab
[j
].errstr
);
1022 while (isdigit(*message
[i
])) message
[i
]++ ;
1023 ERRBUF_APPEND(message
[i
]);
1024 ERRBUF_APPEND("\n");
1026 errbuf
[strlen(errbuf
)-1] = '\0'; /* trim off last newline */
1027 PyErr_SetString(PyExc_ImportError
, errbuf
);
1034 /* ----------------------------------------------------------------------
1035 * BeOS dynamic loading support
1037 * This uses shared libraries, but BeOS has its own way of doing things
1038 * (much easier than dlfnc.h, from the look of things). We'll use a
1039 * Python Dictionary object to store the images_ids so we can be very
1040 * nice and unload them when we exit.
1042 * Note that this is thread-safe. Probably irrelevent, because of losing
1043 * systems... Python probably disables threads while loading modules.
1044 * Note the use of "probably"! Better to be safe than sorry. [chrish]
1046 * As of 1.5.1 this should also work properly when you've configured
1047 * Python without thread support; the 1.5 version required it, which wasn't
1048 * very friendly. Note that I haven't tested it without threading... why
1049 * would you want to avoid threads on BeOS? [chrish]
1051 * As of 1.5.2, the PyImport_BeImageID() function has been removed; Donn
1052 * tells me it's not necessary anymore because of PyCObject_Import().
1057 * Initialize our dictionary, and the dictionary mutex.
1059 static void beos_init_dyn( void )
1061 /* We're protected from a race condition here by the atomic init_count
1064 static int32 init_count
= 0;
1067 val
= atomic_add( &init_count
, 1 );
1068 if( beos_dyn_images
== NULL
&& val
== 0 ) {
1069 beos_dyn_images
= PyDict_New();
1071 beos_dyn_lock
= PyThread_allocate_lock();
1073 atexit( beos_cleanup_dyn
);
1077 /* atexit() handler that'll call unload_add_on() for every item in the
1080 static void beos_cleanup_dyn( void )
1082 if( beos_dyn_images
) {
1088 PyThread_acquire_lock( beos_dyn_lock
, 1 );
1091 id_list
= PyDict_Values( beos_dyn_images
);
1093 list_size
= PyList_Size( id_list
);
1094 for( idx
= 0; idx
< list_size
; idx
++ ) {
1097 the_item
= PyList_GetItem( id_list
, idx
);
1098 beos_nuke_dyn( the_item
);
1101 PyDict_Clear( beos_dyn_images
);
1104 PyThread_free_lock( beos_dyn_lock
);
1109 /* Whack an item; the item is an image_id in disguise, so we'll call
1110 * unload_add_on() for it.
1112 static void beos_nuke_dyn( PyObject
*item
)
1117 image_id id
= (image_id
)PyInt_AsLong( item
);
1119 retval
= unload_add_on( id
);
1124 * Add an image_id to the dictionary; the module name of the loaded image
1125 * is the key. Note that if the key is already in the dict, we unload
1126 * that image; this should allow reload() to work on dynamically loaded
1127 * modules (super-keen!).
1129 static void beos_add_dyn( char *name
, image_id id
)
1134 if( beos_dyn_images
== NULL
) {
1139 retval
= PyThread_acquire_lock( beos_dyn_lock
, 1 );
1142 /* If there's already an object with this key in the dictionary,
1143 * we're doing a reload(), so let's nuke it.
1145 py_id
= PyDict_GetItemString( beos_dyn_images
, name
);
1147 beos_nuke_dyn( py_id
);
1148 retval
= PyDict_DelItemString( beos_dyn_images
, name
);
1151 py_id
= PyInt_FromLong( (long)id
);
1153 retval
= PyDict_SetItemString( beos_dyn_images
, name
, py_id
);
1157 PyThread_release_lock( beos_dyn_lock
);
1161 #endif /* __BEOS__ */