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.
diff --git a/Python/import.c b/Python/import.c
index ea6a6fe..a0af050 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -37,634 +37,43 @@
 #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
-
-#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
-#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 */
-
-#endif /* DYNAMIC_LINK */
-
-/* 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 */
 
-static object *modules;
+object *import_modules; /* This becomes sys.modules */
 
-/* Forward */
-static int init_builtin PROTO((char *));
 
-/* Helper for reading .pyc files */
-
-long
-get_pyc_magic()
-{
-	return MAGIC;
-}
-
-/* Initialization */
+/* Initialize things */
 
 void
 initimport()
 {
-	if ((modules = newdictobject()) == NULL)
+	if (import_modules != NULL)
+		fatal("duplicate initimport() call");
+	if ((import_modules = newdictobject()) == NULL)
 		fatal("no mem for dictionary of modules");
 }
 
-object *
-get_modules()
-{
-	return modules;
-}
 
-object *
-add_module(name)
-	char *name;
-{
-	object *m;
-	if ((m = dictlookup(modules, name)) != NULL && is_moduleobject(m))
-		return m;
-	m = newmoduleobject(name);
-	if (m == NULL)
-		return NULL;
-	if (dictinsert(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}
-};
-
-#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 */
-#ifdef hpux
-	{
-		shl_t lib;
-		int flags;
-
-		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);
-	}
-#endif /* hpux */
-	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;
-	char *name;
-	object **m_ret;
-{
-	int err, npath, i, len, namelen;
-	long magic;
-	long mtime, pyc_mtime;
-	char namebuf[MAXPATHLEN+1];
-	struct filedescr *fdp;
-	FILE *fp = NULL, *fpc = NULL;
-	node *n = NULL;
-	object *path, *v, *d;
-	codeobject *co = NULL;
-
-	path = sysget("path");
-	if (path == NULL || !is_listobject(path)) {
-		err_setstr(ImportError,
-			   "sys.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);
-		if (!is_stringobject(v))
-			continue;
-		len = getstringsize(v);
-		if (len + 1 + namelen + MAXSUFFIXSIZE >= MAXPATHLEN)
-			continue; /* Too long */
-		strcpy(namebuf, getstringvalue(v));
-		if (strlen(namebuf) != len)
-			continue; /* v contains '\0' */
-		if (len > 0 && namebuf[len-1] != SEP)
-			namebuf[len++] = SEP;
-		strcpy(namebuf+len, name);
-		len += namelen;
-		for (fdp = filetab; fdp->suffix != NULL; fdp++) {
-			strcpy(namebuf+len, fdp->suffix);
-			if (verbose > 1)
-				fprintf(stderr, "# trying %s\n", namebuf);
-			fp = fopen(namebuf, fdp->mode);
-			if (fp != NULL)
-				break;
-		}
-		if (fp != NULL)
-			break;
-	}
-	if (fp == NULL) {
-		sprintf(namebuf, "No module named %.200s", name);
-		err_setstr(ImportError, namebuf);
-		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);
-			}
-		}
-		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);
-		break;
-
-#ifdef DYNAMIC_LINK
-	case C_EXTENSION:
-		fclose(fp);
-		return load_dynamic_module(name, namebuf, m, m_ret);
-#endif /* DYNAMIC_LINK */
-
-	default:
-		fclose(fp);
-		err_setstr(SystemError,
-			   "search loop returned unexpected result");
-		return NULL;
-
-	}
-
-	/* We get here for either PY_SOURCE or PY_COMPILED */
-	if (m == NULL) {
-		m = add_module(name);
-		if (m == NULL) {
-			freetree(n);
-			return NULL;
-		}
-		*m_ret = m;
-	}
-	d = getmoduledict(m);
-	v = eval_code(co, d, d, d, (object *)NULL);
-	DECREF(co);
-	return v;
-}
-
-static object *
-load_module(name)
-	char *name;
-{
-	object *m, *v;
-	v = get_module((object *)NULL, name, &m);
-	if (v == NULL)
-		return NULL;
-	DECREF(v);
-	return m;
-}
-
-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)
-				return NULL;
-			if ((m = dictlookup(modules, name)) == NULL) {
-				if (err_occurred() == NULL)
-					err_setstr(SystemError,
-				   "builtin module not initialized properly");
-			}
-		}
-		else {
-			m = load_module(name);
-		}
-	}
-	return m;
-}
-
-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;
-	}
-	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;
-		}
-	}
-	/* 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);
-}
+/* Un-initialize things, as good as we can */
 
 void
 doneimport()
 {
-	if (modules != NULL) {
+	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(modules, &pos, &modname, &module)) {
+		while (mappinggetnext(import_modules,
+				      &pos, &modname, &module)) {
 			if (is_moduleobject(module)) {
 				object *dict;
 				dict = getmoduledict(module);
@@ -672,14 +81,415 @@
 					mappingclear(dict);
 			}
 		}
-		mappingclear(modules);
+		mappingclear(import_modules);
+		DECREF(import_modules);
 	}
-	DECREF(modules);
-	modules = NULL;
+	import_modules = NULL;
 }
 
 
-/* Initialize built-in modules when first imported */
+/* Helper for pythonrun.c -- return magic number */
+
+long
+get_pyc_magic()
+{
+	return MAGIC;
+}
+
+
+/* Helper for sysmodule.c -- return modules dictionary */
+
+object *
+get_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(import_modules, name)) != NULL &&
+	    is_moduleobject(m))
+		return m;
+	m = newmoduleobject(name);
+	if (m == NULL)
+		return NULL;
+	if (dictinsert(import_modules, name, m) != 0) {
+		DECREF(m);
+		return NULL;
+	}
+	DECREF(m); /* Yes, it still exists, in modules! */
+
+	return m;
+}
+
+
+/* Execute a code object in a module and return its module object */
+
+static object *
+exec_code_module(name, co)
+	char *name;
+	codeobject *co;
+{
+	object *m, *d, *v;
+
+	m = add_module(name);
+	if (m == NULL)
+		return NULL;
+	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)
+			fprintf(stderr, "# %s has bad magic\n", cpathname);
+		fclose(fp);
+		return NULL;
+	}
+	pyc_mtime = rd_long(fp);
+	if (pyc_mtime != mtime) {
+		if (verbose)
+			fprintf(stderr, "# %s has bad mtime\n", cpathname);
+		fclose(fp);
+		return NULL;
+	}
+	if (verbose)
+		fprintf(stderr, "# %s matches %s\n", cpathname, pathname);
+	return fp;
+}
+
+
+/* Read a code object from a file and check it for validity */
+
+static codeobject *
+read_compiled_module(fp)
+	FILE *fp;
+{
+	object *co;
+
+	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;
+	}
+	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;
+	}
+	(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;
+
+	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, "# wrote %s\n", cpathname);
+#ifdef macintosh
+	setfiletype(cpathname, 'PYTH', 'PYC ');
+#endif
+}
+
+
+/* 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 *
+load_source_module(name, pathname, fp)
+	char *name;
+	char *pathname;
+	FILE *fp;
+{
+	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;
+
+	if (path == NULL)
+		path = sysget("path");
+	if (path == NULL || !is_listobject(path)) {
+		err_setstr(ImportError,
+		    "module search path must be list of directory names");
+		return NULL;
+	}
+	npath = getlistsize(path);
+	namelen = strlen(name);
+	for (i = 0; i < npath; i++) {
+		object *v = getlistitem(path, i);
+		if (!is_stringobject(v))
+			continue;
+		len = getstringsize(v);
+		if (len + 2 + namelen + import_maxsuffixsize >= buflen)
+			continue; /* Too long */
+		strcpy(buf, getstringvalue(v));
+		if (strlen(buf) != len)
+			continue; /* v contains '\0' */
+		if (len > 0 && buf[len-1] != SEP)
+			buf[len++] = SEP;
+		strcpy(buf+len, name);
+		len += namelen;
+		for (fdp = import_filetab; fdp->suffix != NULL; fdp++) {
+			strcpy(buf+len, fdp->suffix);
+			if (verbose > 1)
+				fprintf(stderr, "# trying %s\n", buf);
+			fp = fopen(buf, fdp->mode);
+			if (fp != NULL)
+				break;
+		}
+		if (fp != NULL)
+			break;
+	}
+	if (fp == NULL) {
+		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:
+		m = load_source_module(name, buf, fp);
+		break;
+
+	case PY_COMPILED:
+		m = load_compiled_module(name, buf, fp);
+		break;
+
+	case C_EXTENSION:
+		m = load_dynamic_module(name, buf);
+		break;
+
+	default:
+		err_setstr(SystemError,
+			   "find_module returned unexpected result");
+
+	}
+	fclose(fp);
+
+	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)
@@ -697,25 +507,32 @@
 				fprintf(stderr, "import %s # builtin\n",
 					name);
 			(*inittab[i].initfunc)();
+			if (err_occurred())
+				return -1;
 			return 1;
 		}
 	}
 	return 0;
 }
 
+
+/* 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[];
 
-int
+static int
 init_frozen(name)
 	char *name;
 {
 	struct frozen *p;
-	codeobject *co;
-	object *m, *d, *v;
+	object *co;
+	object *m;
 	for (p = frozen_modules; ; p++) {
 		if (p->name == NULL)
 			return 0;
@@ -724,71 +541,367 @@
 	}
 	if (verbose)
 		fprintf(stderr, "import %s # frozen\n", name);
-	co = (codeobject *) rds_object(p->code, p->size);
+	co = 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) {
+	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);
-	DECREF(v);
-	return 1;
+	return m == NULL ? -1 : 1;
 }
 
 
-#ifdef _AIX
+/* Import a module, either built-in, frozen, or external, and return
+   its module object */
 
-#include <ctype.h>	/* for isdigit()	*/
-#include <errno.h>	/* for global errno	*/
-#include <string.h>	/* for strerror()	*/
-
-void aix_loaderror(char *namebuf)
+object *
+import_module(name)
+	char *name;
 {
+	object *m;
 
-	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)-strlen(errbuf)-1)
-
-	sprintf(errbuf, " from module %.200s ", 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);
+	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(import_modules, name)) == NULL) {
+			    if (err_occurred() == NULL)
+			        err_setstr(SystemError,
+				 "built-in module not initialized properly");
+			}
 		}
-		while (isdigit(*message[i])) message[i]++ ; 
-		ERRBUF_APPEND(message[i]);
-		ERRBUF_APPEND("\n");
+		else
+			m = load_module(name);
 	}
-	errbuf[strlen(errbuf)-1] = '\0';	/* trim off last newline */
-	err_setstr(ImportError, errbuf); 
-	return; 
+
+	return m;
 }
 
-#endif /* _AIX */
+
+/* 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;
+	}
+	name = getmodulename(m);
+	if (name == NULL)
+		return NULL;
+	if (m != dictlookup(import_modules, name)) {
+		err_setstr(ImportError, "reload() module not in sys.modules");
+		return NULL;
+	}
+	/* Check for built-in and frozen modules */
+	if ((i = init_builtin(name)) || (i = init_frozen(name))) {
+		if (i < 0)
+			return NULL;
+	}
+	else
+		m = load_module(name);
+	XINCREF(m);
+	return m;
+}
+
+
+/* Module 'imp' provides Python access to the primitives used for
+   importing modules.
+*/
+
+static object *
+imp_get_magic(self, args)
+	object *self;
+	object *args;
+{
+	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;
+		}
+		if (addlistitem(list, item) < 0) {
+			DECREF(list);
+			DECREF(item);
+			return NULL;
+		}
+		DECREF(item);
+	}
+	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;
+}
+
+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 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)
+				return newintobject(-1);
+			else
+				return newintobject(1);
+		}
+	}
+	return newintobject(0);
+}
+
+static object *
+imp_is_frozen(self, args)
+	object *self;
+	object *args;
+{
+	struct frozen *p;
+	char *name;
+	if (!newgetargs(args, "s", &name))
+		return NULL;
+	for (p = frozen_modules; ; p++) {
+		if (p->name == NULL)
+			break;
+		if (strcmp(p->name, name) == 0)
+			return newintobject(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);
+	}
+	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;
+}
+
+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);
+}
+
+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;
+}
+
+static object *
+imp_new_module(self, args)
+	object *self;
+	object *args;
+{
+	char *name;
+	if (!newgetargs(args, "s", &name))
+		return NULL;
+	return newmoduleobject(name);
+}
+
+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 */
+};
+
+void
+initimp()
+{
+	object *m, *d, *v;
+
+	m = initmodule("imp", imp_methods);
+	d = getmoduledict(m);
+
+	v = newintobject(SEARCH_ERROR);
+	dictinsert(d, "SEARCH_ERROR", v);
+	XDECREF(v);
+
+	v = newintobject(PY_SOURCE);
+	dictinsert(d, "PY_SOURCE", v);
+	XDECREF(v);
+
+	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");
+}