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/Makefile.in b/Python/Makefile.in
index 54be6af..d5ced26 100644
--- a/Python/Makefile.in
+++ b/Python/Makefile.in
@@ -35,7 +35,7 @@
 		errors.o \
 		frozenmain.o \
 		getargs.o getmtime.o graminit.o \
-		import.o \
+		import.o importdl.o \
 		marshal.o modsupport.o mystrtoul.o \
 		pythonmain.o pythonrun.o \
 		sigcheck.o structmember.o sysmodule.o \
@@ -66,8 +66,8 @@
 		(cd ..; CONFIG_FILES=Python/Makefile CONFIG_HEADERS= \
 		$(SHELL) config.status)
 
-import.o:	import.c
-		$(CC) $(CFLAGS) -I$(DLINCLDIR) -c $(srcdir)/import.c
+importdl.o:	importdl.c
+		$(CC) $(CFLAGS) -I$(DLINCLDIR) -c $(srcdir)/importdl.c
 
 depend:
 		$(MKDEP) $(CFLAGS) `echo $(OBJS) | tr ' ' '\012' | \
@@ -88,6 +88,7 @@
 getmtime.o: getmtime.c
 graminit.o: graminit.c
 import.o: import.c
+importdl.o: importdl.c
 marshal.o: marshal.c
 memmove.o: memmove.c
 modsupport.o: modsupport.c
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 4f6c852..39dcc41 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -40,15 +40,35 @@
 /* Forward */
 static object *filterstring PROTO((object *, object *));
 static object *filtertuple  PROTO((object *, object *));
-static object *exec_eval PROTO((object *v, int start));
 
 static object *
-builtin_abs(self, v)
+builtin___import__(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
+	char *name;
+	object *m;
+
+	if (!newgetargs(args, "s:__import__", &name))
+		return NULL;
+	m = import_module(name);
+	XINCREF(m);
+
+	return m;
+}
+
+
+static object *
+builtin_abs(self, args)
+	object *self;
+	object *args;
+{
+	object *v;
 	number_methods *nm;
-	if (v == NULL || (nm = v->ob_type->tp_as_number) == NULL) {
+
+	if (!newgetargs(args, "O:abs", &v))
+		return NULL;
+	if ((nm = v->ob_type->tp_as_number) == NULL) {
 		err_setstr(TypeError, "abs() requires numeric argument");
 		return NULL;
 	}
@@ -61,7 +81,8 @@
 	object *args;
 {
 	object *func, *arglist;
-	if (!getargs(args, "(OO)", &func, &arglist))
+
+	if (!newgetargs(args, "OO:apply", &func, &arglist))
 		return NULL;
 	if (!is_tupleobject(arglist)) {
 		err_setstr(TypeError, "apply() 2nd argument must be tuple");
@@ -101,12 +122,11 @@
 	object *self;
 	object *args;
 {
-	if (args == NULL) {
-		err_setstr(TypeError,
-			   "callable requires exactly one argument");
+	object *v;
+
+	if (!newgetargs(args, "O:callable", &v))
 		return NULL;
-	}
-	return newintobject((long)callable(args));
+	return newintobject((long)callable(v));
 }
 
 static object *
@@ -119,7 +139,7 @@
 	int len;
 	register int i, j;
 
-	if (!getargs(args, "(OO)", &func, &seq))
+	if (!newgetargs(args, "OO:filter", &func, &seq))
 		return NULL;
 
 	if (is_stringobject(seq)) {
@@ -212,7 +232,8 @@
 {
 	long x;
 	char s[1];
-	if (!getargs(args, "l", &x))
+
+	if (!newgetargs(args, "l:chr", &x))
 		return NULL;
 	if (x < 0 || x >= 256) {
 		err_setstr(ValueError, "chr() arg not in range(256)");
@@ -228,7 +249,8 @@
 	object *args;
 {
 	object *a, *b;
-	if (!getargs(args, "(OO)", &a, &b))
+
+	if (!newgetargs(args, "OO:cmp", &a, &b))
 		return NULL;
 	return newintobject((long)cmpobject(a, b));
 }
@@ -241,7 +263,7 @@
 	object *v, *w;
 	object *res;
 
-	if (!getargs(args, "(OO)", &v, &w))
+	if (!newgetargs(args, "OO:coerce", &v, &w))
 		return NULL;
 	if (is_instanceobject(v) || is_instanceobject(w))
 		return instancebinop(v, w, "__coerce__", "__rcoerce__");
@@ -262,7 +284,8 @@
 	char *filename;
 	char *startstr;
 	int start;
-	if (!getargs(args, "(sss)", &str, &filename, &startstr))
+
+	if (!newgetargs(args, "sss:compile", &str, &filename, &startstr))
 		return NULL;
 	if (strcmp(startstr, "exec") == 0)
 		start = file_input;
@@ -277,11 +300,15 @@
 }
 
 static object *
-builtin_dir(self, v)
+builtin_dir(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
+	object *v = NULL;
 	object *d;
+
+	if (!newgetargs(args, "|O:dir", &v))
+		return NULL;
 	if (v == NULL) {
 		d = getlocals();
 		INCREF(d);
@@ -314,13 +341,15 @@
 	object *args;
 {
 	object *v, *w, *x;
-	if (!getargs(args, "(OO)", &v, &w))
+
+	if (!newgetargs(args, "OO:divmod", &v, &w))
 		return NULL;
 	if (is_instanceobject(v) || is_instanceobject(w))
 		return instancebinop(v, w, "__divmod__", "__rdivmod__");
 	if (v->ob_type->tp_as_number == NULL ||
 				w->ob_type->tp_as_number == NULL) {
-		err_setstr(TypeError, "divmod() requires numeric or class instance arguments");
+		err_setstr(TypeError,
+		    "divmod() requires numeric or class instance arguments");
 		return NULL;
 	}
 	if (coerce(&v, &w) != 0)
@@ -332,110 +361,80 @@
 }
 
 static object *
-exec_eval(v, start)
-	object *v;
-	int start;
+builtin_eval(self, args)
+	object *self;
+	object *args;
 {
-	object *str = NULL, *globals = NULL, *locals = NULL;
-	char *s;
-	int n;
-	/* XXX This is a bit of a mess.  Should make it varargs */
-	if (v != NULL) {
-		if (is_tupleobject(v) &&
-				((n = gettuplesize(v)) == 2 || n == 3)) {
-			str = gettupleitem(v, 0);
-			globals = gettupleitem(v, 1);
-			if (n == 3)
-				locals = gettupleitem(v, 2);
-		}
-		else
-			str = v;
-	}
-	if (str == NULL || (!is_stringobject(str) && !is_codeobject(str)) ||
-			globals != NULL && !is_dictobject(globals) ||
-			locals != NULL && !is_dictobject(locals)) {
-		err_setstr(TypeError,
-		  "eval arguments must be (string|code)[,dict[,dict]]");
-		return NULL;
-	}
+	object *cmd;
+	object *globals = NULL, *locals = NULL;
+	char *str;
 
-	if (is_codeobject(str))
-		return eval_code((codeobject *) str, globals, locals,
+	if (!newgetargs(args, "O|O!O!:eval",
+			&cmd,
+			&Mappingtype, &globals,
+			&Mappingtype, &locals))
+		return NULL;
+	if (is_codeobject(cmd))
+		return eval_code((codeobject *) cmd, globals, locals,
 				 (object *)NULL, (object *)NULL);
-	s = getstringvalue(str);
-	if (strlen(s) != getstringsize(str)) {
-		err_setstr(ValueError, "embedded '\\0' in string arg");
+	if (!is_stringobject(cmd)) {
+		err_setstr(TypeError,
+			   "eval() argument 1 must be string or code object");
 		return NULL;
 	}
-	if (start == eval_input) {
-		while (*s == ' ' || *s == '\t')
-			s++;
+	str = getstringvalue(cmd);
+	if (strlen(str) != getstringsize(cmd)) {
+		err_setstr(ValueError,
+			   "embedded '\\0' in string arg");
+		return NULL;
 	}
-	return run_string(s, start, globals, locals);
+	while (*str == ' ' || *str == '\t')
+		str++;
+	return run_string(str, eval_input, globals, locals);
 }
 
 static object *
-builtin_eval(self, v)
+builtin_execfile(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
-	return exec_eval(v, eval_input);
-}
-
-static object *
-builtin_execfile(self, v)
-	object *self;
-	object *v;
-{
-	object *str = NULL, *globals = NULL, *locals = NULL, *w;
+	char *filename;
+	object *globals = NULL, *locals = NULL;
+	object *res;
 	FILE* fp;
 	char *s;
 	int n;
-	if (v != NULL) {
-		if (is_stringobject(v))
-			str = v;
-		else if (is_tupleobject(v) &&
-				((n = gettuplesize(v)) == 2 || n == 3)) {
-			str = gettupleitem(v, 0);
-			globals = gettupleitem(v, 1);
-			if (n == 3)
-				locals = gettupleitem(v, 2);
-		}
-	}
-	if (str == NULL || !is_stringobject(str) ||
-			globals != NULL && !is_dictobject(globals) ||
-			locals != NULL && !is_dictobject(locals)) {
-		err_setstr(TypeError,
-		    "execfile arguments must be filename[,dict[,dict]]");
+
+	if (!newgetargs(args, "s|O!O!:execfile",
+			&filename,
+			&Mappingtype, &globals,
+			&Mappingtype, &locals))
 		return NULL;
-	}
-	s = getstringvalue(str);
-	if (strlen(s) != getstringsize(str)) {
-		err_setstr(ValueError, "embedded '\\0' in string arg");
-		return NULL;
-	}
 	BGN_SAVE
-	fp = fopen(s, "r");
+	fp = fopen(filename, "r");
 	END_SAVE
 	if (fp == NULL) {
-		err_setstr(IOError, "execfile cannot open the file argument");
+		err_errno(IOError);
 		return NULL;
 	}
-	w = run_file(fp, getstringvalue(str), file_input, globals, locals);
+	res = run_file(fp, filename, file_input, globals, locals);
 	BGN_SAVE
 	fclose(fp);
 	END_SAVE
-	return w;
+	return res;
 }
 
 static object *
-builtin_float(self, v)
+builtin_float(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
+	object *v;
 	number_methods *nb;
-	
-	if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
+
+	if (!newgetargs(args, "O:float", &v))
+		return NULL;
+	if ((nb = v->ob_type->tp_as_number) == NULL ||
 	    nb->nb_float == NULL) {
 		err_setstr(TypeError,
 			   "float() argument can't be converted to float");
@@ -451,7 +450,8 @@
 {
 	object *v;
 	object *name;
-	if (!getargs(args, "(OS)", &v, &name))
+
+	if (!newgetargs(args, "OS:getattr", &v, &name))
 		return NULL;
 	return getattro(v, name);
 }
@@ -463,7 +463,8 @@
 {
 	object *v;
 	object *name;
-	if (!getargs(args, "(OS)", &v, &name))
+
+	if (!newgetargs(args, "OS:hasattr", &v, &name))
 		return NULL;
 	v = getattro(v, name);
 	if (v == NULL) {
@@ -480,7 +481,8 @@
 	object *args;
 {
 	object *v;
-	if (!getargs(args, "O", &v))
+
+	if (!newgetargs(args, "O:id", &v))
 		return NULL;
 	return newintobject((long)v);
 }
@@ -498,16 +500,17 @@
 
 	object *func, *result;
 	sequence *seqs = NULL, *sqp;
-	int n, len, newfunc = 0;
+	int n, len;
 	register int i, j;
 
-	if (args == NULL || !is_tupleobject(args)) {
+	n = gettuplesize(args);
+	if (n < 2) {
 		err_setstr(TypeError, "map() requires at least two args");
 		return NULL;
 	}
 
 	func = gettupleitem(args, 0);
-	n    = gettuplesize(args) - 1;
+	n--;
 
 	if ((seqs = NEW(sequence, n)) == NULL) {
 		err_nomem();
@@ -633,7 +636,8 @@
 	object *v;
 	object *name;
 	object *value;
-	if (!getargs(args, "(OSO)", &v, &name, &value))
+
+	if (!newgetargs(args, "OSO:setattr", &v, &name, &value))
 		return NULL;
 	if (setattro(v, name, value) != 0)
 		return NULL;
@@ -648,7 +652,8 @@
 {
 	object *v;
 	object *name;
-	if (!getargs(args, "(OS)", &v, &name))
+
+	if (!newgetargs(args, "OS:delattr", &v, &name))
 		return NULL;
 	if (setattro(v, name, (object *)NULL) != 0)
 		return NULL;
@@ -663,7 +668,8 @@
 {
 	object *v;
 	long x;
-	if (!getargs(args, "O", &v))
+
+	if (!newgetargs(args, "O:hash", &v))
 		return NULL;
 	x = hashobject(v);
 	if (x == -1)
@@ -672,13 +678,17 @@
 }
 
 static object *
-builtin_hex(self, v)
+builtin_hex(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
+	object *v;
 	number_methods *nb;
+
+	if (!newgetargs(args, "O:hex", &v))
+		return NULL;
 	
-	if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
+	if ((nb = v->ob_type->tp_as_number) == NULL ||
 	    nb->nb_hex == NULL) {
 		err_setstr(TypeError,
 			   "hex() argument can't be converted to hex");
@@ -690,26 +700,37 @@
 static object *builtin_raw_input PROTO((object *, object *));
 
 static object *
-builtin_input(self, v)
+builtin_input(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
-	object *line = builtin_raw_input(self, v);
+	object *line;
+	char *str;
+	object *res;
+
+	line = builtin_raw_input(self, args);
 	if (line == NULL)
 		return line;
-	v = exec_eval(line, eval_input);
+	if (!getargs(line, "s;embedded '\\0' in input line", &str))
+		return NULL;
+	while (*str == ' ' || *str == '\t')
+			str++;
+	res = run_string(str, eval_input, (object *)NULL, (object *)NULL);
 	DECREF(line);
-	return v;
+	return res;
 }
 
 static object *
-builtin_int(self, v)
+builtin_int(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
+	object *v;
 	number_methods *nb;
-	
-	if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
+
+	if (!newgetargs(args, "O:int", &v))
+		return NULL;
+	if ((nb = v->ob_type->tp_as_number) == NULL ||
 	    nb->nb_int == NULL) {
 		err_setstr(TypeError,
 			   "int() argument can't be converted to int");
@@ -719,16 +740,16 @@
 }
 
 static object *
-builtin_len(self, v)
+builtin_len(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
+	object *v;
 	long len;
 	typeobject *tp;
-	if (v == NULL) {
-		err_setstr(TypeError, "len() without argument");
+
+	if (!newgetargs(args, "O:len", &v))
 		return NULL;
-	}
 	tp = v->ob_type;
 	if (tp->tp_as_sequence != NULL) {
 		len = (*tp->tp_as_sequence->sq_length)(v);
@@ -747,13 +768,16 @@
 }
 
 static object *
-builtin_long(self, v)
+builtin_long(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
+	object *v;
 	number_methods *nb;
 	
-	if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
+	if (!newgetargs(args, "O:long", &v))
+		return NULL;
+	if ((nb = v->ob_type->tp_as_number) == NULL ||
 	    nb->nb_long == NULL) {
 		err_setstr(TypeError,
 			   "long() argument can't be converted to long");
@@ -763,17 +787,18 @@
 }
 
 static object *
-min_max(v, sign)
-	object *v;
+min_max(args, sign)
+	object *args;
 	int sign;
 {
 	int i;
-	object *w, *x;
+	object *v, *w, *x;
 	sequence_methods *sq;
-	if (v == NULL) {
-		err_setstr(TypeError, "min() or max() without argument");
+
+	if (gettuplesize(args) > 1)
+		v = args;
+	else if (!newgetargs(args, "O:min/max", &v))
 		return NULL;
-	}
 	sq = v->ob_type->tp_as_sequence;
 	if (sq == NULL) {
 		err_setstr(TypeError, "min() or max() of non-sequence");
@@ -823,12 +848,15 @@
 }
 
 static object *
-builtin_oct(self, v)
+builtin_oct(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
+	object *v;
 	number_methods *nb;
-	
+
+	if (!newgetargs(args, "O:oct", &v))
+		return NULL;
 	if (v == NULL || (nb = v->ob_type->tp_as_number) == NULL ||
 	    nb->nb_oct == NULL) {
 		err_setstr(TypeError,
@@ -847,9 +875,8 @@
 	char *mode = "r";
 	int bufsize = -1;
 	object *f;
-	if (!getargs(args, "s", &name) &&
-	    (err_clear(), !getargs(args, "(ss)", &name, &mode)) &&
-	    (err_clear(), !getargs(args, "(ssi)", &name, &mode, &bufsize)))
+
+	if (!newgetargs(args, "s|si:open", &name, &mode, &bufsize))
 		return NULL;
 	f = newfileobject(name, mode);
 	if (f != NULL)
@@ -862,15 +889,11 @@
 	object *self;
 	object *args;
 {
-	char *s;
-	int len;
-	if (!getargs(args, "s#", &s, &len))
+	char c;
+
+	if (!newgetargs(args, "c:ord", &c))
 		return NULL;
-	if (len != 1) {
-		err_setstr(ValueError, "ord() arg must have length 1");
-		return NULL;
-	}
-	return newintobject((long)(s[0] & 0xff));
+	return newintobject((long)(c & 0xff));
 }
 
 static object *
@@ -878,9 +901,9 @@
 	object *self;
 	object *args;
 {
-	object *v, *w, *z, *x;
- 	z = None;
-	if (!newgetargs(args, "OO|O", &v, &w, &z))
+	object *v, *w, *z = None, *x;
+
+	if (!newgetargs(args, "OO|O:pow", &v, &w, &z))
 		return NULL;
 	if (z == None) {
 		if (is_instanceobject(v) || is_instanceobject(w))
@@ -913,43 +936,25 @@
 }
 
 static object *
-builtin_range(self, v)
+builtin_range(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
-	static char *errmsg = "range() requires 1-3 int arguments";
+	long ilow = 0, ihigh = 0, istep = 1;
 	int i, n;
-	long ilow, ihigh, istep;
-	if (v != NULL && is_intobject(v)) {
-		ilow = 0; ihigh = getintvalue(v); istep = 1;
-	}
-	else if (v == NULL || !is_tupleobject(v)) {
-		err_setstr(TypeError, errmsg);
-		return NULL;
+	object *v;
+
+	if (gettuplesize(args) <= 1) {
+		if (!newgetargs(args,
+				"i;range() requires 1-3 int arguments",
+				&ihigh))
+			return NULL;
 	}
 	else {
-		n = gettuplesize(v);
-		if (n < 1 || n > 3) {
-			err_setstr(TypeError, errmsg);
+		if (!newgetargs(args,
+				"ii|i;range() requires 1-3 int arguments",
+				&ilow, &ihigh, &istep))
 			return NULL;
-		}
-		for (i = 0; i < n; i++) {
-			if (!is_intobject(gettupleitem(v, i))) {
-				err_setstr(TypeError, errmsg);
-				return NULL;
-			}
-		}
-		if (n == 3) {
-			istep = getintvalue(gettupleitem(v, 2));
-			--n;
-		}
-		else
-			istep = 1;
-		ihigh = getintvalue(gettupleitem(v, --n));
-		if (n > 0)
-			ilow = getintvalue(gettupleitem(v, 0));
-		else
-			ilow = 0;
 	}
 	if (istep == 0) {
 		err_setstr(ValueError, "zero step for range()");
@@ -978,73 +983,66 @@
 }
 
 static object *
-builtin_xrange(self, v)
+builtin_xrange(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
-	static char *errmsg = "xrange() requires 1-3 int arguments";
-	int i, n;
-	long start, stop, step, len;
-	if (v != NULL && is_intobject(v))
-		start = 0, stop = getintvalue(v), step = 1;
+	long ilow = 0, ihigh = 0, istep = 1;
+	int n;
+	object *v;
 
-	else if (v == NULL || !is_tupleobject(v)) {
-		err_setstr(TypeError, errmsg);
-		return NULL;
+	if (gettuplesize(args) <= 1) {
+		if (!newgetargs(args,
+				"i;xrange() requires 1-3 int arguments",
+				&ihigh))
+			return NULL;
 	}
 	else {
-		n = gettuplesize(v);
-		if (n < 1 || n > 3) {
-			err_setstr(TypeError, errmsg);
+		if (!newgetargs(args,
+				"ii|i;xrange() requires 1-3 int arguments",
+				&ilow, &ihigh, &istep))
 			return NULL;
-		}
-		for (i = 0; i < n; i++) {
-			if (!is_intobject(gettupleitem(v, i))) {
-				err_setstr(TypeError, errmsg);
-				return NULL;
-			}
-		}
-		if (n == 3) {
-			step = getintvalue(gettupleitem(v, 2));
-			--n;
-		}
-		else
-			step = 1;
-		stop = getintvalue(gettupleitem(v, --n));
-		if (n > 0)
-			start = getintvalue(gettupleitem(v, 0));
-		else
-			start = 0;
 	}
-
-	if (step == 0) {
+	if (istep == 0) {
 		err_setstr(ValueError, "zero step for xrange()");
 		return NULL;
 	}
-
-	len = (stop - start + step + ((step > 0) ? -1 : 1)) / step;
-	if (len < 0)
-		len = 0;
-
-	return newrangeobject(start, len, step, 1);
+	/* XXX ought to check overflow of subtraction */
+	if (istep > 0)
+		n = (ihigh - ilow + istep - 1) / istep;
+	else
+		n = (ihigh - ilow + istep + 1) / istep;
+	if (n < 0)
+		n = 0;
+	return newrangeobject(ilow, n, istep, 1);
 }
 
 static object *
-builtin_raw_input(self, v)
+builtin_raw_input(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
-	object *f = sysget("stdout");
-	if (f == NULL) {
-		err_setstr(RuntimeError, "lost sys.stdout");
+	object *v = NULL;
+	object *f;
+
+	if (!newgetargs(args, "|O:[raw_]input", &v))
 		return NULL;
-	}
-	flushline();
 	if (v != NULL) {
+		f = sysget("stdout");
+		if (f == NULL) {
+			err_setstr(RuntimeError, "lost sys.stdout");
+			return NULL;
+		}
+		flushline();
 		if (writeobject(v, f, PRINT_RAW) != 0)
 			return NULL;
 	}
-	return filegetline(sysget("stdin"), -1);
+	f = sysget("stdin");
+	if (f == NULL) {
+		err_setstr(RuntimeError, "lost sys.stdin");
+		return NULL;
+	}
+	return filegetline(f, -1);
 }
 
 static object *
@@ -1052,18 +1050,14 @@
 	object *self;
 	object *args;
 {
-	object *seq, *func, *result;
+	object *seq, *func, *result = NULL;
 	sequence_methods *sqf;
 	register int i;
 
-	if (getargs(args, "(OO)", &func, &seq))
-		result = NULL;
-	else {
-		err_clear();
-		if (!getargs(args, "(OOO)", &func, &seq, &result))
-			return NULL;
+	if (!newgetargs(args, "OO|O:reduce", &func, &seq, &result))
+		return NULL;
+	if (result != NULL)
 		INCREF(result);
-	}
 
 	if ((sqf = seq->ob_type->tp_as_sequence) == NULL) {
 		err_setstr(TypeError,
@@ -1116,22 +1110,26 @@
 }
 
 static object *
-builtin_reload(self, v)
+builtin_reload(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
+	object *v;
+
+	if (!newgetargs(args, "O:reload", &v))
+		return NULL;
 	return reload_module(v);
 }
 
 static object *
-builtin_repr(self, v)
+builtin_repr(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
-	if (v == NULL) {
-		err_badarg();
+	object *v;
+
+	if (!newgetargs(args, "O:repr", &v))
 		return NULL;
-	}
 	return reprobject(v);
 }
 
@@ -1145,13 +1143,10 @@
 	double x;
 	double f;
 	int ndigits = 0;
-	int sign = 1;
 	int i;
-	if (!getargs(args, "d", &x)) {
-		err_clear();
-		if (!getargs(args, "(di)", &x, &ndigits))
+
+	if (!newgetargs(args, "d|i:round", &x, &ndigits))
 			return NULL;
-	}
 	f = 1.0;
 	for (i = ndigits; --i >= 0; )
 		f = f*10.0;
@@ -1164,25 +1159,27 @@
 }
 
 static object *
-builtin_str(self, v)
+builtin_str(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
-	if (v == NULL) {
-		err_badarg();
+	object *v;
+
+	if (!newgetargs(args, "O:str", &v))
 		return NULL;
-	}
 	return strobject(v);
 }
 
 static object *
-builtin_tuple(self, v)
+builtin_tuple(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
+	object *v;
 	sequence_methods *sqf;
-	if (v == NULL)
-		v = None; /* Force error later */
+
+	if (!newgetargs(args, "O:tuple", &v))
+		return NULL;
 	if (is_tupleobject(v)) {
 		INCREF(v);
 		return v;
@@ -1235,25 +1232,29 @@
 }
 
 static object *
-builtin_type(self, v)
+builtin_type(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
-	if (v == NULL) {
-		err_setstr(TypeError, "type() requires an argument");
+	object *v;
+
+	if (!newgetargs(args, "O:type", &v))
 		return NULL;
-	}
 	v = (object *)v->ob_type;
 	INCREF(v);
 	return v;
 }
 
 static object *
-builtin_vars(self, v)
+builtin_vars(self, args)
 	object *self;
-	object *v;
+	object *args;
 {
+	object *v = NULL;
 	object *d;
+
+	if (!newgetargs(args, "|O:vars", &v))
+		return NULL;
 	if (v == NULL) {
 		d = getlocals();
 		INCREF(d);
@@ -1270,48 +1271,49 @@
 }
 
 static struct methodlist builtin_methods[] = {
-	{"abs",		builtin_abs},
-	{"apply",	builtin_apply},
-	{"callable",	builtin_callable},
-	{"chr",		builtin_chr},
-	{"cmp",		builtin_cmp},
-	{"coerce",	builtin_coerce},
-	{"compile",	builtin_compile},
-	{"delattr",	builtin_delattr},
-	{"dir",		builtin_dir},
-	{"divmod",	builtin_divmod},
-	{"eval",	builtin_eval},
-	{"execfile",	builtin_execfile},
-	{"filter",	builtin_filter},
-	{"float",	builtin_float},
-	{"getattr",	builtin_getattr},
-	{"hasattr",	builtin_hasattr},
-	{"hash",	builtin_hash},
-	{"hex",		builtin_hex},
-	{"id",		builtin_id},
-	{"input",	builtin_input},
-	{"int",		builtin_int},
-	{"len",		builtin_len},
-	{"long",	builtin_long},
-	{"map",		builtin_map},
-	{"max",		builtin_max},
-	{"min",		builtin_min},
-	{"oct",		builtin_oct},
-	{"open",	builtin_open},
-	{"ord",		builtin_ord},
+	{"__import__",	builtin___import__, 1},
+	{"abs",		builtin_abs, 1},
+	{"apply",	builtin_apply, 1},
+	{"callable",	builtin_callable, 1},
+	{"chr",		builtin_chr, 1},
+	{"cmp",		builtin_cmp, 1},
+	{"coerce",	builtin_coerce, 1},
+	{"compile",	builtin_compile, 1},
+	{"delattr",	builtin_delattr, 1},
+	{"dir",		builtin_dir, 1},
+	{"divmod",	builtin_divmod, 1},
+	{"eval",	builtin_eval, 1},
+	{"execfile",	builtin_execfile, 1},
+	{"filter",	builtin_filter, 1},
+	{"float",	builtin_float, 1},
+	{"getattr",	builtin_getattr, 1},
+	{"hasattr",	builtin_hasattr, 1},
+	{"hash",	builtin_hash, 1},
+	{"hex",		builtin_hex, 1},
+	{"id",		builtin_id, 1},
+	{"input",	builtin_input, 1},
+	{"int",		builtin_int, 1},
+	{"len",		builtin_len, 1},
+	{"long",	builtin_long, 1},
+	{"map",		builtin_map, 1},
+	{"max",		builtin_max, 1},
+	{"min",		builtin_min, 1},
+	{"oct",		builtin_oct, 1},
+	{"open",	builtin_open, 1},
+	{"ord",		builtin_ord, 1},
 	{"pow",		builtin_pow, 1},
-	{"range",	builtin_range},
-	{"raw_input",	builtin_raw_input},
-	{"reduce",	builtin_reduce},
-	{"reload",	builtin_reload},
-	{"repr",	builtin_repr},
-	{"round",	builtin_round},
-	{"setattr",	builtin_setattr},
-	{"str",		builtin_str},
-	{"tuple",	builtin_tuple},
-	{"type",	builtin_type},
-	{"vars",	builtin_vars},
-	{"xrange",	builtin_xrange},
+	{"range",	builtin_range, 1},
+	{"raw_input",	builtin_raw_input, 1},
+	{"reduce",	builtin_reduce, 1},
+	{"reload",	builtin_reload, 1},
+	{"repr",	builtin_repr, 1},
+	{"round",	builtin_round, 1},
+	{"setattr",	builtin_setattr, 1},
+	{"str",		builtin_str, 1},
+	{"tuple",	builtin_tuple, 1},
+	{"type",	builtin_type, 1},
+	{"vars",	builtin_vars, 1},
+	{"xrange",	builtin_xrange, 1},
 	{NULL,		NULL},
 };
 
@@ -1324,6 +1326,13 @@
 	return mappinglookup(builtin_dict, name);
 }
 
+object *
+getbuiltins(name)
+	char *name;
+{
+	return dictlookup(builtin_dict, name);
+}
+
 int
 setbuiltin(cname, value)
 	char *cname;
diff --git a/Python/ceval.c b/Python/ceval.c
index 26b3ce3..2a3fe7b 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -43,11 +43,11 @@
 extern int suppress_print; /* Declared in pythonrun.c, set in pythonmain.c */
 
 /* Turn this on if your compiler chokes on the big switch: */
-/* #define CASE_TOO_BIG 1  	/**/
+/* #define CASE_TOO_BIG 1 */
 
 /* Turn this on if you want to debug the interpreter: */
 /* (This can be on even if NDEBUG is defined) */
-/* #define DEBUG 1  		/**/
+/* #define DEBUG 1 */
 
 #if defined(DEBUG) || !defined(NDEBUG)
 /* For debugging the interpreter: */
@@ -1254,8 +1254,8 @@
 				DECREF(v);
 				break;
 			}
-			XDECREF(w);
 			GETLISTITEM(fastlocals, oparg) = v;
+			XDECREF(w);
 			break;
 
 		case DELETE_FAST:
@@ -1270,8 +1270,8 @@
 						     (object *)NULL);
 				break;
 			}
-			DECREF(x);
 			GETLISTITEM(fastlocals, oparg) = NULL;
+			DECREF(x);
 			break;
 		
 		case BUILD_TUPLE:
@@ -1323,10 +1323,22 @@
 			break;
 		
 		case IMPORT_NAME:
-			name = GETNAME(oparg);
-			x = import_module(name);
-			XINCREF(x);
-			PUSH(x);
+			w = GETNAMEV(oparg);
+			x = getbuiltins("__import__");
+			if (x == NULL) {
+				err_setstr(ImportError,
+					   "__import__ not found");
+				break;
+			}
+			w = mkvalue("(O)", w);
+			if (w == NULL) {
+				x = NULL;
+				break;
+			}
+			x = call_object(x, w);
+			DECREF(w);
+			if (x)
+				PUSH(x);
 			break;
 		
 		case IMPORT_FROM:
@@ -1408,7 +1420,7 @@
 		case SET_LINENO:
 #ifdef LLTRACE
 			if (lltrace)
-				printf("--- Line %d ---\n", oparg);
+				printf("--- %s:%d \n", filename, oparg);
 #endif
 			f->f_lineno = oparg;
 			if (f->f_trace != NULL) {
@@ -1497,24 +1509,23 @@
 					b->b_type == SETUP_EXCEPT &&
 					why == WHY_EXCEPTION) {
 				if (why == WHY_EXCEPTION) {
-					object *exc, *val;
-					err_get(&exc, &val);
+					object *exc, *val, *tb;
+					err_fetch(&exc, &val, &tb);
 					if (val == NULL) {
 						val = None;
 						INCREF(val);
 					}
-					v = tb_fetch();
 					/* Make the raw exception data
 					   available to the handler,
 					   so a program can emulate the
 					   Python main loop.  Don't do
 					   this for 'finally'. */
 					if (b->b_type == SETUP_EXCEPT) {
-						sysset("exc_traceback", v);
+						sysset("exc_traceback", tb);
 						sysset("exc_value", val);
 						sysset("exc_type", exc);
 					}
-					PUSH(v);
+					PUSH(tb);
 					PUSH(val);
 					PUSH(exc);
 				}
@@ -1598,26 +1609,25 @@
 {
 	object *type, *value, *traceback, *arg;
 	int err;
-	err_get(&type, &value);
+	err_fetch(&type, &value, &traceback);
 	if (value == NULL) {
 		value = None;
 		INCREF(value);
 	}
-	traceback = tb_fetch();
-	arg = newtupleobject(3);
-	if (arg == NULL)
-		goto cleanup;
-	settupleitem(arg, 0, type);
-	settupleitem(arg, 1, value);
-	settupleitem(arg, 2, traceback);
-	err = call_trace(p_trace, p_newtrace, f, "exception", arg);
-	if (!err) {
- cleanup:
-		/* Restore original exception */
-		err_setval(type, value);
-		tb_store(traceback);
+	arg = mkvalue("(OOO)", type, value, traceback);
+	if (arg == NULL) {
+		err_restore(type, value, traceback);
+		return;
 	}
-	XDECREF(arg);
+	err = call_trace(p_trace, p_newtrace, f, "exception", arg);
+	DECREF(arg);
+	if (err == 0)
+		err_restore(type, value, traceback);
+	else {
+		XDECREF(type);
+		XDECREF(value);
+		XDECREF(traceback);
+	}
 }
 
 static int
@@ -1724,18 +1734,6 @@
 }
 
 void
-printtraceback(f)
-	object *f;
-{
-	object *v = tb_fetch();
-	if (v != NULL) {
-		tb_print(v, f);
-		DECREF(v);
-	}
-}
-
-
-void
 flushline()
 {
 	object *f = sysget("stdout");
@@ -1818,7 +1816,7 @@
 lshift(v, w)
 	object *v, *w;
 {
-	BINOP("__lshift__", "__rshift__");
+	BINOP("__lshift__", "__rlshift__");
 	if (v->ob_type->tp_as_number != NULL) {
 		object *x;
 		object * (*f) FPROTO((object *, object *));
@@ -1962,6 +1960,9 @@
 rem(v, w)
 	object *v, *w;
 {
+	if (is_stringobject(v)) {
+		return formatstring(v, w);
+	}
 	BINOP("__mod__", "__rmod__");
 	if (v->ob_type->tp_as_number != NULL) {
 		object *x;
@@ -1972,9 +1973,6 @@
 		DECREF(w);
 		return x;
 	}
-	if (is_stringobject(v)) {
-		return formatstring(v, w);
-	}
 	err_setstr(TypeError, "bad operand type(s) for %");
 	return NULL;
 }
@@ -2492,6 +2490,10 @@
 	object *name;
 {
 	object *w, *x;
+	if (!is_moduleobject(v)) {
+		err_setstr(TypeError, "import-from require module object");
+		return -1;
+	}
 	w = getmoduledict(v);
 	if (getstringvalue(name)[0] == '*') {
 		int pos, err;
@@ -2542,6 +2544,22 @@
 		err_setstr(SystemError, "build_class with non-tuple bases");
 		return NULL;
 	}
+	if (gettuplesize(bases) > 0) {
+		object *base;
+		base = gettupleitem(bases, 0);
+		/* Call the base's *type*, if it is callable.
+		   This code is a hook for Donald Beaudry's type extensions.
+		   In unexended Python it will never be triggered since its
+		   types are not callable. */
+		if (base->ob_type->ob_type->tp_call) {
+			object *args;
+			object *class;
+			args = mkvalue("(OOO)", name, bases, methods);
+			class = call_object((object *)base->ob_type, args);
+			DECREF(args);
+			return class;
+		}
+	}
 	if (!is_dictobject(methods)) {
 		err_setstr(SystemError, "build_class with non-dictionary");
 		return NULL;
diff --git a/Python/compile.c b/Python/compile.c
index b3b610a..dbc6314 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -336,7 +336,7 @@
 	if (byte < 0 || byte > 255) {
 		/*
 		fprintf(stderr, "XXX compiling bad byte: %d\n", byte);
-		abort();
+		fatal("com_addbyte: byte out of range");
 		*/
 		err_setstr(SystemError, "com_addbyte: byte out of range");
 		c->c_errors++;
@@ -2379,7 +2379,7 @@
 	int oparg;
 	object *name;
 	int fast_reserved;
-	object *error_type, *error_value;
+	object *error_type, *error_value, *error_traceback;
 	
 #define NEXTOP()	(*next_instr++)
 #define NEXTARG()	(next_instr += 2, (next_instr[-1]<<8) + next_instr[-2])
@@ -2393,7 +2393,7 @@
 	}
 	nlocals = 0;
 
-	err_get(&error_type, &error_value);
+	err_fetch(&error_type, &error_value, &error_traceback);
 	
 	next_instr = (unsigned char *) getstringvalue(c->c_code);
 	for (;;) {
@@ -2493,7 +2493,7 @@
 	}
 
  end:
-	err_setval(error_type, error_value);
+	err_restore(error_type, error_value, error_traceback);
  err:
 	DECREF(locals);
 }
diff --git a/Python/errors.c b/Python/errors.c
index bb3b605..9b0a8d2 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -60,6 +60,7 @@
 
 #include <errno.h>
 
+#ifndef NT
 #ifdef macintosh
 /*
 ** For the mac, there's a function macstrerror in macosmodule.c. We can't
@@ -68,9 +69,9 @@
 */
 #define strerror macstrerror
 #include "macdefs.h"    /* For CW to find EINTR */
-#endif /* macintosh */
-
+#endif /* !macintosh */
 extern char *strerror PROTO((int));
+#endif /* !NT */
 
 /* Last exception stored by err_setval() */
 
@@ -78,17 +79,27 @@
 static object *last_exc_val;
 
 void
+err_restore(exception, value, traceback)
+	object *exception;
+	object *value;
+	object *traceback;
+{
+	err_clear();
+
+	last_exception = exception;
+	last_exc_val = value;
+	(void) tb_store(traceback);
+	XDECREF(traceback);
+}
+
+void
 err_setval(exception, value)
 	object *exception;
 	object *value;
 {
-	err_clear();
-
 	XINCREF(exception);
-	last_exception = exception;
-	
 	XINCREF(value);
-	last_exc_val = value;
+	err_restore(exception, value, (object *)NULL);
 }
 
 void
@@ -116,14 +127,16 @@
 }
 
 void
-err_get(p_exc, p_val)
+err_fetch(p_exc, p_val, p_tb)
 	object **p_exc;
 	object **p_val;
+	object **p_tb;
 {
 	*p_exc = last_exception;
 	last_exception = NULL;
 	*p_val = last_exc_val;
 	last_exc_val = NULL;
+	*p_tb = tb_fetch();
 }
 
 void
diff --git a/Python/getargs.c b/Python/getargs.c
index 15cd4e6..1232fd0 100644
--- a/Python/getargs.c
+++ b/Python/getargs.c
@@ -38,7 +38,7 @@
 
 
 /* Forward */
-static int vgetargs1 PROTO((object *, char *, va_list, int));
+static int vgetargs1 PROTO((object *, char *, va_list *, int));
 static void seterror PROTO((int, char *, int *, char *, char *));
 static char *convertitem PROTO((object *, char **, va_list *, int *, char *));
 static char *converttuple PROTO((object *, char **, va_list *,
@@ -68,7 +68,7 @@
 	args = va_arg(va, object *);
 	format = va_arg(va, char *);
 #endif
-	retval = vgetargs1(args, format, va, 1);
+	retval = vgetargs1(args, format, &va, 1);
 	va_end(va);
 	return retval;
 }
@@ -95,7 +95,7 @@
 	args = va_arg(va, object *);
 	format = va_arg(va, char *);
 #endif
-	retval = vgetargs1(args, format, va, 0);
+	retval = vgetargs1(args, format, &va, 0);
 	va_end(va);
 	return retval;
 }
@@ -107,15 +107,23 @@
 	char *format;
 	va_list va;
 {
-	return vgetargs1(args, format, va, 0);
+	va_list lva;
+
+#ifdef VA_LIST_IS_ARRAY
+	memcpy(lva, va, sizeof(va_list));
+#else
+	lva = va;
+#endif
+
+	return vgetargs1(args, format, &lva, 0);
 }
 
 
 static int
-vgetargs1(args, format, va, compat)
+vgetargs1(args, format, p_va, compat)
 	object *args;
 	char *format;
-	va_list va;
+	va_list *p_va;
 	int compat;
 {
 	char msgbuf[256];
@@ -186,7 +194,7 @@
 				err_setstr(TypeError, msgbuf);
 				return 0;
 			}
-			msg = convertitem(args, &format, &va, levels, msgbuf);
+			msg = convertitem(args, &format, p_va, levels, msgbuf);
 			if (msg == NULL)
 				return 1;
 			seterror(levels[0], msg, levels+1, fname, message);
@@ -226,7 +234,7 @@
 	for (i = 0; i < len; i++) {
 		if (*format == '|')
 			format++;
-		msg = convertitem(gettupleitem(args, i), &format, &va,
+		msg = convertitem(gettupleitem(args, i), &format, p_va,
 				 levels, msgbuf);
 		if (msg) {
 			seterror(i+1, msg, levels, fname, message);
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");
+}
diff --git a/Python/importdl.c b/Python/importdl.c
new file mode 100644
index 0000000..f377c61
--- /dev/null
+++ b/Python/importdl.c
@@ -0,0 +1,381 @@
+/***********************************************************
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
+Amsterdam, The Netherlands.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its 
+documentation for any purpose and without fee is hereby granted, 
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in 
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Support for dynamic loading of extension modules */
+/* If no dynamic linking is supported, this file still generates some code! */
+
+#include "allobjects.h"
+#include "osdefs.h"
+#include "importdl.h"
+
+extern int verbose; /* Defined in pythonrun.c */
+
+/* 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%.200s"
+#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%.200s"
+#else
+#define FUNCNAME_PATTERN "init%.200s"
+#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
+
+/* Pass it on to import.c */
+int import_maxsuffixsize = MAXSUFFIXSIZE;
+
+struct filedescr import_filetab[] = {
+#ifdef SHORT_EXT
+	{SHORT_EXT, "rb", C_EXTENSION},
+#endif /* !SHORT_EXT */
+#ifdef LONG_EXT
+	{LONG_EXT, "rb", C_EXTENSION},
+#endif /* !LONG_EXT */
+	{".py", "r", PY_SOURCE},
+	{".pyc", "rb", PY_COMPILED},
+	{0, 0}
+};
+
+object *
+load_dynamic_module(name, pathname)
+	char *name;
+	char *pathname;
+{
+#ifndef DYNAMIC_LINK
+	err_setstr(ImportError, "dynamically linked modules not supported");
+	return NULL;
+#else
+	object *m;
+	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(pathname);
+		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(pathname, RTLD_NOW);
+#else
+		void *handle;
+		if (verbose)
+			printf("dlopen(\"%s\", %d);\n", pathname, RTLD_LAZY);
+		handle = dlopen(pathname, 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(pathname, 1, 0);
+	if (p == NULL) {
+		aix_loaderror(pathname);
+		return NULL;
+	}
+#endif /* _AIX */
+#ifdef NT
+	{
+		HINSTANCE hDLL;
+		hDLL = LoadLibrary(pathname);
+		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(), pathname, 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] = pathname;
+		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",pathname);
+                }
+                lib = shl_load(pathname, flags, 0);
+                if (lib == NULL)
+                {
+                        char buf[256];
+                        if (verbose)
+                                perror(pathname);
+                        sprintf(buf, "Failed to load %.200s", pathname);
+                        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 = dictlookup(import_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, pathname);
+	INCREF(m);
+	return m;
+#endif /* DYNAMIC_LINK */
+}
+
+
+#ifdef _AIX
+
+#include <ctype.h>	/* for isdigit()	*/
+#include <errno.h>	/* for global errno	*/
+#include <string.h>	/* for strerror()	*/
+
+void aix_loaderror(char *pathname)
+{
+
+	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 ", pathname);
+
+	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 */
diff --git a/Python/importdl.h b/Python/importdl.h
new file mode 100644
index 0000000..c90608e
--- /dev/null
+++ b/Python/importdl.h
@@ -0,0 +1,39 @@
+/***********************************************************
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
+Amsterdam, The Netherlands.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its 
+documentation for any purpose and without fee is hereby granted, 
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in 
+supporting documentation, and that the names of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+******************************************************************/
+
+/* Definitions for dynamic loading of extension modules */
+
+enum filetype {SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION};
+
+extern struct filedescr {
+	char *suffix;
+	char *mode;
+	enum filetype type;
+} import_filetab[];
+
+extern object *import_modules;
+
+extern object *load_dynamic_module PROTO((char *name, char *pathname));
+
+extern int import_maxsuffixsize;
diff --git a/Python/marshal.c b/Python/marshal.c
index 96c530a..48612b0 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -406,6 +406,10 @@
 	FILE *fp;
 {
 	RFILE rf;
+	if (err_occurred()) {
+		fprintf(stderr, "XXX rd_object called with exception set\n");
+		return NULL;
+	}
 	rf.fp = fp;
 	return r_object(&rf);
 }
@@ -416,6 +420,10 @@
 	int len;
 {
 	RFILE rf;
+	if (err_occurred()) {
+		fprintf(stderr, "XXX rds_object called with exception set\n");
+		return NULL;
+	}
 	rf.fp = NULL;
 	rf.str = NULL;
 	rf.ptr = str;
diff --git a/Python/modsupport.c b/Python/modsupport.c
index ae9a838..2952189 100644
--- a/Python/modsupport.c
+++ b/Python/modsupport.c
@@ -29,7 +29,7 @@
 
 #ifdef MPW /* MPW pushes 'extended' for float and double types with varargs */
 typedef extended va_double;
-#else 
+#else
 typedef double va_double;
 #endif
 
@@ -42,7 +42,7 @@
 initmodule2(name, methods, passthrough)
 	char *name;
 	struct methodlist *methods;
-	object *passthrough; 
+	object *passthrough;
 {
 	object *m, *d, *v;
 	struct methodlist *ml;
@@ -58,7 +58,7 @@
 			fatal("out of mem for method name");
 		sprintf(namebuf, "%s.%s", name, ml->ml_name);
 		v = newmethodobject(namebuf, ml->ml_meth,
-					(object *)passthrough, ml->ml_varargs);
+				    (object *)passthrough, ml->ml_varargs);
 		/* XXX The malloc'ed memory in namebuf is never freed */
 		if (v == NULL || dictinsert(d, ml->ml_name, v) != 0) {
 			fprintf(stderr, "initializing module: %s\n", name);
@@ -90,20 +90,33 @@
 	int count = 0;
 	int level = 0;
 	while (level > 0 || *format != endchar) {
-		if (*format == '\0') {
+		switch (*format) {
+		case '\0':
 			/* Premature end */
 			err_setstr(SystemError, "unmatched paren in format");
 			return -1;
-		}
-		else if (*format == '(') {
+		case '(':
+		case '[':
+		case '{':
 			if (level == 0)
 				count++;
 			level++;
-		}
-		else if (*format == ')')
+			break;
+		case ')':
+		case ']':
+		case '}':
 			level--;
-		else if (level == 0 && *format != '#')
-			count++;
+			break;
+		case '#':
+		case ',':
+		case ':':
+		case ' ':
+		case '\t':
+			break;
+		default:
+			if (level == 0)
+				count++;
+		}
 		format++;
 	}
 	return count;
@@ -114,8 +127,85 @@
 /* After an original idea and first implementation by Steven Miale */
 
 static object *do_mktuple PROTO((char**, va_list *, int, int));
+static object *do_mklist PROTO((char**, va_list *, int, int));
+static object *do_mkdict PROTO((char**, va_list *, int, int));
 static object *do_mkvalue PROTO((char**, va_list *));
 
+
+static object *
+do_mkdict(p_format, p_va, endchar, n)
+	char **p_format;
+	va_list *p_va;
+	int endchar;
+	int n;
+{
+	object *d;
+	int i;
+	if (n < 0)
+		return NULL;
+	if ((d = newdictobject()) == NULL)
+		return NULL;
+	for (i = 0; i < n; i+= 2) {
+		object *k, *v;
+		k = do_mkvalue(p_format, p_va);
+		if (k == NULL) {
+			DECREF(d);
+			return NULL;
+		}
+		v = do_mkvalue(p_format, p_va);
+		if (v == NULL) {
+			DECREF(k);
+			DECREF(d);
+			return NULL;
+		}
+		if (dict2insert(d, k, v) < 0) {
+			DECREF(k);
+			DECREF(v);
+			DECREF(d);
+			return NULL;
+		}
+	}
+	if (d != NULL && **p_format != endchar) {
+		DECREF(d);
+		d = NULL;
+		err_setstr(SystemError, "Unmatched paren in format");
+	}
+	else if (endchar)
+		++*p_format;
+	return d;
+}
+
+static object *
+do_mklist(p_format, p_va, endchar, n)
+	char **p_format;
+	va_list *p_va;
+	int endchar;
+	int n;
+{
+	object *v;
+	int i;
+	if (n < 0)
+		return NULL;
+	if ((v = newlistobject(n)) == NULL)
+		return NULL;
+	for (i = 0; i < n; i++) {
+		object *w = do_mkvalue(p_format, p_va);
+		if (w == NULL) {
+			DECREF(v);
+			return NULL;
+		}
+		setlistitem(v, i, w);
+	}
+	if (v != NULL && **p_format != endchar) {
+		DECREF(v);
+		v = NULL;
+		err_setstr(SystemError, "Unmatched paren in format");
+	}
+	else if (endchar)
+		++*p_format;
+	return v;
+}
+
 static object *
 do_mktuple(p_format, p_va, endchar, n)
 	char **p_format;
@@ -152,34 +242,41 @@
 	char **p_format;
 	va_list *p_va;
 {
-	
-	switch (*(*p_format)++) {
-	
-	case '(':
-		return do_mktuple(p_format, p_va, ')',
-				  countformat(*p_format, ')'));
-		
-	case 'b':
-	case 'h':
-	case 'i':
-		return newintobject((long)va_arg(*p_va, int));
-		
-	case 'l':
-		return newintobject((long)va_arg(*p_va, long));
-		
-	case 'f':
-	case 'd':
-		return newfloatobject((double)va_arg(*p_va, va_double));
-		
-	case 'c':
+	for (;;) {
+		switch (*(*p_format)++) {
+		case '(':
+			return do_mktuple(p_format, p_va, ')',
+					  countformat(*p_format, ')'));
+
+		case '[':
+			return do_mklist(p_format, p_va, ']',
+					 countformat(*p_format, ']'));
+
+		case '{':
+			return do_mkdict(p_format, p_va, '}',
+					 countformat(*p_format, '}'));
+
+		case 'b':
+		case 'h':
+		case 'i':
+			return newintobject((long)va_arg(*p_va, int));
+
+		case 'l':
+			return newintobject((long)va_arg(*p_va, long));
+
+		case 'f':
+		case 'd':
+			return newfloatobject((double)va_arg(*p_va, double));
+
+		case 'c':
 		{
 			char p[1];
 			p[0] = va_arg(*p_va, int);
 			return newsizedstringobject(p, 1);
 		}
-	
-	case 's':
-	case 'z':
+
+		case 's':
+		case 'z':
 		{
 			object *v;
 			char *str = va_arg(*p_va, char *);
@@ -201,33 +298,44 @@
 			}
 			return v;
 		}
-	
-	case 'S':
-	case 'O':
+
+		case 'S':
+		case 'O':
 		{
 			object *v;
 			v = va_arg(*p_va, object *);
 			if (v != NULL)
 				INCREF(v);
 			else if (!err_occurred())
-				/* If a NULL was passed because a call
-				   that should have constructed a value
-				   failed, that's OK, and we pass the error
-				   on; but if no error occurred it's not
-				   clear that the caller knew what she
-				   was doing. */
+				/* If a NULL was passed
+				 * because a call that should
+				 * have constructed a value
+				 * failed, that's OK, and we
+				 * pass the error on; but if
+				 * no error occurred it's not
+				 * clear that the caller knew
+				 * what she was doing. */
 				err_setstr(SystemError,
 					   "NULL object passed to mkvalue");
 			return v;
 		}
-	
-	default:
-		err_setstr(SystemError, "bad format char passed to mkvalue");
-		return NULL;
-	
+
+		case ':':
+		case ',':
+		case ' ':
+		case '\t':
+			break;
+
+		default:
+			err_setstr(SystemError,
+				   "bad format char passed to mkvalue");
+			return NULL;
+
+		}
 	}
 }
 
+
 #ifdef HAVE_STDARG_PROTOTYPES
 /* VARARGS 2 */
 object *mkvalue(char *format, ...)
@@ -257,6 +365,14 @@
 {
 	char *f = format;
 	int n = countformat(f, '\0');
+	va_list lva;
+
+#ifdef VA_LIST_IS_ARRAY
+	memcpy(lva, va, sizeof(va_list));
+#else
+	lva = va;
+#endif
+
 	if (n < 0)
 		return NULL;
 	if (n == 0) {
@@ -264,6 +380,83 @@
 		return None;
 	}
 	if (n == 1)
-		return do_mkvalue(&f, &va);
-	return do_mktuple(&f, &va, '\0', n);
+		return do_mkvalue(&f, &lva);
+	return do_mktuple(&f, &lva, '\0', n);
+}
+
+
+#ifdef HAVE_STDARG_PROTOTYPES
+object *
+PyEval_CallFunction(object *obj, char *format, ...)
+#else
+object *
+PyEval_CallFunction(obj, format, va_alist)
+	object *obj;
+	char *format;
+	va_dcl
+#endif
+{
+	va_list vargs;
+	object *args;
+	object *res;
+
+#ifdef HAVE_STDARG_PROTOTYPES
+	va_start(vargs, format);
+#else
+	va_start(vargs);
+#endif
+
+	args = vmkvalue(format, vargs);
+	va_end(vargs);
+
+	if (args == NULL)
+		return NULL;
+
+	res = call_object(obj, args);
+	DECREF(args);
+
+	return res;
+}
+
+
+#ifdef HAVE_STDARG_PROTOTYPES
+object *
+PyEval_CallMethod(object *obj, char *method, char *format, ...)
+#else
+object *
+PyEval_CallMethod(obj, method, format, va_alist)
+	object *obj;
+	char *method;
+	char *format;
+	va_dcl
+#endif
+{
+	va_list vargs;
+	object *meth;
+	object *args;
+	object *res;
+
+	meth = getattr(obj, method);
+	if (meth == NULL)
+		return NULL;
+
+#ifdef HAVE_STDARG_PROTOTYPES
+	va_start(vargs, format);
+#else
+	va_start(vargs);
+#endif
+
+	args = vmkvalue(format, vargs);
+	va_end(vargs);
+
+	if (args == NULL) {
+		DECREF(meth);
+		return NULL;
+	}
+
+	res = call_object(meth, args);
+	DECREF(meth);
+	DECREF(args);
+
+	return res;
 }
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index de0de07..f66c8d7 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -242,12 +242,10 @@
 void
 print_error()
 {
-	object *exception, *v, *f;
-	err_get(&exception, &v);
-	if (exception == NULL) {
-		fprintf(stderr, "print_error called but no exception\n");
-		abort();
-	}
+	object *exception, *v, *tb, *f;
+	err_fetch(&exception, &v, &tb);
+	if (exception == NULL)
+		fatal("print_error called but no exception");
 	if (exception == SystemExit) {
 		if (v == NULL || v == None)
 			goaway(0);
@@ -262,11 +260,12 @@
 	}
 	sysset("last_type", exception);
 	sysset("last_value", v);
+	sysset("last_traceback", tb);
 	f = sysget("stderr");
 	if (f == NULL)
 		fprintf(stderr, "lost sys.stderr\n");
 	else {
-		printtraceback(f);
+		tb_print(tb, f);
 		if (exception == SyntaxError) {
 			object *message;
 			char *filename, *text;
@@ -331,6 +330,7 @@
 	}
 	XDECREF(exception);
 	XDECREF(v);
+	XDECREF(tb);
 }
 
 object *
@@ -421,7 +421,6 @@
 	int start;
 {
 	node *n;
-	int err;
 	codeobject *co;
 	n = parse_string(str, start);
 	if (n == NULL)
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 509b819..4cb1658 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -204,7 +204,8 @@
 	XDECREF(v);
 	dictinsert(sysdict, "modules", get_modules());
 	dictinsert(sysdict, "builtin_module_names",
-		   list_builtin_module_names());
+		   v = list_builtin_module_names());
+	XDECREF(v);
 	if (err_occurred())
 		fatal("can't insert sys.* objects in sys dict");
 }
diff --git a/Python/thread_solaris.h b/Python/thread_solaris.h
index 8bbbeb0..97be126 100644
--- a/Python/thread_solaris.h
+++ b/Python/thread_solaris.h
@@ -68,7 +68,7 @@
 	funcarg = (struct func_arg *) malloc(sizeof(struct func_arg));
 	funcarg->func = func;
 	funcarg->arg = arg;
-	if (thr_create(0, 0, new_func, funcarg, THR_NEW_LWP, 0)) {
+	if (thr_create(0, 0, new_func, funcarg, THR_DETACHED, 0)) {
 		perror("thr_create");
 		free((void *) funcarg);
 		success = -1;
diff --git a/Python/traceback.c b/Python/traceback.c
index 1db9c94..414fc8d 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -258,7 +258,6 @@
 		err_badcall();
 		return -1;
 	}
-	sysset("last_traceback", v);
 	limitv = sysget("tracebacklimit");
 	if (limitv && is_intobject(limitv)) {
 		limit = getintvalue(limitv);