diff options
author | Guido van Rossum <guido@python.org> | 1995-01-02 19:04:15 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1995-01-02 19:04:15 (GMT) |
commit | 1ae940a5870df2f706fa884afd533847f6b0b1a8 (patch) | |
tree | ac19577f141b553bd56f998a62478719d5b81cd4 /Python/import.c | |
parent | 824de25fe2edade0ded378b4d602351272f4cf63 (diff) | |
download | cpython-1ae940a5870df2f706fa884afd533847f6b0b1a8.zip cpython-1ae940a5870df2f706fa884afd533847f6b0b1a8.tar.gz cpython-1ae940a5870df2f706fa884afd533847f6b0b1a8.tar.bz2 |
Lots of changes, most minor (fatal() instead of abort(), use of
err_fetch/err_restore and so on). But...
NOTE: import.c has been rewritten and all the DL stuff is now in the
new file importdl.c.
Diffstat (limited to 'Python/import.c')
-rw-r--r-- | Python/import.c | 1249 |
1 files changed, 681 insertions, 568 deletions
diff --git a/Python/import.c b/Python/import.c index ea6a6fe..a0af050 100644 --- a/Python/import.c +++ b/Python/import.c @@ -37,150 +37,58 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "compile.h" #include "eval.h" #include "osdefs.h" +#include "importdl.h" extern int verbose; /* Defined in pythonrun.c */ extern long getmtime(); /* In getmtime.c */ -#ifdef DEBUG -#define D(x) x -#else -#define D(x) -#endif - -/* 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" - hpux -- HP-UX Dynamic Linking - defined by the compiler - - (The other WITH_* symbols are used only once, to set the - appropriate symbols.) -*/ - -/* Configure dynamic linking */ - -#ifdef hpux -#define DYNAMIC_LINK -#include <errno.h> -typedef void (*dl_funcptr)(); -#define _DL_FUNCPTR_DEFINED 1 -#define SHORT_EXT ".sl" -#define LONG_EXT "module.sl" -#endif - -#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 */ - -#if defined(USE_DL) || defined(hpux) -#include "dl.h" -#endif - -#ifdef WITH_MAC_DL -#include "dynamic_load.h" -#endif +/* Magic word to reject .pyc files generated by other Python versions */ +#define MAGIC 0x999903L /* Increment by one for each incompatible change */ -#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 */ +object *import_modules; /* This becomes sys.modules */ -extern char *getprogramname(); -#ifndef FUNCNAME_PATTERN -#if defined(__hp9000s300) -#define FUNCNAME_PATTERN "_init%s" -#else -#define FUNCNAME_PATTERN "init%s" -#endif -#endif - -#if !defined(SHORT_EXT) && !defined(LONG_EXT) -#define SHORT_EXT ".o" -#define LONG_EXT "module.o" -#endif /* !SHORT_EXT && !LONG_EXT */ +/* Initialize things */ -#endif /* DYNAMIC_LINK */ +void +initimport() +{ + if (import_modules != NULL) + fatal("duplicate initimport() call"); + if ((import_modules = newdictobject()) == NULL) + fatal("no mem for dictionary of modules"); +} -/* Max length of module suffix searched for -- accommodates "module.so" */ -#ifndef MAXSUFFIXSIZE -#define MAXSUFFIXSIZE 10 -#endif -/* Magic word to reject .pyc files generated by other Python versions */ -#define MAGIC 0x999903L /* Increment by one for each incompatible change */ +/* Un-initialize things, as good as we can */ -static object *modules; +void +doneimport() +{ + if (import_modules != NULL) { + int pos; + object *modname, *module; + /* Explicitly erase all modules; this is the safest way + to get rid of at least *some* circular dependencies */ + pos = 0; + while (mappinggetnext(import_modules, + &pos, &modname, &module)) { + if (is_moduleobject(module)) { + object *dict; + dict = getmoduledict(module); + if (dict != NULL && is_dictobject(dict)) + mappingclear(dict); + } + } + mappingclear(import_modules); + DECREF(import_modules); + } + import_modules = NULL; +} -/* Forward */ -static int init_builtin PROTO((char *)); -/* Helper for reading .pyc files */ +/* Helper for pythonrun.c -- return magic number */ long get_pyc_magic() @@ -188,255 +96,338 @@ get_pyc_magic() return MAGIC; } -/* Initialization */ -void -initimport() -{ - if ((modules = newdictobject()) == NULL) - fatal("no mem for dictionary of modules"); -} +/* Helper for sysmodule.c -- return modules dictionary */ object * get_modules() { - return modules; + return import_modules; } + +/* Get the module object corresponding to a module name. + First check the modules dictionary if there's one there, + if not, create a new one and insert in in the modules dictionary. + Because the former action is most common, this does not return a + 'new' reference! */ + object * add_module(name) char *name; { object *m; - if ((m = dictlookup(modules, name)) != NULL && is_moduleobject(m)) + + if ((m = dictlookup(import_modules, name)) != NULL && + is_moduleobject(m)) return m; m = newmoduleobject(name); if (m == NULL) return NULL; - if (dictinsert(modules, name, m) != 0) { + if (dictinsert(import_modules, name, m) != 0) { DECREF(m); return NULL; } DECREF(m); /* Yes, it still exists, in modules! */ + return m; } -enum filetype {SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION}; -static struct filedescr { - char *suffix; - char *mode; - enum filetype type; -} filetab[] = { -#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} -}; +/* Execute a code object in a module and return its module object */ -#ifdef DYNAMIC_LINK static object * -load_dynamic_module(name, namebuf, m, m_ret) +exec_code_module(name, co) char *name; - char *namebuf; - object *m; - object **m_ret; + codeobject *co; { - char funcname[258]; - dl_funcptr p = NULL; - if (m != NULL) { - err_setstr(ImportError, - "cannot reload dynamically loaded module"); + object *m, *d, *v; + + m = add_module(name); + if (m == NULL) 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; + d = getmoduledict(m); + v = eval_code((codeobject *)co, d, d, d, (object *)NULL); + if (v == NULL) + return NULL; + DECREF(v); + INCREF(m); + + return m; +} + + +/* Given a pathname for a Python source file, fill a buffer with the + pathname for the corresponding compiled file. Return the pathname + for the compiled file, or NULL if there's no space in the buffer. + Doesn't set an exception. */ + +static char * +make_compiled_pathname(pathname, buf, buflen) + char *pathname; + char *buf; + int buflen; +{ + int len; + + len = strlen(pathname); + if (len+2 > buflen) + return NULL; + strcpy(buf, pathname); + strcpy(buf+len, "c"); + + return buf; +} + + +/* Given a pathname for a Python source file, its time of last + modification, and a pathname for a compiled file, check whether the + compiled file represents the same version of the source. If so, + return a FILE pointer for the compiled file, positioned just after + the header; if not, return NULL. + Doesn't set an exception. */ + +static FILE * +check_compiled_module(pathname, mtime, cpathname) + char *pathname; + long mtime; + char *cpathname; +{ + FILE *fp; + long magic; + long pyc_mtime; + + fp = fopen(cpathname, "rb"); + if (fp == NULL) + return NULL; + magic = rd_long(fp); + if (magic != MAGIC) { 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); + fprintf(stderr, "# %s has bad magic\n", cpathname); + fclose(fp); 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); + pyc_mtime = rd_long(fp); + if (pyc_mtime != mtime) { + if (verbose) + fprintf(stderr, "# %s has bad mtime\n", cpathname); + fclose(fp); 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 (verbose) + fprintf(stderr, "# %s matches %s\n", cpathname, pathname); + return fp; +} - if(ret && rld_lookup(errorStream, funcname, &ptr)) - p = (dl_funcptr) ptr; - NXCloseMemory(errorStream, NX_FREEBUFFER); +/* Read a code object from a file and check it for validity */ - if(!ret) - return NULL; - } -#endif /* USE_RLD */ -#ifdef hpux - { - shl_t lib; - int flags; +static codeobject * +read_compiled_module(fp) + FILE *fp; +{ + object *co; - flags = BIND_DEFERRED; - if (verbose) - { - flags = BIND_IMMEDIATE | BIND_NONFATAL | BIND_VERBOSE; - printf("shl_load %s\n",namebuf); - } - lib = shl_load(namebuf, flags, 0); - if (lib == NULL) - { - char buf[256]; - if (verbose) - perror(namebuf); - sprintf(buf, "Failed to load %.200s", namebuf); - err_setstr(ImportError, buf); - return NULL; - } - if (verbose) - printf("shl_findsym %s\n", funcname); - shl_findsym(&lib, funcname, TYPE_UNDEFINED, (void *) &p); - if (p == NULL && verbose) - perror(funcname); + co = rd_object(fp); + /* Ugly: rd_object() may return NULL with or without error */ + if (co == NULL || !is_codeobject(co)) { + if (!err_occurred()) + err_setstr(ImportError, + "Non-code object in .pyc file"); + XDECREF(co); + return NULL; } -#endif /* hpux */ - if (p == NULL) { - err_setstr(ImportError, - "dynamic module does not define init function"); + return (codeobject *)co; +} + + +/* Load a module from a compiled file, execute it, and return its + module object */ + +static object * +load_compiled_module(name, cpathname, fp) + char *name; + char *cpathname; + FILE *fp; +{ + long magic; + codeobject *co; + object *m; + + magic = rd_long(fp); + if (magic != MAGIC) { + err_setstr(ImportError, "Bad magic number in .pyc file"); return NULL; } - (*p)(); + (void) rd_long(fp); + co = read_compiled_module(fp); + if (co == NULL) + return NULL; + if (verbose) + fprintf(stderr, "import %s # precompiled from %s\n", + name, cpathname); + m = exec_code_module(name, co); + DECREF(co); + + return m; +} + + +/* Parse a source file and return the corresponding code object */ + +static codeobject * +parse_source_module(pathname, fp) + char *pathname; + FILE *fp; +{ + codeobject *co; + node *n; -#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"); + n = parse_file(fp, pathname, file_input); + if (n == NULL) return NULL; + co = compile(n, pathname); + freetree(n); + + return co; +} + + +/* Write a compiled module to a file, placing the time of last + modification of its source into the header. + Errors are ignored, if a write error occurs an attempt is made to + remove the file. */ + +static void +write_compiled_module(co, cpathname, mtime) + codeobject *co; + char *cpathname; + long mtime; +{ + FILE *fp; + + fp = fopen(cpathname, "wb"); + if (fp == NULL) { + if (verbose) + fprintf(stderr, + "# can't create %s\n", cpathname); + return; + } + wr_long(MAGIC, fp); + /* First write a 0 for mtime */ + wr_long(0L, fp); + wr_object((object *)co, fp); + if (ferror(fp)) { + if (verbose) + fprintf(stderr, "# can't write %s\n", cpathname); + /* Don't keep partial file */ + fclose(fp); + (void) unlink(cpathname); + return; } + /* Now write the true mtime */ + fseek(fp, 4L, 0); + wr_long(mtime, fp); + fflush(fp); + fclose(fp); if (verbose) - fprintf(stderr, - "import %s # dynamically loaded from %s\n", - name, namebuf); - INCREF(None); - return None; + fprintf(stderr, "# wrote %s\n", cpathname); +#ifdef macintosh + setfiletype(cpathname, 'PYTH', 'PYC '); +#endif } -#endif /* DYNAMIC_LINK */ + + +/* Load a source module from a given file and return its module + object. If there's a matching byte-compiled file, use that + instead. */ static object * -get_module(m, name, m_ret) - /*module*/object *m; +load_source_module(name, pathname, fp) char *name; - object **m_ret; + char *pathname; + FILE *fp; { - int err, npath, i, len, namelen; - long magic; - long mtime, pyc_mtime; - char namebuf[MAXPATHLEN+1]; + long mtime; + FILE *fpc; + char buf[MAXPATHLEN+1]; + char *cpathname; + codeobject *co; + object *m; + + mtime = getmtime(pathname); + cpathname = make_compiled_pathname(pathname, buf, MAXPATHLEN+1); + if (cpathname != NULL && + (fpc = check_compiled_module(pathname, mtime, cpathname))) { + co = read_compiled_module(fpc); + fclose(fpc); + if (co == NULL) + return NULL; + if (verbose) + fprintf(stderr, "import %s # precompiled from %s\n", + name, cpathname); + } + else { + co = parse_source_module(pathname, fp); + if (co == NULL) + return NULL; + if (verbose) + fprintf(stderr, "import %s # from %s\n", + name, pathname); + write_compiled_module(co, cpathname, mtime); + } + m = exec_code_module(name, co); + DECREF(co); + + return m; +} + + +/* Search the path (default sys.path) for a module. Return the + corresponding filedescr struct, and (via return arguments) the + pathname and an open file. Return NULL if the module is not found. */ + +static struct filedescr * +find_module(name, path, buf, buflen, p_fp) + char *name; + object *path; + /* Output parameters: */ + char *buf; + int buflen; + FILE **p_fp; +{ + int i, npath, len, namelen; struct filedescr *fdp; - FILE *fp = NULL, *fpc = NULL; - node *n = NULL; - object *path, *v, *d; - codeobject *co = NULL; + FILE *fp; - path = sysget("path"); + if (path == NULL) + path = sysget("path"); if (path == NULL || !is_listobject(path)) { err_setstr(ImportError, - "sys.path must be list of directory names"); + "module search path must be list of directory names"); return NULL; } npath = getlistsize(path); namelen = strlen(name); for (i = 0; i < npath; i++) { - v = getlistitem(path, i); + object *v = getlistitem(path, i); if (!is_stringobject(v)) continue; len = getstringsize(v); - if (len + 1 + namelen + MAXSUFFIXSIZE >= MAXPATHLEN) + if (len + 2 + namelen + import_maxsuffixsize >= buflen) continue; /* Too long */ - strcpy(namebuf, getstringvalue(v)); - if (strlen(namebuf) != len) + strcpy(buf, getstringvalue(v)); + if (strlen(buf) != len) continue; /* v contains '\0' */ - if (len > 0 && namebuf[len-1] != SEP) - namebuf[len++] = SEP; - strcpy(namebuf+len, name); + if (len > 0 && buf[len-1] != SEP) + buf[len++] = SEP; + strcpy(buf+len, name); len += namelen; - for (fdp = filetab; fdp->suffix != NULL; fdp++) { - strcpy(namebuf+len, fdp->suffix); + for (fdp = import_filetab; fdp->suffix != NULL; fdp++) { + strcpy(buf+len, fdp->suffix); if (verbose > 1) - fprintf(stderr, "# trying %s\n", namebuf); - fp = fopen(namebuf, fdp->mode); + fprintf(stderr, "# trying %s\n", buf); + fp = fopen(buf, fdp->mode); if (fp != NULL) break; } @@ -444,192 +435,164 @@ get_module(m, name, m_ret) break; } if (fp == NULL) { - sprintf(namebuf, "No module named %.200s", name); - err_setstr(ImportError, namebuf); + char buf[256]; + sprintf(buf, "No module named %.200s", name); + err_setstr(ImportError, buf); return NULL; } + *p_fp = fp; + return fdp; +} + + +/* Load an external module using the default search path and return + its module object */ + +static object * +load_module(name) + char *name; +{ + char buf[MAXPATHLEN+1]; + struct filedescr *fdp; + FILE *fp = NULL; + object *m = NULL; + + fdp = find_module(name, (object *)NULL, buf, MAXPATHLEN+1, &fp); + if (fdp == NULL) + return NULL; + switch (fdp->type) { case PY_SOURCE: - mtime = getmtime(namebuf); - len = strlen(namebuf); - strcpy(namebuf + len, "c"); - fpc = fopen(namebuf, "rb"); - if (fpc != NULL) { - magic = rd_long(fpc); - if (magic != MAGIC) { - if (verbose) - fprintf(stderr, - "# %s has bad magic\n", - namebuf); - } - else { - pyc_mtime = rd_long(fpc); - if (pyc_mtime != mtime) { - if (verbose) - fprintf(stderr, - "# %s has bad mtime\n", - namebuf); - } - else { - fclose(fp); - fp = fpc; - if (verbose) - fprintf(stderr, - "# %s matches %s.py\n", - namebuf, name); - goto use_compiled; - } - } - fclose(fpc); - } - namebuf[len] = '\0'; - n = parse_file(fp, namebuf, file_input); - fclose(fp); - if (n == NULL) - return NULL; - co = compile(n, namebuf); - freetree(n); - if (co == NULL) - return NULL; - if (verbose) - fprintf(stderr, - "import %s # from %s\n", name, namebuf); - /* Now write the code object to the ".pyc" file */ - strcpy(namebuf + len, "c"); - fpc = fopen(namebuf, "wb"); -#ifdef macintosh - setfiletype(namebuf, 'PYTH', 'PYC '); -#endif - if (fpc == NULL) { - if (verbose) - fprintf(stderr, - "# can't create %s\n", namebuf); - } - else { - wr_long(MAGIC, fpc); - /* First write a 0 for mtime */ - wr_long(0L, fpc); - wr_object((object *)co, fpc); - if (ferror(fpc)) { - if (verbose) - fprintf(stderr, - "# can't write %s\n", namebuf); - /* Don't keep partial file */ - fclose(fpc); - (void) unlink(namebuf); - } - else { - /* Now write the true mtime */ - fseek(fpc, 4L, 0); - wr_long(mtime, fpc); - fflush(fpc); - fclose(fpc); - if (verbose) - fprintf(stderr, - "# wrote %s\n", namebuf); - } - } + m = load_source_module(name, buf, fp); break; case PY_COMPILED: - if (verbose) - fprintf(stderr, "# %s without %s.py\n", - namebuf, name); - magic = rd_long(fp); - if (magic != MAGIC) { - err_setstr(ImportError, - "Bad magic number in .pyc file"); - return NULL; - } - (void) rd_long(fp); - use_compiled: - v = rd_object(fp); - fclose(fp); - if (v == NULL || !is_codeobject(v)) { - XDECREF(v); - err_setstr(ImportError, - "Bad code object in .pyc file"); - return NULL; - } - co = (codeobject *)v; - if (verbose) - fprintf(stderr, - "import %s # precompiled from %s\n", - name, namebuf); + m = load_compiled_module(name, buf, fp); break; -#ifdef DYNAMIC_LINK case C_EXTENSION: - fclose(fp); - return load_dynamic_module(name, namebuf, m, m_ret); -#endif /* DYNAMIC_LINK */ + m = load_dynamic_module(name, buf); + break; default: - fclose(fp); err_setstr(SystemError, - "search loop returned unexpected result"); - return NULL; + "find_module returned unexpected result"); } + fclose(fp); - /* We get here for either PY_SOURCE or PY_COMPILED */ - if (m == NULL) { - m = add_module(name); - if (m == NULL) { - freetree(n); - return NULL; + return m; +} + + +/* Initialize a built-in module. + Return 1 for succes, 0 if the module is not found, and -1 with + an exception set if the initialization failed. */ + +static int +init_builtin(name) + char *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); + (*inittab[i].initfunc)(); + if (err_occurred()) + return -1; + return 1; } - *m_ret = m; } - d = getmoduledict(m); - v = eval_code(co, d, d, d, (object *)NULL); - DECREF(co); - return v; + return 0; } -static object * -load_module(name) + +/* Initialize a frozen module. + Return 1 for succes, 0 if the module is not found, and -1 with + an exception set if the initialization failed. */ + +extern struct frozen { + char *name; + char *code; + int size; +} frozen_modules[]; + +static int +init_frozen(name) char *name; { - object *m, *v; - v = get_module((object *)NULL, name, &m); - if (v == NULL) - return NULL; - DECREF(v); - return m; + struct frozen *p; + object *co; + object *m; + for (p = frozen_modules; ; p++) { + if (p->name == NULL) + return 0; + if (strcmp(p->name, name) == 0) + break; + } + if (verbose) + fprintf(stderr, "import %s # frozen\n", name); + co = rds_object(p->code, p->size); + if (co == NULL) + return -1; + if (!is_codeobject(co)) { + DECREF(co); + err_setstr(SystemError, "frozen object is not a code object"); + return -1; + } + m = exec_code_module(name, (codeobject *)co); + DECREF(co); + return m == NULL ? -1 : 1; } + +/* Import a module, either built-in, frozen, or external, and return + its module object */ + object * import_module(name) char *name; { object *m; - int n; - if ((m = dictlookup(modules, name)) == NULL) { - if ((n = init_builtin(name)) || (n = init_frozen(name))) { - if (n < 0) + + if ((m = dictlookup(import_modules, name)) == NULL) { + int i; + if ((i = init_builtin(name)) || (i = init_frozen(name))) { + if (i < 0) return NULL; - if ((m = dictlookup(modules, name)) == NULL) { - if (err_occurred() == NULL) - err_setstr(SystemError, - "builtin module not initialized properly"); + if ((m = dictlookup(import_modules, name)) == NULL) { + if (err_occurred() == NULL) + err_setstr(SystemError, + "built-in module not initialized properly"); } } - else { + else m = load_module(name); - } } + return m; } + +/* Re-import a module of any kind and return its module object, WITH + INCREMENTED REFERENCE COUNT */ + object * 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; @@ -637,158 +600,308 @@ reload_module(m) name = getmodulename(m); if (name == NULL) return NULL; - /* 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; - } + if (m != dictlookup(import_modules, name)) { + err_setstr(ImportError, "reload() module not in sys.modules"); + return NULL; } - /* Check for frozen modules */ - if ((i = init_frozen(name)) != 0) { + /* Check for built-in and frozen modules */ + if ((i = init_builtin(name)) || (i = init_frozen(name))) { if (i < 0) return NULL; - INCREF(None); - return None; } - return get_module(m, name, (object **)NULL); + else + m = load_module(name); + XINCREF(m); + return m; } -void -doneimport() + +/* Module 'imp' provides Python access to the primitives used for + importing modules. +*/ + +static object * +imp_get_magic(self, args) + object *self; + object *args; { - if (modules != NULL) { - int pos; - object *modname, *module; - /* Explicitly erase all modules; this is the safest way - to get rid of at least *some* circular dependencies */ - pos = 0; - while (mappinggetnext(modules, &pos, &modname, &module)) { - if (is_moduleobject(module)) { - object *dict; - dict = getmoduledict(module); - if (dict != NULL && is_dictobject(dict)) - mappingclear(dict); - } + char buf[4]; + + if (!newgetargs(args, "")) + return NULL; + buf[0] = (MAGIC >> 0) & 0xff; + buf[1] = (MAGIC >> 8) & 0xff; + buf[3] = (MAGIC >> 16) & 0xff; + buf[4] = (MAGIC >> 24) & 0xff; + + return newsizedstringobject(buf, 4); +} + +static object * +imp_get_suffixes(self, args) + object *self; + object *args; +{ + object *list; + struct filedescr *fdp; + + if (!newgetargs(args, "")) + return NULL; + list = newlistobject(0); + if (list == NULL) + return NULL; + for (fdp = import_filetab; fdp->suffix != NULL; fdp++) { + object *item = mkvalue("ssi", + fdp->suffix, fdp->mode, fdp->type); + if (item == NULL) { + DECREF(list); + return NULL; } - mappingclear(modules); + if (addlistitem(list, item) < 0) { + DECREF(list); + DECREF(item); + return NULL; + } + DECREF(item); } - DECREF(modules); - modules = NULL; + return list; } +static object * +imp_find_module(self, args) + object *self; + object *args; +{ + extern int fclose PROTO((FILE *)); + char *name; + object *path = NULL; + object *fob, *ret; + struct filedescr *fdp; + char pathname[MAXPATHLEN+1]; + FILE *fp; + if (!newgetargs(args, "s|O!", &name, &Listtype, &path)) + return NULL; + fdp = find_module(name, path, pathname, MAXPATHLEN+1, &fp); + if (fdp == NULL) + return NULL; + fob = newopenfileobject(fp, pathname, fdp->mode, fclose); + if (fob == NULL) { + fclose(fp); + return NULL; + } + ret = mkvalue("Os(ssi)", + fob, pathname, fdp->suffix, fdp->mode, fdp->type); + DECREF(fob); + return ret; +} -/* Initialize built-in modules when first imported */ +static object * +imp_init_builtin(self, args) + object *self; + object *args; +{ + char *name; + int ret; + object *m; + if (!newgetargs(args, "s", &name)) + return NULL; + ret = init_builtin(name); + if (ret < 0) + return NULL; + if (ret == 0) { + INCREF(None); + return None; + } + m = add_module(name); + XINCREF(m); + return m; +} -static int -init_builtin(name) +static object * +imp_init_frozen(self, args) + object *self; + object *args; +{ char *name; + int ret; + object *m; + if (!newgetargs(args, "s", &name)) + return NULL; + ret = init_frozen(name); + if (ret < 0) + return NULL; + if (ret == 0) { + INCREF(None); + return None; + } + m = add_module(name); + XINCREF(m); + return m; +} + +static object * +imp_is_builtin(self, args) + object *self; + object *args; { int i; + char *name; + if (!newgetargs(args, "s", &name)) + return NULL; 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); - (*inittab[i].initfunc)(); - return 1; + if (inittab[i].initfunc == NULL) + return newintobject(-1); + else + return newintobject(1); } } - return 0; + return newintobject(0); } -extern struct frozen { - char *name; - char *code; - int size; -} frozen_modules[]; - -int -init_frozen(name) - char *name; +static object * +imp_is_frozen(self, args) + object *self; + object *args; { struct frozen *p; - codeobject *co; - object *m, *d, *v; + char *name; + if (!newgetargs(args, "s", &name)) + return NULL; for (p = frozen_modules; ; p++) { if (p->name == NULL) - return 0; - if (strcmp(p->name, name) == 0) break; + if (strcmp(p->name, name) == 0) + return newintobject(1); } - if (verbose) - fprintf(stderr, "import %s # frozen\n", name); - co = (codeobject *) rds_object(p->code, p->size); - if (co == NULL) - return -1; - if ((m = add_module(name)) == NULL || - (d = getmoduledict(m)) == NULL || - (v = eval_code(co, d, d, d, (object*)NULL)) == NULL) { - DECREF(co); - return -1; + return newintobject(0); +} + +static FILE * +get_file(pathname, fob, mode) + char *pathname; + object *fob; + char *mode; +{ + FILE *fp; + if (fob == NULL) { + fp = fopen(pathname, mode); + if (fp == NULL) + err_errno(IOError); } - DECREF(co); - DECREF(v); - return 1; + else { + fp = getfilefile(fob); + if (fp == NULL) + err_setstr(ValueError, "bad/closed file object"); + } + return fp; } +static object * +imp_load_compiled(self, args) + object *self; + object *args; +{ + char *name; + char *pathname; + object *fob = NULL; + object *m; + FILE *fp; + if (!newgetargs(args, "ss|O!", &name, &pathname, &Filetype, &fob)) + return NULL; + fp = get_file(pathname, fob, "rb"); + if (fp == NULL) + return NULL; + m = load_compiled_module(name, pathname, fp); + if (fob == NULL) + fclose(fp); + return m; +} -#ifdef _AIX +static object * +imp_load_dynamic(self, args) + object *self; + object *args; +{ + char *name; + char *pathname; + object *dummy; + if (!newgetargs(args, "ss|O", &name, &pathname, &dummy)) + return NULL; + return load_dynamic_module(name, pathname); +} -#include <ctype.h> /* for isdigit() */ -#include <errno.h> /* for global errno */ -#include <string.h> /* for strerror() */ +static object * +imp_load_source(self, args) + object *self; + object *args; +{ + char *name; + char *pathname; + object *fob = NULL; + object *m; + FILE *fp; + if (!newgetargs(args, "ss|O!", &name, &pathname, &Filetype, &fob)) + return NULL; + fp = get_file(pathname, fob, "r"); + if (fp == NULL) + return NULL; + m = load_source_module(name, pathname, fp); + if (fob == NULL) + fclose(fp); + return m; +} -void aix_loaderror(char *namebuf) +static object * +imp_new_module(self, args) + object *self; + object *args; { + char *name; + if (!newgetargs(args, "s", &name)) + return NULL; + return newmoduleobject(name); +} - char *message[8], errbuf[1024]; - int i,j; +static struct methodlist imp_methods[] = { + {"get_magic", imp_get_magic, 1}, + {"get_suffixes", imp_get_suffixes, 1}, + {"find_module", imp_find_module, 1}, + {"init_builtin", imp_init_builtin, 1}, + {"init_frozen", imp_init_frozen, 1}, + {"is_builtin", imp_is_builtin, 1}, + {"is_frozen", imp_is_frozen, 1}, + {"load_compiled", imp_load_compiled, 1}, + {"load_dynamic", imp_load_dynamic, 1}, + {"load_source", imp_load_source, 1}, + {"new_module", imp_new_module, 1}, + {NULL, NULL} /* sentinel */ +}; - 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} - }; +void +initimp() +{ + object *m, *d, *v; -#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0])) -#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1) + m = initmodule("imp", imp_methods); + d = getmoduledict(m); - sprintf(errbuf, " from module %.200s ", namebuf); + v = newintobject(SEARCH_ERROR); + dictinsert(d, "SEARCH_ERROR", v); + XDECREF(v); - 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; -} + v = newintobject(PY_SOURCE); + dictinsert(d, "PY_SOURCE", v); + XDECREF(v); -#endif /* _AIX */ + v = newintobject(PY_COMPILED); + dictinsert(d, "PY_COMPILED", v); + XDECREF(v); + + v = newintobject(C_EXTENSION); + dictinsert(d, "C_EXTENSION", v); + XDECREF(v); + + if (err_occurred()) + fatal("imp module initialization failed"); +} |