summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1994-08-29 12:54:38 (GMT)
committerGuido van Rossum <guido@python.org>1994-08-29 12:54:38 (GMT)
commit74e6a118caa67a5ea3671c03203fe6946df381dd (patch)
tree08d87d70741cc19f55e13d4e3c2a62adda3d5550
parent14144fcdfde3efdac2d2c609b985ade5edc4eda2 (diff)
downloadcpython-74e6a118caa67a5ea3671c03203fe6946df381dd.zip
cpython-74e6a118caa67a5ea3671c03203fe6946df381dd.tar.gz
cpython-74e6a118caa67a5ea3671c03203fe6946df381dd.tar.bz2
* 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
-rw-r--r--Python/import.c400
1 files changed, 332 insertions, 68 deletions
diff --git a/Python/import.c b/Python/import.c
index a8cfe5b..980ccd2 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
+/* Explanation of some of the the various #defines used by dynamic linking...
+
+ 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 <windows.h>
+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 <sys/ldr.h>
+typedef void (*dl_funcptr)();
+#define _DL_FUNCPTR_DEFINED
+static void aix_loaderror(char *name);
+#endif
+
+#ifdef DYNAMIC_LINK
+
+#ifdef USE_SHLIB
#include <dlfcn.h>
+#ifndef _DL_FUNCPTR_DEFINED
typedef void (*dl_funcptr)();
-#else
+#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 /* SUN_SHLIB */
+#endif
-extern char *argv0;
+#ifdef WITH_MAC_DL
+#include "dynamic_load.h"
#endif
+#ifdef USE_RLD
+#include <mach-o/rld.h>
+#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 <ctype.h> /* for isdigit() */
+#include <errno.h> /* for global errno */
+#include <string.h> /* 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<LOAD_ERRTAB_LEN ; j++) {
+ if (nerr == load_errtab[i].errno && load_errtab[i].errstr)
+ ERRBUF_APPEND(load_errtab[i].errstr);
+ }
+ while (isdigit(*message[i])) message[i]++ ;
+ ERRBUF_APPEND(message[i]);
+ ERRBUF_APPEND("\n");
+ }
+ errbuf[strlen(errbuf)-1] = '\0' ; /* trim off last newline */
+ err_setstr(ImportError, errbuf);
+ return;
+}
+
+#endif /* _AIX */