* import.c (get_module): total rewrite, to ensure proper search order: for
  each dir in sys.path, try each possible extension.  (Note: C extensions
  are loaded before Python modules in the same directory, to allow having
  a C version used when dynamic loading is supported and a Python version
  as a back-up.)
* import.c (reload_module): test for error from getmodulename()
* moduleobject.c: implement module name as dict entry '__name__' instead
  of special-casing it in module_getattr(); this way a module (or
  function!) can access its own module name, and programs that know what
  they are doing can rename modules.
* stdwinmodule.c (initstdwin): strip ".py" suffix of argv[0].
diff --git a/Modules/stdwinmodule.c b/Modules/stdwinmodule.c
index 1fff814..fc81cff 100644
--- a/Modules/stdwinmodule.c
+++ b/Modules/stdwinmodule.c
@@ -2598,6 +2598,7 @@
 {
 	object *m, *d;
 	static int inited = 0;
+	char buf[1000];
 
 	if (!inited) {
 		int argc = 0;
@@ -2607,6 +2608,18 @@
 			if (!checkstringlist(sys_argv, &argv, &argc))
 				err_clear();
 		}
+		if (argc > 0) {
+			/* If argv[0] has a ".py" suffix, remove the suffix */
+			char *p = strrchr(argv[0], '.');
+			if (p != NULL && strcmp(p, ".py") == 0) {
+				int n = p - argv[0];
+				if (n >= sizeof(buf))
+					n = sizeof(buf)-1;
+				strncpy(buf, argv[0], n);
+				buf[n] = '\0';
+				argv[0] = buf;
+			}
+		}
 		winitargs(&argc, &argv);
 		if (argv != NULL) {
 			if (!putbackstringlist(sys_argv, argv, argc))
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index dca5543..9a687b4 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -29,7 +29,6 @@
 
 typedef struct {
 	OB_HEAD
-	object *md_name;
 	object *md_dict;
 } moduleobject;
 
@@ -37,16 +36,24 @@
 newmoduleobject(name)
 	char *name;
 {
-	moduleobject *m = NEWOBJ(moduleobject, &Moduletype);
+	moduleobject *m;
+	object *nameobj;
+	m = NEWOBJ(moduleobject, &Moduletype);
 	if (m == NULL)
 		return NULL;
-	m->md_name = newstringobject(name);
+	nameobj = newstringobject(name);
 	m->md_dict = newdictobject();
-	if (m->md_name == NULL || m->md_dict == NULL) {
-		DECREF(m);
-		return NULL;
-	}
+	if (m->md_dict == NULL || nameobj == NULL)
+		goto fail;
+	if (dictinsert(m->md_dict, "__name__", nameobj) != 0)
+		goto fail;
+	DECREF(nameobj);
 	return (object *)m;
+
+ fail:
+	XDECREF(nameobj);
+	DECREF(m);
+	return NULL;
 }
 
 object *
@@ -64,11 +71,17 @@
 getmodulename(m)
 	object *m;
 {
+	object *nameobj;
 	if (!is_moduleobject(m)) {
 		err_badarg();
 		return NULL;
 	}
-	return getstringvalue(((moduleobject *)m) -> md_name);
+	nameobj = dictlookup(((moduleobject *)m)->md_dict, "__name__");
+	if (nameobj == NULL || !is_stringobject(nameobj)) {
+		err_setstr(SystemError, "nameless module");
+		return NULL;
+	}
+	return getstringvalue(nameobj);
 }
 
 /* Methods */
@@ -77,8 +90,6 @@
 module_dealloc(m)
 	moduleobject *m;
 {
-	if (m->md_name != NULL)
-		DECREF(m->md_name);
 	if (m->md_dict != NULL)
 		DECREF(m->md_dict);
 	free((char *)m);
@@ -89,7 +100,12 @@
 	moduleobject *m;
 {
 	char buf[100];
-	sprintf(buf, "<module '%.80s'>", getstringvalue(m->md_name));
+	char *name = getmodulename((object *)m);
+	if (name == NULL) {
+		err_clear();
+		name = "?";
+	}
+	sprintf(buf, "<module '%.80s'>", name);
 	return newstringobject(buf);
 }
 
@@ -103,10 +119,6 @@
 		INCREF(m->md_dict);
 		return m->md_dict;
 	}
-	if (strcmp(name, "__name__") == 0) {
-		INCREF(m->md_name);
-		return m->md_name;
-	}
 	res = dictlookup(m->md_dict, name);
 	if (res == NULL)
 		err_setstr(AttributeError, name);
@@ -126,12 +138,9 @@
 	object *v;
 {
 	object *ac;
-	if (name[0] == '_' && name[1] == '_') {
-		int n = strlen(name);
-		if (name[n-1] == '_' && name[n-2] == '_') {
-			err_setstr(TypeError, "read-only special attribute");
-			return -1;
-		}
+	if (name[0] == '_' && strcmp(name, "__dict__") == 0) {
+		err_setstr(TypeError, "read-only special attribute");
+		return -1;
 	}
 	ac = dictlookup(m->md_dict, name);
 	if (ac != NULL && is_accessobject(ac))
diff --git a/Python/import.c b/Python/import.c
index b81a41e..2fc3995 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -101,66 +101,24 @@
 	return m;
 }
 
-/* Suffixes used by find_module: */
+enum filetype {SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION};
 
-#define PY_SUFFIX	".py"
-#define PYC_SUFFIX	".pyc"
+static struct filedescr {
+	char *suffix;
+	char *mode;
+	enum filetype type;
+} filetab[] = {
 #ifdef USE_DL
 #ifdef SUN_SHLIB
-#define O_SUFFIX	"module.so"
+	{"module.so", "rb", C_EXTENSION},
 #else
-#define O_SUFFIX	"module.o"
+	{"module.o", "rb", C_EXTENSION},
 #endif /* SUN_SHLIB */
-#endif
-
-/* This will search for a module named 'name' with the extension 'ext'
-   and return it in 'namebuf' and return the mtime of each in 'mtime'.
-   It returns a file pointer opened for 'mode' if successful, NULL if
-   unsuccessful.
- */
-static FILE *
-find_module(name, ext, mode, namebuf, mtime)
-	char *name;
-	char *ext;
-	char *mode;
-	char *namebuf;
-	long *mtime;
-{
-	object *path;
-	FILE *fp;
-
-	path = sysget("path");
-	if (path == NULL || !is_listobject(path)) {
-		/* No path -- at least try current directory */
-		strcpy(namebuf, name);
-		strcat(namebuf, ext);
-		if ((fp = fopen(namebuf, mode)) == NULL)
-			return NULL;
-		*mtime = getmtime(namebuf);
-		return fp;
-	} else {
-		int npath = getlistsize(path);
-		int i;
-		for (i = 0; i < npath; i++) {
-			object *v = getlistitem(path, i);
-			int len;
-			if (!is_stringobject(v))
-				continue;
-			strcpy(namebuf, getstringvalue(v));
-			len = getstringsize(v);
-			if (len > 0 && namebuf[len-1] != SEP)
-				namebuf[len++] = SEP;
-			strcpy(namebuf+len, name);
-			strcat(namebuf, ext);
-			if ((fp = fopen(namebuf, mode)) == NULL)
-				continue;
-			*mtime = getmtime(namebuf);
-			return fp;
-		}
-	}
-	namebuf[0] = '\0';
-	return NULL;
-}
+#endif /* USE_DL */
+	{".py", "r", PY_SOURCE},
+	{".pyc", "rb", PY_COMPILED},
+	{0, 0}
+};
 
 static object *
 get_module(m, name, m_ret)
@@ -168,150 +126,113 @@
 	char *name;
 	object **m_ret;
 {
-	codeobject *co = NULL;
-	object *v, *d;
-	FILE *fp, *fpc;
-	node *n;
-	int err;
+	int err, npath, i, len;
+	long magic;
+	long mtime, pyc_mtime;
 	char namebuf[MAXPATHLEN+1];
-	int namelen;
-	long mtime;
+	struct filedescr *fdp;
+	FILE *fp = NULL, *fpc = NULL;
+	node *n = NULL;
+	object *path, *v, *d;
+	codeobject *co = NULL;
 
-#ifdef USE_DL
-	if ((fpc = find_module(name, O_SUFFIX, "rb",
-			       namebuf, &mtime)) != NULL) {
-		char funcname[258];
-		dl_funcptr p;
-		D(fprintf(stderr, "Found %s\n", namebuf));
-		fclose(fpc);
-		sprintf(funcname, "init%s", name);
-#ifdef SUN_SHLIB
-		{
-		  void *handle = dlopen (namebuf, 1);
-		  p = (dl_funcptr) dlsym(handle, funcname);
-		}
-#else
-		if (verbose)
-			fprintf(stderr,
-				"import %s # dynamically loaded from \"%s\"\n",
-				name, namebuf);
-		p =  dl_loadmod(argv0, namebuf, funcname);
-#endif /* SUN_SHLIB */
-		if (p == NULL) {
-			err_setstr(SystemError,
-			   "dynamic module does not define init function");
-			return NULL;
-		} else {
-			(*p)();
-			*m_ret = m = dictlookup(modules, name);
-			if (m == NULL) {
-				err_setstr(SystemError,
-				   "dynamic module not initialized properly");
-				return NULL;
-			} else {
-				D(fprintf(stderr,
-					"module %s loaded!\n", name));
-				INCREF(None);
-				return None;
-			}
-		}
+	path = sysget("path");
+	if (path == NULL || !is_listobject(path)) {
+		err_setstr(ImportError,
+			   "sys.path must be list of directory names");
+		return NULL;
 	}
-	else
-#endif
-	if ((fpc = find_module(name, PYC_SUFFIX, "rb",
-			      namebuf, &mtime)) != NULL) {
-		long pyc_mtime;
-		long magic;
-		namebuf[(strlen(namebuf)-1)] = '\0';
+	npath = getlistsize(path);
+	for (i = 0; i < npath; i++) {
+		v = getlistitem(path, i);
+		if (!is_stringobject(v))
+			continue;
+		strcpy(namebuf, getstringvalue(v));
+		len = getstringsize(v);
+		if (len > 0 && namebuf[len-1] != SEP)
+			namebuf[len++] = SEP;
+		strcpy(namebuf+len, name);
+		len += strlen(name);
+		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 %s", name);
+		err_setstr(ImportError, namebuf);
+		return NULL;
+	}
+
+	switch (fdp->type) {
+
+	case PY_SOURCE:
 		mtime = getmtime(namebuf);
-		magic = rd_long(fpc);
-		pyc_mtime = rd_long(fpc);
-		if (mtime != -1 && mtime > pyc_mtime) {
-			fclose(fpc);
-			goto read_py;
-		}
-		if (magic == MAGIC) {
-			v = rd_object(fpc);
-			if (v == NULL || err_occurred() ||
-			    !is_codeobject(v)) {
-				err_clear();
-				XDECREF(v);
-			}
-			else
-				co = (codeobject *)v;
-		}
-		fclose(fpc);
-		if (verbose) {
-			if (co != NULL)
-				fprintf(stderr,
-			"import %s # precompiled from \"%s\"\n",
-					name, namebuf);
-			else {
-				fprintf(stderr,
-				"# invalid precompiled file \"%s\"\n",
-					namebuf);
-			}
-		}
-		if (co == NULL)
-			goto read_py;
-	}
-	else {
-read_py:
-		if ((fp = find_module(name, PY_SUFFIX, "r",
-				      namebuf, &mtime)) != NULL) {
-			namelen = strlen(namebuf);
-			if (co == NULL) {
+		strcat(namebuf, "c");
+		fpc = fopen(namebuf, "rb");
+		if (fpc != NULL) {
+			magic = rd_long(fpc);
+			if (magic != MAGIC) {
 				if (verbose)
 					fprintf(stderr,
-						"import %s # from \"%s\"\n",
-						name, namebuf);
-				err = parse_file(fp, namebuf, file_input, &n);
-			} else
-				err = E_DONE;
-			fclose(fp);
-			if (err != E_DONE) {
-				err_input(err);
-				return NULL;
-			}
-		}
-		else {
-			if (m == NULL) {
-				sprintf(namebuf, "no module named %.200s",
-					name);
-				err_setstr(ImportError, namebuf);
+						"# %s.pyc has bad magic\n",
+						name);
 			}
 			else {
-				sprintf(namebuf, "no source for module %.200s",
-					name);
-				err_setstr(ImportError, namebuf);
+				pyc_mtime = rd_long(fpc);
+				if (pyc_mtime != mtime) {
+					if (verbose)
+						fprintf(stderr,
+						  "# %s.pyc has bad mtime\n",
+						  name);
+				}
+				else {
+					fclose(fp);
+					fp = fpc;
+					if (verbose)
+					   fprintf(stderr,
+					     "# %s.pyc matches %s.py\n",
+						   name, name);
+					goto use_compiled;
+				}
 			}
+			fclose(fpc);
+		}
+		err = parse_file(fp, namebuf, file_input, &n);
+		if (err != E_DONE) {
+			err_input(err);
 			return NULL;
 		}
-	}
-	if (m == NULL) {
-		m = add_module(name);
-		if (m == NULL) {
-			freetree(n);
-			return NULL;
-		}
-		*m_ret = m;
-	}
-	d = getmoduledict(m);
-	if (co == NULL) {
 		co = compile(n, namebuf);
 		freetree(n);
 		if (co == NULL)
 			return NULL;
+		if (verbose)
+			fprintf(stderr,
+				"import %s # from %.*s\n",
+				name, strlen(namebuf)-1, namebuf);
 		/* Now write the code object to the ".pyc" file */
-		namebuf[namelen] = 'c';
-		namebuf[namelen+1] = '\0';
 		fpc = fopen(namebuf, "wb");
-		if (fpc != NULL) {
+		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);
@@ -322,9 +243,97 @@
 				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.pyc without %s.py\n",
+				name, 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 USE_DL
+	case C_EXTENSION:
+	      {
+		char funcname[258];
+		dl_funcptr p;
+		fclose(fp);
+		sprintf(funcname, "init%s", name);
+#ifdef SUN_SHLIB
+		{
+		  void *handle = dlopen (namebuf, 1);
+		  p = (dl_funcptr) dlsym(handle, funcname);
+		}
+#else
+		p =  dl_loadmod(argv0, namebuf, funcname);
+#endif /* SUN_SHLIB */
+		if (p == NULL) {
+			err_setstr(ImportError,
+			   "dynamic module does not define init function");
+			return NULL;
+		} else {
+			(*p)();
+			*m_ret = m = dictlookup(modules, name);
+			if (m == NULL) {
+				err_setstr(SystemError,
+				   "dynamic module not initialized properly");
+				return NULL;
+			} else {
+				if (verbose)
+					fprintf(stderr,
+				"import %s # dynamically loaded from %s\n",
+						name, namebuf);
+				INCREF(None);
+				return None;
+			}
+		}
+		break;
+	      }
+#endif /* USE_DL */
+
+	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;
@@ -367,12 +376,16 @@
 reload_module(m)
 	object *m;
 {
+	char *name;
 	if (m == NULL || !is_moduleobject(m)) {
 		err_setstr(TypeError, "reload() argument must be module");
 		return NULL;
 	}
+	name = getmodulename(m);
+	if (name == NULL)
+		return NULL;
 	/* XXX Ought to check for builtin modules -- can't reload these... */
-	return get_module(m, getmodulename(m), (object **)NULL);
+	return get_module(m, name, (object **)NULL);
 }
 
 void