From 74e6a118caa67a5ea3671c03203fe6946df381dd Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Mon, 29 Aug 1994 12:54:38 +0000 Subject: [PATCH] * Python/import.c: support *.o/*.so as alternative for *module.o/*module.so * Python/import.c: if initializing a module did not enter the module into sys.modules, it may have raised an exception -- don't override this exception. Merged NT changes * Python/import.c: add lost NT-specific code back in Fixed NT changes --- Python/import.c | 406 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 335 insertions(+), 71 deletions(-) diff --git a/Python/import.c b/Python/import.c index a8cfe5b5ea8..980ccd23b5e 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1,5 +1,5 @@ /*********************************************************** -Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum, +Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum, Amsterdam, The Netherlands. All Rights Reserved @@ -38,9 +38,9 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "eval.h" #include "osdefs.h" -extern int verbose; /* Defined in pythonmain.c */ +extern int verbose; /* Defined in pythonrun.c */ -extern long getmtime(); /* Defined in posixmodule.c */ +extern long getmtime(); /* In getmtime.c */ #ifdef DEBUG #define D(x) x @@ -48,20 +48,114 @@ extern long getmtime(); /* Defined in posixmodule.c */ #define D(x) #endif -#ifdef USE_DL -#ifdef SUN_SHLIB -#include -typedef void (*dl_funcptr)(); -#else -#include "dl.h" -#endif /* SUN_SHLIB */ +/* Explanation of some of the the various #defines used by dynamic linking... -extern char *argv0; + symbol -- defined for: + + DYNAMIC_LINK -- any kind of dynamic linking + USE_RLD -- NeXT dynamic linking + USE_DL -- Jack's dl for IRIX 4 or GNU dld with emulation for Jack's dl + USE_SHLIB -- SunOS or IRIX 5 (SVR4?) shared libraries + _AIX -- AIX style dynamic linking + NT -- NT style dynamic linking (using DLLs) + _DL_FUNCPTR_DEFINED -- if the typedef dl_funcptr has been defined + WITH_MAC_DL -- Mac dynamic linking (highly experimental) + SHORT_EXT -- short extension for dynamic module, e.g. ".so" + LONG_EXT -- long extension, e.g. "module.so" + + (The other WITH_* symbols are used only once, to set the + appropriate symbols.) +*/ + +/* Configure dynamic linking */ + +#ifdef NT +#define DYNAMIC_LINK +#include +typedef FARPROC dl_funcptr; +#define _DL_FUNCPTR_DEFINED +#define SHORT_EXT ".dll" +#define LONG_EXT "module.dll" #endif +#if defined(NeXT) || defined(WITH_RLD) +#define DYNAMIC_LINK +#define USE_RLD +#endif + +#ifdef WITH_SGI_DL +#define DYNAMIC_LINK +#define USE_DL +#endif + +#ifdef WITH_DL_DLD +#define DYNAMIC_LINK +#define USE_DL +#endif + +#ifdef WITH_MAC_DL +#define DYNAMIC_LINK +#endif + +#if !defined(DYNAMIC_LINK) && defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN) +#define DYNAMIC_LINK +#define USE_SHLIB +#endif + +#ifdef _AIX +#define DYNAMIC_LINK +#include +typedef void (*dl_funcptr)(); +#define _DL_FUNCPTR_DEFINED +static void aix_loaderror(char *name); +#endif + +#ifdef DYNAMIC_LINK + +#ifdef USE_SHLIB +#include +#ifndef _DL_FUNCPTR_DEFINED +typedef void (*dl_funcptr)(); +#endif +#ifndef RTLD_LAZY +#define RTLD_LAZY 1 +#endif +#define SHORT_EXT ".so" +#define LONG_EXT "module.so" +#endif /* USE_SHLIB */ + +#ifdef USE_DL +#include "dl.h" +#endif + +#ifdef WITH_MAC_DL +#include "dynamic_load.h" +#endif + +#ifdef USE_RLD +#include +#define FUNCNAME_PATTERN "_init%s" +#ifndef _DL_FUNCPTR_DEFINED +typedef void (*dl_funcptr)(); +#endif +#endif /* USE_RLD */ + +extern char *getprogramname(); + +#ifndef FUNCNAME_PATTERN +#define FUNCNAME_PATTERN "init%s" +#endif + +#if !defined(SHORT_EXT) && !defined(LONG_EXT) +#define SHORT_EXT ".o" +#define LONG_EXT "module.o" +#endif /* !SHORT_EXT && !LONG_EXT */ + +#endif /* DYNAMIC_LINK */ + /* Magic word to reject .pyc files generated by other Python versions */ -#define MAGIC 0x999902L /* Increment by one for each incompatible change */ +#define MAGIC 0x999903L /* Increment by one for each incompatible change */ static object *modules; @@ -108,18 +202,145 @@ static struct filedescr { char *mode; enum filetype type; } filetab[] = { -#ifdef USE_DL -#ifdef SUN_SHLIB - {"module.so", "rb", C_EXTENSION}, -#else - {"module.o", "rb", C_EXTENSION}, -#endif /* SUN_SHLIB */ -#endif /* USE_DL */ +#ifdef DYNAMIC_LINK +#ifdef SHORT_EXT + {SHORT_EXT, "rb", C_EXTENSION}, +#endif /* !SHORT_EXT */ +#ifdef LONG_EXT + {LONG_EXT, "rb", C_EXTENSION}, +#endif /* !LONG_EXT */ +#endif /* DYNAMIC_LINK */ {".py", "r", PY_SOURCE}, {".pyc", "rb", PY_COMPILED}, {0, 0} }; +#ifdef DYNAMIC_LINK +static object * +load_dynamic_module(name, namebuf, m, m_ret) + char *name; + char *namebuf; + object *m; + object **m_ret; +{ + char funcname[258]; + dl_funcptr p = NULL; + if (m != NULL) { + err_setstr(ImportError, + "cannot reload dynamically loaded module"); + return NULL; + } + sprintf(funcname, FUNCNAME_PATTERN, name); +#ifdef WITH_MAC_DL + { + object *v = dynamic_load(namebuf); + if (v == NULL) + return NULL; + } +#else /* !WITH_MAC_DL */ +#ifdef USE_SHLIB + { +#ifdef RTLD_NOW + /* RTLD_NOW: resolve externals now + (i.e. core dump now if some are missing) */ + void *handle = dlopen(namebuf, RTLD_NOW); +#else + void *handle; + if (verbose) + printf("dlopen(\"%s\", %d);\n", namebuf, RTLD_LAZY); + handle = dlopen(namebuf, RTLD_LAZY); +#endif /* RTLD_NOW */ + if (handle == NULL) { + err_setstr(ImportError, dlerror()); + return NULL; + } + p = (dl_funcptr) dlsym(handle, funcname); + } +#endif /* USE_SHLIB */ +#ifdef _AIX + p = (dl_funcptr) load(namebuf, 1, 0); + if (p == NULL) { + aix_loaderror(namebuf); + return NULL; + } +#endif /* _AIX */ +#ifdef NT + { + HINSTANCE hDLL; + hDLL = LoadLibrary(namebuf); + if (hDLL==NULL){ + char errBuf[64]; + sprintf(errBuf, "DLL load failed with error code %d", + GetLastError()); + err_setstr(ImportError, errBuf); + return NULL; + } + p = GetProcAddress(hDLL, funcname); + } +#endif /* NT */ +#ifdef USE_DL + p = dl_loadmod(getprogramname(), namebuf, funcname); +#endif /* USE_DL */ +#ifdef USE_RLD + { + NXStream *errorStream; + struct mach_header *new_header; + const char *filenames[2]; + long ret; + unsigned long ptr; + + errorStream = NXOpenMemory(NULL, 0, NX_WRITEONLY); + filenames[0] = namebuf; + filenames[1] = NULL; + ret = rld_load(errorStream, &new_header, + filenames, NULL); + + /* extract the error messages for the exception */ + if(!ret) { + char *streamBuf; + int len, maxLen; + + NXPutc(errorStream, (char)0); + + NXGetMemoryBuffer(errorStream, + &streamBuf, &len, &maxLen); + err_setstr(ImportError, streamBuf); + } + + if(ret && rld_lookup(errorStream, funcname, &ptr)) + p = (dl_funcptr) ptr; + + NXCloseMemory(errorStream, NX_FREEBUFFER); + + if(!ret) + return NULL; + } +#endif /* USE_RLD */ + + if (p == NULL) { + err_setstr(ImportError, + "dynamic module does not define init function"); + return NULL; + } + (*p)(); + +#endif /* !WITH_MAC_DL */ + *m_ret = m = dictlookup(modules, name); + if (m == NULL) { + if (err_occurred() == NULL) + err_setstr(SystemError, + "dynamic module not initialized properly"); + return NULL; + } + if (verbose) + fprintf(stderr, + "import %s # dynamically loaded from %s\n", + name, namebuf); + INCREF(None); + return None; +} +#endif /* DYNAMIC_LINK */ + static object * get_module(m, name, m_ret) /*module*/object *m; @@ -182,35 +403,34 @@ get_module(m, name, m_ret) if (magic != MAGIC) { if (verbose) fprintf(stderr, - "# %s.pyc has bad magic\n", - name); + "# %s has bad magic\n", + namebuf); } else { pyc_mtime = rd_long(fpc); if (pyc_mtime != mtime) { if (verbose) fprintf(stderr, - "# %s.pyc has bad mtime\n", - name); + "# %s has bad mtime\n", + namebuf); } else { fclose(fp); fp = fpc; if (verbose) fprintf(stderr, - "# %s.pyc matches %s.py\n", - name, name); + "# %s matches %s.py\n", + namebuf, name); goto use_compiled; } } fclose(fpc); } namebuf[len] = '\0'; - err = parse_file(fp, namebuf, file_input, &n); - if (err != E_DONE) { - err_input(err); + n = parse_file(fp, namebuf, file_input); + fclose(fp); + if (n == NULL) return NULL; - } co = compile(n, namebuf); freetree(n); if (co == NULL) @@ -254,8 +474,8 @@ get_module(m, name, m_ret) case PY_COMPILED: if (verbose) - fprintf(stderr, "# %s.pyc without %s.py\n", - name, name); + fprintf(stderr, "# %s without %s.py\n", + namebuf, name); magic = rd_long(fp); if (magic != MAGIC) { err_setstr(ImportError, @@ -279,44 +499,11 @@ get_module(m, name, m_ret) name, namebuf); break; -#ifdef USE_DL +#ifdef DYNAMIC_LINK case C_EXTENSION: - { - char funcname[258]; - dl_funcptr p; fclose(fp); - sprintf(funcname, "init%s", name); -#ifdef SUN_SHLIB - { - void *handle = dlopen (namebuf, 1); - p = (dl_funcptr) dlsym(handle, funcname); - } -#else - p = dl_loadmod(argv0, namebuf, funcname); -#endif /* SUN_SHLIB */ - if (p == NULL) { - err_setstr(ImportError, - "dynamic module does not define init function"); - return NULL; - } else { - (*p)(); - *m_ret = m = dictlookup(modules, name); - if (m == NULL) { - err_setstr(SystemError, - "dynamic module not initialized properly"); - return NULL; - } else { - if (verbose) - fprintf(stderr, - "import %s # dynamically loaded from %s\n", - name, namebuf); - INCREF(None); - return None; - } - } - break; - } -#endif /* USE_DL */ + return load_dynamic_module(name, namebuf, m, m_ret); +#endif /* DYNAMIC_LINK */ default: fclose(fp); @@ -363,9 +550,11 @@ import_module(name) if ((n = init_builtin(name)) || (n = init_frozen(name))) { if (n < 0) return NULL; - if ((m = dictlookup(modules, name)) == NULL) - err_setstr(SystemError, - "builtin module missing"); + if ((m = dictlookup(modules, name)) == NULL) { + if (err_occurred() == NULL) + err_setstr(SystemError, + "builtin module not initialized properly"); + } } else { m = load_module(name); @@ -379,6 +568,7 @@ reload_module(m) object *m; { char *name; + int i; if (m == NULL || !is_moduleobject(m)) { err_setstr(TypeError, "reload() argument must be module"); return NULL; @@ -386,7 +576,21 @@ reload_module(m) name = getmodulename(m); if (name == NULL) return NULL; - /* XXX Ought to check for builtin modules -- can't reload these... */ + /* Check for built-in modules */ + for (i = 0; inittab[i].name != NULL; i++) { + if (strcmp(name, inittab[i].name) == 0) { + err_setstr(ImportError, + "cannot reload built-in module"); + return NULL; + } + } + /* Check for frozen modules */ + if ((i = init_frozen(name)) != 0) { + if (i < 0) + return NULL; + INCREF(None); + return None; + } return get_module(m, name, (object **)NULL); } @@ -423,6 +627,11 @@ init_builtin(name) int i; for (i = 0; inittab[i].name != NULL; i++) { if (strcmp(name, inittab[i].name) == 0) { + if (inittab[i].initfunc == NULL) { + err_setstr(ImportError, + "cannot re-init internal module"); + return -1; + } if (verbose) fprintf(stderr, "import %s # builtin\n", name); @@ -467,3 +676,58 @@ init_frozen(name) DECREF(v); return 1; } + + +#ifdef _AIX + +#include /* for isdigit() */ +#include /* for global errno */ +#include /* for strerror() */ + +void aix_loaderror(char *namebuf) +{ + + char *message[8], errbuf[1024]; + int i,j; + + struct errtab { + int errno; + char *errstr; + } load_errtab[] = { + {L_ERROR_TOOMANY, "to many errors, rest skipped."}, + {L_ERROR_NOLIB, "can't load library:"}, + {L_ERROR_UNDEF, "can't find symbol in library:"}, + {L_ERROR_RLDBAD, + "RLD index out of range or bad relocation type:"}, + {L_ERROR_FORMAT, "not a valid, executable xcoff file:"}, + {L_ERROR_MEMBER, + "file not an archive or does not contain requested member:"}, + {L_ERROR_TYPE, "symbol table mismatch:"}, + {L_ERROR_ALIGN, "text allignment in file is wrong."}, + {L_ERROR_SYSTEM, "System error:"}, + {L_ERROR_ERRNO, NULL} + }; + +#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0])) +#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)) + + sprintf(errbuf, " from module %s ", namebuf); + + if (!loadquery(1, &message[0], sizeof(message))) + ERRBUF_APPEND(strerror(errno)); + for(i = 0; message[i] && *message[i]; i++) { + int nerr = atoi(message[i]); + for (j=0; j