diff Python/compile.c @ 16823:acbe74f3a786 legacy-trunk

Presumed correct compiler pass for future statements XXX still need to integrate into symtable API compile.h: Remove ff_n_simple_stmt; obsolete. Add ff_found_docstring used internally to skip one and only one string at the beginning of a module. compile.c: Add check for from __future__ imports to far into the file. In symtable_global() check for -1 returned from symtable_lookup(), which signifies name not defined. Add missing DECERF in symtable_add_def. Free c->c_future. future.c: Add special handling for multiple statements joined on a single line using one or more semicolons; this form can include an illegal future statement that would otherwise be hard to detect. Add support for detecting and skipping doc strings.
author Jeremy Hylton <jeremy@alum.mit.edu>
date Wed, 28 Feb 2001 01:58:08 +0000
parents 08d937107fe6
children 27f04d714ecb
line wrap: on
line diff
--- a/Python/compile.c	Wed Feb 28 01:51:01 2001 +0000
+++ b/Python/compile.c	Wed Feb 28 01:58:08 2001 +0000
@@ -64,6 +64,9 @@
 #define LOCAL_GLOBAL \
 "name '%.400s' is a function paramter and declared global"
 
+#define LATE_FUTURE \
+"from __future__ imports must occur at the beginning of the file"
+
 #define MANGLE_LEN 256
 
 #define OFF(x) offsetof(PyCodeObject, x)
@@ -605,6 +608,8 @@
 	Py_XDECREF(c->c_freevars);
 	Py_XDECREF(c->c_cellvars);
 	Py_XDECREF(c->c_lnotab);
+	if (c->c_future)
+		PyMem_Free((void *)c->c_future);
 }
 
 static void
@@ -1544,9 +1549,12 @@
 		PyObject *v = PyString_InternFromString(STR(m));
 		if (v != NULL && *pkeywords == NULL)
 			*pkeywords = PyDict_New();
-		if (v == NULL || *pkeywords == NULL)
+		if (v == NULL)
 			c->c_errors++;
-		else {
+		else if (*pkeywords == NULL) {
+			c->c_errors++;
+			Py_DECREF(v);
+		} else {
 			if (PyDict_GetItem(*pkeywords, v) != NULL)
 				com_error(c, PyExc_SyntaxError,
 					  "duplicate keyword argument");
@@ -3995,6 +4003,7 @@
 {
 	if ((c->c_symtable = symtable_init()) == NULL)
 		return -1;
+	c->c_symtable->st_future = c->c_future;
 	if (c->c_future->ff_nested_scopes)
 		c->c_symtable->st_nested_scopes = 1;
 	c->c_symtable->st_filename = c->c_filename;
@@ -4482,12 +4491,15 @@
 {
 	PyObject *s;
 	char buffer[MANGLE_LEN];
+	int ret;
 
 	if (mangle(st->st_private, name, buffer, sizeof(buffer)))
 		name = buffer;
 	if ((s = PyString_InternFromString(name)) == NULL)
 		return -1;
-	return symtable_add_def_o(st, st->st_cur->ste_symbols, s, flag);
+	ret = symtable_add_def_o(st, st->st_cur->ste_symbols, s, flag);
+	Py_DECREF(s);
+	return ret;
 }
 
 /* Must only be called with mangled names */
@@ -4819,12 +4831,14 @@
 		int flags;
 
 		flags = symtable_lookup(st, name);
+		if (flags < 0)
+			continue;
 		if (flags && flags != DEF_GLOBAL) {
 			char buf[500];
 			if (flags & DEF_PARAM) {
 				PyErr_Format(PyExc_SyntaxError,
 				     "name '%.400s' is local and global",
-					     PyString_AS_STRING(name));
+					     name);
 				set_error_location(st->st_filename,
 						   st->st_cur->ste_lineno);
 				st->st_errors++;
@@ -4873,6 +4887,18 @@
 	   import_as_name: NAME [NAME NAME]
 	*/
 	if (STR(CHILD(n, 0))[0] == 'f') {  /* from */
+		node *dotname = CHILD(n, 1);
+		if (strcmp(STR(CHILD(dotname, 0)), "__future__") == 0) {
+			/* check for bogus imports */
+			if (n->n_lineno >= st->st_future->ff_last_lineno) {
+				PyErr_SetString(PyExc_SyntaxError,
+						LATE_FUTURE);
+ 				set_error_location(st->st_filename,
+						   n->n_lineno);
+				st->st_errors++;
+				return;
+			}
+		}
 		if (TYPE(CHILD(n, 3)) == STAR) {
 			st->st_cur->ste_optimized |= OPT_IMPORT_STAR;
 		} else {