Create two new exceptions:  IndentationError and TabError.  These are
used for indentation related errors.  This patch includes Ping's
improvements for indentation-related error messages.

Closes SourceForge patches #100734 and #100856.
diff --git a/Python/exceptions.c b/Python/exceptions.c
index f766ba5..a70e6c6 100644
--- a/Python/exceptions.c
+++ b/Python/exceptions.c
@@ -68,6 +68,11 @@
       |\n\
       +-- AttributeError\n\
       +-- SyntaxError\n\
+      |    |\n\
+      |    +-- IndentationError\n\
+      |         |\n\
+      |         +-- TabError\n\
+      |\n\
       +-- TypeError\n\
       +-- AssertionError\n\
       +-- LookupError\n\
@@ -783,6 +788,12 @@
 static char
 MemoryError__doc__[] = "Out of memory.";
 
+static char
+IndentationError__doc__[] = "Improper indentation.";
+
+static char
+TabError__doc__[] = "Improper mixture of spaces and tabs.";
+
 
 
 /* module global functions */
@@ -817,6 +828,8 @@
 PyObject *PyExc_RuntimeError;
 PyObject *PyExc_NotImplementedError;
 PyObject *PyExc_SyntaxError;
+PyObject *PyExc_IndentationError;
+PyObject *PyExc_TabError;
 PyObject *PyExc_SystemError;
 PyObject *PyExc_SystemExit;
 PyObject *PyExc_UnboundLocalError;
@@ -878,6 +891,10 @@
  {"AttributeError",     &PyExc_AttributeError, 0, AttributeError__doc__},
  {"SyntaxError",        &PyExc_SyntaxError,    0, SyntaxError__doc__,
   SyntaxError_methods, SyntaxError__classinit__},
+ {"IndentationError",   &PyExc_IndentationError, &PyExc_SyntaxError,
+  IndentationError__doc__},
+ {"TabError",   &PyExc_TabError, &PyExc_IndentationError,
+  TabError__doc__},
  {"AssertionError",     &PyExc_AssertionError, 0, AssertionError__doc__},
  {"LookupError",        &PyExc_LookupError,    0, LookupError__doc__},
  {"IndexError",         &PyExc_IndexError,     &PyExc_LookupError,
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 74dffae..9cc8072 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -14,6 +14,7 @@
 
 #include "grammar.h"
 #include "node.h"
+#include "token.h"
 #include "parsetok.h"
 #include "errcode.h"
 #include "compile.h"
@@ -983,8 +984,9 @@
 err_input(err)
 	perrdetail *err;
 {
-	PyObject *v, *w;
+	PyObject *v, *w, *errtype;
 	char *msg = NULL;
+	errtype = PyExc_SyntaxError;
 	v = Py_BuildValue("(ziiz)", err->filename,
 			    err->lineno, err->offset, err->text);
 	if (err->text != NULL) {
@@ -993,7 +995,17 @@
 	}
 	switch (err->error) {
 	case E_SYNTAX:
-		msg = "invalid syntax";
+		errtype = PyExc_IndentationError;
+		if (err->expected == INDENT)
+			msg = "expected an indented block";
+		else if (err->token == INDENT)
+			msg = "unexpected indent";
+		else if (err->token == DEDENT)
+			msg = "unexpected unindent";
+		else {
+			errtype = PyExc_SyntaxError;
+			msg = "invalid syntax";
+		}
 		break;
 	case E_TOKEN:
 		msg = "invalid token";
@@ -1009,12 +1021,21 @@
 	case E_EOF:
 		msg = "unexpected EOF while parsing";
 		break;
-	case E_INDENT:
+	case E_TABSPACE:
+		errtype = PyExc_TabError;
 		msg = "inconsistent use of tabs and spaces in indentation";
 		break;
 	case E_OVERFLOW:
 		msg = "expression too long";
 		break;
+	case E_DEDENT:
+		errtype = PyExc_IndentationError;
+		msg = "unindent does not match any outer indentation level";
+		break;
+	case E_TOODEEP:
+		errtype = PyExc_IndentationError;
+		msg = "too many levels of indentation";
+		break;
 	default:
 		fprintf(stderr, "error=%d\n", err->error);
 		msg = "unknown parsing error";
@@ -1022,7 +1043,7 @@
 	}
 	w = Py_BuildValue("(sO)", msg, v);
 	Py_XDECREF(v);
-	PyErr_SetObject(PyExc_SyntaxError, w);
+	PyErr_SetObject(errtype, w);
 	Py_XDECREF(w);
 }