Removed obsolete exception PyExc_AccessError.

Added PyErr_MemoryErrorInst to hold the pre-instantiated instance when
using class based exceptions.

Simplified the creation of all built-in exceptions, both class based
and string based.  Actually, for class based exceptions, the string
ones are still created just in case there's a problem creating the
class based ones (so you still get *some* exception handling!).  Now
the init and fini functions run through a list of structure elements,
creating the strings (and optionally classes) for every entry.

initerrors(): the new base class exceptions StandardError,
LookupError, and NumberError are initialized when using string
exceptions, to tuples containing the list of derived string
exceptions.  This GvR trick enables forward compatibility!  One bit of
nastiness is that the C code has to know the inheritance tree embodied
in exceptions.py.

Added the two phase init and fini functions.
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index a89b3fc..358b6f1 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1724,7 +1724,10 @@
 
 /* Predefined exceptions */
 
-PyObject *PyExc_AccessError;
+PyObject *PyExc_StandardError;
+PyObject *PyExc_NumberError;
+PyObject *PyExc_LookupError;
+
 PyObject *PyExc_AssertionError;
 PyObject *PyExc_AttributeError;
 PyObject *PyExc_EOFError;
@@ -1745,6 +1748,108 @@
 PyObject *PyExc_ValueError;
 PyObject *PyExc_ZeroDivisionError;
 
+PyObject *PyExc_MemoryErrorInst;
+
+static struct 
+{
+	char* name;
+	PyObject** exc;
+	int leaf_exc;
+}
+bltin_exc[] = {
+	{"StandardError",      &PyExc_StandardError,      0},
+	{"NumberError",        &PyExc_NumberError,        0},
+	{"LookupError",        &PyExc_LookupError,        0},
+	{"AssertionError",     &PyExc_AssertionError,     1},
+	{"AttributeError",     &PyExc_AttributeError,     1},
+	{"EOFError",           &PyExc_EOFError,           1},
+	{"FloatingPointError", &PyExc_FloatingPointError, 1},
+	{"IOError",            &PyExc_IOError,            1},
+	{"ImportError",        &PyExc_ImportError,        1},
+	{"IndexError",         &PyExc_IndexError,         1},
+	{"KeyError",           &PyExc_KeyError,           1},
+	{"KeyboardInterrupt",  &PyExc_KeyboardInterrupt,  1},
+	{"MemoryError",        &PyExc_MemoryError,        1},
+	{"NameError",          &PyExc_NameError,          1},
+	{"OverflowError",      &PyExc_OverflowError,      1},
+	{"RuntimeError",       &PyExc_RuntimeError,       1},
+	{"SyntaxError",        &PyExc_SyntaxError,        1},
+	{"SystemError",        &PyExc_SystemError,        1},
+	{"SystemExit",         &PyExc_SystemExit,         1},
+	{"TypeError",          &PyExc_TypeError,          1},
+	{"ValueError",         &PyExc_ValueError,         1},
+	{"ZeroDivisionError",  &PyExc_ZeroDivisionError,  1},
+	{NULL, NULL}
+};
+
+
+/* import exceptions module to extract class exceptions */
+static void
+init_class_exc(dict)
+	PyObject *dict;
+{
+	int i;
+	PyObject *m = PyImport_ImportModule("exceptions");
+	PyObject *d;
+	PyObject *args;
+
+	if (m == NULL ||
+	    (d = PyModule_GetDict(m)) == NULL)
+	{
+		PyObject *f = PySys_GetObject("stderr");
+		if (Py_VerboseFlag) {
+			PyFile_WriteString(
+				"'import exceptions' failed; traceback:\n", f);
+			PyErr_Print();
+		}
+		else {
+			PyFile_WriteString(
+		      "'import exceptions' failed; use -v for traceback\n", f);
+			PyErr_Clear();
+		}
+		PyFile_WriteString("defaulting to old style exceptions\n", f);
+		return;
+	}
+	for (i = 0; bltin_exc[i].name; i++) {
+		/* dig the exception out of the module */
+		PyObject *exc = PyDict_GetItemString(d, bltin_exc[i].name);
+		if (!exc)
+		     Py_FatalError("built-in exception cannot be initialized");
+		
+		Py_XDECREF(*bltin_exc[i].exc);
+
+		/* squirrel away a pointer to the exception */
+		Py_INCREF(exc);
+		*bltin_exc[i].exc = exc;
+
+		/* and insert the name in the __builtin__ module */
+		PyDict_SetItemString(dict, bltin_exc[i].name, exc);
+	}
+
+	/* we need one pre-allocated instance */
+	args = Py_BuildValue("()");
+	if (args) {
+		PyExc_MemoryErrorInst =
+			PyEval_CallObject(PyExc_MemoryError, args);
+		Py_DECREF(args);
+	}
+
+	/* we're done with the exceptions module */
+	Py_DECREF(m);
+
+	if (PyErr_Occurred())
+		Py_FatalError("can't instantiate standard exceptions");
+}
+
+
+static void
+fini_instances()
+{
+	Py_XDECREF(PyExc_MemoryErrorInst);
+	PyExc_MemoryErrorInst = NULL;
+}
+
+
 static PyObject *
 newstdexception(dict, name)
 	PyObject *dict;
@@ -1760,55 +1865,60 @@
 initerrors(dict)
 	PyObject *dict;
 {
-	PyExc_AccessError = newstdexception(dict, "AccessError");
-	PyExc_AssertionError = newstdexception(dict, "AssertionError");
-	PyExc_AttributeError = newstdexception(dict, "AttributeError");
-	PyExc_EOFError = newstdexception(dict, "EOFError");
-	PyExc_FloatingPointError = newstdexception(dict, "FloatingPointError");
-	PyExc_IOError = newstdexception(dict, "IOError");
-	PyExc_ImportError = newstdexception(dict, "ImportError");
-	PyExc_IndexError = newstdexception(dict, "IndexError");
-	PyExc_KeyError = newstdexception(dict, "KeyError");
-	PyExc_KeyboardInterrupt = newstdexception(dict, "KeyboardInterrupt");
-	PyExc_MemoryError = newstdexception(dict, "MemoryError");
-	PyExc_NameError = newstdexception(dict, "NameError");
-	PyExc_OverflowError = newstdexception(dict, "OverflowError");
-	PyExc_RuntimeError = newstdexception(dict, "RuntimeError");
-	PyExc_SyntaxError = newstdexception(dict, "SyntaxError");
-	PyExc_SystemError = newstdexception(dict, "SystemError");
-	PyExc_SystemExit = newstdexception(dict, "SystemExit");
-	PyExc_TypeError = newstdexception(dict, "TypeError");
-	PyExc_ValueError = newstdexception(dict, "ValueError");
-	PyExc_ZeroDivisionError = newstdexception(dict, "ZeroDivisionError");
+	int i;
+	int exccnt = 0;
+	for (i = 0; bltin_exc[i].name; i++, exccnt++) {
+		if (bltin_exc[i].leaf_exc)
+			*bltin_exc[i].exc =
+				newstdexception(dict, bltin_exc[i].name);
+	}
+
+	/* This is kind of bogus because we special case the three new
+	   exceptions to be nearly forward compatible.  But this means we
+	   hard code knowledge about exceptions.py into C here.  I don't
+	   have a better solution, though
+	*/
+	PyExc_LookupError = PyTuple_New(2);
+	Py_INCREF(PyExc_IndexError);
+	PyTuple_SET_ITEM(PyExc_LookupError, 0, PyExc_IndexError);
+	Py_INCREF(PyExc_KeyError);
+	PyTuple_SET_ITEM(PyExc_LookupError, 1, PyExc_KeyError);
+	PyDict_SetItemString(dict, "LookupError", PyExc_LookupError);
+
+	PyExc_NumberError = PyTuple_New(3);
+	Py_INCREF(PyExc_OverflowError);
+	PyTuple_SET_ITEM(PyExc_NumberError, 0, PyExc_OverflowError);
+	Py_INCREF(PyExc_ZeroDivisionError);
+	PyTuple_SET_ITEM(PyExc_NumberError, 1, PyExc_ZeroDivisionError);
+	Py_INCREF(PyExc_FloatingPointError);
+	PyTuple_SET_ITEM(PyExc_NumberError, 2, PyExc_FloatingPointError);
+	PyDict_SetItemString(dict, "NumberError", PyExc_NumberError);
+
+	PyExc_StandardError = PyTuple_New(exccnt-1);
+	for (i = 1; bltin_exc[i].name; i++) {
+		PyObject *exc = *bltin_exc[i].exc;
+		Py_INCREF(exc);
+		PyTuple_SET_ITEM(PyExc_StandardError, i-1, exc);
+	}
+	PyDict_SetItemString(dict, "StandardError", PyExc_StandardError);
+	
+	if (PyErr_Occurred())
+	      Py_FatalError("Could not initialize built-in string exceptions");
 }
 
 static void
 finierrors()
 {
-	Py_XDECREF(PyExc_AccessError); PyExc_AccessError = NULL;
-	Py_XDECREF(PyExc_AssertionError); PyExc_AssertionError = NULL;
-	Py_XDECREF(PyExc_AttributeError); PyExc_AttributeError = NULL;
-	Py_XDECREF(PyExc_EOFError); PyExc_EOFError = NULL;
-	Py_XDECREF(PyExc_FloatingPointError); PyExc_FloatingPointError = NULL;
-	Py_XDECREF(PyExc_IOError); PyExc_IOError = NULL;
-	Py_XDECREF(PyExc_ImportError); PyExc_ImportError = NULL;
-	Py_XDECREF(PyExc_IndexError); PyExc_IndexError = NULL;
-	Py_XDECREF(PyExc_KeyError); PyExc_KeyError = NULL;
-	Py_XDECREF(PyExc_KeyboardInterrupt); PyExc_KeyboardInterrupt = NULL;
-	Py_XDECREF(PyExc_MemoryError); PyExc_MemoryError = NULL;
-	Py_XDECREF(PyExc_NameError); PyExc_NameError = NULL;
-	Py_XDECREF(PyExc_OverflowError); PyExc_OverflowError = NULL;
-	Py_XDECREF(PyExc_RuntimeError); PyExc_RuntimeError = NULL;
-	Py_XDECREF(PyExc_SyntaxError); PyExc_SyntaxError = NULL;
-	Py_XDECREF(PyExc_SystemError); PyExc_SystemError = NULL;
-	Py_XDECREF(PyExc_SystemExit); PyExc_SystemExit = NULL;
-	Py_XDECREF(PyExc_TypeError); PyExc_TypeError = NULL;
-	Py_XDECREF(PyExc_ValueError); PyExc_ValueError = NULL;
-	Py_XDECREF(PyExc_ZeroDivisionError); PyExc_ZeroDivisionError = NULL;
+	int i;
+	for (i = 0; bltin_exc[i].name; i++) {
+		PyObject *exc = *bltin_exc[i].exc;
+		Py_XDECREF(exc);
+		*bltin_exc[i].exc = NULL;
+	}
 }
 
 PyObject *
-_PyBuiltin_Init()
+_PyBuiltin_Init_1()
 {
 	PyObject *mod, *dict;
 	mod = Py_InitModule("__builtin__", builtin_methods);
@@ -1823,11 +1933,29 @@
 	if (PyDict_SetItemString(dict, "__debug__",
 			  PyInt_FromLong(Py_OptimizeFlag == 0)) < 0)
 		return NULL;
+
 	return mod;
 }
 
 void
-_PyBuiltin_Fini()
+_PyBuiltin_Init_2(dict)
+	PyObject *dict;
+{
+	/* if Python was started with -X, initialize the class exceptions */
+	if (Py_UseClassExceptionsFlag)
+		init_class_exc(dict);
+}
+
+
+void
+_PyBuiltin_Fini_1()
+{
+	fini_instances();
+}
+
+
+void
+_PyBuiltin_Fini_2()
 {
 	finierrors();
 }