--- /dev/null
+\r
+/* Error handling */\r
+\r
+#include "Python.h"\r
+\r
+#ifndef __STDC__\r
+#ifndef MS_WINDOWS\r
+extern char *strerror(int);\r
+#endif\r
+#endif\r
+\r
+#ifdef MS_WINDOWS\r
+#include "windows.h"\r
+#include "winbase.h"\r
+#endif\r
+\r
+#include <ctype.h>\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+\r
+void\r
+PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)\r
+{\r
+ PyThreadState *tstate = PyThreadState_GET();\r
+ PyObject *oldtype, *oldvalue, *oldtraceback;\r
+\r
+ if (traceback != NULL && !PyTraceBack_Check(traceback)) {\r
+ /* XXX Should never happen -- fatal error instead? */\r
+ /* Well, it could be None. */\r
+ Py_DECREF(traceback);\r
+ traceback = NULL;\r
+ }\r
+\r
+ /* Save these in locals to safeguard against recursive\r
+ invocation through Py_XDECREF */\r
+ oldtype = tstate->curexc_type;\r
+ oldvalue = tstate->curexc_value;\r
+ oldtraceback = tstate->curexc_traceback;\r
+\r
+ tstate->curexc_type = type;\r
+ tstate->curexc_value = value;\r
+ tstate->curexc_traceback = traceback;\r
+\r
+ Py_XDECREF(oldtype);\r
+ Py_XDECREF(oldvalue);\r
+ Py_XDECREF(oldtraceback);\r
+}\r
+\r
+void\r
+PyErr_SetObject(PyObject *exception, PyObject *value)\r
+{\r
+ Py_XINCREF(exception);\r
+ Py_XINCREF(value);\r
+ PyErr_Restore(exception, value, (PyObject *)NULL);\r
+}\r
+\r
+void\r
+PyErr_SetNone(PyObject *exception)\r
+{\r
+ PyErr_SetObject(exception, (PyObject *)NULL);\r
+}\r
+\r
+void\r
+PyErr_SetString(PyObject *exception, const char *string)\r
+{\r
+ PyObject *value = PyString_FromString(string);\r
+ PyErr_SetObject(exception, value);\r
+ Py_XDECREF(value);\r
+}\r
+\r
+\r
+PyObject *\r
+PyErr_Occurred(void)\r
+{\r
+ PyThreadState *tstate = PyThreadState_GET();\r
+\r
+ return tstate->curexc_type;\r
+}\r
+\r
+\r
+int\r
+PyErr_GivenExceptionMatches(PyObject *err, PyObject *exc)\r
+{\r
+ if (err == NULL || exc == NULL) {\r
+ /* maybe caused by "import exceptions" that failed early on */\r
+ return 0;\r
+ }\r
+ if (PyTuple_Check(exc)) {\r
+ Py_ssize_t i, n;\r
+ n = PyTuple_Size(exc);\r
+ for (i = 0; i < n; i++) {\r
+ /* Test recursively */\r
+ if (PyErr_GivenExceptionMatches(\r
+ err, PyTuple_GET_ITEM(exc, i)))\r
+ {\r
+ return 1;\r
+ }\r
+ }\r
+ return 0;\r
+ }\r
+ /* err might be an instance, so check its class. */\r
+ if (PyExceptionInstance_Check(err))\r
+ err = PyExceptionInstance_Class(err);\r
+\r
+ if (PyExceptionClass_Check(err) && PyExceptionClass_Check(exc)) {\r
+ int res = 0, reclimit;\r
+ PyObject *exception, *value, *tb;\r
+ PyErr_Fetch(&exception, &value, &tb);\r
+ /* Temporarily bump the recursion limit, so that in the most\r
+ common case PyObject_IsSubclass will not raise a recursion\r
+ error we have to ignore anyway. Don't do it when the limit\r
+ is already insanely high, to avoid overflow */\r
+ reclimit = Py_GetRecursionLimit();\r
+ if (reclimit < (1 << 30))\r
+ Py_SetRecursionLimit(reclimit + 5);\r
+ res = PyObject_IsSubclass(err, exc);\r
+ Py_SetRecursionLimit(reclimit);\r
+ /* This function must not fail, so print the error here */\r
+ if (res == -1) {\r
+ PyErr_WriteUnraisable(err);\r
+ res = 0;\r
+ }\r
+ PyErr_Restore(exception, value, tb);\r
+ return res;\r
+ }\r
+\r
+ return err == exc;\r
+}\r
+\r
+\r
+int\r
+PyErr_ExceptionMatches(PyObject *exc)\r
+{\r
+ return PyErr_GivenExceptionMatches(PyErr_Occurred(), exc);\r
+}\r
+\r
+\r
+/* Used in many places to normalize a raised exception, including in\r
+ eval_code2(), do_raise(), and PyErr_Print()\r
+*/\r
+void\r
+PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)\r
+{\r
+ PyObject *type = *exc;\r
+ PyObject *value = *val;\r
+ PyObject *inclass = NULL;\r
+ PyObject *initial_tb = NULL;\r
+ PyThreadState *tstate = NULL;\r
+\r
+ if (type == NULL) {\r
+ /* There was no exception, so nothing to do. */\r
+ return;\r
+ }\r
+\r
+ /* If PyErr_SetNone() was used, the value will have been actually\r
+ set to NULL.\r
+ */\r
+ if (!value) {\r
+ value = Py_None;\r
+ Py_INCREF(value);\r
+ }\r
+\r
+ if (PyExceptionInstance_Check(value))\r
+ inclass = PyExceptionInstance_Class(value);\r
+\r
+ /* Normalize the exception so that if the type is a class, the\r
+ value will be an instance.\r
+ */\r
+ if (PyExceptionClass_Check(type)) {\r
+ /* if the value was not an instance, or is not an instance\r
+ whose class is (or is derived from) type, then use the\r
+ value as an argument to instantiation of the type\r
+ class.\r
+ */\r
+ if (!inclass || !PyObject_IsSubclass(inclass, type)) {\r
+ PyObject *args, *res;\r
+\r
+ if (value == Py_None)\r
+ args = PyTuple_New(0);\r
+ else if (PyTuple_Check(value)) {\r
+ Py_INCREF(value);\r
+ args = value;\r
+ }\r
+ else\r
+ args = PyTuple_Pack(1, value);\r
+\r
+ if (args == NULL)\r
+ goto finally;\r
+ res = PyEval_CallObject(type, args);\r
+ Py_DECREF(args);\r
+ if (res == NULL)\r
+ goto finally;\r
+ Py_DECREF(value);\r
+ value = res;\r
+ }\r
+ /* if the class of the instance doesn't exactly match the\r
+ class of the type, believe the instance\r
+ */\r
+ else if (inclass != type) {\r
+ Py_DECREF(type);\r
+ type = inclass;\r
+ Py_INCREF(type);\r
+ }\r
+ }\r
+ *exc = type;\r
+ *val = value;\r
+ return;\r
+finally:\r
+ Py_DECREF(type);\r
+ Py_DECREF(value);\r
+ /* If the new exception doesn't set a traceback and the old\r
+ exception had a traceback, use the old traceback for the\r
+ new exception. It's better than nothing.\r
+ */\r
+ initial_tb = *tb;\r
+ PyErr_Fetch(exc, val, tb);\r
+ if (initial_tb != NULL) {\r
+ if (*tb == NULL)\r
+ *tb = initial_tb;\r
+ else\r
+ Py_DECREF(initial_tb);\r
+ }\r
+ /* normalize recursively */\r
+ tstate = PyThreadState_GET();\r
+ if (++tstate->recursion_depth > Py_GetRecursionLimit()) {\r
+ --tstate->recursion_depth;\r
+ /* throw away the old exception... */\r
+ Py_DECREF(*exc);\r
+ Py_DECREF(*val);\r
+ /* ... and use the recursion error instead */\r
+ *exc = PyExc_RuntimeError;\r
+ *val = PyExc_RecursionErrorInst;\r
+ Py_INCREF(*exc);\r
+ Py_INCREF(*val);\r
+ /* just keeping the old traceback */\r
+ return;\r
+ }\r
+ PyErr_NormalizeException(exc, val, tb);\r
+ --tstate->recursion_depth;\r
+}\r
+\r
+\r
+void\r
+PyErr_Fetch(PyObject **p_type, PyObject **p_value, PyObject **p_traceback)\r
+{\r
+ PyThreadState *tstate = PyThreadState_GET();\r
+\r
+ *p_type = tstate->curexc_type;\r
+ *p_value = tstate->curexc_value;\r
+ *p_traceback = tstate->curexc_traceback;\r
+\r
+ tstate->curexc_type = NULL;\r
+ tstate->curexc_value = NULL;\r
+ tstate->curexc_traceback = NULL;\r
+}\r
+\r
+void\r
+PyErr_Clear(void)\r
+{\r
+ PyErr_Restore(NULL, NULL, NULL);\r
+}\r
+\r
+/* Restore previously fetched exception if an exception is not set,\r
+ otherwise drop previously fetched exception.\r
+ Like _PyErr_ChainExceptions() in Python 3, but doesn't set the context.\r
+ */\r
+void\r
+_PyErr_ReplaceException(PyObject *exc, PyObject *val, PyObject *tb)\r
+{\r
+ if (exc == NULL)\r
+ return;\r
+\r
+ if (PyErr_Occurred()) {\r
+ Py_DECREF(exc);\r
+ Py_XDECREF(val);\r
+ Py_XDECREF(tb);\r
+ }\r
+ else {\r
+ PyErr_Restore(exc, val, tb);\r
+ }\r
+}\r
+\r
+/* Convenience functions to set a type error exception and return 0 */\r
+\r
+int\r
+PyErr_BadArgument(void)\r
+{\r
+ PyErr_SetString(PyExc_TypeError,\r
+ "bad argument type for built-in operation");\r
+ return 0;\r
+}\r
+\r
+PyObject *\r
+PyErr_NoMemory(void)\r
+{\r
+ if (PyErr_ExceptionMatches(PyExc_MemoryError))\r
+ /* already current */\r
+ return NULL;\r
+\r
+ /* raise the pre-allocated instance if it still exists */\r
+ if (PyExc_MemoryErrorInst)\r
+ PyErr_SetObject(PyExc_MemoryError, PyExc_MemoryErrorInst);\r
+ else\r
+ /* this will probably fail since there's no memory and hee,\r
+ hee, we have to instantiate this class\r
+ */\r
+ PyErr_SetNone(PyExc_MemoryError);\r
+\r
+ return NULL;\r
+}\r
+\r
+PyObject *\r
+PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)\r
+{\r
+ PyObject *v;\r
+ char *s;\r
+ int i = errno;\r
+#ifdef PLAN9\r
+ char errbuf[ERRMAX];\r
+#endif\r
+#ifdef MS_WINDOWS\r
+ char *s_buf = NULL;\r
+ char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */\r
+#endif\r
+#ifdef EINTR\r
+ if (i == EINTR && PyErr_CheckSignals())\r
+ return NULL;\r
+#endif\r
+#ifdef PLAN9\r
+ rerrstr(errbuf, sizeof errbuf);\r
+ s = errbuf;\r
+#else\r
+ if (i == 0)\r
+ s = "Error"; /* Sometimes errno didn't get set */\r
+ else\r
+#ifndef MS_WINDOWS\r
+ s = strerror(i);\r
+#else\r
+ {\r
+ /* Note that the Win32 errors do not lineup with the\r
+ errno error. So if the error is in the MSVC error\r
+ table, we use it, otherwise we assume it really _is_\r
+ a Win32 error code\r
+ */\r
+ if (i > 0 && i < _sys_nerr) {\r
+ s = _sys_errlist[i];\r
+ }\r
+ else {\r
+ int len = FormatMessage(\r
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |\r
+ FORMAT_MESSAGE_FROM_SYSTEM |\r
+ FORMAT_MESSAGE_IGNORE_INSERTS,\r
+ NULL, /* no message source */\r
+ i,\r
+ MAKELANGID(LANG_NEUTRAL,\r
+ SUBLANG_DEFAULT),\r
+ /* Default language */\r
+ (LPTSTR) &s_buf,\r
+ 0, /* size not used */\r
+ NULL); /* no args */\r
+ if (len==0) {\r
+ /* Only ever seen this in out-of-mem\r
+ situations */\r
+ sprintf(s_small_buf, "Windows Error 0x%X", i);\r
+ s = s_small_buf;\r
+ s_buf = NULL;\r
+ } else {\r
+ s = s_buf;\r
+ /* remove trailing cr/lf and dots */\r
+ while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))\r
+ s[--len] = '\0';\r
+ }\r
+ }\r
+ }\r
+#endif /* Unix/Windows */\r
+#endif /* PLAN 9*/\r
+ if (filenameObject != NULL)\r
+ v = Py_BuildValue("(isO)", i, s, filenameObject);\r
+ else\r
+ v = Py_BuildValue("(is)", i, s);\r
+ if (v != NULL) {\r
+ PyErr_SetObject(exc, v);\r
+ Py_DECREF(v);\r
+ }\r
+#ifdef MS_WINDOWS\r
+ LocalFree(s_buf);\r
+#endif\r
+ return NULL;\r
+}\r
+\r
+\r
+PyObject *\r
+PyErr_SetFromErrnoWithFilename(PyObject *exc, const char *filename)\r
+{\r
+ PyObject *name = filename ? PyString_FromString(filename) : NULL;\r
+ PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name);\r
+ Py_XDECREF(name);\r
+ return result;\r
+}\r
+\r
+#ifdef MS_WINDOWS\r
+PyObject *\r
+PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, const Py_UNICODE *filename)\r
+{\r
+ PyObject *name = filename ?\r
+ PyUnicode_FromUnicode(filename, wcslen(filename)) :\r
+ NULL;\r
+ PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name);\r
+ Py_XDECREF(name);\r
+ return result;\r
+}\r
+#endif /* MS_WINDOWS */\r
+\r
+PyObject *\r
+PyErr_SetFromErrno(PyObject *exc)\r
+{\r
+ return PyErr_SetFromErrnoWithFilenameObject(exc, NULL);\r
+}\r
+\r
+#ifdef MS_WINDOWS\r
+/* Windows specific error code handling */\r
+PyObject *PyErr_SetExcFromWindowsErrWithFilenameObject(\r
+ PyObject *exc,\r
+ int ierr,\r
+ PyObject *filenameObject)\r
+{\r
+ int len;\r
+ char *s;\r
+ char *s_buf = NULL; /* Free via LocalFree */\r
+ char s_small_buf[28]; /* Room for "Windows Error 0xFFFFFFFF" */\r
+ PyObject *v;\r
+ DWORD err = (DWORD)ierr;\r
+ if (err==0) err = GetLastError();\r
+ len = FormatMessage(\r
+ /* Error API error */\r
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |\r
+ FORMAT_MESSAGE_FROM_SYSTEM |\r
+ FORMAT_MESSAGE_IGNORE_INSERTS,\r
+ NULL, /* no message source */\r
+ err,\r
+ MAKELANGID(LANG_NEUTRAL,\r
+ SUBLANG_DEFAULT), /* Default language */\r
+ (LPTSTR) &s_buf,\r
+ 0, /* size not used */\r
+ NULL); /* no args */\r
+ if (len==0) {\r
+ /* Only seen this in out of mem situations */\r
+ sprintf(s_small_buf, "Windows Error 0x%X", err);\r
+ s = s_small_buf;\r
+ s_buf = NULL;\r
+ } else {\r
+ s = s_buf;\r
+ /* remove trailing cr/lf and dots */\r
+ while (len > 0 && (s[len-1] <= ' ' || s[len-1] == '.'))\r
+ s[--len] = '\0';\r
+ }\r
+ if (filenameObject != NULL)\r
+ v = Py_BuildValue("(isO)", err, s, filenameObject);\r
+ else\r
+ v = Py_BuildValue("(is)", err, s);\r
+ if (v != NULL) {\r
+ PyErr_SetObject(exc, v);\r
+ Py_DECREF(v);\r
+ }\r
+ LocalFree(s_buf);\r
+ return NULL;\r
+}\r
+\r
+PyObject *PyErr_SetExcFromWindowsErrWithFilename(\r
+ PyObject *exc,\r
+ int ierr,\r
+ const char *filename)\r
+{\r
+ PyObject *name = filename ? PyString_FromString(filename) : NULL;\r
+ PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,\r
+ ierr,\r
+ name);\r
+ Py_XDECREF(name);\r
+ return ret;\r
+}\r
+\r
+PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename(\r
+ PyObject *exc,\r
+ int ierr,\r
+ const Py_UNICODE *filename)\r
+{\r
+ PyObject *name = filename ?\r
+ PyUnicode_FromUnicode(filename, wcslen(filename)) :\r
+ NULL;\r
+ PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,\r
+ ierr,\r
+ name);\r
+ Py_XDECREF(name);\r
+ return ret;\r
+}\r
+\r
+PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr)\r
+{\r
+ return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL);\r
+}\r
+\r
+PyObject *PyErr_SetFromWindowsErr(int ierr)\r
+{\r
+ return PyErr_SetExcFromWindowsErrWithFilename(PyExc_WindowsError,\r
+ ierr, NULL);\r
+}\r
+PyObject *PyErr_SetFromWindowsErrWithFilename(\r
+ int ierr,\r
+ const char *filename)\r
+{\r
+ PyObject *name = filename ? PyString_FromString(filename) : NULL;\r
+ PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject(\r
+ PyExc_WindowsError,\r
+ ierr, name);\r
+ Py_XDECREF(name);\r
+ return result;\r
+}\r
+\r
+PyObject *PyErr_SetFromWindowsErrWithUnicodeFilename(\r
+ int ierr,\r
+ const Py_UNICODE *filename)\r
+{\r
+ PyObject *name = filename ?\r
+ PyUnicode_FromUnicode(filename, wcslen(filename)) :\r
+ NULL;\r
+ PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject(\r
+ PyExc_WindowsError,\r
+ ierr, name);\r
+ Py_XDECREF(name);\r
+ return result;\r
+}\r
+#endif /* MS_WINDOWS */\r
+\r
+void\r
+_PyErr_BadInternalCall(char *filename, int lineno)\r
+{\r
+ PyErr_Format(PyExc_SystemError,\r
+ "%s:%d: bad argument to internal function",\r
+ filename, lineno);\r
+}\r
+\r
+/* Remove the preprocessor macro for PyErr_BadInternalCall() so that we can\r
+ export the entry point for existing object code: */\r
+#undef PyErr_BadInternalCall\r
+void\r
+PyErr_BadInternalCall(void)\r
+{\r
+ PyErr_Format(PyExc_SystemError,\r
+ "bad argument to internal function");\r
+}\r
+#define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__)\r
+\r
+\r
+\r
+PyObject *\r
+PyErr_Format(PyObject *exception, const char *format, ...)\r
+{\r
+ va_list vargs;\r
+ PyObject* string;\r
+\r
+#ifdef HAVE_STDARG_PROTOTYPES\r
+ va_start(vargs, format);\r
+#else\r
+ va_start(vargs);\r
+#endif\r
+\r
+ string = PyString_FromFormatV(format, vargs);\r
+ PyErr_SetObject(exception, string);\r
+ Py_XDECREF(string);\r
+ va_end(vargs);\r
+ return NULL;\r
+}\r
+\r
+\r
+\r
+PyObject *\r
+PyErr_NewException(char *name, PyObject *base, PyObject *dict)\r
+{\r
+ char *dot;\r
+ PyObject *modulename = NULL;\r
+ PyObject *classname = NULL;\r
+ PyObject *mydict = NULL;\r
+ PyObject *bases = NULL;\r
+ PyObject *result = NULL;\r
+ dot = strrchr(name, '.');\r
+ if (dot == NULL) {\r
+ PyErr_SetString(PyExc_SystemError,\r
+ "PyErr_NewException: name must be module.class");\r
+ return NULL;\r
+ }\r
+ if (base == NULL)\r
+ base = PyExc_Exception;\r
+ if (dict == NULL) {\r
+ dict = mydict = PyDict_New();\r
+ if (dict == NULL)\r
+ goto failure;\r
+ }\r
+ if (PyDict_GetItemString(dict, "__module__") == NULL) {\r
+ modulename = PyString_FromStringAndSize(name,\r
+ (Py_ssize_t)(dot-name));\r
+ if (modulename == NULL)\r
+ goto failure;\r
+ if (PyDict_SetItemString(dict, "__module__", modulename) != 0)\r
+ goto failure;\r
+ }\r
+ if (PyTuple_Check(base)) {\r
+ bases = base;\r
+ /* INCREF as we create a new ref in the else branch */\r
+ Py_INCREF(bases);\r
+ } else {\r
+ bases = PyTuple_Pack(1, base);\r
+ if (bases == NULL)\r
+ goto failure;\r
+ }\r
+ /* Create a real new-style class. */\r
+ result = PyObject_CallFunction((PyObject *)&PyType_Type, "sOO",\r
+ dot+1, bases, dict);\r
+ failure:\r
+ Py_XDECREF(bases);\r
+ Py_XDECREF(mydict);\r
+ Py_XDECREF(classname);\r
+ Py_XDECREF(modulename);\r
+ return result;\r
+}\r
+\r
+\r
+/* Create an exception with docstring */\r
+PyObject *\r
+PyErr_NewExceptionWithDoc(char *name, char *doc, PyObject *base, PyObject *dict)\r
+{\r
+ int result;\r
+ PyObject *ret = NULL;\r
+ PyObject *mydict = NULL; /* points to the dict only if we create it */\r
+ PyObject *docobj;\r
+\r
+ if (dict == NULL) {\r
+ dict = mydict = PyDict_New();\r
+ if (dict == NULL) {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ if (doc != NULL) {\r
+ docobj = PyString_FromString(doc);\r
+ if (docobj == NULL)\r
+ goto failure;\r
+ result = PyDict_SetItemString(dict, "__doc__", docobj);\r
+ Py_DECREF(docobj);\r
+ if (result < 0)\r
+ goto failure;\r
+ }\r
+\r
+ ret = PyErr_NewException(name, base, dict);\r
+ failure:\r
+ Py_XDECREF(mydict);\r
+ return ret;\r
+}\r
+\r
+\r
+/* Call when an exception has occurred but there is no way for Python\r
+ to handle it. Examples: exception in __del__ or during GC. */\r
+void\r
+PyErr_WriteUnraisable(PyObject *obj)\r
+{\r
+ PyObject *f, *t, *v, *tb;\r
+ PyErr_Fetch(&t, &v, &tb);\r
+ f = PySys_GetObject("stderr");\r
+ if (f != NULL) {\r
+ PyFile_WriteString("Exception ", f);\r
+ if (t) {\r
+ PyObject* moduleName;\r
+ char* className;\r
+ assert(PyExceptionClass_Check(t));\r
+ className = PyExceptionClass_Name(t);\r
+ if (className != NULL) {\r
+ char *dot = strrchr(className, '.');\r
+ if (dot != NULL)\r
+ className = dot+1;\r
+ }\r
+\r
+ moduleName = PyObject_GetAttrString(t, "__module__");\r
+ if (moduleName == NULL)\r
+ PyFile_WriteString("<unknown>", f);\r
+ else {\r
+ char* modstr = PyString_AsString(moduleName);\r
+ if (modstr &&\r
+ strcmp(modstr, "exceptions") != 0)\r
+ {\r
+ PyFile_WriteString(modstr, f);\r
+ PyFile_WriteString(".", f);\r
+ }\r
+ }\r
+ if (className == NULL)\r
+ PyFile_WriteString("<unknown>", f);\r
+ else\r
+ PyFile_WriteString(className, f);\r
+ if (v && v != Py_None) {\r
+ PyFile_WriteString(": ", f);\r
+ PyFile_WriteObject(v, f, 0);\r
+ }\r
+ Py_XDECREF(moduleName);\r
+ }\r
+ PyFile_WriteString(" in ", f);\r
+ PyFile_WriteObject(obj, f, 0);\r
+ PyFile_WriteString(" ignored\n", f);\r
+ PyErr_Clear(); /* Just in case */\r
+ }\r
+ Py_XDECREF(t);\r
+ Py_XDECREF(v);\r
+ Py_XDECREF(tb);\r
+}\r
+\r
+extern PyObject *PyModule_GetWarningsModule(void);\r
+\r
+\r
+/* Set file and line information for the current exception.\r
+ If the exception is not a SyntaxError, also sets additional attributes\r
+ to make printing of exceptions believe it is a syntax error. */\r
+\r
+void\r
+PyErr_SyntaxLocation(const char *filename, int lineno)\r
+{\r
+ PyObject *exc, *v, *tb, *tmp;\r
+\r
+ /* add attributes for the line number and filename for the error */\r
+ PyErr_Fetch(&exc, &v, &tb);\r
+ PyErr_NormalizeException(&exc, &v, &tb);\r
+ /* XXX check that it is, indeed, a syntax error. It might not\r
+ * be, though. */\r
+ tmp = PyInt_FromLong(lineno);\r
+ if (tmp == NULL)\r
+ PyErr_Clear();\r
+ else {\r
+ if (PyObject_SetAttrString(v, "lineno", tmp))\r
+ PyErr_Clear();\r
+ Py_DECREF(tmp);\r
+ }\r
+ if (filename != NULL) {\r
+ tmp = PyString_FromString(filename);\r
+ if (tmp == NULL)\r
+ PyErr_Clear();\r
+ else {\r
+ if (PyObject_SetAttrString(v, "filename", tmp))\r
+ PyErr_Clear();\r
+ Py_DECREF(tmp);\r
+ }\r
+\r
+ tmp = PyErr_ProgramText(filename, lineno);\r
+ if (tmp) {\r
+ if (PyObject_SetAttrString(v, "text", tmp))\r
+ PyErr_Clear();\r
+ Py_DECREF(tmp);\r
+ }\r
+ }\r
+ if (PyObject_SetAttrString(v, "offset", Py_None)) {\r
+ PyErr_Clear();\r
+ }\r
+ if (exc != PyExc_SyntaxError) {\r
+ if (!PyObject_HasAttrString(v, "msg")) {\r
+ tmp = PyObject_Str(v);\r
+ if (tmp) {\r
+ if (PyObject_SetAttrString(v, "msg", tmp))\r
+ PyErr_Clear();\r
+ Py_DECREF(tmp);\r
+ } else {\r
+ PyErr_Clear();\r
+ }\r
+ }\r
+ if (!PyObject_HasAttrString(v, "print_file_and_line")) {\r
+ if (PyObject_SetAttrString(v, "print_file_and_line",\r
+ Py_None))\r
+ PyErr_Clear();\r
+ }\r
+ }\r
+ PyErr_Restore(exc, v, tb);\r
+}\r
+\r
+/* com_fetch_program_text will attempt to load the line of text that\r
+ the exception refers to. If it fails, it will return NULL but will\r
+ not set an exception.\r
+\r
+ XXX The functionality of this function is quite similar to the\r
+ functionality in tb_displayline() in traceback.c.\r
+*/\r
+\r
+PyObject *\r
+PyErr_ProgramText(const char *filename, int lineno)\r
+{\r
+ FILE *fp;\r
+ int i;\r
+ char linebuf[1000];\r
+\r
+ if (filename == NULL || *filename == '\0' || lineno <= 0)\r
+ return NULL;\r
+ fp = fopen(filename, "r" PY_STDIOTEXTMODE);\r
+ if (fp == NULL)\r
+ return NULL;\r
+ for (i = 0; i < lineno; i++) {\r
+ char *pLastChar = &linebuf[sizeof(linebuf) - 2];\r
+ do {\r
+ *pLastChar = '\0';\r
+ if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf, fp, NULL) == NULL)\r
+ break;\r
+ /* fgets read *something*; if it didn't get as\r
+ far as pLastChar, it must have found a newline\r
+ or hit the end of the file; if pLastChar is \n,\r
+ it obviously found a newline; else we haven't\r
+ yet seen a newline, so must continue */\r
+ } while (*pLastChar != '\0' && *pLastChar != '\n');\r
+ }\r
+ fclose(fp);\r
+ if (i == lineno) {\r
+ char *p = linebuf;\r
+ while (*p == ' ' || *p == '\t' || *p == '\014')\r
+ p++;\r
+ return PyString_FromString(p);\r
+ }\r
+ return NULL;\r
+}\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r