[Python-checkins] CVS: python/dist/src/Python future.c,2.3,2.4 compile.c,2.176,2.177 errors.c,2.59,2.60
Jeremy Hylton
jhylton@users.sourceforge.net
Wed, 28 Feb 2001 09:47:14 -0800
- Previous message: [Python-checkins] CVS: python/dist/src/Include pyerrors.h,2.42,2.43
- Next message: [Python-checkins] CVS: python/dist/src/Lib/test test_future.py,NONE,1.1 test_future1.py,NONE,1.1 test_future2.py,NONE,1.1 test_future3.py,NONE,1.1 test_future4.py,NONE,1.1 test_future5.py,NONE,1.1 test_future6.py,NONE,1.1 test_future7.py,NONE,1.1 regrtest.py,1.31,1.32
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv19377/Python
Modified Files:
future.c compile.c errors.c
Log Message:
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().
Index: future.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/future.c,v
retrieving revision 2.3
retrieving revision 2.4
diff -C2 -r2.3 -r2.4
*** future.c 2001/02/28 02:26:14 2.3
--- future.c 2001/02/28 17:47:12 2.4
***************
*** 7,28 ****
#define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
#define FUTURE_POSSIBLE(FF) ((FF)->ff_last_lineno == -1)
static int
! future_check_features(PyFutureFeatures *ff, node *n)
{
int i;
char *feature;
REQ(n, import_stmt); /* must by from __future__ import ... */
for (i = 3; i < NCH(n); ++i) {
! feature = STR(CHILD(CHILD(n, i), 0));
if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
ff->ff_nested_scopes = 1;
} else {
PyErr_Format(PyExc_SyntaxError,
UNDEFINED_FUTURE_FEATURE, feature);
return -1;
}
--- 7,44 ----
#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, char *filename)
{
int i;
char *feature;
+ node *ch;
REQ(n, import_stmt); /* must by from __future__ import ... */
for (i = 3; i < NCH(n); ++i) {
! 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;
}
***************
*** 37,40 ****
--- 53,57 ----
"from __future__ imports must occur at the "
"beginning of the file");
+ PyErr_SyntaxLocation(filename, n->n_lineno);
/* XXX set filename and lineno */
}
***************
*** 46,51 ****
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)*)
import_as_name: NAME [NAME NAME]
dotted_as_name: dotted_name [NAME NAME]
--- 63,70 ----
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)*)
import_as_name: NAME [NAME NAME]
dotted_as_name: dotted_name [NAME NAME]
***************
*** 65,73 ****
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)) {
--- 84,87 ----
***************
*** 163,167 ****
if (strcmp(STR(CHILD(name, 0)), "__future__") != 0)
return 0;
! if (future_check_features(ff, n) < 0)
return -1;
ff->ff_last_lineno = n->n_lineno + 1;
--- 177,181 ----
if (strcmp(STR(CHILD(name, 0)), "__future__") != 0)
return 0;
! if (future_check_features(ff, n, filename) < 0)
return -1;
ff->ff_last_lineno = n->n_lineno + 1;
Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.176
retrieving revision 2.177
diff -C2 -r2.176 -r2.177
*** compile.c 2001/02/28 07:07:43 2.176
--- compile.c 2001/02/28 17:47:12 2.177
***************
*** 382,428 ****
}
- /* 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)
--- 382,385 ----
***************
*** 446,450 ****
return; /* MemoryError, too bad */
! line = fetch_program_text(c->c_filename, c->c_lineno);
if (line == NULL) {
Py_INCREF(Py_None);
--- 403,407 ----
return; /* MemoryError, too bad */
! line = PyErr_ProgramText(c->c_filename, c->c_lineno);
if (line == NULL) {
Py_INCREF(Py_None);
***************
*** 4029,4067 ****
/* 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)
--- 3986,3989 ----
***************
*** 4199,4203 ****
ILLEGAL_DYNAMIC_SCOPE,
PyString_AS_STRING(ste->ste_name));
! set_error_location(c->c_symtable->st_filename,
ste->ste_lineno);
return -1;
--- 4121,4125 ----
ILLEGAL_DYNAMIC_SCOPE,
PyString_AS_STRING(ste->ste_name));
! PyErr_SyntaxLocation(c->c_symtable->st_filename,
ste->ste_lineno);
return -1;
***************
*** 4274,4278 ****
PyErr_Format(PyExc_SyntaxError, LOCAL_GLOBAL,
PyString_AS_STRING(name));
! set_error_location(st->st_filename,
ste->ste_lineno);
st->st_errors++;
--- 4196,4200 ----
PyErr_Format(PyExc_SyntaxError, LOCAL_GLOBAL,
PyString_AS_STRING(name));
! PyErr_SyntaxLocation(st->st_filename,
ste->ste_lineno);
st->st_errors++;
***************
*** 4582,4586 ****
PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT,
PyString_AsString(name));
! set_error_location(st->st_filename,
st->st_cur->ste_lineno);
return -1;
--- 4504,4508 ----
PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT,
PyString_AsString(name));
! PyErr_SyntaxLocation(st->st_filename,
st->st_cur->ste_lineno);
return -1;
***************
*** 4905,4909 ****
"name '%.400s' is local and global",
name);
! set_error_location(st->st_filename,
st->st_cur->ste_lineno);
st->st_errors++;
--- 4827,4831 ----
"name '%.400s' is local and global",
name);
! PyErr_SyntaxLocation(st->st_filename,
st->st_cur->ste_lineno);
st->st_errors++;
***************
*** 4959,4963 ****
PyErr_SetString(PyExc_SyntaxError,
LATE_FUTURE);
! set_error_location(st->st_filename,
n->n_lineno);
st->st_errors++;
--- 4881,4885 ----
PyErr_SetString(PyExc_SyntaxError,
LATE_FUTURE);
! PyErr_SyntaxLocation(st->st_filename,
n->n_lineno);
st->st_errors++;
Index: errors.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/errors.c,v
retrieving revision 2.59
retrieving revision 2.60
diff -C2 -r2.59 -r2.60
*** errors.c 2000/12/15 21:58:52 2.59
--- errors.c 2001/02/28 17:47:12 2.60
***************
*** 623,624 ****
--- 623,703 ----
}
}
+
+ 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;
+ }
- Previous message: [Python-checkins] CVS: python/dist/src/Include pyerrors.h,2.42,2.43
- Next message: [Python-checkins] CVS: python/dist/src/Lib/test test_future.py,NONE,1.1 test_future1.py,NONE,1.1 test_future2.py,NONE,1.1 test_future3.py,NONE,1.1 test_future4.py,NONE,1.1 test_future5.py,NONE,1.1 test_future6.py,NONE,1.1 test_future7.py,NONE,1.1 regrtest.py,1.31,1.32
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]