History

add hg and python

cinap_lenrek committed 15 years ago

Commit 4bb9e221 parent 987265c3706 files · +1228772 −-233Browse files

Showing the changes to sys/src/cmd/python/Python/traceback.c (1 of 3706 files). Show all

Unified · Split

sys/src/cmd/python/Python/traceback.c+262−0
@@ -0,0 +1,262 @@
1+
2+/* Traceback implementation */
3+
4+#include "Python.h"
5+
6+#include "code.h"
7+#include "frameobject.h"
8+#include "structmember.h"
9+#include "osdefs.h"
10+#include "traceback.h"
11+
12+#define OFF(x) offsetof(PyTracebackObject, x)
13+
14+static struct memberlist tb_memberlist[] = {
15+ {"tb_next", T_OBJECT, OFF(tb_next)},
16+ {"tb_frame", T_OBJECT, OFF(tb_frame)},
17+ {"tb_lasti", T_INT, OFF(tb_lasti)},
18+ {"tb_lineno", T_INT, OFF(tb_lineno)},
19+ {NULL} /* Sentinel */
20+};
21+
22+static PyObject *
23+tb_getattr(PyTracebackObject *tb, char *name)
24+{
25+ return PyMember_Get((char *)tb, tb_memberlist, name);
26+}
27+
28+static void
29+tb_dealloc(PyTracebackObject *tb)
30+{
31+ PyObject_GC_UnTrack(tb);
32+ Py_TRASHCAN_SAFE_BEGIN(tb)
33+ Py_XDECREF(tb->tb_next);
34+ Py_XDECREF(tb->tb_frame);
35+ PyObject_GC_Del(tb);
36+ Py_TRASHCAN_SAFE_END(tb)
37+}
38+
39+static int
40+tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg)
41+{
42+ Py_VISIT(tb->tb_next);
43+ Py_VISIT(tb->tb_frame);
44+ return 0;
45+}
46+
47+static void
48+tb_clear(PyTracebackObject *tb)
49+{
50+ Py_CLEAR(tb->tb_next);
51+ Py_CLEAR(tb->tb_frame);
52+}
53+
54+PyTypeObject PyTraceBack_Type = {
55+ PyObject_HEAD_INIT(&PyType_Type)
56+ 0,
57+ "traceback",
58+ sizeof(PyTracebackObject),
59+ 0,
60+ (destructor)tb_dealloc, /*tp_dealloc*/
61+ 0, /*tp_print*/
62+ (getattrfunc)tb_getattr, /*tp_getattr*/
63+ 0, /*tp_setattr*/
64+ 0, /*tp_compare*/
65+ 0, /*tp_repr*/
66+ 0, /*tp_as_number*/
67+ 0, /*tp_as_sequence*/
68+ 0, /*tp_as_mapping*/
69+ 0, /* tp_hash */
70+ 0, /* tp_call */
71+ 0, /* tp_str */
72+ 0, /* tp_getattro */
73+ 0, /* tp_setattro */
74+ 0, /* tp_as_buffer */
75+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
76+ 0, /* tp_doc */
77+ (traverseproc)tb_traverse, /* tp_traverse */
78+ (inquiry)tb_clear, /* tp_clear */
79+ 0, /* tp_richcompare */
80+ 0, /* tp_weaklistoffset */
81+ 0, /* tp_iter */
82+ 0, /* tp_iternext */
83+ 0, /* tp_methods */
84+ 0, /* tp_members */
85+ 0, /* tp_getset */
86+ 0, /* tp_base */
87+ 0, /* tp_dict */
88+};
89+
90+static PyTracebackObject *
91+newtracebackobject(PyTracebackObject *next, PyFrameObject *frame)
92+{
93+ PyTracebackObject *tb;
94+ if ((next != NULL && !PyTraceBack_Check(next)) ||
95+ frame == NULL || !PyFrame_Check(frame)) {
96+ PyErr_BadInternalCall();
97+ return NULL;
98+ }
99+ tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
100+ if (tb != NULL) {
101+ Py_XINCREF(next);
102+ tb->tb_next = next;
103+ Py_XINCREF(frame);
104+ tb->tb_frame = frame;
105+ tb->tb_lasti = frame->f_lasti;
106+ tb->tb_lineno = PyCode_Addr2Line(frame->f_code,
107+ frame->f_lasti);
108+ PyObject_GC_Track(tb);
109+ }
110+ return tb;
111+}
112+
113+int
114+PyTraceBack_Here(PyFrameObject *frame)
115+{
116+ PyThreadState *tstate = PyThreadState_GET();
117+ PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback;
118+ PyTracebackObject *tb = newtracebackobject(oldtb, frame);
119+ if (tb == NULL)
120+ return -1;
121+ tstate->curexc_traceback = (PyObject *)tb;
122+ Py_XDECREF(oldtb);
123+ return 0;
124+}
125+
126+static int
127+tb_displayline(PyObject *f, char *filename, int lineno, char *name)
128+{
129+ int err = 0;
130+ FILE *xfp;
131+ char linebuf[2000];
132+ int i;
133+ if (filename == NULL || name == NULL)
134+ return -1;
135+ /* This is needed by Emacs' compile command */
136+#define FMT " File \"%.500s\", line %d, in %.500s\n"
137+ xfp = fopen(filename, "r" PY_STDIOTEXTMODE);
138+ if (xfp == NULL) {
139+ /* Search tail of filename in sys.path before giving up */
140+ PyObject *path;
141+ char *tail = strrchr(filename, SEP);
142+ if (tail == NULL)
143+ tail = filename;
144+ else
145+ tail++;
146+ path = PySys_GetObject("path");
147+ if (path != NULL && PyList_Check(path)) {
148+ Py_ssize_t _npath = PyList_Size(path);
149+ int npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int);
150+ size_t taillen = strlen(tail);
151+ char namebuf[MAXPATHLEN+1];
152+ for (i = 0; i < npath; i++) {
153+ PyObject *v = PyList_GetItem(path, i);
154+ if (v == NULL) {
155+ PyErr_Clear();
156+ break;
157+ }
158+ if (PyString_Check(v)) {
159+ size_t len;
160+ len = PyString_GET_SIZE(v);
161+ if (len + 1 + taillen >= MAXPATHLEN)
162+ continue; /* Too long */
163+ strcpy(namebuf, PyString_AsString(v));
164+ if (strlen(namebuf) != len)
165+ continue; /* v contains '\0' */
166+ if (len > 0 && namebuf[len-1] != SEP)
167+ namebuf[len++] = SEP;
168+ strcpy(namebuf+len, tail);
169+ xfp = fopen(namebuf, "r" PY_STDIOTEXTMODE);
170+ if (xfp != NULL) {
171+ filename = namebuf;
172+ break;
173+ }
174+ }
175+ }
176+ }
177+ }
178+ PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name);
179+ err = PyFile_WriteString(linebuf, f);
180+ if (xfp == NULL)
181+ return err;
182+ else if (err != 0) {
183+ fclose(xfp);
184+ return err;
185+ }
186+ for (i = 0; i < lineno; i++) {
187+ char* pLastChar = &linebuf[sizeof(linebuf)-2];
188+ do {
189+ *pLastChar = '\0';
190+ if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf, xfp, NULL) == NULL)
191+ break;
192+ /* fgets read *something*; if it didn't get as
193+ far as pLastChar, it must have found a newline
194+ or hit the end of the file; if pLastChar is \n,
195+ it obviously found a newline; else we haven't
196+ yet seen a newline, so must continue */
197+ } while (*pLastChar != '\0' && *pLastChar != '\n');
198+ }
199+ if (i == lineno) {
200+ char *p = linebuf;
201+ while (*p == ' ' || *p == '\t' || *p == '\014')
202+ p++;
203+ err = PyFile_WriteString(" ", f);
204+ if (err == 0) {
205+ err = PyFile_WriteString(p, f);
206+ if (err == 0 && strchr(p, '\n') == NULL)
207+ err = PyFile_WriteString("\n", f);
208+ }
209+ }
210+ fclose(xfp);
211+ return err;
212+}
213+
214+static int
215+tb_printinternal(PyTracebackObject *tb, PyObject *f, int limit)
216+{
217+ int err = 0;
218+ int depth = 0;
219+ PyTracebackObject *tb1 = tb;
220+ while (tb1 != NULL) {
221+ depth++;
222+ tb1 = tb1->tb_next;
223+ }
224+ while (tb != NULL && err == 0) {
225+ if (depth <= limit) {
226+ err = tb_displayline(f,
227+ PyString_AsString(
228+ tb->tb_frame->f_code->co_filename),
229+ tb->tb_lineno,
230+ PyString_AsString(tb->tb_frame->f_code->co_name));
231+ }
232+ depth--;
233+ tb = tb->tb_next;
234+ if (err == 0)
235+ err = PyErr_CheckSignals();
236+ }
237+ return err;
238+}
239+
240+int
241+PyTraceBack_Print(PyObject *v, PyObject *f)
242+{
243+ int err;
244+ PyObject *limitv;
245+ int limit = 1000;
246+ if (v == NULL)
247+ return 0;
248+ if (!PyTraceBack_Check(v)) {
249+ PyErr_BadInternalCall();
250+ return -1;
251+ }
252+ limitv = PySys_GetObject("tracebacklimit");
253+ if (limitv && PyInt_Check(limitv)) {
254+ limit = PyInt_AsLong(limitv);
255+ if (limit <= 0)
256+ return 0;
257+ }
258+ err = PyFile_WriteString("Traceback (most recent call last):\n", f);
259+ if (!err)
260+ err = tb_printinternal((PyTracebackObject *)v, f, limit);
261+ return err;
262+}