Patch #50002: Display line information for bad \x escapes:
- recognize "SyntaxError"s by the print_file_and_line attribute.
- add the syntaxerror attributes to all exceptions in compile.c.
Fixes #221791
diff --git a/Misc/NEWS b/Misc/NEWS
index 15644b8..58d5a66 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -6,6 +6,9 @@
 
 Core and builtins
 
+- PyErr_Display will provide file and line information for all exceptions
+  that have an attribute print_file_and_line, not just SyntaxErrors.
+
 - The UTF-8 codec will now encode and decode Unicode surrogates
   correctly and without raising exceptions for unpaired ones.
 
diff --git a/Python/compile.c b/Python/compile.c
index dbae00d..de0a8e2 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -465,14 +465,21 @@
 		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);
+	if (exc == PyExc_SyntaxError) {
+		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);
+	} else {
+		/* Make sure additional exceptions are printed with
+		   file and line, also. */
+		PyErr_SetObject(exc, v);
+		PyErr_SyntaxLocation(c->c_filename, c->c_lineno);
+	}
  exit:
 	Py_XDECREF(t);
 	Py_XDECREF(v);
@@ -1153,7 +1160,8 @@
 	s++;
 	len = strlen(s);
 	if (len > INT_MAX) {
-		PyErr_SetString(PyExc_OverflowError, "string to parse is too long");
+		com_error(com, PyExc_OverflowError, 
+			  "string to parse is too long");
 		return NULL;
 	}
 	if (s[--len] != quote) {
@@ -1171,11 +1179,15 @@
 #ifdef Py_USING_UNICODE
 	if (unicode || Py_UnicodeFlag) {
 		if (rawmode)
-			return PyUnicode_DecodeRawUnicodeEscape(
-				s, len, NULL);
+			v = PyUnicode_DecodeRawUnicodeEscape(
+				 s, len, NULL);
 		else
-			return PyUnicode_DecodeUnicodeEscape(
+			v = PyUnicode_DecodeUnicodeEscape(
 				s, len, NULL);
+		if (v == NULL)
+			PyErr_SyntaxLocation(com->c_filename, com->c_lineno);
+		return v;
+			
 	}
 #endif
 	if (rawmode || strchr(s, '\\') == NULL)
@@ -1238,9 +1250,9 @@
 				*p++ = x;
 				break;
 			}
-			PyErr_SetString(PyExc_ValueError, 
-					"invalid \\x escape");
 			Py_DECREF(v);
+			com_error(com, PyExc_ValueError, 
+				  "invalid \\x escape");
 			return NULL;
 		default:
 			*p++ = '\\';
diff --git a/Python/errors.c b/Python/errors.c
index 2799cff..13b3d11 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -561,7 +561,9 @@
 }
 
 
-/* XXX There's a comment missing here */
+/* Set file and line information for the current exception.
+   If the exception is not a SyntaxError, also sets additional attributes
+   to make printing of exceptions believe it is a syntax error. */
 
 void
 PyErr_SyntaxLocation(char *filename, int lineno)
@@ -596,6 +598,26 @@
 			Py_DECREF(tmp);
 		}
 	}
+	if (PyObject_SetAttrString(v, "offset", Py_None)) {
+		PyErr_Clear();
+	}
+	if (exc != PyExc_SyntaxError) {
+		if (!PyObject_HasAttrString(v, "msg")) {
+			tmp = PyObject_Str(v);
+			if (tmp) {
+				if (PyObject_SetAttrString(v, "msg", tmp))
+					PyErr_Clear();
+				Py_DECREF(tmp);
+			} else {
+				PyErr_Clear();
+			}
+		}
+		if (!PyObject_HasAttrString(v, "print_file_and_line")) {
+			if (PyObject_SetAttrString(v, "print_file_and_line",
+						   Py_None))
+				PyErr_Clear();
+		}
+	}
 	PyErr_Restore(exc, v, tb);
 }
 
diff --git a/Python/exceptions.c b/Python/exceptions.c
index 99002bf..adfd699 100644
--- a/Python/exceptions.c
+++ b/Python/exceptions.c
@@ -670,7 +670,8 @@
 	PyObject_SetAttrString(klass, "filename", Py_None) ||
 	PyObject_SetAttrString(klass, "lineno", Py_None) ||
 	PyObject_SetAttrString(klass, "offset", Py_None) ||
-	PyObject_SetAttrString(klass, "text", Py_None))
+	PyObject_SetAttrString(klass, "text", Py_None) ||
+	PyObject_SetAttrString(klass, "print_file_and_line", Py_None))
     {
 	retval = -1;
     }
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 6b70739..ad92004 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -920,7 +920,7 @@
 		if (tb && tb != Py_None)
 			err = PyTraceBack_Print(tb, f);
 		if (err == 0 &&
-		    PyErr_GivenExceptionMatches(exception, PyExc_SyntaxError))
+		    PyObject_HasAttrString(v, "print_file_and_line"))
 		{
 			PyObject *message;
 			char *filename, *text;