typedef struct {
int error;
- const char *filename; /* decoded from the filesystem encoding */
+#ifndef PGEN
+ /* The filename is useless for pgen, see comment in tok_state structure */
+ PyObject *filename;
+#endif
int lineno;
int offset;
char *text; /* UTF-8-encoded string */
perrdetail *err_ret,
int *flags);
-/* Note that he following function is defined in pythonrun.c not parsetok.c. */
+/* Note that the following functions are defined in pythonrun.c,
+ not in parsetok.c */
PyAPI_FUNC(void) PyParser_SetError(perrdetail *);
+PyAPI_FUNC(void) PyParser_ClearError(perrdetail *);
#ifdef __cplusplus
}
Parser/listnode.o \
Parser/node.o \
Parser/parser.o \
- Parser/parsetok.o \
Parser/bitset.o \
Parser/metagrammar.o \
Parser/firstsets.o \
Parser/grammar.o \
Parser/pgen.o
-PARSER_OBJS= $(POBJS) Parser/myreadline.o Parser/tokenizer.o
+PARSER_OBJS= $(POBJS) Parser/myreadline.o Parser/parsetok.o Parser/tokenizer.o
PGOBJS= \
Objects/obmalloc.o \
Python/pyctype.o \
Parser/tokenizer_pgen.o \
Parser/printgrammar.o \
+ Parser/parsetok_pgen.o \
Parser/pgenmain.o
PARSER_HEADERS= \
Parser/parser.h \
+ Include/parsetok.h \
Parser/tokenizer.h
PGENOBJS= $(PGENMAIN) $(POBJS) $(PGOBJS)
Parser/metagrammar.o: $(srcdir)/Parser/metagrammar.c
Parser/tokenizer_pgen.o: $(srcdir)/Parser/tokenizer.c
+Parser/parsetok_pgen.o: $(srcdir)/Parser/parsetok.c
Parser/pgenmain.o: $(srcdir)/Include/parsetok.h
Include/objimpl.h \
Include/opcode.h \
Include/osdefs.h \
- Include/parsetok.h \
Include/patchlevel.h \
Include/pgen.h \
Include/pgenheaders.h \
Core and Builtins
-----------------
+- Issue #10785: Store the filename as Unicode in the Python parser.
+
- Issue #11619: _PyImport_LoadDynamicModule() doesn't encode the path to bytes
on Windows.
else
PyParser_SetError(&err);
}
+ PyParser_ClearError(&err);
return (res);
}
/* Forward */
static node *parsetok(struct tok_state *, grammar *, int, perrdetail *, int *);
-static void initerr(perrdetail *err_ret, const char* filename);
+static int initerr(perrdetail *err_ret, const char* filename);
/* Parse input coming from a string. Return error code, print some errors. */
node *
struct tok_state *tok;
int exec_input = start == file_input;
- initerr(err_ret, filename);
+ if (initerr(err_ret, filename) < 0)
+ return NULL;
if (*flags & PyPARSE_IGNORE_COOKIE)
tok = PyTokenizer_FromUTF8(s, exec_input);
return NULL;
}
- tok->filename = filename ? filename : "<string>";
+#ifndef PGEN
+ Py_INCREF(err_ret->filename);
+ tok->filename = err_ret->filename;
+#endif
return parsetok(tok, g, start, err_ret, flags);
}
{
struct tok_state *tok;
- initerr(err_ret, filename);
+ if (initerr(err_ret, filename) < 0)
+ return NULL;
if ((tok = PyTokenizer_FromFile(fp, (char *)enc, ps1, ps2)) == NULL) {
err_ret->error = E_NOMEM;
return NULL;
}
- tok->filename = filename;
+#ifndef PGEN
+ Py_INCREF(err_ret->filename);
+ tok->filename = err_ret->filename;
+#endif
return parsetok(tok, g, start, err_ret, flags);
}
return n;
}
-static void
+static int
initerr(perrdetail *err_ret, const char *filename)
{
err_ret->error = E_OK;
- err_ret->filename = filename;
err_ret->lineno = 0;
err_ret->offset = 0;
err_ret->text = NULL;
err_ret->token = -1;
err_ret->expected = -1;
+#ifndef PGEN
+ if (filename)
+ err_ret->filename = PyUnicode_DecodeFSDefault(filename);
+ else
+ err_ret->filename = PyUnicode_FromString("<string>");
+ if (err_ret->filename == NULL) {
+ err_ret->error = E_ERROR;
+ return -1;
+ }
+#endif
+ return 0;
}
--- /dev/null
+#define PGEN
+#include "parsetok.c"
tok->prompt = tok->nextprompt = NULL;
tok->lineno = 0;
tok->level = 0;
- tok->filename = NULL;
tok->altwarning = 1;
tok->alterror = 1;
tok->alttabsize = 1;
tok->encoding = NULL;
tok->cont_line = 0;
#ifndef PGEN
+ tok->filename = NULL;
tok->decoding_readline = NULL;
tok->decoding_buffer = NULL;
#endif
{
char *line = NULL;
int badchar = 0;
- PyObject *filename;
for (;;) {
if (tok->decoding_state == STATE_NORMAL) {
/* We already have a codec associated with
if (badchar) {
/* Need to add 1 to the line number, since this line
has not been counted, yet. */
- filename = PyUnicode_DecodeFSDefault(tok->filename);
- if (filename != NULL) {
- PyErr_Format(PyExc_SyntaxError,
- "Non-UTF-8 code starting with '\\x%.2x' "
- "in file %U on line %i, "
- "but no encoding declared; "
- "see http://python.org/dev/peps/pep-0263/ for details",
- badchar, filename, tok->lineno + 1);
- Py_DECREF(filename);
- }
+ PyErr_Format(PyExc_SyntaxError,
+ "Non-UTF-8 code starting with '\\x%.2x' "
+ "in file %U on line %i, "
+ "but no encoding declared; "
+ "see http://python.org/dev/peps/pep-0263/ for details",
+ badchar, tok->filename, tok->lineno + 1);
return error_ret(tok);
}
#endif
#ifndef PGEN
Py_XDECREF(tok->decoding_readline);
Py_XDECREF(tok->decoding_buffer);
+ Py_XDECREF(tok->filename);
#endif
if (tok->fp != NULL && tok->buf != NULL)
PyMem_FREE(tok->buf);
return 1;
}
if (tok->altwarning) {
- PySys_WriteStderr("%s: inconsistent use of tabs and spaces "
+#ifdef PGEN
+ PySys_WriteStderr("inconsistent use of tabs and spaces "
+ "in indentation\n");
+#else
+ PySys_FormatStderr("%U: inconsistent use of tabs and spaces "
"in indentation\n", tok->filename);
+#endif
tok->altwarning = 0;
}
return 0;
fclose(fp);
return NULL;
}
+#ifndef PGEN
+ tok->filename = PyUnicode_FromString("<string>");
+ if (tok->filename == NULL)
+ goto error;
+#endif
while (tok->lineno < 2 && tok->done == E_OK) {
PyTokenizer_Get(tok, &p_start, &p_end);
}
if (encoding)
strcpy(encoding, tok->encoding);
}
+#ifndef PGEN
+error:
+#endif
PyTokenizer_Free(tok);
return encoding;
}
int level; /* () [] {} Parentheses nesting level */
/* Used to allow free continuations inside them */
/* Stuff for checking on different tab sizes */
- const char *filename; /* encoded to the filesystem encoding */
+#ifndef PGEN
+ /* pgen doesn't have access to Python codecs, it cannot decode the input
+ filename. The bytes filename might be kept, but it is only used by
+ indenterror() and it is not really needed: pgen only compiles one file
+ (Grammar/Grammar). */
+ PyObject *filename;
+#endif
int altwarning; /* Issue warning if alternate tabs don't match */
int alterror; /* Issue error if alternate tabs don't match */
int alttabsize; /* Alternate tab spacing */
static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *,
PyCompilerFlags *);
static void err_input(perrdetail *);
+static void err_free(perrdetail *);
static void initsigs(void);
static void call_py_exitfuncs(void);
static void wait_for_thread_shutdown(void);
flags->cf_flags |= iflags & PyCF_MASK;
mod = PyAST_FromNode(n, flags, filename, arena);
PyNode_Free(n);
- return mod;
}
else {
err_input(&err);
- return NULL;
+ mod = NULL;
}
+ err_free(&err);
+ return mod;
}
mod_ty
flags->cf_flags |= iflags & PyCF_MASK;
mod = PyAST_FromNode(n, flags, filename, arena);
PyNode_Free(n);
- return mod;
}
else {
err_input(&err);
if (errcode)
*errcode = err.error;
- return NULL;
+ mod = NULL;
}
+ err_free(&err);
+ return mod;
}
/* Simplified interface to parsefile -- return node or set exception */
start, NULL, NULL, &err, flags);
if (n == NULL)
err_input(&err);
+ err_free(&err);
return n;
}
start, &err, flags);
if (n == NULL)
err_input(&err);
+ err_free(&err);
return n;
}
&_PyParser_Grammar, start, &err, flags);
if (n == NULL)
err_input(&err);
+ err_free(&err);
return n;
}
/* May want to move a more generalized form of this to parsetok.c or
even parser modules. */
+void
+PyParser_ClearError(perrdetail *err)
+{
+ err_free(err);
+}
+
void
PyParser_SetError(perrdetail *err)
{
err_input(err);
}
+static void
+err_free(perrdetail *err)
+{
+ Py_CLEAR(err->filename);
+}
+
/* Set the error appropriate to the given input error code (see errcode.h) */
static void
{
PyObject *v, *w, *errtype, *errtext;
PyObject *msg_obj = NULL;
- PyObject *filename;
char *msg = NULL;
errtype = PyExc_SyntaxError;
errtext = PyUnicode_DecodeUTF8(err->text, strlen(err->text),
"replace");
}
- if (err->filename != NULL)
- filename = PyUnicode_DecodeFSDefault(err->filename);
- else {
- Py_INCREF(Py_None);
- filename = Py_None;
- }
- if (filename != NULL)
- v = Py_BuildValue("(NiiN)", filename,
- err->lineno, err->offset, errtext);
- else
- v = NULL;
+ v = Py_BuildValue("(OiiN)", err->filename,
+ err->lineno, err->offset, errtext);
if (v != NULL) {
if (msg_obj)
w = Py_BuildValue("(OO)", msg_obj, v);