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().
diff --git a/Python/compile.c b/Python/compile.c
index c540d6b..b445122 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -381,49 +381,6 @@
 	return 0;
 }
 
-/* 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.
-*/
-
-static PyObject *
-fetch_program_text(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;
-}
-
 static void
 com_error(struct compiling *c, PyObject *exc, char *msg)
 {
@@ -445,7 +402,7 @@
 	if (v == NULL)
 		return; /* MemoryError, too bad */
 
-	line = fetch_program_text(c->c_filename, c->c_lineno);
+	line = PyErr_ProgramText(c->c_filename, c->c_lineno);
 	if (line == NULL) {
 		Py_INCREF(Py_None);
 		line = Py_None;
@@ -4028,41 +3985,6 @@
 
 /* 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)
 {
@@ -4198,7 +4120,7 @@
 				PyErr_Format(PyExc_SyntaxError,
 					     ILLEGAL_DYNAMIC_SCOPE, 
 				     PyString_AS_STRING(ste->ste_name));
-				set_error_location(c->c_symtable->st_filename,
+				PyErr_SyntaxLocation(c->c_symtable->st_filename,
 						   ste->ste_lineno);
 				return -1;
 			} else {
@@ -4273,7 +4195,7 @@
 			if (flags & DEF_PARAM) {
 				PyErr_Format(PyExc_SyntaxError, LOCAL_GLOBAL,
 					     PyString_AS_STRING(name));
-				set_error_location(st->st_filename, 
+				PyErr_SyntaxLocation(st->st_filename, 
 						   ste->ste_lineno);
 				st->st_errors++;
 				goto fail;
@@ -4581,7 +4503,7 @@
 	    if ((flag & DEF_PARAM) && (val & DEF_PARAM)) {
 		    PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT,
 				 PyString_AsString(name));
-		    set_error_location(st->st_filename,
+		    PyErr_SyntaxLocation(st->st_filename,
 				       st->st_cur->ste_lineno);
 		    return -1;
 	    }
@@ -4904,7 +4826,7 @@
 				PyErr_Format(PyExc_SyntaxError,
 				     "name '%.400s' is local and global",
 					     name);
-				set_error_location(st->st_filename,
+				PyErr_SyntaxLocation(st->st_filename,
 						   st->st_cur->ste_lineno);
 				st->st_errors++;
 				return;
@@ -4958,7 +4880,7 @@
 			if (n->n_lineno >= st->st_future->ff_last_lineno) {
 				PyErr_SetString(PyExc_SyntaxError,
 						LATE_FUTURE);
- 				set_error_location(st->st_filename,
+ 				PyErr_SyntaxLocation(st->st_filename,
 						   n->n_lineno);
 				st->st_errors++;
 				return;
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 @@
 		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;
+}
diff --git a/Python/future.c b/Python/future.c
index 37d5476..89466f0 100644
--- a/Python/future.c
+++ b/Python/future.c
@@ -6,24 +6,40 @@
 #include "symtable.h"
 
 #define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
+#define FUTURE_IMPORT_STAR "future statement does not support import *"
 
 #define FUTURE_POSSIBLE(FF) ((FF)->ff_last_lineno == -1)
 
 static int
-future_check_features(PyFutureFeatures *ff, node *n)
+future_check_features(PyFutureFeatures *ff, node *n, char *filename)
 {
 	int i;
 	char *feature;
+	node *ch;
 
 	REQ(n, import_stmt); /* must by from __future__ import ... */
 
 	for (i = 3; i < NCH(n); ++i) {
-		feature = STR(CHILD(CHILD(n, i), 0));
+		ch = CHILD(n, i);
+		if (TYPE(ch) == STAR) {
+			PyErr_SetString(PyExc_SyntaxError,
+					FUTURE_IMPORT_STAR);
+			PyErr_SyntaxLocation(filename, ch->n_lineno);
+			return -1;
+		}
+		REQ(ch, import_as_name);
+		feature = STR(CHILD(ch, 0));
 		if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
 			ff->ff_nested_scopes = 1;
+		} else if (strcmp(feature, "braces") == 0) {
+			PyErr_SetString(PyExc_SyntaxError,
+					"not a chance");
+			PyErr_SyntaxLocation(filename, CHILD(ch, 0)->n_lineno);
+			return -1;
 		} else {
 			PyErr_Format(PyExc_SyntaxError,
 				     UNDEFINED_FUTURE_FEATURE, feature);
+			PyErr_SyntaxLocation(filename, CHILD(ch, 0)->n_lineno);
 			return -1;
 		}
 	}
@@ -36,6 +52,7 @@
 	PyErr_SetString(PyExc_SyntaxError,
 			"from __future__ imports must occur at the "
 			"beginning of the file");
+	PyErr_SyntaxLocation(filename, n->n_lineno);
 	/* XXX set filename and lineno */
 }
 
@@ -45,8 +62,10 @@
 file_input: (NEWLINE | stmt)* ENDMARKER
 stmt: simple_stmt | compound_stmt
 simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
-small_stmt: expr_stmt | print_stmt  | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt
-import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*)
+small_stmt: expr_stmt | print_stmt  | del_stmt | pass_stmt | flow_stmt 
+    | import_stmt | global_stmt | exec_stmt | assert_stmt
+import_stmt: 'import' dotted_as_name (',' dotted_as_name)* 
+    | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*)
 import_as_name: NAME [NAME NAME]
 dotted_as_name: dotted_name [NAME NAME]
 dotted_name: NAME ('.' NAME)*
@@ -64,11 +83,6 @@
 	int i, r;
  loop:
 
-/*	fprintf(stderr, "future_parse(%d, %d, %s, %d)\n",
-		TYPE(n), NCH(n), (n == NULL) ? "NULL" : STR(n),
-		n->n_lineno);
-*/
-
 	switch (TYPE(n)) {
 
 	case single_input:
@@ -162,7 +176,7 @@
 		name = CHILD(n, 1);
 		if (strcmp(STR(CHILD(name, 0)), "__future__") != 0)
 			return 0;
-		if (future_check_features(ff, n) < 0)
+		if (future_check_features(ff, n, filename) < 0)
 			return -1;
 		ff->ff_last_lineno = n->n_lineno + 1;
 		return 1;