* 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
This commit is contained in:
Guido van Rossum 1994-08-29 12:54:38 +00:00
parent 14144fcdfd
commit 74e6a118ca
1 changed files with 335 additions and 71 deletions

View File

@ -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 <dlfcn.h>
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 <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)();
#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 <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)
if ((m = dictlookup(modules, name)) == NULL) {
if (err_occurred() == NULL)
err_setstr(SystemError,
"builtin module missing");
"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 */