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