Index: Python/pythonrun.c =================================================================== --- Python/pythonrun.c (révision 70384) +++ Python/pythonrun.c (copie de travail) @@ -1212,15 +1212,18 @@ static int parse_syntax_error(PyObject *err, PyObject **message, const char **filename, - int *lineno, int *offset, const char **text) + int *lineno, int *offset, PyObject **text) { long hold; PyObject *v; /* old style errors */ - if (PyTuple_Check(err)) - return PyArg_ParseTuple(err, "O(ziiz)", message, filename, - lineno, offset, text); + if (PyTuple_Check(err)) { + if (!PyArg_ParseTuple(err, "O(ziiO)", message, filename, + lineno, offset, text)) + return 0; + return PyUnicode_Check(*text); + } /* new style errors. `err' is an instance */ @@ -1262,12 +1265,13 @@ if (!(v = PyObject_GetAttrString(err, "text"))) goto finally; - if (v == Py_None) + if (v == Py_None) { *text = NULL; - else if (!PyUnicode_Check(v) || - !(*text = _PyUnicode_AsString(v))) - goto finally; Py_DECREF(v); + } else if (!PyUnicode_Check(v)) + goto finally; + else + *text = v; return 1; finally: @@ -1282,32 +1286,63 @@ } static void -print_error_text(PyObject *f, int offset, const char *text) +print_error_text(PyObject *f, int offset, PyObject *textobj) { - char *nl; + Py_UNICODE *nl, *text = PyUnicode_AS_UNICODE(textobj); + Py_ssize_t textlen = PyUnicode_GET_SIZE(textobj); + PyObject *truncated; + if (offset >= 0) { - if (offset > 0 && offset == (int)strlen(text)) + if (offset > 0 && offset == textlen) offset--; for (;;) { - nl = strchr(text, '\n'); + int diff; + nl = Py_UNICODE_strchr(text, '\n'); if (nl == NULL || nl-text >= offset) break; - offset -= (int)(nl+1-text); + diff = (int)(nl+1-text); + offset -= diff; + textlen -= diff; text = nl+1; } while (*text == ' ' || *text == '\t') { text++; + textlen--; offset--; } } + PyFile_WriteString(" ", f); - PyFile_WriteString(text, f); - if (*text == '\0' || text[strlen(text)-1] != '\n') + + truncated = PyUnicode_FromUnicode(text, textlen); + if (truncated) { + PyFile_WriteObject(truncated, f, Py_PRINT_RAW); + Py_DECREF(truncated); + if (*text == '\0' || text[textlen-1] != '\n') + PyFile_WriteString("\n", f); + } else { + PyErr_Clear(); + PyFile_WriteObject(textobj, f, Py_PRINT_RAW); PyFile_WriteString("\n", f); + } + if (offset == -1) return; PyFile_WriteString(" ", f); - offset--; + + /* get string width */ + truncated = PyUnicode_FromUnicode(text, offset); + if (truncated) { + int width = PyUnicode_Width(truncated); + if (0 <= width) + offset = width; + else + PyErr_Clear(); + Py_DECREF(truncated); + } else { + PyErr_Clear(); + } + while (offset > 0) { PyFile_WriteString(" ", f); offset--; @@ -1450,8 +1485,8 @@ if (err == 0 && PyObject_HasAttrString(value, "print_file_and_line")) { - PyObject *message; - const char *filename, *text; + PyObject *message, *text; + const char *filename; int lineno, offset; if (!parse_syntax_error(value, &message, &filename, &lineno, &offset, &text)) @@ -1467,8 +1502,10 @@ PyOS_snprintf(buf, sizeof(buf), "%d", lineno); PyFile_WriteString(buf, f); PyFile_WriteString("\n", f); - if (text != NULL) + if (text != NULL) { print_error_text(f, offset, text); + Py_DECREF(text); + } Py_DECREF(value); value = message; /* Can't be bothered to check all those