mirror of
https://github.com/python/cpython.git
synced 2025-07-13 06:15:17 +00:00

svn+ssh://pythondev@svn.python.org/python/trunk ........ r62260 | gregory.p.smith | 2008-04-10 01:11:56 +0200 (Thu, 10 Apr 2008) | 2 lines better diagnostics ........ r62261 | gregory.p.smith | 2008-04-10 01:16:37 +0200 (Thu, 10 Apr 2008) | 3 lines Raise SystemError when size < 0 is passed into PyString_FromStringAndSize, PyBytes_FromStringAndSize or PyUnicode_FromStringAndSize. [issue2587] ........ r62266 | neal.norwitz | 2008-04-10 07:46:39 +0200 (Thu, 10 Apr 2008) | 5 lines Remove the test file before writing it in case there is no write permission. This might help fix some of the failures on Windows box(es). It doesn't hurt either way and ensure the tests are a little more self contained (ie have less assumptions). ........ r62271 | gregory.p.smith | 2008-04-10 21:50:36 +0200 (Thu, 10 Apr 2008) | 2 lines get rid of assert (size >= 0) now that an explicit if (size < 0) is in the code. ........ r62277 | andrew.kuchling | 2008-04-10 23:27:10 +0200 (Thu, 10 Apr 2008) | 1 line Remove forward-looking statement ........ r62278 | andrew.kuchling | 2008-04-10 23:28:51 +0200 (Thu, 10 Apr 2008) | 1 line Add punctuation ........ r62279 | andrew.kuchling | 2008-04-10 23:29:01 +0200 (Thu, 10 Apr 2008) | 1 line Use issue directive ........ r62289 | thomas.heller | 2008-04-11 15:05:38 +0200 (Fri, 11 Apr 2008) | 3 lines Move backwards compatibility macro to the correct place; PyIndex_Check() was introduced in Python 2.5. ........ r62290 | thomas.heller | 2008-04-11 16:20:26 +0200 (Fri, 11 Apr 2008) | 2 lines Performance improvements. ........ r62293 | christian.heimes | 2008-04-12 15:03:03 +0200 (Sat, 12 Apr 2008) | 2 lines Applied patch #2617 from Frank Wierzbicki wit some extras from me -J and -X are now reserved for Jython and non-standard arguments (e.g. IronPython). I've added some extra comments to make sure the reservation don't get missed in the future. ........ r62294 | georg.brandl | 2008-04-12 20:11:18 +0200 (Sat, 12 Apr 2008) | 2 lines Use absolute path in sys.path. ........ r62295 | georg.brandl | 2008-04-12 20:36:09 +0200 (Sat, 12 Apr 2008) | 2 lines #2615: small consistency update by Jeroen Ruigrok van der Werven. ........ r62296 | georg.brandl | 2008-04-12 21:00:20 +0200 (Sat, 12 Apr 2008) | 2 lines Add Jeroen. ........ r62297 | georg.brandl | 2008-04-12 21:05:37 +0200 (Sat, 12 Apr 2008) | 2 lines Don't offend snake lovers. ........ r62298 | gregory.p.smith | 2008-04-12 22:37:48 +0200 (Sat, 12 Apr 2008) | 2 lines fix compiler warnings ........ r62302 | gregory.p.smith | 2008-04-13 00:24:04 +0200 (Sun, 13 Apr 2008) | 3 lines socket.error inherits from IOError, it no longer needs listing in the all_errors tuple. ........ r62303 | brett.cannon | 2008-04-13 01:44:07 +0200 (Sun, 13 Apr 2008) | 8 lines Re-implement the 'warnings' module in C. This allows for usage of the 'warnings' code in places where it was previously not possible (e.g., the parser). It could also potentially lead to a speed-up in interpreter start-up if the C version of the code (_warnings) is imported over the use of the Python version in key places. Closes issue #1631171. ........ r62304 | gregory.p.smith | 2008-04-13 02:03:25 +0200 (Sun, 13 Apr 2008) | 3 lines Adds a profile-opt target for easy compilation of a python binary using gcc's profile guided optimization. ........ r62305 | brett.cannon | 2008-04-13 02:18:44 +0200 (Sun, 13 Apr 2008) | 3 lines Fix a bug in PySys_HasWarnOption() where it was not properly checking the length of the list storing the warning options. ........ r62306 | brett.cannon | 2008-04-13 02:25:15 +0200 (Sun, 13 Apr 2008) | 2 lines Fix an accidental bug of an non-existent init function. ........ r62308 | andrew.kuchling | 2008-04-13 03:05:59 +0200 (Sun, 13 Apr 2008) | 1 line Mention -J, -X ........ r62311 | benjamin.peterson | 2008-04-13 04:20:05 +0200 (Sun, 13 Apr 2008) | 2 lines Give the "Interactive Interpreter Changes" section in 2.6 whatsnew a unique link name ........ r62313 | brett.cannon | 2008-04-13 04:42:36 +0200 (Sun, 13 Apr 2008) | 3 lines Fix test_warnings by making the state of things more consistent for each test when it is run. ........ r62314 | skip.montanaro | 2008-04-13 05:17:30 +0200 (Sun, 13 Apr 2008) | 2 lines spelling ........ r62315 | georg.brandl | 2008-04-13 09:07:44 +0200 (Sun, 13 Apr 2008) | 2 lines Fix markup. ........ r62319 | christian.heimes | 2008-04-13 11:30:17 +0200 (Sun, 13 Apr 2008) | 1 line Fix compiler warning Include/warnings.h:19:28: warning: no newline at end of file ........ r62320 | christian.heimes | 2008-04-13 11:33:24 +0200 (Sun, 13 Apr 2008) | 1 line Use PyString_InternFromString instead of PyString_FromString for static vars ........ r62321 | christian.heimes | 2008-04-13 11:37:05 +0200 (Sun, 13 Apr 2008) | 1 line Added new files to the pcbuild files ........
303 lines
7.2 KiB
C
303 lines
7.2 KiB
C
|
|
/* Traceback implementation */
|
|
|
|
#include "Python.h"
|
|
|
|
#include "code.h"
|
|
#include "frameobject.h"
|
|
#include "structmember.h"
|
|
#include "osdefs.h"
|
|
#include "traceback.h"
|
|
|
|
#define OFF(x) offsetof(PyTracebackObject, x)
|
|
|
|
static PyObject *
|
|
tb_dir(PyTracebackObject *self)
|
|
{
|
|
return Py_BuildValue("[ssss]", "tb_frame", "tb_next",
|
|
"tb_lasti", "tb_lineno");
|
|
}
|
|
|
|
static PyMethodDef tb_methods[] = {
|
|
{"__dir__", (PyCFunction)tb_dir, METH_NOARGS},
|
|
{NULL, NULL, 0, NULL},
|
|
};
|
|
|
|
static PyMemberDef tb_memberlist[] = {
|
|
{"tb_next", T_OBJECT, OFF(tb_next), READONLY},
|
|
{"tb_frame", T_OBJECT, OFF(tb_frame), READONLY},
|
|
{"tb_lasti", T_INT, OFF(tb_lasti), READONLY},
|
|
{"tb_lineno", T_INT, OFF(tb_lineno), READONLY},
|
|
{NULL} /* Sentinel */
|
|
};
|
|
|
|
static void
|
|
tb_dealloc(PyTracebackObject *tb)
|
|
{
|
|
PyObject_GC_UnTrack(tb);
|
|
Py_TRASHCAN_SAFE_BEGIN(tb)
|
|
Py_XDECREF(tb->tb_next);
|
|
Py_XDECREF(tb->tb_frame);
|
|
PyObject_GC_Del(tb);
|
|
Py_TRASHCAN_SAFE_END(tb)
|
|
}
|
|
|
|
static int
|
|
tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg)
|
|
{
|
|
Py_VISIT(tb->tb_next);
|
|
Py_VISIT(tb->tb_frame);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
tb_clear(PyTracebackObject *tb)
|
|
{
|
|
Py_CLEAR(tb->tb_next);
|
|
Py_CLEAR(tb->tb_frame);
|
|
}
|
|
|
|
PyTypeObject PyTraceBack_Type = {
|
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
|
"traceback",
|
|
sizeof(PyTracebackObject),
|
|
0,
|
|
(destructor)tb_dealloc, /*tp_dealloc*/
|
|
0, /*tp_print*/
|
|
0, /*tp_getattr*/
|
|
0, /*tp_setattr*/
|
|
0, /*tp_compare*/
|
|
0, /*tp_repr*/
|
|
0, /*tp_as_number*/
|
|
0, /*tp_as_sequence*/
|
|
0, /*tp_as_mapping*/
|
|
0, /* tp_hash */
|
|
0, /* tp_call */
|
|
0, /* tp_str */
|
|
PyObject_GenericGetAttr, /* tp_getattro */
|
|
0, /* tp_setattro */
|
|
0, /* tp_as_buffer */
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
|
|
0, /* tp_doc */
|
|
(traverseproc)tb_traverse, /* tp_traverse */
|
|
(inquiry)tb_clear, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
tb_methods, /* tp_methods */
|
|
tb_memberlist, /* tp_members */
|
|
0, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
};
|
|
|
|
static PyTracebackObject *
|
|
newtracebackobject(PyTracebackObject *next, PyFrameObject *frame)
|
|
{
|
|
PyTracebackObject *tb;
|
|
if ((next != NULL && !PyTraceBack_Check(next)) ||
|
|
frame == NULL || !PyFrame_Check(frame)) {
|
|
PyErr_BadInternalCall();
|
|
return NULL;
|
|
}
|
|
tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
|
|
if (tb != NULL) {
|
|
Py_XINCREF(next);
|
|
tb->tb_next = next;
|
|
Py_XINCREF(frame);
|
|
tb->tb_frame = frame;
|
|
tb->tb_lasti = frame->f_lasti;
|
|
tb->tb_lineno = PyCode_Addr2Line(frame->f_code,
|
|
frame->f_lasti);
|
|
PyObject_GC_Track(tb);
|
|
}
|
|
return tb;
|
|
}
|
|
|
|
int
|
|
PyTraceBack_Here(PyFrameObject *frame)
|
|
{
|
|
PyThreadState *tstate = PyThreadState_GET();
|
|
PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback;
|
|
PyTracebackObject *tb = newtracebackobject(oldtb, frame);
|
|
if (tb == NULL)
|
|
return -1;
|
|
tstate->curexc_traceback = (PyObject *)tb;
|
|
Py_XDECREF(oldtb);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno)
|
|
{
|
|
int err = 0;
|
|
FILE *xfp = NULL;
|
|
char linebuf[2000];
|
|
int i;
|
|
char namebuf[MAXPATHLEN+1];
|
|
|
|
if (filename == NULL)
|
|
return -1;
|
|
/* This is needed by Emacs' compile command */
|
|
#define FMT " File \"%.500s\", line %d, in %.500s\n"
|
|
xfp = fopen(filename, "r" PY_STDIOTEXTMODE);
|
|
if (xfp == NULL) {
|
|
/* Search tail of filename in sys.path before giving up */
|
|
PyObject *path;
|
|
const char *tail = strrchr(filename, SEP);
|
|
if (tail == NULL)
|
|
tail = filename;
|
|
else
|
|
tail++;
|
|
path = PySys_GetObject("path");
|
|
if (path != NULL && PyList_Check(path)) {
|
|
Py_ssize_t _npath = PyList_Size(path);
|
|
int npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int);
|
|
size_t taillen = strlen(tail);
|
|
for (i = 0; i < npath; i++) {
|
|
PyObject *v = PyList_GetItem(path, i);
|
|
if (v == NULL) {
|
|
PyErr_Clear();
|
|
break;
|
|
}
|
|
if (PyString_Check(v)) {
|
|
size_t len;
|
|
len = PyString_GET_SIZE(v);
|
|
if (len + 1 + taillen >= MAXPATHLEN)
|
|
continue; /* Too long */
|
|
strcpy(namebuf, PyString_AsString(v));
|
|
if (strlen(namebuf) != len)
|
|
continue; /* v contains '\0' */
|
|
if (len > 0 && namebuf[len-1] != SEP)
|
|
namebuf[len++] = SEP;
|
|
strcpy(namebuf+len, tail);
|
|
xfp = fopen(namebuf, "r" PY_STDIOTEXTMODE);
|
|
if (xfp != NULL) {
|
|
filename = namebuf;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (xfp == NULL)
|
|
return err;
|
|
if (err != 0) {
|
|
fclose(xfp);
|
|
return err;
|
|
}
|
|
|
|
for (i = 0; i < lineno; i++) {
|
|
char* pLastChar = &linebuf[sizeof(linebuf)-2];
|
|
do {
|
|
*pLastChar = '\0';
|
|
if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf, xfp, NULL) == NULL)
|
|
break;
|
|
/* fgets read *something*; if it didn't get as
|
|
far as pLastChar, it must have found a newline
|
|
or hit the end of the file; if pLastChar is \n,
|
|
it obviously found a newline; else we haven't
|
|
yet seen a newline, so must continue */
|
|
} while (*pLastChar != '\0' && *pLastChar != '\n');
|
|
}
|
|
if (i == lineno) {
|
|
char *p = linebuf;
|
|
while (*p == ' ' || *p == '\t' || *p == '\014')
|
|
p++;
|
|
err = PyFile_WriteString(p, f);
|
|
if (err == 0 && strchr(p, '\n') == NULL)
|
|
err = PyFile_WriteString("\n", f);
|
|
}
|
|
fclose(xfp);
|
|
return err;
|
|
}
|
|
|
|
static int
|
|
tb_displayline(PyObject *f, const char *filename, int lineno, const char *name)
|
|
{
|
|
int err = 0;
|
|
char linebuf[2000];
|
|
|
|
if (filename == NULL || name == NULL)
|
|
return -1;
|
|
/* This is needed by Emacs' compile command */
|
|
#define FMT " File \"%.500s\", line %d, in %.500s\n"
|
|
PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name);
|
|
err = PyFile_WriteString(linebuf, f);
|
|
if (err != 0)
|
|
return err;
|
|
|
|
err = PyFile_WriteString(" ", f);
|
|
return Py_DisplaySourceLine(f, filename, lineno);
|
|
}
|
|
|
|
static int
|
|
tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
|
|
{
|
|
int err = 0;
|
|
long depth = 0;
|
|
PyTracebackObject *tb1 = tb;
|
|
while (tb1 != NULL) {
|
|
depth++;
|
|
tb1 = tb1->tb_next;
|
|
}
|
|
while (tb != NULL && err == 0) {
|
|
if (depth <= limit) {
|
|
err = tb_displayline(f,
|
|
PyUnicode_AsString(
|
|
tb->tb_frame->f_code->co_filename),
|
|
tb->tb_lineno,
|
|
PyUnicode_AsString(tb->tb_frame->f_code->co_name));
|
|
}
|
|
depth--;
|
|
tb = tb->tb_next;
|
|
if (err == 0)
|
|
err = PyErr_CheckSignals();
|
|
}
|
|
return err;
|
|
}
|
|
|
|
#define PyTraceBack_LIMIT 1000
|
|
|
|
int
|
|
PyTraceBack_Print(PyObject *v, PyObject *f)
|
|
{
|
|
int err;
|
|
PyObject *limitv;
|
|
long limit = PyTraceBack_LIMIT;
|
|
|
|
if (v == NULL)
|
|
return 0;
|
|
if (!PyTraceBack_Check(v)) {
|
|
PyErr_BadInternalCall();
|
|
return -1;
|
|
}
|
|
limitv = PySys_GetObject("tracebacklimit");
|
|
if (limitv) {
|
|
PyObject *exc_type, *exc_value, *exc_tb;
|
|
|
|
PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
|
|
limit = PyLong_AsLong(limitv);
|
|
if (limit == -1 && PyErr_Occurred()) {
|
|
if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
|
|
limit = PyTraceBack_LIMIT;
|
|
}
|
|
else {
|
|
Py_XDECREF(exc_type);
|
|
Py_XDECREF(exc_value);
|
|
Py_XDECREF(exc_tb);
|
|
return 0;
|
|
}
|
|
}
|
|
else if (limit <= 0) {
|
|
limit = PyTraceBack_LIMIT;
|
|
}
|
|
PyErr_Restore(exc_type, exc_value, exc_tb);
|
|
}
|
|
err = PyFile_WriteString("Traceback (most recent call last):\n", f);
|
|
if (!err)
|
|
err = tb_printinternal((PyTracebackObject *)v, f, limit);
|
|
return err;
|
|
}
|