diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2001-02-28 17:47:12 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2001-02-28 17:47:12 (GMT) |
commit | ad3d3f2f3f19833f59fd7e9ec59e1714e0986e08 (patch) | |
tree | 3b1b99d9f5330c80768ceb14484050a3ff7162d7 /Python/errors.c | |
parent | 5687ffe0c56a827b538589fc46e79dfacfd857f3 (diff) | |
download | cpython-ad3d3f2f3f19833f59fd7e9ec59e1714e0986e08.zip cpython-ad3d3f2f3f19833f59fd7e9ec59e1714e0986e08.tar.gz cpython-ad3d3f2f3f19833f59fd7e9ec59e1714e0986e08.tar.bz2 |
Improve SyntaxErrors for bad future statements. Set file and location
for errors raised in future.c.
Move some helper functions from compile.c to errors.c and make them
API functions: PyErr_SyntaxLocation() and PyErr_ProgramText().
Diffstat (limited to 'Python/errors.c')
-rw-r--r-- | Python/errors.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/Python/errors.c b/Python/errors.c index 908c0c1..41050ce 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -622,3 +622,82 @@ PyErr_Warn(PyObject *category, char *message) return 0; } } + +void +PyErr_SyntaxLocation(char *filename, int lineno) +{ + PyObject *exc, *v, *tb, *tmp; + + /* add attributes for the line number and filename for the error */ + PyErr_Fetch(&exc, &v, &tb); + PyErr_NormalizeException(&exc, &v, &tb); + /* XXX check that it is, indeed, a syntax error */ + tmp = PyInt_FromLong(lineno); + if (tmp == NULL) + PyErr_Clear(); + else { + if (PyObject_SetAttrString(v, "lineno", tmp)) + PyErr_Clear(); + Py_DECREF(tmp); + } + if (filename != NULL) { + tmp = PyString_FromString(filename); + if (tmp == NULL) + PyErr_Clear(); + else { + if (PyObject_SetAttrString(v, "filename", tmp)) + PyErr_Clear(); + Py_DECREF(tmp); + } + + tmp = PyErr_ProgramText(filename, lineno); + if (tmp) { + PyObject_SetAttrString(v, "text", tmp); + Py_DECREF(tmp); + } + } + PyErr_Restore(exc, v, tb); +} + +/* com_fetch_program_text will attempt to load the line of text that + the exception refers to. If it fails, it will return NULL but will + not set an exception. + + XXX The functionality of this function is quite similar to the + functionality in tb_displayline() in traceback.c. +*/ + +PyObject * +PyErr_ProgramText(char *filename, int lineno) +{ + FILE *fp; + int i; + char linebuf[1000]; + + if (filename == NULL || lineno <= 0) + return NULL; + fp = fopen(filename, "r"); + if (fp == NULL) + return NULL; + for (i = 0; i < lineno; i++) { + char *pLastChar = &linebuf[sizeof(linebuf) - 2]; + do { + *pLastChar = '\0'; + if (fgets(linebuf, sizeof linebuf, fp) == 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'); + } + fclose(fp); + if (i == lineno) { + char *p = linebuf; + while (*p == ' ' || *p == '\t' || *p == '\014') + p++; + return PyString_FromString(p); + } + return NULL; +} |