diff options
Diffstat (limited to 'Python/pythonrun.c')
-rw-r--r-- | Python/pythonrun.c | 111 |
1 files changed, 106 insertions, 5 deletions
diff --git a/Python/pythonrun.c b/Python/pythonrun.c index c1c5d36..f9b33fc 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -75,6 +75,7 @@ static void call_ll_exitfuncs Py_PROTO((void)); int Py_DebugFlag; /* Needed by parser.c */ int Py_VerboseFlag; /* Needed by import.c */ int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */ +int Py_UseClassExceptionsFlag; /* Needed by bltinmodule.c */ static int initialized = 0; @@ -127,7 +128,7 @@ Py_Initialize() if (interp->modules == NULL) Py_FatalError("Py_Initialize: can't make modules dictionary"); - bimod = _PyBuiltin_Init(); + bimod = _PyBuiltin_Init_1(); if (bimod == NULL) Py_FatalError("Py_Initialize: can't initialize __builtin__"); interp->builtins = PyModule_GetDict(bimod); @@ -144,6 +145,9 @@ Py_Initialize() PyDict_SetItemString(interp->sysdict, "modules", interp->modules); + /* phase 2 of builtins */ + _PyBuiltin_Init_2(interp->builtins); + _PyImport_Init(); initsigs(); /* Signal handling stuff, including initintr() */ @@ -178,6 +182,12 @@ Py_Finalize() if (initialized < 0) Py_FatalError("Py_Finalize: not initialized"); + /* We must call this before the current thread gets removed because + it decrefs class instances, which in turn save and restore the + current error state, which is a per thread data structure. + */ + _PyBuiltin_Fini_1(); + tstate = PyThreadState_Get(); interp = tstate->interp; @@ -188,7 +198,13 @@ Py_Finalize() finisigs(); _PyImport_Fini(); - _PyBuiltin_Fini(); + + /* Now we decref the exception classes. After this point nothing + can raise an exception. That's okay, because each Fini() method + below has been checked to make sure no exceptions are ever + raised. + */ + _PyBuiltin_Fini_2(); PyMethod_Fini(); PyFrame_Fini(); PyCFunction_Fini(); @@ -522,19 +538,99 @@ PyRun_SimpleString(command) return 0; } +static int +parse_syntax_error(err, message, filename, lineno, offset, text) + PyObject* err; + PyObject** message; + char** filename; + int* lineno; + int* offset; + char** text; +{ + long hold; + PyObject *v; + + /* old style errors */ + if (PyTuple_Check(err)) + return PyArg_Parse(err, "(O(ziiz))", message, filename, + lineno, offset, text); + + /* new style errors. `err' is an instance */ + + if (! (v = PyObject_GetAttrString(err, "msg"))) + goto finally; + *message = v; + + if (!(v = PyObject_GetAttrString(err, "filename"))) + goto finally; + if (v == Py_None) + *filename = NULL; + else if (! (*filename = PyString_AsString(v))) + goto finally; + + Py_DECREF(v); + if (!(v = PyObject_GetAttrString(err, "lineno"))) + goto finally; + hold = PyInt_AsLong(v); + Py_DECREF(v); + v = NULL; + if (hold < 0 && PyErr_Occurred()) + goto finally; + *lineno = (int)hold; + + if (!(v = PyObject_GetAttrString(err, "offset"))) + goto finally; + hold = PyInt_AsLong(v); + Py_DECREF(v); + v = NULL; + if (hold < 0 && PyErr_Occurred()) + goto finally; + *offset = (int)hold; + + if (!(v = PyObject_GetAttrString(err, "text"))) + goto finally; + if (v == Py_None) + *text = NULL; + else if (! (*text = PyString_AsString(v))) + goto finally; + Py_DECREF(v); + return 1; + +finally: + Py_XDECREF(v); + return 0; +} + void PyErr_Print() { int err = 0; PyObject *exception, *v, *tb, *f; PyErr_Fetch(&exception, &v, &tb); + PyErr_NormalizeException(&exception, &v, &tb); + if (exception == NULL) return; + if (PyErr_GivenExceptionMatches(exception, PyExc_SystemExit)) { err = Py_FlushLine(); fflush(stdout); if (v == NULL || v == Py_None) Py_Exit(0); + if (PyInstance_Check(v)) { + /* we expect the error code to be store in the + `code' attribute + */ + PyObject *code = PyObject_GetAttrString(v, "code"); + if (code) { + Py_DECREF(v); + v = code; + } + /* if we failed to dig out the "code" attribute, + then just let the else clause below print the + error + */ + } if (PyInt_Check(v)) Py_Exit((int)PyInt_AsLong(v)); else { @@ -561,8 +657,8 @@ PyErr_Print() PyObject *message; char *filename, *text; int lineno, offset; - if (!PyArg_Parse(v, "(O(ziiz))", &message, - &filename, &lineno, &offset, &text)) + if (!parse_syntax_error(v, &message, &filename, + &lineno, &offset, &text)) PyErr_Clear(); else { char buf[10]; @@ -630,7 +726,12 @@ PyErr_Print() err = PyFile_WriteObject(exception, f, Py_PRINT_RAW); if (err == 0) { if (v != NULL && v != Py_None) { - err = PyFile_WriteString(": ", f); + PyObject *s = PyObject_Str(v); + /* only print colon if the str() of the + object is not the empty string + */ + if (s && strcmp(PyString_AsString(s), "")) + err = PyFile_WriteString(": ", f); if (err == 0) err = PyFile_WriteObject(v, f, Py_PRINT_RAW); } |