summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Python/compile.c127
-rw-r--r--Python/pythonrun.c84
2 files changed, 144 insertions, 67 deletions
diff --git a/Python/compile.c b/Python/compile.c
index d9294d4..c540d6b 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -381,41 +381,54 @@ int is_free(int v)
return 0;
}
-/* Error message including line number */
+/* 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.
-static void
-set_error_location(char *filename, int lineno)
+ XXX The functionality of this function is quite similar to the
+ functionality in tb_displayline() in traceback.c.
+*/
+
+static PyObject *
+fetch_program_text(char *filename, int lineno)
{
- PyObject *exc, *v, *tb, *tmp;
+ FILE *fp;
+ int i;
+ char linebuf[1000];
- /* add attributes for the line number and filename for the error */
- PyErr_Fetch(&exc, &v, &tb);
- PyErr_NormalizeException(&exc, &v, &tb);
- 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);
- }
+ 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);
}
- PyErr_Restore(exc, v, tb);
+ return NULL;
}
static void
com_error(struct compiling *c, PyObject *exc, char *msg)
{
- PyObject *v;
+ PyObject *t = NULL, *v = NULL, *w = NULL, *line = NULL;
+
if (c == NULL) {
/* Error occurred via symtable call to
is_constant_false */
@@ -423,18 +436,33 @@ com_error(struct compiling *c, PyObject *exc, char *msg)
return;
}
c->c_errors++;
- if (c->c_lineno <= 1) {
- /* Unknown line number or single interactive command */
+ if (c->c_lineno < 1 || c->c_interactive) {
+ /* Unknown line number or interactive input */
PyErr_SetString(exc, msg);
return;
}
v = PyString_FromString(msg);
if (v == NULL)
return; /* MemoryError, too bad */
- PyErr_SetObject(exc, v);
- Py_DECREF(v);
- set_error_location(c->c_filename, c->c_lineno);
+ line = fetch_program_text(c->c_filename, c->c_lineno);
+ if (line == NULL) {
+ Py_INCREF(Py_None);
+ line = Py_None;
+ }
+ t = Py_BuildValue("(ziOO)", c->c_filename, c->c_lineno,
+ Py_None, line);
+ if (t == NULL)
+ goto exit;
+ w = Py_BuildValue("(OO)", v, t);
+ if (w == NULL)
+ goto exit;
+ PyErr_SetObject(exc, w);
+ exit:
+ Py_XDECREF(t);
+ Py_XDECREF(v);
+ Py_XDECREF(w);
+ Py_XDECREF(line);
}
/* Interface to the block stack */
@@ -3998,6 +4026,43 @@ get_ref_type(struct compiling *c, char *name)
return -1; /* can't get here */
}
+/* Helper function for setting lineno and filename */
+
+static void
+set_error_location(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);
+ 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 = fetch_program_text(filename, lineno);
+ if (tmp) {
+ PyObject_SetAttrString(v, "text", tmp);
+ Py_DECREF(tmp);
+ }
+ }
+ PyErr_Restore(exc, v, tb);
+}
+
static int
symtable_build(struct compiling *c, node *n)
{
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 48b875e..40611b6 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -693,12 +693,18 @@ parse_syntax_error(PyObject *err, PyObject **message, char **filename,
if (!(v = PyObject_GetAttrString(err, "offset")))
goto finally;
- hold = PyInt_AsLong(v);
- Py_DECREF(v);
- v = NULL;
- if (hold < 0 && PyErr_Occurred())
- goto finally;
- *offset = (int)hold;
+ if (v == Py_None) {
+ *offset = -1;
+ Py_DECREF(v);
+ v = NULL;
+ } else {
+ hold = PyInt_AsLong(v);
+ Py_DECREF(v);
+ v = NULL;
+ if (hold < 0 && PyErr_Occurred())
+ goto finally;
+ *offset = (int)hold;
+ }
if (!(v = PyObject_GetAttrString(err, "text")))
goto finally;
@@ -720,6 +726,40 @@ PyErr_Print(void)
PyErr_PrintEx(1);
}
+static void
+print_error_text(PyObject *f, int offset, char *text)
+{
+ char *nl;
+ if (offset >= 0) {
+ if (offset > 0 && offset == (int)strlen(text))
+ offset--;
+ for (;;) {
+ nl = strchr(text, '\n');
+ if (nl == NULL || nl-text >= offset)
+ break;
+ offset -= (nl+1-text);
+ text = nl+1;
+ }
+ while (*text == ' ' || *text == '\t') {
+ text++;
+ offset--;
+ }
+ }
+ PyFile_WriteString(" ", f);
+ PyFile_WriteString(text, f);
+ if (*text == '\0' || text[strlen(text)-1] != '\n')
+ PyFile_WriteString("\n", f);
+ if (offset == -1)
+ return;
+ PyFile_WriteString(" ", f);
+ offset--;
+ while (offset > 0) {
+ PyFile_WriteString(" ", f);
+ offset--;
+ }
+ PyFile_WriteString("^\n", f);
+}
+
void
PyErr_PrintEx(int set_sys_last_vars)
{
@@ -795,36 +835,8 @@ PyErr_PrintEx(int set_sys_last_vars)
sprintf(buf, "%d", lineno);
PyFile_WriteString(buf, f);
PyFile_WriteString("\n", f);
- if (text != NULL) {
- char *nl;
- if (offset > 0 &&
- offset == (int)strlen(text))
- offset--;
- for (;;) {
- nl = strchr(text, '\n');
- if (nl == NULL ||
- nl-text >= offset)
- break;
- offset -= (nl+1-text);
- text = nl+1;
- }
- while (*text == ' ' || *text == '\t') {
- text++;
- offset--;
- }
- PyFile_WriteString(" ", f);
- PyFile_WriteString(text, f);
- if (*text == '\0' ||
- text[strlen(text)-1] != '\n')
- PyFile_WriteString("\n", f);
- PyFile_WriteString(" ", f);
- offset--;
- while (offset > 0) {
- PyFile_WriteString(" ", f);
- offset--;
- }
- PyFile_WriteString("^\n", f);
- }
+ if (text != NULL)
+ print_error_text(f, offset, text);
Py_INCREF(message);
Py_DECREF(v);
v = message;