Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * ***** END GPL LICENSE BLOCK ***** 00019 */ 00020 00029 #include <Python.h> 00030 #include <frameobject.h> 00031 00032 #include "bpy_traceback.h" 00033 00034 static const char *traceback_filepath(PyTracebackObject *tb, PyObject **coerce) 00035 { 00036 return PyBytes_AS_STRING((*coerce = PyUnicode_EncodeFSDefault(tb->tb_frame->f_code->co_filename))); 00037 } 00038 00039 /* copied from pythonrun.c, 3.2.0 */ 00040 static int 00041 parse_syntax_error(PyObject *err, PyObject **message, const char **filename, 00042 int *lineno, int *offset, const char **text) 00043 { 00044 long hold; 00045 PyObject *v; 00046 00047 /* old style errors */ 00048 if (PyTuple_Check(err)) 00049 return PyArg_ParseTuple(err, "O(ziiz)", message, filename, 00050 lineno, offset, text); 00051 00052 /* new style errors. `err' is an instance */ 00053 00054 if (! (v = PyObject_GetAttrString(err, "msg"))) 00055 goto finally; 00056 *message = v; 00057 00058 if (!(v = PyObject_GetAttrString(err, "filename"))) 00059 goto finally; 00060 if (v == Py_None) 00061 *filename = NULL; 00062 else if (! (*filename = _PyUnicode_AsString(v))) 00063 goto finally; 00064 00065 Py_DECREF(v); 00066 if (!(v = PyObject_GetAttrString(err, "lineno"))) 00067 goto finally; 00068 hold = PyLong_AsLong(v); 00069 Py_DECREF(v); 00070 v = NULL; 00071 if (hold < 0 && PyErr_Occurred()) 00072 goto finally; 00073 *lineno = (int)hold; 00074 00075 if (!(v = PyObject_GetAttrString(err, "offset"))) 00076 goto finally; 00077 if (v == Py_None) { 00078 *offset = -1; 00079 Py_DECREF(v); 00080 v = NULL; 00081 } 00082 else { 00083 hold = PyLong_AsLong(v); 00084 Py_DECREF(v); 00085 v = NULL; 00086 if (hold < 0 && PyErr_Occurred()) 00087 goto finally; 00088 *offset = (int)hold; 00089 } 00090 00091 if (!(v = PyObject_GetAttrString(err, "text"))) 00092 goto finally; 00093 if (v == Py_None) 00094 *text = NULL; 00095 else if (!PyUnicode_Check(v) || 00096 !(*text = _PyUnicode_AsString(v))) 00097 goto finally; 00098 Py_DECREF(v); 00099 return 1; 00100 00101 finally: 00102 Py_XDECREF(v); 00103 return 0; 00104 } 00105 /* end copied function! */ 00106 00107 00108 void python_script_error_jump(const char *filepath, int *lineno, int *offset) 00109 { 00110 PyObject *exception, *value; 00111 PyTracebackObject *tb; 00112 00113 *lineno = -1; 00114 *offset = 0; 00115 00116 PyErr_Fetch(&exception, &value, (PyObject **)&tb); 00117 00118 if (exception && PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError)) { 00119 /* no traceback available when SyntaxError. 00120 * python has no api's to this. reference parse_syntax_error() from pythonrun.c */ 00121 PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); 00122 PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ 00123 00124 if (value) { /* should always be true */ 00125 PyObject *message; 00126 const char *filename, *text; 00127 00128 if (parse_syntax_error(value, &message, &filename, lineno, offset, &text)) { 00129 /* python adds a '/', prefix, so check for both */ 00130 if ((strcmp(filename, filepath) == 0) || 00131 ((filename[0] == '\\' || filename[0] == '/') && strcmp(filename + 1, filepath) == 0) 00132 ) { 00133 /* good */ 00134 } 00135 else { 00136 *lineno = -1; 00137 } 00138 } 00139 else { 00140 *lineno = -1; 00141 } 00142 } 00143 } 00144 else { 00145 PyErr_NormalizeException(&exception, &value, (PyObject **)&tb); 00146 PyErr_Restore(exception, value, (PyObject *)tb); /* takes away reference! */ 00147 PyErr_Print(); 00148 00149 for (tb = (PyTracebackObject *)PySys_GetObject("last_traceback"); 00150 tb && (PyObject *)tb != Py_None; 00151 tb = tb->tb_next) 00152 { 00153 PyObject *coerce; 00154 const char *tb_filepath = traceback_filepath(tb, &coerce); 00155 const int match = strcmp(tb_filepath, filepath) != 0; 00156 Py_DECREF(coerce); 00157 00158 if (match) { 00159 *lineno = tb->tb_lineno; 00160 break; 00161 } 00162 } 00163 } 00164 }