? Lib.nn
? zip-comments
Index: Include/import.h
===================================================================
RCS file: /cvsroot/python/python/dist/src/Include/import.h,v
retrieving revision 2.29
diff -w -u -r2.29 import.h
--- Include/import.h	29 Jul 2002 13:41:59 -0000	2.29
+++ Include/import.h	29 Nov 2002 18:33:53 -0000
@@ -21,6 +21,7 @@
 PyAPI_FUNC(void) PyImport_Cleanup(void);
 PyAPI_FUNC(int) PyImport_ImportFrozenModule(char *);
 
+PyAPI_FUNC(void) _PyImport_InitZip(void);
 PyAPI_FUNC(PyObject *)_PyImport_FindExtension(char *, char *);
 PyAPI_FUNC(PyObject *)_PyImport_FixupExtension(char *, char *);
 
Index: Include/pythonrun.h
===================================================================
RCS file: /cvsroot/python/python/dist/src/Include/pythonrun.h,v
retrieving revision 2.55
diff -w -u -r2.55 pythonrun.h
--- Include/pythonrun.h	26 Oct 2002 14:39:09 -0000	2.55
+++ Include/pythonrun.h	29 Nov 2002 18:33:53 -0000
@@ -17,6 +17,9 @@
 PyAPI_FUNC(void) Py_SetProgramName(char *);
 PyAPI_FUNC(char *) Py_GetProgramName(void);
 
+PyAPI_FUNC(void) Py_SetScriptName(char *);
+PyAPI_FUNC(char *) Py_GetScriptName(void);
+
 PyAPI_FUNC(void) Py_SetPythonHome(char *);
 PyAPI_FUNC(char *) Py_GetPythonHome(void);
 
Index: Lib/site.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/site.py,v
retrieving revision 1.46
diff -w -u -r1.46 site.py
--- Lib/site.py	9 Nov 2002 05:08:06 -0000	1.46
+++ Lib/site.py	29 Nov 2002 18:33:53 -0000
@@ -75,13 +75,13 @@
 _dirs_in_sys_path = {}
 for dir in sys.path:
     # Filter out paths that don't exist, but leave in the empty string
-    # since it's a special case. We also need to special-case the Mac,
-    # as file names are allowed on sys.path there.
-    if sys.platform != 'mac':
-        if dir and not os.path.isdir(dir):
+    # since it's a special case.  For the Mac, file names are allowed
+    # in sys.path.  For all platforms, zip archive file names are allowed.
+    if dir:
+        if not os.path.exists(dir):
             continue
-    else:
-        if dir and not os.path.exists(dir):
+        if sys.platform != 'mac':
+	    if not (os.path.isdir(dir) or dir.endswith('.zip')):
             continue
     dir, dircase = makepath(dir)
     if not dircase in _dirs_in_sys_path:
Index: Modules/getpath.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/getpath.c,v
retrieving revision 1.42
diff -w -u -r1.42 getpath.c
--- Modules/getpath.c	13 Sep 2002 14:35:56 -0000	1.42
+++ Modules/getpath.c	29 Nov 2002 18:33:55 -0000
@@ -76,12 +76,14 @@
  *
  * That's it!
  *
- * Well, almost.  Once we have determined prefix and exec_prefix, the
- * preprocessor variable PYTHONPATH is used to construct a path.  Each
- * relative path on PYTHONPATH is prefixed with prefix.  Then the directory
- * containing the shared library modules is appended.  The environment
- * variable $PYTHONPATH is inserted in front of it all.  Finally, the
- * prefix and exec_prefix globals are tweaked so they reflect the values
+ * Well, almost.  Once we have determined prefix and exec_prefix, we
+ * can construct the module_search_path that is returned by Py_GetPath().
+ * The first item is the environment variable $PYTHONPATH.  Next is the
+ * directory of the Python script being run, or "", or perhaps nothing.
+ * Next is the zip file name.  Next we add each item of the preprocessor
+ * variable PYTHONPATH, prepending each relative path with prefix.  Then
+ * the directory containing the shared library modules is added.  Finally,
+ * the prefix and exec_prefix globals are tweaked so they reflect the values
  * expected by other code, by stripping the "lib/python$VERSION/..." stuff
  * off.  If either points to the build directory, the globals are reset to
  * the corresponding preprocessor variables (so sys.prefix will reflect the
@@ -347,12 +349,83 @@
     return 0;
 }
 
+/* get the real pathname from a symlink, real_path must be MAXPATHLEN+1 */
+#if HAVE_READLINK
+static char *
+get_path_from_symlink(char* orig_path, char* real_path)
+{
+    char tmpbuffer[MAXPATHLEN+1];
+    int linklen = readlink(orig_path, tmpbuffer, MAXPATHLEN);
+    while (linklen != -1) {
+        /* It's not null terminated! */
+        tmpbuffer[linklen] = '\0';
+        if (tmpbuffer[0] == SEP) {
+            /* tmpbuffer should never be longer than MAXPATHLEN,
+               but extra check does not hurt */
+            strncpy(real_path, tmpbuffer, MAXPATHLEN);
+            real_path[MAXPATHLEN] = '\0';
+        }
+        else {
+            /* Interpret relatively */
+            reduce(real_path);
+            joinpath(real_path, tmpbuffer);
+        }
+        linklen = readlink(real_path, tmpbuffer, MAXPATHLEN);
+    }
+
+    return real_path;
+}
+#endif /* HAVE_READLINK */
+
+/*
+ * Calculate item 0 of sys.path from the Python script name.
+ * If the script name is NULL, do not insert an item 0.
+ * The special name "" means item 0 is "".
+ * For a real script name, try to generate an absolute path.
+*/
+static int
+get_sys_path_0(char *path)
+{
+    char *argv0 = Py_GetScriptName();
+    char copy[MAXPATHLEN+1];
+    char *p;
+
+    path[0] = '\0';
+    if (argv0 == NULL)	/* No sys.path[0] insertion */
+        return 0;
+
+    if (!argv0[0])	/* Insert "" as sys.path[0] */
+        return 1;
+
+#ifdef HAVE_READLINK
+    argv0 = get_path_from_symlink(argv0, copy);
+#endif /* HAVE_READLINK */
+
+    /* remove the filename from argv0 and only keep the pathname */
+    strncpy(path, argv0, MAXPATHLEN);
+    p = strrchr(path, SEP);
+    if (p == NULL) {		/* No separator at all */
+        path[0] = '\0';
+        getcwd(path, MAXPATHLEN);
+    }
+    else if (p == path) {	/* A single initial separator */
+        path[0] = SEP;
+        path[1] = '\0';
+    }
+    else {			/* Last separator occurs within the name */
+#ifdef macintosh
+        *(p + 1) = '\0';	/* Keep trailing separator */
+#else
+        *p = '\0';		/* Remove trailing separator */
+#endif
+        absolutize(path);
+    }
+    return 1;
+}
 
 static void
 calculate_path(void)
 {
-    extern char *Py_GetProgramName(void);
-
     static char delimiter[2] = {DELIM, '\0'};
     static char separator[2] = {SEP, '\0'};
     char *pythonpath = PYTHONPATH;
@@ -361,6 +434,9 @@
     char *path = getenv("PATH");
     char *prog = Py_GetProgramName();
     char argv0_path[MAXPATHLEN+1];
+    char zip_path[MAXPATHLEN+1];
+    char syspath0[MAXPATHLEN+1];
+    int have_syspath0;
     int pfound, efound; /* 1 if found; -1 if found build directory */
     char *buf;
     size_t bufsz;
@@ -444,24 +520,7 @@
 #endif
 
 #if HAVE_READLINK
-    {
-        char tmpbuffer[MAXPATHLEN+1];
-        int linklen = readlink(progpath, tmpbuffer, MAXPATHLEN);
-        while (linklen != -1) {
-            /* It's not null terminated! */
-            tmpbuffer[linklen] = '\0';
-            if (tmpbuffer[0] == SEP)
-                /* tmpbuffer should never be longer than MAXPATHLEN,
-                   but extra check does not hurt */
-                strncpy(argv0_path, tmpbuffer, MAXPATHLEN);
-            else {
-                /* Interpret relative to progpath */
-                reduce(argv0_path);
-                joinpath(argv0_path, tmpbuffer);
-            }
-            linklen = readlink(argv0_path, tmpbuffer, MAXPATHLEN);
-        }
-    }
+    get_path_from_symlink(progpath, argv0_path);
 #endif /* HAVE_READLINK */
 
     reduce(argv0_path);
@@ -479,6 +538,17 @@
     else
         reduce(prefix);
 
+    strncpy(zip_path, prefix, MAXPATHLEN);
+    zip_path[MAXPATHLEN] = '\0';
+    if (pfound == 0) { /* Use the reduced prefix returned by Py_GetPrefix() */
+        strncpy(zip_path, PREFIX, MAXPATHLEN);
+        zip_path[MAXPATHLEN] = '\0';
+    }
+    joinpath(zip_path, "python00.zip");
+    bufsz = strlen(zip_path);	/* Replace "00" with version */
+    zip_path[bufsz - 6] = VERSION[0];
+    zip_path[bufsz - 5] = VERSION[2];
+
     if (!(efound = search_for_exec_prefix(argv0_path, home))) {
         if (!Py_FrozenFlag)
             fprintf(stderr,
@@ -496,6 +566,10 @@
      */
     bufsz = 0;
 
+    have_syspath0 = get_sys_path_0(syspath0);
+    if (have_syspath0)
+        bufsz += strlen(syspath0) + 1;
+
     if (rtpypath)
         bufsz += strlen(rtpypath) + 1;
 
@@ -517,6 +591,7 @@
         defpath = delim + 1;
     }
 
+    bufsz += strlen(zip_path) + 1;
     bufsz += strlen(exec_prefix) + 1;
 
     /* This is the only malloc call in this file */
@@ -536,6 +611,16 @@
         }
         else
             buf[0] = '\0';
+
+        /* Next is syspath0 calculated from the script name */
+        if (have_syspath0) {
+                strcat(buf, syspath0);
+                strcat(buf, delimiter);
+        }
+
+        /* Next is the default zip path */
+        strcat(buf, zip_path);
+        strcat(buf, delimiter);
 
         /* Next goes merge of compile-time $PYTHONPATH with
          * dynamically located prefix.
Index: Modules/main.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/main.c,v
retrieving revision 1.70
diff -w -u -r1.70 main.c
--- Modules/main.c	17 Oct 2002 20:37:50 -0000	1.70
+++ Modules/main.c	29 Nov 2002 18:33:55 -0000
@@ -339,7 +339,10 @@
 		/* Leave stderr alone - it should be unbuffered anyway. */
   	}
 
+	/* Py_SetProgramName/Py_SetScriptName for use by Py_GetPath() */
 	Py_SetProgramName(argv[0]);
+	if (filename)
+		Py_SetScriptName(filename);
 	Py_Initialize();
 
 	if (Py_VerboseFlag ||
Index: Objects/classobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/classobject.c,v
retrieving revision 2.164
diff -w -u -r2.164 classobject.c
--- Objects/classobject.c	29 Oct 2002 18:36:40 -0000	2.164
+++ Objects/classobject.c	29 Nov 2002 18:33:56 -0000
@@ -745,7 +745,7 @@
 		args = Py_BuildValue("(OO)", inst, name);
 		if (args == NULL)
 			return NULL;
-		res = PyEval_CallObject(func, args);
+		res = PyObject_Call(func, args, NULL);
 		Py_DECREF(args);
 	}
 	return res;
@@ -823,7 +823,7 @@
 		args = Py_BuildValue("(OOO)", inst, name, v);
 	if (args == NULL)
 		return -1;
-	res = PyEval_CallObject(func, args);
+	res = PyObject_Call(func, args, NULL);
 	Py_DECREF(args);
 	if (res == NULL)
 		return -1;
@@ -1013,7 +1013,7 @@
 		Py_DECREF(func);
 		return NULL;
 	}
-	res = PyEval_CallObject(func, arg);
+	res = PyObject_Call(func, arg, NULL);
 	Py_DECREF(func);
 	Py_DECREF(arg);
 	return res;
@@ -1046,7 +1046,7 @@
 		Py_DECREF(func);
 		return -1;
 	}
-	res = PyEval_CallObject(func, arg);
+	res = PyObject_Call(func, arg, NULL);
 	Py_DECREF(func);
 	Py_DECREF(arg);
 	if (res == NULL)
@@ -1076,7 +1076,7 @@
 		Py_DECREF(func);
 		return NULL;
 	}
-	res = PyEval_CallObject(func, arg);
+	res = PyObject_Call(func, arg, NULL);
 	Py_DECREF(func);
 	Py_DECREF(arg);
 	return res;
@@ -1131,7 +1131,7 @@
 		Py_DECREF(func);
 		return NULL;
 	}
-	res = PyEval_CallObject(func, arg);
+	res = PyObject_Call(func, arg, NULL);
 	Py_DECREF(func);
 	Py_DECREF(arg);
 	return res;
@@ -1162,7 +1162,7 @@
 		Py_DECREF(func);
 		return -1;
 	}
-	res = PyEval_CallObject(func, arg);
+	res = PyObject_Call(func, arg, NULL);
 	Py_DECREF(func);
 	Py_DECREF(arg);
 	if (res == NULL)
@@ -1223,7 +1223,7 @@
 		Py_DECREF(func);
 		return -1;
 	}
-	res = PyEval_CallObject(func, arg);
+	res = PyObject_Call(func, arg, NULL);
 	Py_DECREF(func);
 	Py_DECREF(arg);
 	if (res == NULL)
@@ -1256,7 +1256,7 @@
 			Py_DECREF(func);
 			return -1;
 		}
-		res = PyEval_CallObject(func, arg);
+		res = PyObject_Call(func, arg, NULL);
 		Py_DECREF(func);
 		Py_DECREF(arg);
 		if(res == NULL)
@@ -1321,7 +1321,7 @@
 		Py_DECREF(func);
 		return NULL;
 	}
-	result = PyEval_CallObject(func, args);
+	result = PyObject_Call(func, args, NULL);
 	Py_DECREF(args);
 	Py_DECREF(func);
 	return result;
@@ -1364,7 +1364,7 @@
 		Py_DECREF(coercefunc);
 		return NULL;
 	}
-	coerced = PyEval_CallObject(coercefunc, args);
+	coerced = PyObject_Call(coercefunc, args, NULL);
 	Py_DECREF(args);
 	Py_DECREF(coercefunc);
 	if (coerced == NULL) {
@@ -1448,7 +1448,7 @@
 	if (args == NULL) {
 		return -1;
 	}
-	coerced = PyEval_CallObject(coercefunc, args);
+	coerced = PyObject_Call(coercefunc, args, NULL);
 	Py_DECREF(args);
 	Py_DECREF(coercefunc);
 	if (coerced == NULL) {
@@ -1563,7 +1563,7 @@
 		return -2;
 	}
 
-	result = PyEval_CallObject(cmp_func, args);
+	result = PyObject_Call(cmp_func, args, NULL);
 	Py_DECREF(args);
 	Py_DECREF(cmp_func);
 
@@ -1722,7 +1722,7 @@
 			Py_DECREF(func);
 			return NULL;
 		}
-		result = PyEval_CallObject(func, args);
+		result = PyObject_Call(func, args, NULL);
 		Py_DECREF(func);
 		Py_DECREF(args);
 		return result;
@@ -1761,7 +1761,7 @@
 			Py_DECREF(func);
 			return NULL;
 		}
-		result = PyEval_CallObject(func, args);
+		result = PyObject_Call(func, args, NULL);
 		Py_DECREF(func);
 		Py_DECREF(args);
 		return result;
@@ -1835,7 +1835,7 @@
 		return NULL;
 	}
 
-	res = PyEval_CallObject(method, args);
+	res = PyObject_Call(method, args, NULL);
 	Py_DECREF(args);
 	Py_DECREF(method);
 
Index: Objects/descrobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/descrobject.c,v
retrieving revision 2.31
diff -w -u -r2.31 descrobject.c
--- Objects/descrobject.c	31 Aug 2002 15:51:04 -0000	2.31
+++ Objects/descrobject.c	29 Nov 2002 18:33:56 -0000
@@ -206,7 +206,7 @@
 		Py_DECREF(func);
 		return NULL;
 	}
-	result = PyEval_CallObjectWithKeywords(func, args, kwds);
+	result = PyObject_Call(func, args, kwds);
 	Py_DECREF(args);
 	Py_DECREF(func);
 	return result;
@@ -249,7 +249,7 @@
 		Py_DECREF(func);
 		return NULL;
 	}
-	result = PyEval_CallObjectWithKeywords(func, args, kwds);
+	result = PyObject_Call(func, args, kwds);
 	Py_DECREF(args);
 	Py_DECREF(func);
 	return result;
Index: Objects/fileobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/fileobject.c,v
retrieving revision 2.170
diff -w -u -r2.170 fileobject.c
--- Objects/fileobject.c	21 Nov 2002 23:52:35 -0000	2.170
+++ Objects/fileobject.c	29 Nov 2002 18:33:58 -0000
@@ -1184,7 +1184,7 @@
 			Py_DECREF(reader);
 			return NULL;
 		}
-		result = PyEval_CallObject(reader, args);
+		result = PyObject_Call(reader, args, NULL);
 		Py_DECREF(reader);
 		Py_DECREF(args);
 		if (result != NULL && !PyString_Check(result)) {
@@ -2015,7 +2015,7 @@
 		Py_DECREF(writer);
 		return -1;
 	}
-	result = PyEval_CallObject(writer, args);
+	result = PyObject_Call(writer, args, NULL);
 	Py_DECREF(args);
 	Py_DECREF(value);
 	Py_DECREF(writer);
Index: Python/bltinmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v
retrieving revision 2.266
diff -w -u -r2.266 bltinmodule.c
--- Python/bltinmodule.c	26 Oct 2002 14:39:10 -0000	2.266
+++ Python/bltinmodule.c	29 Nov 2002 18:33:58 -0000
@@ -1414,7 +1414,7 @@
 		else {
 			PyTuple_SetItem(args, 0, result);
 			PyTuple_SetItem(args, 1, op2);
-			if ((result = PyEval_CallObject(func, args)) == NULL)
+			if ((result = PyObject_Call(func, args, NULL)) == NULL)
 				goto Fail;
 		}
 	}
@@ -1847,7 +1847,7 @@
 			PyObject *arg = Py_BuildValue("(O)", item);
 			if (arg == NULL)
 				goto Fail_1;
-			good = PyEval_CallObject(func, arg);
+			good = PyObject_Call(func, arg, NULL);
 			Py_DECREF(arg);
 			if (good == NULL)
 				goto Fail_1;
@@ -1901,7 +1901,7 @@
 			Py_DECREF(item);
 			goto Fail_1;
 		}
-		good = PyEval_CallObject(func, arg);
+		good = PyObject_Call(func, arg, NULL);
 		Py_DECREF(arg);
 		if (good == NULL) {
 			Py_DECREF(item);
Index: Python/errors.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/errors.c,v
retrieving revision 2.74
diff -w -u -r2.74 errors.c
--- Python/errors.c	4 Oct 2002 00:13:02 -0000	2.74
+++ Python/errors.c	29 Nov 2002 18:34:00 -0000
@@ -170,7 +170,7 @@
 
 			if (args == NULL)
 				goto finally;
-			res = PyEval_CallObject(type, args);
+			res = PyObject_Call(type, args, NULL);
 			Py_DECREF(args);
 			if (res == NULL)
 				goto finally;
@@ -625,7 +625,7 @@
 		args = Py_BuildValue("(sO)", message, category);
 		if (args == NULL)
 			return -1;
-		res = PyEval_CallObject(func, args);
+		res = PyObject_Call(func, args, NULL);
 		Py_DECREF(args);
 		if (res == NULL)
 			return -1;
@@ -664,7 +664,7 @@
 				     filename, lineno, module, registry);
 		if (args == NULL)
 			return -1;
-		res = PyEval_CallObject(func, args);
+		res = PyObject_Call(func, args, NULL);
 		Py_DECREF(args);
 		if (res == NULL)
 			return -1;
Index: Python/import.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/import.c,v
retrieving revision 2.210
diff -w -u -r2.210 import.c
--- Python/import.c	31 Aug 2002 15:16:14 -0000	2.210
+++ Python/import.c	29 Nov 2002 18:34:01 -0000
@@ -88,6 +88,73 @@
 /* these tables define the module suffixes that Python recognizes */
 struct filedescr * _PyImport_Filetab = NULL;
 
+static struct filedescr fd_frozen = {"", "", PY_FROZEN};
+static struct filedescr fd_builtin = {"", "", C_BUILTIN};
+static struct filedescr fd_package = {"", "", PKG_DIRECTORY};
+static struct filedescr fd_zip = {"", "", PY_ZIPFILE};
+
+static struct stZipSearchOrder {
+	char suffix[16];
+	int type;
+} ZipSearchOrder[] = {
+	{"/__init__.pyc", PKG_DIRECTORY},
+	{"/__init__.pyo", PKG_DIRECTORY},
+	{"/__init__.py", PKG_DIRECTORY},
+	{".pyc", PY_ZIPFILE},
+	{".pyo", PY_ZIPFILE},
+	{".py", PY_ZIPFILE},
+	{"", 0}
+};
+
+#define PY_IMP_NO_VALUE		0
+#define PY_IMP_BUILTIN		1
+#define PY_IMP_FROZEN		2
+#define PY_IMP_LISTDIR		3
+#define PY_IMP_NO_LISTDIR	4
+#define PY_IMP_FILE		5
+#define PY_IMP_ZIP		6
+
+#define ZIP_LEN			4	/* length of suffix ".zip" */
+
+#define PY_CACHE_USING_OS_LISTDIR	1
+static int use_os_listdir = 0;	/* use a cached os.listdir() */
+
+static PyObject *ExternalNames = NULL;
+static PyObject *InternalNames = NULL;
+static void get_internal_names(void);
+static struct filedescr *search_using_fopen(char *, char *,
+					size_t, size_t, FILE **, PyObject *);
+
+/*
+  Import dictionary entries have values of int or tuple.  An int value
+  must be one of the PY_IMP_ constants.  For a sequence, the first item
+  of the sequence must be one of the PY_IMP_ constants.
+
+  InternalNames is a dictionary: keys are the names of all builtin and
+  frozen modules, value is PY_IMP_BUILTIN or PY_IMP_FROZEN.  It is
+  used to speed up searching for internal modules.
+
+  ExternalNames is a dictionary used to speed up imports.  Keys are:
+    Names of zip archive files; value is PY_IMP_ZIP.
+       For example, /A/B/python22.zip.
+    Names of items in sys.path; values are:
+       PY_IMP_ZIP:     The string ".zip" appears in the sys.path item.
+         For example, /A/B/python22.zip, /A/B/python22.zip/LibFoo.
+       PY_IMP_LISTDIR: A directory; use os.listdir() to record contents.
+         For example, /A/B/C.
+       PY_IMP_NO_LISTDIR: os.listdir() is not available.
+         For example, /A/B/C.
+    Names of files in the zip archive joined with the zip archive name.
+       For example, /usr/lib/python22.zip/Dir/mymodule.py.
+       Zip paths are always spelled with SEP instead of '/'.
+       The value is a tuple, and the first item is PY_IMP_ZIP.
+    Names of files in the directory joined with the directory name.
+       Names are returned using os.listdir().
+       For example, /A/B/C/jim.pyc
+       The value is PY_IMP_FILE.
+  If os.listdir() is not available, the directory entries are absent.
+*/
+
 #ifdef RISCOS
 static const struct filedescr _PyImport_StandardFiletab[] = {
 	{"/py", "U", PY_SOURCE},
@@ -150,6 +217,29 @@
 		   code created in normal operation mode. */
 		pyc_magic = MAGIC + 1;
 	}
+
+	if (ExternalNames)
+		PyDict_Clear(ExternalNames);
+	else
+		ExternalNames = PyDict_New();
+	if (InternalNames)
+		PyDict_Clear(InternalNames);
+	else
+		InternalNames = PyDict_New();
+
+	ZipSearchOrder[0].suffix[0] = SEP;  /* Correct directory separator */
+	ZipSearchOrder[1].suffix[0] = SEP;
+	ZipSearchOrder[2].suffix[0] = SEP;
+	if (Py_OptimizeFlag) {	/* Reverse *.pyc and *.pyo */
+		struct stZipSearchOrder zso;
+		zso = ZipSearchOrder[0];
+		ZipSearchOrder[0] = ZipSearchOrder[1];
+		ZipSearchOrder[1] = zso;
+		zso = ZipSearchOrder[3];
+		ZipSearchOrder[3] = ZipSearchOrder[4];
+		ZipSearchOrder[4] = zso;
+	}
+	get_internal_names();
 }
 
 void
@@ -159,6 +249,10 @@
 	extensions = NULL;
 	PyMem_DEL(_PyImport_Filetab);
 	_PyImport_Filetab = NULL;
+	Py_XDECREF(ExternalNames);
+	ExternalNames = NULL;
+	Py_XDECREF(InternalNames);
+	InternalNames = NULL;
 }
 
 
@@ -229,6 +323,583 @@
 #endif
 }
 
+/* Helper functions to import from zip archives */
+
+void _PyImport_InitZip()
+{
+	PyObject *zlib = PyImport_ImportModule("zlib");
+	if (zlib)
+		Py_DECREF(zlib);
+	else
+		PyErr_Clear();
+	if (Py_VerboseFlag)
+		PySys_WriteStderr("# PyImport_InitZip: zlib %s\n",
+			zlib == NULL ? "UNAVAILABLE" : "available");
+
+#if PY_CACHE_USING_OS_LISTDIR
+	{
+	PyObject *v, *vv;
+	v = PyImport_ImportModule("os");
+	vv = NULL;
+	if (v && (vv = PyObject_GetAttrString(v, "listdir")) != NULL) {
+		if (Py_VerboseFlag)
+			PySys_WriteStderr("Import os.listdir() succeeds\n");
+		use_os_listdir = 1;	/* os.listdir() is available */
+	}
+	else {
+		if (Py_VerboseFlag)
+			PySys_WriteStderr("Import os.listdir() fails\n");
+		PyErr_Clear();
+	}
+	Py_XDECREF(vv);
+	Py_XDECREF(v);
+	}
+#endif
+}
+
+static void
+get_internal_names()
+{
+	int i;
+	PyObject *v;
+	struct _frozen *pFrozen;
+
+	if (!InternalNames)
+		return;
+
+	PyDict_Clear(InternalNames);
+
+	/* Add frozen module names to the import dictionary */
+	v = PyInt_FromLong(PY_IMP_FROZEN);
+	for (pFrozen = PyImport_FrozenModules; pFrozen->name; pFrozen++)
+	    PyDict_SetItemString(InternalNames, pFrozen->name, v);
+	Py_DECREF(v);
+
+	/* Add builtin module names to the import dictionary */
+	v = PyInt_FromLong(PY_IMP_BUILTIN);
+	for (i = 0; PyImport_Inittab[i].name; i++)
+	    PyDict_SetItemString(InternalNames, PyImport_Inittab[i].name, v);
+	Py_DECREF(v);
+}
+
+/* Return TRUE if path is a relative (non-absolute) path */
+static int
+relative_path(char *path)
+{
+	/* zero-length string is current dir */
+	if (path[0] == '\0')	
+		return 1;
+
+#ifdef macintosh
+	return !strchr(path, ':') || path[0] == ':';
+#else
+	/* Windows has a drive letter */
+	if (SEP == '\\')	
+		return !(path[1] == ':' && (path[2] == SEP
+#ifdef ALTSEP
+			|| path[2] == ALTSEP
+#endif
+			));
+	return path[0] != SEP;
+#endif
+}
+
+/* return one of the PY_IMP_ constants for the import dictionary path */
+static int
+get_path_type(PyObject *dict, char *path)
+{ 
+	PyObject *pyobj;
+	int i;
+
+	assert(dict != NULL);
+	pyobj = PyDict_GetItemString(dict, path);
+	if (!pyobj)
+		return PY_IMP_NO_VALUE;
+
+	if (PyInt_Check(pyobj))
+		return (int)PyInt_AS_LONG(pyobj);
+
+	i = PY_IMP_NO_VALUE;
+	if (PySequence_Check(pyobj)) {
+		pyobj = PySequence_GetItem(pyobj, 0);
+		if (pyobj && PyInt_Check(pyobj))
+			i = (int)PyInt_AsLong(pyobj);
+		Py_XDECREF(pyobj);
+	}
+
+	return i;
+}
+
+/* Read the directory names and add to ExternalNames */
+static void
+add_directory_names(char *path)
+{
+	PyObject *v, *modules, *modOS, *pyList, *func, *args, *pyFile;
+	long count, i, length;
+	char name[MAXPATHLEN + 5];
+	char *filename;
+
+	/* Make sure we haven't already seen this directory */
+	if (get_path_type(ExternalNames, path) == PY_IMP_LISTDIR)
+		return;	
+
+	v = PyInt_FromLong(PY_IMP_LISTDIR);
+	PyDict_SetItemString(ExternalNames, path, v);
+	Py_DECREF(v);
+
+	modules = PyImport_GetModuleDict();
+	if (!modules)
+		return;
+
+	modOS = PyDict_GetItemString(modules, "os");
+	if (!modOS)
+		return;
+
+	func = PyObject_GetAttrString(modOS, "listdir");
+        if (!func)
+		return;
+
+	args = Py_BuildValue("(s)", path);
+	pyList = PyObject_Call(func, args, NULL);
+	Py_DECREF(args);
+	Py_DECREF(func);
+
+	if (!pyList || !PyList_Check(pyList)) {
+		PyErr_Clear();
+		if (Py_VerboseFlag)
+			PySys_WriteStderr("# directory:"
+					  " ADD 0 names from %s\n", path);
+		return;
+	}
+
+	count = PyList_Size(pyList);
+	if (Py_VerboseFlag)
+		PySys_WriteStderr("# directory:"
+				  " ADD %ld names from %s\n", count, path);
+	strncpy(name, path, MAXPATHLEN);
+	name[MAXPATHLEN] = '\0';
+	length = strlen(name);
+	if (length < MAXPATHLEN && name[length - 1] != SEP
+#ifdef ALTSEP
+		&& name[length - 1] != ALTSEP
+#endif
+		)
+        		name[length++] = SEP;
+	pyFile = PyInt_FromLong(PY_IMP_FILE);
+	for (i = 0; i < count; i++) {
+		filename = PyString_AsString(PyList_GET_ITEM(pyList, i));
+		if (!filename) {
+			Py_DECREF(pyFile);
+			Py_DECREF(pyList);
+			return;
+		}
+
+		/* Join member name to archive name */
+		strncpy(name + length, filename, MAXPATHLEN - length);
+		name[MAXPATHLEN] = '\0';
+		PyDict_SetItemString(ExternalNames, name, pyFile);
+	}
+	Py_DECREF(pyFile);
+	Py_DECREF(pyList);
+}
+
+/* Read all zip archive names and add to ExternalNames */
+/* Return 1 if path is a zip archive, else 0 */
+static int
+add_zip_names(char *path)
+{
+	PyObject *pyTuple, *pyZip;
+	FILE *fp = NULL;
+	long compress, crc, data_size, file_size, file_offset, date, time;
+	long header_offset, name_size, header_size;
+	long i, l, length, count;
+	char archive[MAXPATHLEN + 5];
+	char zipname[MAXPATHLEN + 5];
+	char ch, *pt;
+
+	/* The "path" is an item of sys.path.  We need to extract the zip
+	   file name and read the contents of the archive.
+	   Indicate that we have already seen this item by creating a
+	   dictionary entry for the path.
+	*/
+	l = (long)strlen(path) - ZIP_LEN;
+	length = 0;
+	for (i = 1; i <= l; i++)
+		if (memcmp(path + i, ".zip", ZIP_LEN) == 0 &&
+		    ((ch = path[i+4]) == SEP ||
+#ifdef ALTSEP
+		    ch == ALTSEP ||
+#endif
+		    ch == 0)) {
+			length = i + ZIP_LEN;
+			strncpy(archive, path, length);
+			archive[length] = '\0';
+			break;
+	
+		}
+	/* make sure .zip found */
+	if (!length)
+		return 0;
+
+#ifdef ALTSEP
+	/* only use SEP in zip names, convert all the ALTSEPs */
+	for (i = 0; i < length; i++)
+		if (archive[i] == ALTSEP)
+			archive[i] = SEP;
+#endif
+
+	pyZip = PyInt_FromLong(PY_IMP_ZIP);
+	if (!pyZip)
+		return 0;
+
+	/* "archive" is now the path up to and including ".zip" */
+	if (PyDict_GetItemString(ExternalNames, archive)) {
+		PyDict_SetItemString(ExternalNames, path, pyZip);
+		goto cleanup;	/* We have already seen this archive */
+	}
+	else {
+		PyDict_SetItemString(ExternalNames, path, pyZip);
+		PyDict_SetItemString(ExternalNames, archive, pyZip);
+	}
+
+	fp = fopen(archive, "rb");
+	if (!fp)	/* Not an error; no such file */
+		goto cleanup;
+	if (fseek(fp, -22, SEEK_END) < 0)
+		goto cleanup;
+	/* check for End of Central Dir signature */
+	if (PyMarshal_ReadLongFromFile(fp) != 0x06054B50)
+		goto cleanup;
+	if (fseek(fp, -6, SEEK_END) < 0)
+		goto cleanup;
+
+	header_offset = PyMarshal_ReadLongFromFile(fp);
+	/* Start of Central Directory */
+	length = (long)strlen(archive);
+	count = 0;
+	while (1) {
+		if (fseek(fp, header_offset, SEEK_SET) < 0)
+			goto cleanup;
+
+		l = PyMarshal_ReadLongFromFile(fp);
+		if (l != 0x02014B50)
+			break;	/* Bad: Central Dir File Header */
+		if (fseek(fp, header_offset + 10, SEEK_SET) < 0)
+			goto cleanup;
+
+		compress = PyMarshal_ReadShortFromFile(fp);
+		time = PyMarshal_ReadShortFromFile(fp);
+		date = PyMarshal_ReadShortFromFile(fp);
+		crc = PyMarshal_ReadLongFromFile(fp);
+		data_size = PyMarshal_ReadLongFromFile(fp);
+		file_size = PyMarshal_ReadLongFromFile(fp);
+		name_size = PyMarshal_ReadShortFromFile(fp);
+		header_size = 46 + name_size +
+				PyMarshal_ReadShortFromFile(fp) +
+				PyMarshal_ReadShortFromFile(fp);
+
+		if (fseek(fp, header_offset + 42, SEEK_SET) < 0)
+			goto cleanup;
+		file_offset = PyMarshal_ReadLongFromFile(fp);
+		if (name_size > MAXPATHLEN)
+			name_size = MAXPATHLEN;
+
+		/* Unicode:  zipname should work even if sizeof(char) > 1 */
+		pt = zipname;
+		*pt++ = SEP;	/* Add an initial '/' */
+
+		/* FIXME: this could be a perf problem (read char 1 by 1) */
+		for (i = 0; i < name_size; i++) {
+			ch = (char)getc(fp);
+			/* Must change '/' to SEP in archive */
+			if (ch == '/' || ch == '\\') {
+				if (i > 0)	/* Remove an initial '/' */
+					*pt++ = SEP;
+			}
+			else
+				*pt++ = ch;
+		}
+		*pt = '\0';
+
+		header_offset += header_size;
+		/* Check to make sure the local file header is correct */
+		if (fseek(fp, file_offset, SEEK_SET) < 0)
+			goto cleanup;
+		l = PyMarshal_ReadLongFromFile(fp);
+		if (l != 0x04034B50)
+			continue;	/* Bad: Local File Header */
+		if (fseek(fp, file_offset + 26, SEEK_SET) < 0)
+			goto cleanup;
+
+		/* get local header size */
+		file_offset += 30 + PyMarshal_ReadShortFromFile(fp) +
+				    PyMarshal_ReadShortFromFile(fp);
+
+		/* end the archive with .zip again */
+		archive[length] = '\0';
+
+		/* Record zip archive data for this file name */
+		pyTuple = PyTuple_New(6);
+		if (!pyTuple)
+			goto cleanup;
+
+		PyTuple_SetItem(pyTuple, 0, pyZip);
+		PyTuple_SetItem(pyTuple, 1, PyString_FromString(archive));
+		PyTuple_SetItem(pyTuple, 2, PyInt_FromLong(compress));
+		PyTuple_SetItem(pyTuple, 3, PyInt_FromLong(data_size));
+		PyTuple_SetItem(pyTuple, 4, PyInt_FromLong(file_size));
+		PyTuple_SetItem(pyTuple, 5, PyInt_FromLong(file_offset));
+
+		/* Join member name to archive name */
+		strncpy(archive + length, zipname, MAXPATHLEN - length);
+		archive[MAXPATHLEN] = '\0';
+		PyDict_SetItemString(ExternalNames, archive, pyTuple);
+		Py_DECREF(pyTuple);
+		count++;
+	}
+
+	if (Py_VerboseFlag)
+		PySys_WriteStderr("# zip import: add %ld names from %s\n",
+				  count, archive);
+
+cleanup:
+	if (fp)
+		fclose(fp);
+	Py_DECREF(pyZip);
+	return 1;
+}
+
+/* return true if an error occurred */
+static int
+get_int_from_tuple(PyObject *tuple, size_t index, long *value)
+{
+	*value = PyInt_AsLong(PyTuple_GET_ITEM(tuple, index));
+	return *value == -1 && PyErr_Occurred();
+}
+
+/* Return the string from the zip archive */
+static PyObject *
+get_zip_string(char *name)
+{
+	PyObject *modules, *mZlib, *pyTuple, *deobj;
+	PyObject *pyData, *pyFile1, *pyFile2, *method, *decomp, *args;
+	int nerr;
+	long compress, data_size, file_size, file_offset;
+	char *archive, *data;
+	FILE *fp;
+
+	/* This function must set its own errors if it returns NULL */
+	pyTuple = PyDict_GetItemString(ExternalNames, name);
+	if (!pyTuple || !PyTuple_Check(pyTuple)) {
+		PyErr_Format(PyExc_ValueError,
+		   "Zip import: no data for %s", name);
+		return NULL;
+	}
+
+	archive = PyString_AsString(PyTuple_GET_ITEM(pyTuple, 1));
+	if (!archive)
+		return NULL;
+	if (get_int_from_tuple(pyTuple, 2, &compress) ||
+	    get_int_from_tuple(pyTuple, 3, &data_size) ||
+	    get_int_from_tuple(pyTuple, 4, &file_size) ||
+	    get_int_from_tuple(pyTuple, 5, &file_offset))
+		return NULL;
+
+	fp = fopen(archive, "rb");
+	if (!fp) {
+		PyErr_Format(PyExc_IOError,
+		   "Zip import: can not open file %s", archive);
+		return NULL;
+	}
+
+	data = (char *) PyMem_Malloc(data_size);
+	if (fseek(fp, file_offset, SEEK_SET) < 0 ||
+	    fread(data, 1, data_size, fp) != data_size) {
+		PyErr_Format(PyExc_IOError,
+		   	"Zip import: error reading file %s: %s",
+		   	archive, strerror(errno));
+		fclose(fp);
+		PyMem_Free(data);
+		return NULL;
+	}
+	fclose(fp);
+
+	pyData = PyString_FromStringAndSize(data, data_size);
+	PyMem_Free(data);
+	if (!pyData)
+		return NULL;
+
+	if (!compress)
+		return pyData;
+
+	/* Uncompress with zlib */
+	modules = PyImport_GetModuleDict();
+	if (!modules ||
+	    (mZlib = PyDict_GetItemString(modules, "zlib")) == NULL) {
+		Py_DECREF(pyData);
+		PyErr_Format(PyExc_ImportError,
+		   "Zip import: missing zlib, can not decompress %s", name);
+		return NULL;
+	}
+
+/* We would prefer to use zlib.decompress(), but it sometimes returns -5 */
+	decomp = method = NULL;
+	deobj = PyObject_GetAttrString(mZlib, "decompressobj");
+	if (!deobj) {
+		nerr = 1;
+		goto error;
+	}
+
+	args = Py_BuildValue("(l)", -15L);
+	decomp = PyObject_Call(deobj, args, NULL);
+	Py_DECREF(args);
+	if (!decomp) {
+		nerr = 2;
+		goto error;
+	}
+
+	method = PyObject_GetAttrString(decomp, "decompress");
+	if (!method) {
+		nerr = 3;
+		goto error;
+	}
+	args = PyTuple_New(1);
+	if (!args) {
+		nerr = 4;
+		goto error;
+	}
+
+	PyTuple_SetItem(args, 0, pyData);
+	pyData = NULL;
+	pyFile1 = PyObject_Call(method, args, NULL);
+	if (!pyFile1 || !PyString_Check(pyFile1)) {
+		Py_DECREF(args);
+		nerr = 5;
+		goto error;
+	}
+
+	pyFile2 = PyObject_Call(method, args, NULL);
+	while(pyFile2 && PyString_Check(pyFile2) && PyString_Size(pyFile2)) {
+		PyString_ConcatAndDel(&pyFile1, pyFile2);
+		pyFile2 = PyObject_Call(method, args, NULL);
+	}
+
+	Py_XDECREF(pyFile2);
+	Py_DECREF(args);
+	Py_DECREF(method);
+	Py_DECREF(decomp);
+	Py_DECREF(deobj);
+	deobj = decomp = method = NULL;
+
+	if (pyFile1 && PyString_Check(pyFile1) &&
+	    PyString_Size(pyFile1) == file_size)
+		return pyFile1;
+
+	Py_XDECREF(pyFile1);
+	nerr = 6;
+
+error:
+	Py_XDECREF(method);
+	Py_XDECREF(decomp);
+	Py_XDECREF(deobj);
+	Py_XDECREF(pyData);
+	PyErr_Format(PyExc_ImportError,
+	   "Zip import: failure %d in decompressing %s", nerr, name);
+	return NULL;
+}
+
+static PyObject *
+load_zip_source_module(char *name, char *pathname)
+{
+	PyObject *pyStr, *m;
+	PyCodeObject *code;
+	node *n;
+	char *pt;
+
+	/* pathname ends in ".py" */
+	pyStr = get_zip_string(pathname);
+	if (pyStr == NULL)
+		return NULL;
+	pt = PyString_AsString(pyStr);
+	n = PyParser_SimpleParseString(pt, Py_file_input);
+	if (n == NULL) {
+		Py_DECREF(pyStr);
+		return NULL;
+	}
+	code = PyNode_Compile(n, pathname);
+	PyNode_Free(n);
+	if (code == NULL) {
+		Py_DECREF(pyStr);
+		return NULL;
+	}
+	if (Py_VerboseFlag)
+		PySys_WriteStderr("import %s # source from zip %s\n",
+			name, pathname);
+	m = PyImport_ExecCodeModuleEx(name, (PyObject *)code, pathname);
+	Py_DECREF(code);
+	Py_DECREF(pyStr);
+
+	return m;
+}
+
+static PyObject *
+load_zip_module(char *name, char *pathname)
+{
+	int size;
+	PyObject *pyStr, *m, *code;
+	unsigned char *pt;
+	char source[MAXPATHLEN];
+
+	/* pathname ends in ".py" or ".pyc" or ".pyo" */
+	size = (int)strlen(pathname);
+	if (size > 3 && strcmp(pathname + size - 3, ".py") == 0)
+		return load_zip_source_module(name, pathname);
+	pyStr = get_zip_string(pathname);
+	if (pyStr == NULL ||
+	    PyString_AsStringAndSize(pyStr, (char**)&pt, &size) < 0)
+		return NULL;
+
+	/* check for a bad magic # */
+	if (pt[0] != ( pyc_magic & 0xFF) ||
+	    pt[1] != ((pyc_magic >>  8) & 0xFF) ||
+	    pt[2] != ((pyc_magic >> 16) & 0xFF) ||
+	    pt[3] != ((pyc_magic >> 24) & 0xFF)) {
+		/* try to use the original .py file, if it exists */
+		strncpy(source, pathname, MAXPATHLEN);
+		source[strlen(pathname)-1] = '\0';
+		if (PyDict_GetItemString(ExternalNames, source)) {
+		    if (Py_VerboseFlag)
+			PySys_WriteStderr(
+				"Zip import: Bad magic number in %.200s;"
+				" trying source X.py\n", pathname);
+		    Py_DECREF(pyStr);
+		    return load_zip_source_module(name, source);
+		}
+		PyErr_Format(PyExc_ImportError,
+				"Bad magic number in %.200s", pathname);
+		Py_DECREF(pyStr);
+		return NULL;
+	}
+
+	code = PyMarshal_ReadObjectFromString(pt + 8, size - 8);
+	if (!code || !PyCode_Check(code)) {
+		Py_XDECREF(code);
+		PyErr_Format(PyExc_TypeError,
+			"zip compiled file %.200s is not a code object",
+			name);
+		Py_DECREF(pyStr);
+		return NULL;
+	}
+
+	m = PyImport_ExecCodeModuleEx(name, code, pathname);
+	Py_DECREF(code);
+	Py_DECREF(pyStr);
+	if (Py_VerboseFlag)
+		PySys_WriteStderr("import %s # precompiled from zip %s\n",
+				  name, pathname);
+	return m;
+}
+
 /* Helper for sys */
 
 PyObject *
@@ -808,7 +1479,7 @@
 static PyObject *load_module(char *, FILE *, char *, int);
 static struct filedescr *find_module(char *, PyObject *,
 				     char *, size_t, FILE **);
-static struct _frozen *find_frozen(char *name);
+static struct _frozen *find_frozen(const char *name);
 
 /* Load a package and return its module object WITH INCREMENTED
    REFERENCE COUNT */
@@ -898,23 +1569,12 @@
 find_module(char *realname, PyObject *path, char *buf, size_t buflen,
 	    FILE **p_fp)
 {
-	int i, npath;
+	int i, npath, path_type;
 	size_t len, namelen;
 	struct filedescr *fdp = NULL;
-	char *filemode;
+	struct stZipSearchOrder *zso;
 	FILE *fp = NULL;
-#ifndef RISCOS
-	struct stat statbuf;
-#endif
-	static struct filedescr fd_frozen = {"", "", PY_FROZEN};
-	static struct filedescr fd_builtin = {"", "", C_BUILTIN};
-	static struct filedescr fd_package = {"", "", PKG_DIRECTORY};
 	char name[MAXPATHLEN+1];
-#if defined(PYOS_OS2)
-	size_t saved_len;
-	size_t saved_namelen;
-	char *saved_buf = NULL;
-#endif
 
 	if (strlen(realname) > MAXPATHLEN) {
 		PyErr_SetString(PyExc_OverflowError,
@@ -942,21 +1602,19 @@
 		*/
 		path = NULL;
 #else
-		if (find_frozen(name) != NULL) {
-			strcpy(buf, name);
+		if (find_frozen(name) != NULL)
 			return &fd_frozen;
-		}
 		PyErr_Format(PyExc_ImportError,
 			     "No frozen submodule named %.200s", name);
 		return NULL;
 #endif
 	}
 	if (path == NULL) {
-		if (is_builtin(name)) {
+		switch(get_path_type(InternalNames, name)) {
+		case PY_IMP_BUILTIN:
 			strcpy(buf, name);
 			return &fd_builtin;
-		}
-		if ((find_frozen(name)) != NULL) {
+		case PY_IMP_FROZEN:
 			strcpy(buf, name);
 			return &fd_frozen;
 		}
@@ -977,6 +1635,7 @@
 	}
 	npath = PyList_Size(path);
 	namelen = strlen(name);
+	*p_fp = NULL;
 	for (i = 0; i < npath; i++) {
 		PyObject *copy = NULL;
 		PyObject *v = PyList_GetItem(path, i);
@@ -1002,6 +1661,25 @@
 			Py_XDECREF(copy);
 			continue; /* v contains '\0' */
 		}
+		path_type = get_path_type(ExternalNames, buf);
+		if (path_type == PY_IMP_NO_VALUE || path_type == PY_IMP_FILE) {
+			/* Zip imports may fail for relative paths */
+			if (add_zip_names(buf)) {
+				path_type = PY_IMP_ZIP;
+			}
+			else if (!use_os_listdir || relative_path(buf)) {
+			/* Do not cache directories for relative paths */
+				PyObject *vv;
+				vv = PyInt_FromLong(PY_IMP_NO_LISTDIR);
+				PyDict_SetItemString(ExternalNames, buf, vv);
+				Py_DECREF(vv);
+				path_type = PY_IMP_NO_LISTDIR;
+			}
+			else {
+				add_directory_names(buf);
+				path_type = PY_IMP_LISTDIR;
+			}
+		}
 #ifdef macintosh
 		/*
 		** Speedup: each sys.path item is interned, and
@@ -1026,6 +1704,8 @@
 			return &resfiledescr;
 		}
 #endif
+
+		/* join the module name to the path item */
 		if (len > 0 && buf[len-1] != SEP
 #ifdef ALTSEP
 		    && buf[len-1] != ALTSEP
@@ -1035,9 +1715,95 @@
 		strcpy(buf+len, name);
 		len += namelen;
 
+		switch(path_type) {	/* Search according to path type */
+		case PY_IMP_ZIP:	/* Path includes ".zip/" */
+#ifdef ALTSEP
+			{
+			size_t j;
+			/* Use only SEP in zip names, never ALTSEP */
+			for (j = 0; j < len; j++)
+				if (buf[j] == ALTSEP)
+					buf[j] = SEP;
+			}
+#endif
+			for (zso = ZipSearchOrder; zso->type; zso++) {
+				strcpy(buf+len, zso->suffix);
+				if (Py_VerboseFlag > 1)
+					PySys_WriteStderr("# trying %s\n", buf);
+				if (PyDict_GetItemString(ExternalNames, buf)) {
+					if (zso->type == PKG_DIRECTORY) {
+						buf[len] = '\0';
+						return &fd_package;
+					}
+					return &fd_zip;
+				}
+			}
+			break;
+		case PY_IMP_LISTDIR:  /* We have read the directory names */
+			if (PyDict_GetItemString(ExternalNames, buf)) {
+				/* Check for package directory */
+				add_directory_names(buf);
+				buf[len] = SEP;
+# define INIT "__init__.py"
+# define INIT_LEN 12
+				strcpy(buf+len+1, INIT);
+				if (get_path_type(ExternalNames, buf)) {
+					buf[len] = '\0';
+					return &fd_package;
+				}
+				/* Add 'o' or 'c' */
+				buf[len+INIT_LEN] = 'c';
+				if (Py_OptimizeFlag)
+					buf[len+INIT_LEN] = 'o';
+				buf[len+INIT_LEN+1] = '\0';
+# undef INIT
+# undef INIT_LEN
+				if (get_path_type(ExternalNames, buf)) {
+					buf[len] = 0;
+					return &fd_package;
+				}
+			}
+			/* Search the list of suffixes: .pyc, .pyd, ... */
+			for (fdp = _PyImport_Filetab; fdp->suffix; fdp++) {
+				strcpy(buf+len, fdp->suffix);
+				if (Py_VerboseFlag > 1)
+					PySys_WriteStderr("# trying %s\n", buf);
+				if (get_path_type(ExternalNames, buf) &&
+				    (fp = fopen(buf, fdp->mode)) != NULL) {
+					*p_fp = fp;
+					return fdp;
+				}
+			}
+			break;
+		default:	/* Not zip, no names: search using fopen() */
+			fdp = search_using_fopen(name, buf, len, namelen,
+						 p_fp, copy);
+			if (fdp)
+				return fdp;
+			break;
+		}  /* End of switch on path type */
+	}  /* End of loop on path items */
+	PyErr_Format(PyExc_ImportError, "No module named %.200s", name);
+	return NULL;
+}
+
+static struct filedescr *
+search_using_fopen(char *name, char *buf, size_t len, size_t namelen,
+		   FILE **p_fp, PyObject *copy)
+{
+	struct filedescr *fdp;
+	FILE *fp;
+	char *filemode;
+#if defined(PYOS_OS2)
+	size_t saved_len;
+	size_t saved_namelen;
+	char *saved_buf = NULL;
+#endif
+
 		/* Check for package import (buf holds a directory name,
 		   and there's an __init__ module in that directory */
 #ifdef HAVE_STAT
+	struct stat statbuf;
 		if (stat(buf, &statbuf) == 0 &&         /* it exists */
 		    S_ISDIR(statbuf.st_mode) &&         /* it's a directory */
 		    find_init_module(buf) &&            /* it has __init__.py */
@@ -1056,6 +1822,7 @@
 		}
 #endif
 #endif
+	fp = NULL;
 #ifdef macintosh
 		fdp = PyMac_FindModuleExtension(buf, &len, name);
 		if (fdp) {
@@ -1126,15 +1893,10 @@
 		}
 #endif
 		Py_XDECREF(copy);
-		if (fp != NULL)
-			break;
-	}
-	if (fp == NULL) {
-		PyErr_Format(PyExc_ImportError,
-			     "No module named %.200s", name);
-		return NULL;
-	}
 	*p_fp = fp;
+	if (fp == NULL)
+		return NULL;
+	else
 	return fdp;
 }
 
@@ -1520,6 +2282,10 @@
 		Py_INCREF(m);
 		break;
 
+	case PY_ZIPFILE:
+		m = load_zip_module(name, buf);
+		break;
+
 	default:
 		PyErr_Format(PyExc_ImportError,
 			     "Don't know how to import %.200s (type code %d)",
@@ -1569,7 +2335,7 @@
 /* Frozen modules */
 
 static struct _frozen *
-find_frozen(char *name)
+find_frozen(const char *name)
 {
 	struct _frozen *p;
 
@@ -1583,7 +2349,7 @@
 }
 
 static PyObject *
-get_frozen_object(char *name)
+get_frozen_object(const char *name)
 {
 	struct _frozen *p = find_frozen(name);
 	int size;
@@ -2576,6 +3342,7 @@
 	if (setint(d, "C_BUILTIN", C_BUILTIN) < 0) goto failure;
 	if (setint(d, "PY_FROZEN", PY_FROZEN) < 0) goto failure;
 	if (setint(d, "PY_CODERESOURCE", PY_CODERESOURCE) < 0) goto failure;
+	if (setint(d, "PY_ZIPFILE", PY_ZIPFILE) < 0) goto failure;
 
   failure:
 	;
@@ -2615,6 +3382,7 @@
 		memcpy(p, PyImport_Inittab, (i+1) * sizeof(struct _inittab));
 	PyImport_Inittab = our_copy = p;
 	memcpy(p+i, newtab, (n+1) * sizeof(struct _inittab));
+	get_internal_names();
 
 	return 0;
 }
Index: Python/importdl.h
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/importdl.h,v
retrieving revision 2.18
diff -w -u -r2.18 importdl.h
--- Python/importdl.h	26 Feb 2002 11:41:34 -0000	2.18
+++ Python/importdl.h	29 Nov 2002 18:34:01 -0000
@@ -16,7 +16,8 @@
 	PKG_DIRECTORY,
 	C_BUILTIN,
 	PY_FROZEN,
-	PY_CODERESOURCE /* Mac only */
+	PY_CODERESOURCE, /* Mac only */
+	PY_ZIPFILE
 };
 
 struct filedescr {
Index: Python/pythonrun.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/pythonrun.c,v
retrieving revision 2.169
diff -w -u -r2.169 pythonrun.c
--- Python/pythonrun.c	17 Nov 2002 17:52:44 -0000	2.169
+++ Python/pythonrun.c	29 Nov 2002 18:34:02 -0000
@@ -164,6 +164,7 @@
 	initsigs(); /* Signal handling stuff, including initintr() */
 
 	initmain(); /* Module __main__ */
+	_PyImport_InitZip();
 	if (!Py_NoSiteFlag)
 		initsite(); /* Module site */
 }
@@ -392,6 +393,20 @@
 Py_GetProgramName(void)
 {
 	return progname;
+}
+
+static char *scriptname = "";
+
+void
+Py_SetScriptName(char *pn)
+{
+	scriptname = pn;
+}
+
+char *
+Py_GetScriptName(void)
+{
+	return scriptname;
 }
 
 static char *default_home = NULL;
Index: Python/sysmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/sysmodule.c,v
retrieving revision 2.111
diff -w -u -r2.111 sysmodule.c
--- Python/sysmodule.c	8 Oct 2002 02:44:28 -0000	2.111
+++ Python/sysmodule.c	29 Nov 2002 18:34:02 -0000
@@ -970,80 +970,10 @@
 PySys_SetArgv(int argc, char **argv)
 {
 	PyObject *av = makeargvobject(argc, argv);
-	PyObject *path = PySys_GetObject("path");
 	if (av == NULL)
 		Py_FatalError("no mem for sys.argv");
 	if (PySys_SetObject("argv", av) != 0)
 		Py_FatalError("can't assign sys.argv");
-	if (path != NULL) {
-		char *argv0 = argv[0];
-		char *p = NULL;
-		int n = 0;
-		PyObject *a;
-#ifdef HAVE_READLINK
-		char link[MAXPATHLEN+1];
-		char argv0copy[2*MAXPATHLEN+1];
-		int nr = 0;
-		if (argc > 0 && argv0 != NULL)
-			nr = readlink(argv0, link, MAXPATHLEN);
-		if (nr > 0) {
-			/* It's a symlink */
-			link[nr] = '\0';
-			if (link[0] == SEP)
-				argv0 = link; /* Link to absolute path */
-			else if (strchr(link, SEP) == NULL)
-				; /* Link without path */
-			else {
-				/* Must join(dirname(argv0), link) */
-				char *q = strrchr(argv0, SEP);
-				if (q == NULL)
-					argv0 = link; /* argv0 without path */
-				else {
-					/* Must make a copy */
-					strcpy(argv0copy, argv0);
-					q = strrchr(argv0copy, SEP);
-					strcpy(q+1, link);
-					argv0 = argv0copy;
-				}
-			}
-		}
-#endif /* HAVE_READLINK */
-#if SEP == '\\' /* Special case for MS filename syntax */
-		if (argc > 0 && argv0 != NULL) {
-			char *q;
-			p = strrchr(argv0, SEP);
-			/* Test for alternate separator */
-			q = strrchr(p ? p : argv0, '/');
-			if (q != NULL)
-				p = q;
-			if (p != NULL) {
-				n = p + 1 - argv0;
-				if (n > 1 && p[-1] != ':')
-					n--; /* Drop trailing separator */
-			}
-		}
-#else /* All other filename syntaxes */
-		if (argc > 0 && argv0 != NULL)
-			p = strrchr(argv0, SEP);
-		if (p != NULL) {
-#ifndef RISCOS
-			n = p + 1 - argv0;
-#else /* don't include trailing separator */
-			n = p - argv0;
-#endif /* RISCOS */
-#if SEP == '/' /* Special case for Unix filename syntax */
-			if (n > 1)
-				n--; /* Drop trailing separator */
-#endif /* Unix */
-		}
-#endif /* All others */
-		a = PyString_FromStringAndSize(argv0, n);
-		if (a == NULL)
-			Py_FatalError("no mem for sys.path insertion");
-		if (PyList_Insert(path, 0, a) < 0)
-			Py_FatalError("sys.path.insert(0) failed");
-		Py_DECREF(a);
-	}
 	Py_DECREF(av);
 }
 
