diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -230,20 +230,27 @@ in various ways. There is a separate er parameter specifying the exception type to be raised. Availability: Windows. -.. c:function:: void PyErr_SyntaxLocationEx(char *filename, int lineno, int col_offset) +.. c:function:: void PyErr_SyntaxLocationObject(char *filename, int lineno, int col_offset) Set file, line, and offset information for the current exception. If the current exception is not a :exc:`SyntaxError`, then it sets additional attributes, which make the exception printing subsystem think the exception - is a :exc:`SyntaxError`. *filename* is decoded from the filesystem encoding - (:func:`sys.getfilesystemencoding`). + is a :exc:`SyntaxError`. + +.. versionadded:: 3.3 + + +.. c:function:: void PyErr_SyntaxLocationEx(char *filename, int lineno, int col_offset) + + Like :c:func:`PyErr_SyntaxLocationObject`, but *filename* is a byte string + decoded from the filesystem encoding (:func:`sys.getfilesystemencoding`). .. versionadded:: 3.2 .. c:function:: void PyErr_SyntaxLocation(char *filename, int lineno) - Like :c:func:`PyErr_SyntaxLocationExc`, but the col_offset parameter is + Like :c:func:`PyErr_SyntaxLocationEx`, but the *col_offset* parameter is omitted. @@ -292,7 +299,7 @@ in various ways. There is a separate er documentation. There is no C API for warning control. -.. c:function:: int PyErr_WarnExplicit(PyObject *category, const char *message, const char *filename, int lineno, const char *module, PyObject *registry) +.. c:function:: int PyErr_WarnExplicitObject(PyObject *category, PyObject *message, PyObject *filename, int lineno, PyObject *module, PyObject *registry) Issue a warning message with explicit control over all warning attributes. This is a straightforward wrapper around the Python function @@ -302,6 +309,15 @@ in various ways. There is a separate er *filename* is decoded from the filesystem encoding (:func:`sys.getfilesystemencoding`). + .. versionadded:: 3.3 + + +.. c:function:: int PyErr_WarnExplicit(PyObject *category, const char *message, const char *filename, int lineno, const char *module, PyObject *registry) + + Similar to :c:func:`PyErr_WarnExplicitObject` except that *message* and + *module* are UTF-8 encoded strings, and *filename* is decoded from the + filesystem encoding (:func:`sys.getfilesystemencoding`). + .. c:function:: int PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level, const char *format, ...) diff --git a/Include/ast.h b/Include/ast.h --- a/Include/ast.h +++ b/Include/ast.h @@ -9,6 +9,11 @@ PyAPI_FUNC(mod_ty) PyAST_FromNode( PyCompilerFlags *flags, const char *filename, /* decoded from the filesystem encoding */ PyArena *arena); +PyAPI_FUNC(mod_ty) PyAST_FromNodeObject( + const node *n, + PyCompilerFlags *flags, + PyObject *filename, + PyArena *arena); #ifdef __cplusplus } diff --git a/Include/compile.h b/Include/compile.h --- a/Include/compile.h +++ b/Include/compile.h @@ -36,7 +36,20 @@ PyAPI_FUNC(PyCodeObject *) PyAST_Compile PyCompilerFlags *flags, int optimize, PyArena *arena); -PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST(struct _mod *, const char *); +PyAPI_FUNC(PyCodeObject *) PyAST_CompileObject( + struct _mod *mod, + PyObject *filename, + PyCompilerFlags *flags, + int optimize, + PyArena *arena); +PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromAST( + struct _mod * mod, + const char *filename /* decoded from the filesystem encoding */ + ); +PyAPI_FUNC(PyFutureFeatures *) PyFuture_FromASTObject( + struct _mod * mod, + PyObject *filename + ); #ifdef __cplusplus diff --git a/Include/parsetok.h b/Include/parsetok.h --- a/Include/parsetok.h +++ b/Include/parsetok.h @@ -42,10 +42,16 @@ PyAPI_FUNC(node *) PyParser_ParseFile (F PyAPI_FUNC(node *) PyParser_ParseStringFlags(const char *, grammar *, int, perrdetail *, int); -PyAPI_FUNC(node *) PyParser_ParseFileFlags(FILE *, const char *, - const char*, grammar *, - int, char *, char *, - perrdetail *, int); +PyAPI_FUNC(node *) PyParser_ParseFileFlags( + FILE *fp, + const char *filename, /* decoded from the filesystem encoding */ + const char *enc, + grammar *g, + int start, + char *ps1, + char *ps2, + perrdetail *err_ret, + int flags); PyAPI_FUNC(node *) PyParser_ParseFileFlagsEx( FILE *fp, const char *filename, /* decoded from the filesystem encoding */ @@ -56,11 +62,24 @@ PyAPI_FUNC(node *) PyParser_ParseFileFla char *ps2, perrdetail *err_ret, int *flags); +PyAPI_FUNC(node *) PyParser_ParseFileObject( + FILE *fp, + PyObject *filename, + const char *enc, + grammar *g, + int start, + char *ps1, + char *ps2, + perrdetail *err_ret, + int *flags); -PyAPI_FUNC(node *) PyParser_ParseStringFlagsFilename(const char *, - const char *, - grammar *, int, - perrdetail *, int); +PyAPI_FUNC(node *) PyParser_ParseStringFlagsFilename( + const char *s, + const char *filename, /* decoded from the filesystem encoding */ + grammar *g, + int start, + perrdetail *err_ret, + int flags); PyAPI_FUNC(node *) PyParser_ParseStringFlagsFilenameEx( const char *s, const char *filename, /* decoded from the filesystem encoding */ @@ -68,6 +87,13 @@ PyAPI_FUNC(node *) PyParser_ParseStringF int start, perrdetail *err_ret, int *flags); +PyAPI_FUNC(node *) PyParser_ParseStringObject( + const char *s, + PyObject *filename, + grammar *g, + int start, + perrdetail *err_ret, + int *flags); /* Note that the following functions are defined in pythonrun.c, not in parsetok.c */ diff --git a/Include/pyerrors.h b/Include/pyerrors.h --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -263,9 +263,16 @@ PyAPI_FUNC(void) PyErr_SyntaxLocationEx( const char *filename, /* decoded from the filesystem encoding */ int lineno, int col_offset); +PyAPI_FUNC(void) PyErr_SyntaxLocationObject( + PyObject *filename, + int lineno, + int col_offset); PyAPI_FUNC(PyObject *) PyErr_ProgramText( const char *filename, /* decoded from the filesystem encoding */ int lineno); +PyAPI_FUNC(PyObject *) PyErr_ProgramTextObject( + PyObject *filename, + int lineno); /* The following functions are used to create and modify unicode exceptions from C */ diff --git a/Include/pythonrun.h b/Include/pythonrun.h --- a/Include/pythonrun.h +++ b/Include/pythonrun.h @@ -63,6 +63,12 @@ PyAPI_FUNC(struct _mod *) PyParser_ASTFr int start, PyCompilerFlags *flags, PyArena *arena); +PyAPI_FUNC(struct _mod *) PyParser_ASTFromStringObject( + const char *s, + PyObject *filename, + int start, + PyCompilerFlags *flags, + PyArena *arena); PyAPI_FUNC(struct _mod *) PyParser_ASTFromFile( FILE *fp, const char *filename, /* decoded from the filesystem encoding */ @@ -73,6 +79,16 @@ PyAPI_FUNC(struct _mod *) PyParser_ASTFr PyCompilerFlags *flags, int *errcode, PyArena *arena); +PyAPI_FUNC(struct _mod *) PyParser_ASTFromFileObject( + FILE *fp, + PyObject *filename, + const char* enc, + int start, + char *ps1, + char *ps2, + PyCompilerFlags *flags, + int *errcode, + PyArena *arena); #endif #ifndef PyParser_SimpleParseString diff --git a/Include/symtable.h b/Include/symtable.h --- a/Include/symtable.h +++ b/Include/symtable.h @@ -16,7 +16,7 @@ typedef enum _block_type { FunctionBlock struct _symtable_entry; struct symtable { - const char *st_filename; /* name of file being compiled, + PyObject *st_filename; /* name of file being compiled, decoded from the filesystem encoding */ struct _symtable_entry *st_cur; /* current symbol table entry */ struct _symtable_entry *st_top; /* symbol table entry for module */ @@ -68,6 +68,10 @@ PyAPI_FUNC(struct symtable *) PySymtable mod_ty mod, const char *filename, /* decoded from the filesystem encoding */ PyFutureFeatures *future); +PyAPI_FUNC(struct symtable *) PySymtable_BuildObject( + mod_ty mod, + PyObject *filename, + PyFutureFeatures *future); PyAPI_FUNC(PySTEntryObject *) PySymtable_Lookup(struct symtable *, void *); PyAPI_FUNC(void) PySymtable_Free(struct symtable *); diff --git a/Include/warnings.h b/Include/warnings.h --- a/Include/warnings.h +++ b/Include/warnings.h @@ -17,6 +17,13 @@ PyAPI_FUNC(int) PyErr_WarnFormat( Py_ssize_t stack_level, const char *format, /* ASCII-encoded string */ ...); +PyAPI_FUNC(int) PyErr_WarnExplicitObject( + PyObject *category, + PyObject *message, + PyObject *filename, + int lineno, + PyObject *module, + PyObject *registry); PyAPI_FUNC(int) PyErr_WarnExplicit( PyObject *category, const char *message, /* UTF-8 encoded string */ @@ -25,6 +32,7 @@ PyAPI_FUNC(int) PyErr_WarnExplicit( const char *module, /* UTF-8 encoded string */ PyObject *registry); + /* DEPRECATED: Use PyErr_WarnEx() instead. */ #ifndef Py_LIMITED_API #define PyErr_Warn(category, msg) PyErr_WarnEx(category, msg, 1) diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -458,33 +458,46 @@ parser_st2list(PyST_Object *self, PyObje static PyObject* parser_compilest(PyST_Object *self, PyObject *args, PyObject *kw) { - PyObject* res = 0; - PyArena* arena; + PyObject* res = NULL; + PyArena* arena = NULL; mod_ty mod; - char* str = ""; + PyObject* filename = NULL; int ok; static char *keywords[] = {"st", "filename", NULL}; if (self == NULL || PyModule_Check(self)) - ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|s:compilest", keywords, - &PyST_Type, &self, &str); + ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|O&:compilest", keywords, + &PyST_Type, &self, + PyUnicode_FSDecoder, &filename); else - ok = PyArg_ParseTupleAndKeywords(args, kw, "|s:compile", &keywords[1], - &str); - - if (ok) { - arena = PyArena_New(); - if (arena) { - mod = PyAST_FromNode(self->st_node, &(self->st_flags), str, arena); - if (mod) { - res = (PyObject *)PyAST_Compile(mod, str, &(self->st_flags), arena); - } - PyArena_Free(arena); - } + ok = PyArg_ParseTupleAndKeywords(args, kw, "|O&:compile", &keywords[1], + PyUnicode_FSDecoder, &filename); + if (!ok) + goto error; + + if (filename == NULL) { + filename = PyUnicode_FromString(""); + if (filename == NULL) + goto error; } - return (res); + arena = PyArena_New(); + if (!arena) + goto error; + + mod = PyAST_FromNodeObject(self->st_node, &self->st_flags, + filename, arena); + if (!mod) + goto error; + + res = (PyObject *)PyAST_CompileObject(mod, filename, + &self->st_flags, -1, arena); +error: + Py_XDECREF(filename); + if (arena != NULL) + PyArena_Free(arena); + return res; } diff --git a/Modules/symtablemodule.c b/Modules/symtablemodule.c --- a/Modules/symtablemodule.c +++ b/Modules/symtablemodule.c @@ -11,12 +11,12 @@ symtable_symtable(PyObject *self, PyObje PyObject *t; char *str; - char *filename; + PyObject *filename; char *startstr; int start; - if (!PyArg_ParseTuple(args, "sss:symtable", &str, &filename, - &startstr)) + if (!PyArg_ParseTuple(args, "sO&s:symtable", + &str, PyUnicode_FSDecoder, &filename, &startstr)) return NULL; if (strcmp(startstr, "exec") == 0) start = Py_file_input; @@ -27,9 +27,11 @@ symtable_symtable(PyObject *self, PyObje else { PyErr_SetString(PyExc_ValueError, "symtable() arg 3 must be 'exec' or 'eval' or 'single'"); + Py_DECREF(filename); return NULL; } - st = Py_SymtableString(str, filename, start); + st = Py_SymtableStringObject(str, filename, start); + Py_DECREF(filename); if (st == NULL) return NULL; t = st->st_blocks; diff --git a/Parser/parsetok.c b/Parser/parsetok.c --- a/Parser/parsetok.c +++ b/Parser/parsetok.c @@ -13,7 +13,7 @@ /* Forward */ static node *parsetok(struct tok_state *, grammar *, int, perrdetail *, int *); -static int initerr(perrdetail *err_ret, const char* filename); +static int initerr(perrdetail *err_ret, PyObject * filename); /* Parse input coming from a string. Return error code, print some errors. */ node * @@ -41,9 +41,9 @@ PyParser_ParseStringFlagsFilename(const } node * -PyParser_ParseStringFlagsFilenameEx(const char *s, const char *filename, - grammar *g, int start, - perrdetail *err_ret, int *flags) +PyParser_ParseStringObject(const char *s, PyObject *filename, + grammar *g, int start, + perrdetail *err_ret, int *flags) { struct tok_state *tok; int exec_input = start == file_input; @@ -67,6 +67,30 @@ PyParser_ParseStringFlagsFilenameEx(cons return parsetok(tok, g, start, err_ret, flags); } +node * +PyParser_ParseStringFlagsFilenameEx(const char *s, const char *filename_str, + grammar *g, int start, + perrdetail *err_ret, int *flags) +{ + PyObject *filename; + node *n; + filename = NULL; +#ifndef PGEN + if (filename_str != NULL) { + filename = PyUnicode_DecodeFSDefault(filename_str); + if (filename == NULL) { + err_ret->error = E_ERROR; + return NULL; + } + } +#endif + n = PyParser_ParseStringObject(s, filename, g, start, err_ret, flags); +#ifndef PGEN + Py_XDECREF(filename); +#endif + return n; +} + /* Parse input coming from a file. Return error code, print some errors. */ node * @@ -88,9 +112,10 @@ PyParser_ParseFileFlags(FILE *fp, const } node * -PyParser_ParseFileFlagsEx(FILE *fp, const char *filename, - const char *enc, grammar *g, int start, - char *ps1, char *ps2, perrdetail *err_ret, int *flags) +PyParser_ParseFileObject(FILE *fp, PyObject *filename, + const char *enc, grammar *g, int start, + char *ps1, char *ps2, perrdetail *err_ret, + int *flags) { struct tok_state *tok; @@ -108,6 +133,32 @@ PyParser_ParseFileFlagsEx(FILE *fp, cons return parsetok(tok, g, start, err_ret, flags); } +node * +PyParser_ParseFileFlagsEx(FILE *fp, const char *filename, + const char *enc, grammar *g, int start, + char *ps1, char *ps2, perrdetail *err_ret, int *flags) +{ + node *n; + PyObject *fileobj; +#ifndef PGEN + if (filename != NULL) { + fileobj = PyUnicode_DecodeFSDefault(filename); + if (fileobj == NULL) { + err_ret->error = E_ERROR; + return NULL; + } + } + else +#endif + fileobj = NULL; + n = PyParser_ParseFileObject(fp, fileobj, enc, g, + start, ps1, ps2, err_ret, flags); +#ifndef PGEN + Py_XDECREF(fileobj); +#endif + return n; +} + #ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD #if 0 static char with_msg[] = @@ -276,7 +327,7 @@ done: } static int -initerr(perrdetail *err_ret, const char *filename) +initerr(perrdetail *err_ret, PyObject *filename) { err_ret->error = E_OK; err_ret->lineno = 0; @@ -285,13 +336,16 @@ initerr(perrdetail *err_ret, const char err_ret->token = -1; err_ret->expected = -1; #ifndef PGEN - if (filename) - err_ret->filename = PyUnicode_DecodeFSDefault(filename); - else + if (filename) { + Py_INCREF(filename); + err_ret->filename = filename; + } + else { err_ret->filename = PyUnicode_FromString(""); - if (err_ret->filename == NULL) { - err_ret->error = E_ERROR; - return -1; + if (err_ret->filename == NULL) { + err_ret->error = E_ERROR; + return -1; + } } #endif return 0; diff --git a/Python/_warnings.c b/Python/_warnings.c --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -698,14 +698,14 @@ warnings_warn_explicit(PyObject *self, P /* Handle the warning. */ returned = warn_explicit(category, message, filename, lineno, module, - registry, source_line); + registry, source_line); Py_DECREF(source_list); return returned; } standard_call: return warn_explicit(category, message, filename, lineno, module, - registry, NULL); + registry, NULL); } @@ -777,11 +777,26 @@ PyErr_Warn(PyObject *category, char *tex /* Warning with explicit origin */ int +PyErr_WarnExplicitObject(PyObject *category, PyObject *message, + PyObject *filename, int lineno, + PyObject *module, PyObject *registry) +{ + PyObject *res; + if (category == NULL) + category = PyExc_RuntimeWarning; + res = warn_explicit(category, message, filename, lineno, + module, registry, NULL); + if (res == NULL) + return -1; + Py_DECREF(res); + return 0; +} + +int PyErr_WarnExplicit(PyObject *category, const char *text, const char *filename_str, int lineno, const char *module_str, PyObject *registry) { - PyObject *res; PyObject *message = PyUnicode_FromString(text); PyObject *filename = PyUnicode_DecodeFSDefault(filename_str); PyObject *module = NULL; @@ -795,14 +810,8 @@ PyErr_WarnExplicit(PyObject *category, c goto exit; } - if (category == NULL) - category = PyExc_RuntimeWarning; - res = warn_explicit(category, message, filename, lineno, module, registry, - NULL); - if (res == NULL) - goto exit; - Py_DECREF(res); - ret = 0; + ret = PyErr_WarnExplicitObject(category, message, filename, lineno, + module, registry); exit: Py_XDECREF(message); diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -18,7 +18,6 @@ struct compiling { char *c_encoding; /* source encoding */ PyArena *c_arena; /* arena for allocating memeory */ - const char *c_filename; /* filename */ }; static asdl_seq *seq_for_testlist(struct compiling *, const node *); @@ -98,10 +97,9 @@ ast_error(const node *n, const char *err } static void -ast_error_finish(const char *filename) +ast_error_finish(PyObject *filename) { PyObject *type, *value, *tback, *errstr, *offset, *loc, *tmp; - PyObject *filename_obj; long lineno; assert(PyErr_Occurred()); @@ -125,21 +123,13 @@ ast_error_finish(const char *filename) } Py_DECREF(value); - loc = PyErr_ProgramText(filename, lineno); + loc = PyErr_ProgramTextObject(filename, lineno); if (!loc) { Py_INCREF(Py_None); loc = Py_None; } - if (filename != NULL) - filename_obj = PyUnicode_DecodeFSDefault(filename); - else { - Py_INCREF(Py_None); - filename_obj = Py_None; - } - if (filename_obj != NULL) - tmp = Py_BuildValue("(NlOO)", filename_obj, lineno, offset, loc); - else - tmp = NULL; + tmp = Py_BuildValue("(OlOO)", + filename ? filename : Py_None, lineno, offset, loc); Py_DECREF(loc); if (!tmp) { Py_DECREF(errstr); @@ -218,8 +208,8 @@ num_stmts(const node *n) */ mod_ty -PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename, - PyArena *arena) +PyAST_FromNodeObject(const node *n, PyCompilerFlags *flags, + PyObject *filename, PyArena *arena) { int i, j, k, num; asdl_seq *stmts = NULL; @@ -244,7 +234,6 @@ PyAST_FromNode(const node *n, PyCompiler c.c_encoding = "utf-8"; } c.c_arena = arena; - c.c_filename = filename; k = 0; switch (TYPE(n)) { @@ -325,7 +314,7 @@ PyAST_FromNode(const node *n, PyCompiler } default: PyErr_Format(PyExc_SystemError, - "invalid node %d for PyAST_FromNode", TYPE(n)); + "invalid node %d for PyAST_FromNodeObject", TYPE(n)); goto error; } error: @@ -333,6 +322,21 @@ PyAST_FromNode(const node *n, PyCompiler return NULL; } +mod_ty +PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename_str, + PyArena *arena) +{ + mod_ty mod; + PyObject *filename; + filename = PyUnicode_DecodeFSDefault(filename_str); + if (filename == NULL) + return NULL; + mod = PyAST_FromNodeObject(n, flags, filename, arena); + Py_DECREF(filename); + return mod; + +} + /* Return the AST repr. of the operator represented as syntax (|, ^, etc.) */ diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -134,7 +134,7 @@ managed by compiler_enter_scope() and co */ struct compiler { - const char *c_filename; + PyObject *filename; struct symtable *c_st; PyFutureFeatures *c_future; /* pointer to module's __future__ */ PyCompilerFlags *c_flags; @@ -255,8 +255,8 @@ compiler_init(struct compiler *c) } PyCodeObject * -PyAST_CompileEx(mod_ty mod, const char *filename, PyCompilerFlags *flags, - int optimize, PyArena *arena) +PyAST_CompileObject(mod_ty mod, PyObject *filename, PyCompilerFlags *flags, + int optimize, PyArena *arena) { struct compiler c; PyCodeObject *co = NULL; @@ -271,9 +271,10 @@ PyAST_CompileEx(mod_ty mod, const char * if (!compiler_init(&c)) return NULL; - c.c_filename = filename; + Py_INCREF(filename); + c.filename = filename; c.c_arena = arena; - c.c_future = PyFuture_FromAST(mod, filename); + c.c_future = PyFuture_FromASTObject(mod, filename); if (c.c_future == NULL) goto finally; if (!flags) { @@ -287,7 +288,7 @@ PyAST_CompileEx(mod_ty mod, const char * c.c_optimize = (optimize == -1) ? Py_OptimizeFlag : optimize; c.c_nestlevel = 0; - c.c_st = PySymtable_Build(mod, filename, c.c_future); + c.c_st = PySymtable_BuildObject(mod, filename, c.c_future); if (c.c_st == NULL) { if (!PyErr_Occurred()) PyErr_SetString(PyExc_SystemError, "no symtable"); @@ -303,6 +304,21 @@ PyAST_CompileEx(mod_ty mod, const char * } PyCodeObject * +PyAST_CompileEx(mod_ty mod, const char *filename_str, PyCompilerFlags *flags, + int optimize, PyArena *arena) +{ + PyObject *filename; + PyCodeObject *co; + filename = PyUnicode_DecodeFSDefault(filename_str); + if (filename == NULL) + return NULL; + co = PyAST_CompileObject(mod, filename, flags, optimize, arena); + Py_DECREF(filename); + return co; + +} + +PyCodeObject * PyNode_Compile(struct _node *n, const char *filename) { PyCodeObject *co = NULL; @@ -325,6 +341,7 @@ compiler_free(struct compiler *c) if (c->c_future) PyObject_Free(c->c_future); Py_DECREF(c->c_stack); + Py_XDECREF(c->filename); } static PyObject * @@ -1220,12 +1237,11 @@ get_ref_type(struct compiler *c, PyObjec if (scope == 0) { char buf[350]; PyOS_snprintf(buf, sizeof(buf), - "unknown scope for %.100s in %.100s(%s) in %s\n" + "unknown scope for %.100s in %.100s(%s)\n" "symbols: %s\nlocals: %s\nglobals: %s", PyBytes_AS_STRING(name), PyBytes_AS_STRING(c->u->u_name), PyObject_REPR(c->u->u_ste->ste_id), - c->c_filename, PyObject_REPR(c->u->u_ste->ste_symbols), PyObject_REPR(c->u->u_varnames), PyObject_REPR(c->u->u_names) @@ -2212,6 +2228,7 @@ compiler_assert(struct compiler *c, stmt { static PyObject *assertion_error = NULL; basicblock *end; + PyObject* msg; if (c->c_optimize) return 1; @@ -2222,11 +2239,17 @@ compiler_assert(struct compiler *c, stmt } if (s->v.Assert.test->kind == Tuple_kind && asdl_seq_LEN(s->v.Assert.test->v.Tuple.elts) > 0) { - const char* msg = - "assertion is always true, perhaps remove parentheses?"; - if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, c->c_filename, - c->u->u_lineno, NULL, NULL) == -1) + msg = PyUnicode_FromString("assertion is always true, " + "perhaps remove parentheses?"); + if (msg == NULL) return 0; + if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, msg, + c->filename, c->u->u_lineno, + NULL, NULL) == -1) { + Py_DECREF(msg); + return 0; + } + Py_DECREF(msg); } VISIT(c, expr, s->v.Assert.test); end = compiler_new_block(c); @@ -3361,24 +3384,15 @@ compiler_in_loop(struct compiler *c) { static int compiler_error(struct compiler *c, const char *errstr) { - PyObject *loc, *filename; + PyObject *loc; PyObject *u = NULL, *v = NULL; - loc = PyErr_ProgramText(c->c_filename, c->u->u_lineno); + loc = PyErr_ProgramTextObject(c->filename, c->u->u_lineno); if (!loc) { Py_INCREF(Py_None); loc = Py_None; } - if (c->c_filename != NULL) { - filename = PyUnicode_DecodeFSDefault(c->c_filename); - if (!filename) - goto exit; - } - else { - Py_INCREF(Py_None); - filename = Py_None; - } - u = Py_BuildValue("(NiiO)", filename, c->u->u_lineno, + u = Py_BuildValue("(OiiO)", c->filename, c->u->u_lineno, c->u->u_col_offset, loc); if (!u) goto exit; @@ -3927,7 +3941,6 @@ makecode(struct compiler *c, struct asse PyObject *consts = NULL; PyObject *names = NULL; PyObject *varnames = NULL; - PyObject *filename = NULL; PyObject *name = NULL; PyObject *freevars = NULL; PyObject *cellvars = NULL; @@ -3951,9 +3964,6 @@ makecode(struct compiler *c, struct asse freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_Size(cellvars)); if (!freevars) goto error; - filename = PyUnicode_DecodeFSDefault(c->c_filename); - if (!filename) - goto error; nlocals = PyDict_Size(c->u->u_varnames); flags = compute_code_flags(c); @@ -3974,14 +3984,13 @@ makecode(struct compiler *c, struct asse nlocals, stackdepth(c), flags, bytecode, consts, names, varnames, freevars, cellvars, - filename, c->u->u_name, + c->filename, c->u->u_name, c->u->u_firstlineno, a->a_lnotab); error: Py_XDECREF(consts); Py_XDECREF(names); Py_XDECREF(varnames); - Py_XDECREF(filename); Py_XDECREF(name); Py_XDECREF(freevars); Py_XDECREF(cellvars); diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -761,7 +761,8 @@ extern PyObject *PyModule_GetWarningsMod void -PyErr_SyntaxLocation(const char *filename, int lineno) { +PyErr_SyntaxLocation(const char *filename, int lineno) +{ PyErr_SyntaxLocationEx(filename, lineno, -1); } @@ -771,7 +772,7 @@ PyErr_SyntaxLocation(const char *filenam to make printing of exceptions believe it is a syntax error. */ void -PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) +PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset) { PyObject *exc, *v, *tb, *tmp; @@ -799,16 +800,9 @@ PyErr_SyntaxLocationEx(const char *filen } } if (filename != NULL) { - tmp = PyUnicode_DecodeFSDefault(filename); - if (tmp == NULL) + if (PyObject_SetAttrString(v, "filename", filename)) PyErr_Clear(); - else { - if (PyObject_SetAttrString(v, "filename", tmp)) - PyErr_Clear(); - Py_DECREF(tmp); - } - - tmp = PyErr_ProgramText(filename, lineno); + tmp = PyErr_ProgramTextObject(filename, lineno); if (tmp) { if (PyObject_SetAttrString(v, "text", tmp)) PyErr_Clear(); @@ -838,6 +832,21 @@ PyErr_SyntaxLocationEx(const char *filen PyErr_Restore(exc, v, tb); } +void +PyErr_SyntaxLocationEx(const char *filename, int lineno, int col_offset) +{ + PyObject *fileobj; + if (filename != NULL) { + fileobj = PyUnicode_DecodeFSDefault(filename); + if (fileobj == NULL) + PyErr_Clear(); + } + else + fileobj = NULL; + PyErr_SyntaxLocationObject(fileobj, lineno, col_offset); + Py_XDECREF(fileobj); +} + /* 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. @@ -845,15 +854,11 @@ PyErr_SyntaxLocationEx(const char *filen functionality in tb_displayline() in traceback.c. */ PyObject * -PyErr_ProgramText(const char *filename, int lineno) +err_programtext(FILE *fp, int lineno) { - FILE *fp; int i; char linebuf[1000]; - if (filename == NULL || *filename == '\0' || lineno <= 0) - return NULL; - fp = fopen(filename, "r" PY_STDIOTEXTMODE); if (fp == NULL) return NULL; for (i = 0; i < lineno; i++) { @@ -884,6 +889,26 @@ PyErr_ProgramText(const char *filename, return NULL; } +PyObject * +PyErr_ProgramText(const char *filename, int lineno) +{ + FILE *fp; + if (filename == NULL || *filename == '\0' || lineno <= 0) + return NULL; + fp = fopen(filename, "r" PY_STDIOTEXTMODE); + return err_programtext(fp, lineno); +} + +PyObject * +PyErr_ProgramTextObject(PyObject *filename, int lineno) +{ + FILE *fp; + if (filename == NULL || lineno <= 0) + return NULL; + fp = _Py_fopen(filename, "r" PY_STDIOTEXTMODE); + return err_programtext(fp, lineno); +} + #ifdef __cplusplus } #endif diff --git a/Python/future.c b/Python/future.c --- a/Python/future.c +++ b/Python/future.c @@ -11,7 +11,7 @@ "from __future__ imports must occur at the beginning of the file" static int -future_check_features(PyFutureFeatures *ff, stmt_ty s, const char *filename) +future_check_features(PyFutureFeatures *ff, stmt_ty s, PyObject *filename) { int i; asdl_seq *names; @@ -43,12 +43,12 @@ future_check_features(PyFutureFeatures * } else if (strcmp(feature, "braces") == 0) { PyErr_SetString(PyExc_SyntaxError, "not a chance"); - PyErr_SyntaxLocationEx(filename, s->lineno, s->col_offset); + PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset); return 0; } else { PyErr_Format(PyExc_SyntaxError, UNDEFINED_FUTURE_FEATURE, feature); - PyErr_SyntaxLocationEx(filename, s->lineno, s->col_offset); + PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset); return 0; } } @@ -56,7 +56,7 @@ future_check_features(PyFutureFeatures * } static int -future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename) +future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename) { int i, found_docstring = 0, done = 0, prev_line = 0; @@ -97,7 +97,7 @@ future_parse(PyFutureFeatures *ff, mod_t if (done) { PyErr_SetString(PyExc_SyntaxError, ERR_LATE_FUTURE); - PyErr_SyntaxLocationEx(filename, s->lineno, s->col_offset); + PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset); return 0; } if (!future_check_features(ff, s, filename)) @@ -122,7 +122,7 @@ future_parse(PyFutureFeatures *ff, mod_t PyFutureFeatures * -PyFuture_FromAST(mod_ty mod, const char *filename) +PyFuture_FromASTObject(mod_ty mod, PyObject *filename) { PyFutureFeatures *ff; @@ -140,3 +140,18 @@ PyFuture_FromAST(mod_ty mod, const char } return ff; } + + +PyFutureFeatures * +PyFuture_FromAST(mod_ty mod, const char *filename_str) +{ + PyFutureFeatures *ff; + PyObject *filename; + + filename = PyUnicode_DecodeFSDefault(filename_str); + if (filename == NULL) + return NULL; + ff = PyFuture_FromASTObject(mod, filename); + Py_DECREF(filename); + return ff; +} diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1168,30 +1168,22 @@ static PyCodeObject * parse_source_module(PyObject *pathname, FILE *fp) { PyCodeObject *co; - PyObject *pathbytes; mod_ty mod; PyCompilerFlags flags; PyArena *arena; - pathbytes = PyUnicode_EncodeFSDefault(pathname); - if (pathbytes == NULL) + arena = PyArena_New(); + if (arena == NULL) return NULL; - arena = PyArena_New(); - if (arena == NULL) { - Py_DECREF(pathbytes); - return NULL; - } - flags.cf_flags = 0; - mod = PyParser_ASTFromFile(fp, PyBytes_AS_STRING(pathbytes), NULL, - Py_file_input, 0, 0, &flags, - NULL, arena); + mod = PyParser_ASTFromFileObject(fp, pathname, NULL, + Py_file_input, 0, 0, &flags, + NULL, arena); if (mod != NULL) - co = PyAST_Compile(mod, PyBytes_AS_STRING(pathbytes), NULL, arena); + co = PyAST_CompileObject(mod, pathname, NULL, -1, arena); else co = NULL; - Py_DECREF(pathbytes); PyArena_Free(arena); return co; } diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1847,46 +1847,64 @@ PyCompileString(const char *str, const c } struct symtable * -Py_SymtableString(const char *str, const char *filename, int start) +Py_SymtableStringObject(const char *str, PyObject *filename, int start) { struct symtable *st; mod_ty mod; PyCompilerFlags flags; - PyArena *arena = PyArena_New(); + PyArena *arena; + + arena = PyArena_New(); if (arena == NULL) return NULL; flags.cf_flags = 0; - mod = PyParser_ASTFromString(str, filename, start, &flags, arena); + mod = PyParser_ASTFromStringObject(str, filename, start, &flags, arena); if (mod == NULL) { + Py_DECREF(filename); PyArena_Free(arena); return NULL; } - st = PySymtable_Build(mod, filename, 0); + st = PySymtable_BuildObject(mod, filename, 0); + Py_DECREF(filename); PyArena_Free(arena); return st; } +struct symtable * +Py_SymtableString(const char *str, const char *filename_str, int start) +{ + PyObject *filename; + struct symtable *st; + + filename = PyUnicode_DecodeFSDefault(filename_str); + if (filename == NULL) + return NULL; + st = Py_SymtableStringObject(str, filename, start); + Py_DECREF(filename); + return st; +} + /* Preferred access to parser is through AST. */ mod_ty -PyParser_ASTFromString(const char *s, const char *filename, int start, - PyCompilerFlags *flags, PyArena *arena) +PyParser_ASTFromStringObject(const char *s, PyObject *filename, int start, + PyCompilerFlags *flags, PyArena *arena) { mod_ty mod; PyCompilerFlags localflags; perrdetail err; int iflags = PARSER_FLAGS(flags); - node *n = PyParser_ParseStringFlagsFilenameEx(s, filename, - &_PyParser_Grammar, start, &err, - &iflags); + node *n = PyParser_ParseStringObject(s, filename, + &_PyParser_Grammar, start, &err, + &iflags); if (flags == NULL) { localflags.cf_flags = 0; flags = &localflags; } if (n) { flags->cf_flags |= iflags & PyCF_MASK; - mod = PyAST_FromNode(n, flags, filename, arena); + mod = PyAST_FromNodeObject(n, flags, filename, arena); PyNode_Free(n); } else { @@ -1898,26 +1916,40 @@ PyParser_ASTFromString(const char *s, co } mod_ty -PyParser_ASTFromFile(FILE *fp, const char *filename, const char* enc, - int start, char *ps1, - char *ps2, PyCompilerFlags *flags, int *errcode, - PyArena *arena) +PyParser_ASTFromString(const char *s, const char *filename_str, int start, + PyCompilerFlags *flags, PyArena *arena) +{ + PyObject *filename; + mod_ty mod; + filename = PyUnicode_DecodeFSDefault(filename_str); + if (filename == NULL) + return NULL; + mod = PyParser_ASTFromStringObject(s, filename, start, flags, arena); + Py_DECREF(filename); + return mod; +} + +mod_ty +PyParser_ASTFromFileObject(FILE *fp, PyObject *filename, const char* enc, + int start, char *ps1, + char *ps2, PyCompilerFlags *flags, int *errcode, + PyArena *arena) { mod_ty mod; PyCompilerFlags localflags; perrdetail err; int iflags = PARSER_FLAGS(flags); - node *n = PyParser_ParseFileFlagsEx(fp, filename, enc, - &_PyParser_Grammar, - start, ps1, ps2, &err, &iflags); + node *n = PyParser_ParseFileObject(fp, filename, enc, + &_PyParser_Grammar, + start, ps1, ps2, &err, &iflags); if (flags == NULL) { localflags.cf_flags = 0; flags = &localflags; } if (n) { flags->cf_flags |= iflags & PyCF_MASK; - mod = PyAST_FromNode(n, flags, filename, arena); + mod = PyAST_FromNodeObject(n, flags, filename, arena); PyNode_Free(n); } else { @@ -1930,6 +1962,23 @@ PyParser_ASTFromFile(FILE *fp, const cha return mod; } +mod_ty +PyParser_ASTFromFile(FILE *fp, const char *filename_str, const char* enc, + int start, char *ps1, + char *ps2, PyCompilerFlags *flags, int *errcode, + PyArena *arena) +{ + mod_ty mod; + PyObject *filename; + filename = PyUnicode_DecodeFSDefault(filename_str); + if (filename == NULL) + return NULL; + mod = PyParser_ASTFromFileObject(fp, filename, enc, start, ps1, ps2, + flags, errcode, arena); + Py_DECREF(filename); + return mod; +} + /* Simplified interface to parsefile -- return node or set exception */ node * diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -222,15 +222,20 @@ symtable_new(void) } struct symtable * -PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future) +PySymtable_BuildObject(mod_ty mod, PyObject *filename, PyFutureFeatures *future) { struct symtable *st = symtable_new(); asdl_seq *seq; int i; if (st == NULL) - return st; + return NULL; + Py_INCREF(filename); st->st_filename = filename; + if (st->st_filename == NULL) { + PySymtable_Free(st); + return NULL; + } st->st_future = future; /* Make the initial symbol information gathering pass */ if (!GET_IDENTIFIER(top) || @@ -280,9 +285,23 @@ PySymtable_Build(mod_ty mod, const char return NULL; } +struct symtable * +PySymtable_Build(mod_ty mod, const char *filename_str, PyFutureFeatures *future) +{ + PyObject *filename; + struct symtable *st; + filename = PyUnicode_DecodeFSDefault(filename_str); + if (filename == NULL) + return NULL; + st = PySymtable_BuildObject(mod, filename, future); + Py_DECREF(filename); + return st; +} + void PySymtable_Free(struct symtable *st) { + Py_XDECREF(st->st_filename); Py_XDECREF(st->st_blocks); Py_XDECREF(st->st_stack); PyMem_Free((void *)st); @@ -394,8 +413,8 @@ analyze_name(PySTEntryObject *ste, PyObj PyErr_Format(PyExc_SyntaxError, "name '%U' is parameter and global", name); - PyErr_SyntaxLocationEx(ste->ste_table->st_filename, - ste->ste_lineno, ste->ste_col_offset); + PyErr_SyntaxLocationObject(ste->ste_table->st_filename, + ste->ste_lineno, ste->ste_col_offset); return 0; } @@ -538,8 +557,9 @@ check_unoptimized(const PySTEntryObject* break; } - PyErr_SyntaxLocationEx(ste->ste_table->st_filename, ste->ste_opt_lineno, - ste->ste_opt_col_offset); + PyErr_SyntaxLocationObject(ste->ste_table->st_filename, + ste->ste_opt_lineno, + ste->ste_opt_col_offset); return 0; } @@ -873,15 +893,20 @@ symtable_analyze(struct symtable *st) static int symtable_warn(struct symtable *st, char *msg, int lineno) { - if (PyErr_WarnExplicit(PyExc_SyntaxWarning, msg, st->st_filename, - lineno, NULL, NULL) < 0) { + PyObject *message = PyUnicode_FromString(msg); + if (message == NULL) + return 0; + if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, message, st->st_filename, + lineno, NULL, NULL) < 0) { + Py_DECREF(message); if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) { PyErr_SetString(PyExc_SyntaxError, msg); - PyErr_SyntaxLocationEx(st->st_filename, st->st_cur->ste_lineno, - st->st_cur->ste_col_offset); + PyErr_SyntaxLocationObject(st->st_filename, st->st_cur->ste_lineno, + st->st_cur->ste_col_offset); } return 0; } + Py_DECREF(message); return 1; } @@ -967,9 +992,9 @@ symtable_add_def(struct symtable *st, Py if ((flag & DEF_PARAM) && (val & DEF_PARAM)) { /* Is it better to use 'mangled' or 'name' here? */ PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, name); - PyErr_SyntaxLocationEx(st->st_filename, - st->st_cur->ste_lineno, - st->st_cur->ste_col_offset); + PyErr_SyntaxLocationObject(st->st_filename, + st->st_cur->ste_lineno, + st->st_cur->ste_col_offset); goto error; } val |= flag; @@ -1164,9 +1189,9 @@ symtable_visit_stmt(struct symtable *st, if (st->st_cur->ste_generator) { PyErr_SetString(PyExc_SyntaxError, RETURN_VAL_IN_GENERATOR); - PyErr_SyntaxLocationEx(st->st_filename, - s->lineno, - s->col_offset); + PyErr_SyntaxLocationObject(st->st_filename, + s->lineno, + s->col_offset); return 0; } } @@ -1379,8 +1404,8 @@ symtable_visit_expr(struct symtable *st, if (st->st_cur->ste_returns_value) { PyErr_SetString(PyExc_SyntaxError, RETURN_VAL_IN_GENERATOR); - PyErr_SyntaxLocationEx(st->st_filename, - e->lineno, e->col_offset); + PyErr_SyntaxLocationObject(st->st_filename, + e->lineno, e->col_offset); return 0; } break; @@ -1568,12 +1593,12 @@ symtable_visit_alias(struct symtable *st } else { if (st->st_cur->ste_type != ModuleBlock) { - int lineno = st->st_cur->ste_lineno; - int col_offset = st->st_cur->ste_col_offset; - PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING); - PyErr_SyntaxLocationEx(st->st_filename, lineno, col_offset); - Py_DECREF(store_name); - return 0; + int lineno = st->st_cur->ste_lineno; + int col_offset = st->st_cur->ste_col_offset; + PyErr_SetString(PyExc_SyntaxError, IMPORT_STAR_WARNING); + PyErr_SyntaxLocationObject(st->st_filename, lineno, col_offset); + Py_DECREF(store_name); + return 0; } st->st_cur->ste_unoptimized |= OPT_IMPORT_STAR; Py_DECREF(store_name);