blob: b0b1bd38a7bbab2467a23a97e1734cca824ac2de [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00002/* Parser-tokenizer link implementation */
3
Pablo Galindof2cf1e32019-04-13 17:05:14 +01004#include "Python.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00005#include "tokenizer.h"
6#include "node.h"
7#include "grammar.h"
8#include "parser.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +00009#include "parsetok.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000010#include "errcode.h"
Martin v. Löwis00f1e3f2002-08-04 17:29:52 +000011#include "graminit.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000012
Guido van Rossum3f5da241990-12-20 15:06:42 +000013
14/* Forward */
Christian Heimes4d6ec852008-03-26 22:34:47 +000015static node *parsetok(struct tok_state *, grammar *, int, perrdetail *, int *);
Victor Stinner14e461d2013-08-26 22:28:21 +020016static int initerr(perrdetail *err_ret, PyObject * filename);
Guido van Rossum3f5da241990-12-20 15:06:42 +000017
Guido van Rossumdcfcd142019-01-31 03:40:27 -080018typedef struct {
Michael J. Sullivan933e1502019-05-22 07:54:20 -070019 struct {
20 int lineno;
21 char *comment;
22 } *items;
Guido van Rossumdcfcd142019-01-31 03:40:27 -080023 size_t size;
24 size_t num_items;
Michael J. Sullivan933e1502019-05-22 07:54:20 -070025} growable_comment_array;
Guido van Rossumdcfcd142019-01-31 03:40:27 -080026
27static int
Michael J. Sullivan933e1502019-05-22 07:54:20 -070028growable_comment_array_init(growable_comment_array *arr, size_t initial_size) {
Guido van Rossumdcfcd142019-01-31 03:40:27 -080029 assert(initial_size > 0);
30 arr->items = malloc(initial_size * sizeof(*arr->items));
31 arr->size = initial_size;
32 arr->num_items = 0;
33
34 return arr->items != NULL;
35}
36
37static int
Michael J. Sullivan933e1502019-05-22 07:54:20 -070038growable_comment_array_add(growable_comment_array *arr, int lineno, char *comment) {
Guido van Rossumdcfcd142019-01-31 03:40:27 -080039 if (arr->num_items >= arr->size) {
40 arr->size *= 2;
41 arr->items = realloc(arr->items, arr->size * sizeof(*arr->items));
42 if (!arr->items) {
43 return 0;
44 }
45 }
46
Michael J. Sullivan933e1502019-05-22 07:54:20 -070047 arr->items[arr->num_items].lineno = lineno;
48 arr->items[arr->num_items].comment = comment;
Guido van Rossumdcfcd142019-01-31 03:40:27 -080049 arr->num_items++;
50 return 1;
51}
52
53static void
Michael J. Sullivan933e1502019-05-22 07:54:20 -070054growable_comment_array_deallocate(growable_comment_array *arr) {
55 for (unsigned i = 0; i < arr->num_items; i++) {
56 PyObject_FREE(arr->items[i].comment);
57 }
Guido van Rossumdcfcd142019-01-31 03:40:27 -080058 free(arr->items);
59}
60
Guido van Rossum3f5da241990-12-20 15:06:42 +000061/* Parse input coming from a string. Return error code, print some errors. */
Guido van Rossumbd0389d1994-08-29 12:25:45 +000062node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000063PyParser_ParseString(const char *s, grammar *g, int start, perrdetail *err_ret)
Guido van Rossum3f5da241990-12-20 15:06:42 +000064{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 return PyParser_ParseStringFlagsFilename(s, NULL, g, start, err_ret, 0);
Tim Petersfe2127d2001-07-16 05:37:24 +000066}
67
68node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000069PyParser_ParseStringFlags(const char *s, grammar *g, int start,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000070 perrdetail *err_ret, int flags)
Tim Petersfe2127d2001-07-16 05:37:24 +000071{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000072 return PyParser_ParseStringFlagsFilename(s, NULL,
73 g, start, err_ret, flags);
Thomas Heller6b17abf2002-07-09 09:23:27 +000074}
75
76node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000077PyParser_ParseStringFlagsFilename(const char *s, const char *filename,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000078 grammar *g, int start,
79 perrdetail *err_ret, int flags)
Thomas Heller6b17abf2002-07-09 09:23:27 +000080{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000081 int iflags = flags;
82 return PyParser_ParseStringFlagsFilenameEx(s, filename, g, start,
83 err_ret, &iflags);
Christian Heimes4d6ec852008-03-26 22:34:47 +000084}
85
86node *
Victor Stinner14e461d2013-08-26 22:28:21 +020087PyParser_ParseStringObject(const char *s, PyObject *filename,
88 grammar *g, int start,
89 perrdetail *err_ret, int *flags)
Christian Heimes4d6ec852008-03-26 22:34:47 +000090{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000091 struct tok_state *tok;
92 int exec_input = start == file_input;
Guido van Rossumbd0389d1994-08-29 12:25:45 +000093
Victor Stinner7f2fee32011-04-05 00:39:01 +020094 if (initerr(err_ret, filename) < 0)
95 return NULL;
Guido van Rossumbd0389d1994-08-29 12:25:45 +000096
Steve Dowerb82e17e2019-05-23 08:45:22 -070097 if (PySys_Audit("compile", "yO", s, err_ret->filename) < 0) {
98 err_ret->error = E_ERROR;
99 return NULL;
100 }
101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000102 if (*flags & PyPARSE_IGNORE_COOKIE)
103 tok = PyTokenizer_FromUTF8(s, exec_input);
104 else
105 tok = PyTokenizer_FromString(s, exec_input);
106 if (tok == NULL) {
107 err_ret->error = PyErr_Occurred() ? E_DECODE : E_NOMEM;
108 return NULL;
109 }
Guido van Rossumdcfcd142019-01-31 03:40:27 -0800110 if (*flags & PyPARSE_TYPE_COMMENTS) {
111 tok->type_comments = 1;
112 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000113
Victor Stinner7f2fee32011-04-05 00:39:01 +0200114 Py_INCREF(err_ret->filename);
115 tok->filename = err_ret->filename;
Guido van Rossum495da292019-03-07 12:38:08 -0800116 if (*flags & PyPARSE_ASYNC_HACKS)
117 tok->async_hacks = 1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000118 return parsetok(tok, g, start, err_ret, flags);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000119}
120
Victor Stinner14e461d2013-08-26 22:28:21 +0200121node *
122PyParser_ParseStringFlagsFilenameEx(const char *s, const char *filename_str,
123 grammar *g, int start,
124 perrdetail *err_ret, int *flags)
125{
126 node *n;
127 PyObject *filename = NULL;
Victor Stinner14e461d2013-08-26 22:28:21 +0200128 if (filename_str != NULL) {
129 filename = PyUnicode_DecodeFSDefault(filename_str);
130 if (filename == NULL) {
131 err_ret->error = E_ERROR;
132 return NULL;
133 }
134 }
Victor Stinner14e461d2013-08-26 22:28:21 +0200135 n = PyParser_ParseStringObject(s, filename, g, start, err_ret, flags);
Victor Stinner14e461d2013-08-26 22:28:21 +0200136 Py_XDECREF(filename);
Victor Stinner14e461d2013-08-26 22:28:21 +0200137 return n;
138}
139
Guido van Rossum3f5da241990-12-20 15:06:42 +0000140/* Parse input coming from a file. Return error code, print some errors. */
141
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000142node *
Martin v. Löwis95292d62002-12-11 14:04:59 +0000143PyParser_ParseFile(FILE *fp, const char *filename, grammar *g, int start,
Serhiy Storchakac6792272013-10-19 21:03:34 +0300144 const char *ps1, const char *ps2,
145 perrdetail *err_ret)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000146{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000147 return PyParser_ParseFileFlags(fp, filename, NULL,
148 g, start, ps1, ps2, err_ret, 0);
Tim Petersfe2127d2001-07-16 05:37:24 +0000149}
150
151node *
Christian Heimes4d6ec852008-03-26 22:34:47 +0000152PyParser_ParseFileFlags(FILE *fp, const char *filename, const char *enc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000153 grammar *g, int start,
Serhiy Storchakac6792272013-10-19 21:03:34 +0300154 const char *ps1, const char *ps2,
155 perrdetail *err_ret, int flags)
Tim Petersfe2127d2001-07-16 05:37:24 +0000156{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000157 int iflags = flags;
158 return PyParser_ParseFileFlagsEx(fp, filename, enc, g, start, ps1,
159 ps2, err_ret, &iflags);
Christian Heimes4d6ec852008-03-26 22:34:47 +0000160}
161
162node *
Victor Stinner14e461d2013-08-26 22:28:21 +0200163PyParser_ParseFileObject(FILE *fp, PyObject *filename,
164 const char *enc, grammar *g, int start,
Serhiy Storchakac6792272013-10-19 21:03:34 +0300165 const char *ps1, const char *ps2,
166 perrdetail *err_ret, int *flags)
Christian Heimes4d6ec852008-03-26 22:34:47 +0000167{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000168 struct tok_state *tok;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000169
Victor Stinner7f2fee32011-04-05 00:39:01 +0200170 if (initerr(err_ret, filename) < 0)
171 return NULL;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000172
Steve Dowerb82e17e2019-05-23 08:45:22 -0700173 if (PySys_Audit("compile", "OO", Py_None, err_ret->filename) < 0) {
174 return NULL;
175 }
176
Serhiy Storchakac6792272013-10-19 21:03:34 +0300177 if ((tok = PyTokenizer_FromFile(fp, enc, ps1, ps2)) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000178 err_ret->error = E_NOMEM;
179 return NULL;
180 }
Guido van Rossumdcfcd142019-01-31 03:40:27 -0800181 if (*flags & PyPARSE_TYPE_COMMENTS) {
182 tok->type_comments = 1;
183 }
Victor Stinner7f2fee32011-04-05 00:39:01 +0200184 Py_INCREF(err_ret->filename);
185 tok->filename = err_ret->filename;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 return parsetok(tok, g, start, err_ret, flags);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000187}
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000188
Victor Stinner14e461d2013-08-26 22:28:21 +0200189node *
190PyParser_ParseFileFlagsEx(FILE *fp, const char *filename,
191 const char *enc, grammar *g, int start,
Serhiy Storchakac6792272013-10-19 21:03:34 +0300192 const char *ps1, const char *ps2,
193 perrdetail *err_ret, int *flags)
Victor Stinner14e461d2013-08-26 22:28:21 +0200194{
195 node *n;
196 PyObject *fileobj = NULL;
Victor Stinner14e461d2013-08-26 22:28:21 +0200197 if (filename != NULL) {
198 fileobj = PyUnicode_DecodeFSDefault(filename);
199 if (fileobj == NULL) {
200 err_ret->error = E_ERROR;
201 return NULL;
202 }
203 }
Victor Stinner14e461d2013-08-26 22:28:21 +0200204 n = PyParser_ParseFileObject(fp, fileobj, enc, g,
205 start, ps1, ps2, err_ret, flags);
Victor Stinner14e461d2013-08-26 22:28:21 +0200206 Py_XDECREF(fileobj);
Victor Stinner14e461d2013-08-26 22:28:21 +0200207 return n;
208}
209
Thomas Wouters89f507f2006-12-13 04:49:30 +0000210/* Parse input coming from the given tokenizer structure.
211 Return error code. */
212
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000213static node *
Tim Petersfe2127d2001-07-16 05:37:24 +0000214parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000215 int *flags)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000216{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000217 parser_state *ps;
218 node *n;
Brett Cannonb94767f2011-02-22 20:15:44 +0000219 int started = 0;
Ivan Levkivskyi9932a222019-01-22 11:18:22 +0000220 int col_offset, end_col_offset;
Michael J. Sullivan933e1502019-05-22 07:54:20 -0700221 growable_comment_array type_ignores;
Guido van Rossumdcfcd142019-01-31 03:40:27 -0800222
Michael J. Sullivan933e1502019-05-22 07:54:20 -0700223 if (!growable_comment_array_init(&type_ignores, 10)) {
Guido van Rossumdcfcd142019-01-31 03:40:27 -0800224 err_ret->error = E_NOMEM;
225 PyTokenizer_Free(tok);
226 return NULL;
227 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000228
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000229 if ((ps = PyParser_New(g, start)) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000230 err_ret->error = E_NOMEM;
Alex Henrie7ba6f182020-01-13 03:35:47 -0700231 growable_comment_array_deallocate(&type_ignores);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000232 PyTokenizer_Free(tok);
233 return NULL;
234 }
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000235#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000236 if (*flags & PyPARSE_BARRY_AS_BDFL)
237 ps->p_flags |= CO_FUTURE_BARRY_AS_BDFL;
Guido van Rossumdcfcd142019-01-31 03:40:27 -0800238 if (*flags & PyPARSE_TYPE_COMMENTS)
239 ps->p_flags |= PyCF_TYPE_COMMENTS;
Neil Schemenauerc24ea082002-03-22 23:53:36 +0000240#endif
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000241
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000242 for (;;) {
243 char *a, *b;
244 int type;
245 size_t len;
246 char *str;
Ammar Askar025eb982018-09-24 17:12:49 -0400247 col_offset = -1;
Anthony Sottile995d9b92019-01-12 20:05:13 -0800248 int lineno;
249 const char *line_start;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000250
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000251 type = PyTokenizer_Get(tok, &a, &b);
252 if (type == ERRORTOKEN) {
253 err_ret->error = tok->done;
254 break;
255 }
256 if (type == ENDMARKER && started) {
257 type = NEWLINE; /* Add an extra newline */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000258 started = 0;
259 /* Add the right number of dedent tokens,
260 except if a certain flag is given --
261 codeop.py uses this. */
262 if (tok->indent &&
263 !(*flags & PyPARSE_DONT_IMPLY_DEDENT))
264 {
265 tok->pendin = -tok->indent;
266 tok->indent = 0;
267 }
268 }
269 else
270 started = 1;
Zackery Spytz7c4ab2a2018-08-15 00:27:26 -0600271 len = (a != NULL && b != NULL) ? b - a : 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000272 str = (char *) PyObject_MALLOC(len + 1);
273 if (str == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000274 err_ret->error = E_NOMEM;
275 break;
276 }
277 if (len > 0)
278 strncpy(str, a, len);
279 str[len] = '\0';
Guido van Rossumda62ecc2001-07-17 16:53:11 +0000280
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000281#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000282 if (type == NOTEQUAL) {
283 if (!(ps->p_flags & CO_FUTURE_BARRY_AS_BDFL) &&
284 strcmp(str, "!=")) {
Antoine Pitrou9ec25932011-11-13 01:01:23 +0100285 PyObject_FREE(str);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000286 err_ret->error = E_SYNTAX;
287 break;
288 }
289 else if ((ps->p_flags & CO_FUTURE_BARRY_AS_BDFL) &&
290 strcmp(str, "<>")) {
Antoine Pitrou9ec25932011-11-13 01:01:23 +0100291 PyObject_FREE(str);
Serhiy Storchakaaba24ff2018-07-23 23:41:11 +0300292 err_ret->expected = NOTEQUAL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000293 err_ret->error = E_SYNTAX;
294 break;
295 }
296 }
Neil Schemenauerc24ea082002-03-22 23:53:36 +0000297#endif
Anthony Sottile995d9b92019-01-12 20:05:13 -0800298
299 /* Nodes of type STRING, especially multi line strings
300 must be handled differently in order to get both
301 the starting line number and the column offset right.
302 (cf. issue 16806) */
303 lineno = type == STRING ? tok->first_lineno : tok->lineno;
304 line_start = type == STRING ? tok->multi_line_start : tok->line_start;
305 if (a != NULL && a >= line_start) {
306 col_offset = Py_SAFE_DOWNCAST(a - line_start,
Benjamin Petersonca470632016-09-06 13:47:26 -0700307 intptr_t, int);
Zackery Spytz3e26e422018-08-20 21:11:40 -0600308 }
309 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000310 col_offset = -1;
Zackery Spytz3e26e422018-08-20 21:11:40 -0600311 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000312
Ivan Levkivskyi9932a222019-01-22 11:18:22 +0000313 if (b != NULL && b >= tok->line_start) {
314 end_col_offset = Py_SAFE_DOWNCAST(b - tok->line_start,
315 intptr_t, int);
316 }
317 else {
318 end_col_offset = -1;
319 }
Guido van Rossumdcfcd142019-01-31 03:40:27 -0800320
321 if (type == TYPE_IGNORE) {
Michael J. Sullivan933e1502019-05-22 07:54:20 -0700322 if (!growable_comment_array_add(&type_ignores, tok->lineno, str)) {
Guido van Rossumdcfcd142019-01-31 03:40:27 -0800323 err_ret->error = E_NOMEM;
324 break;
325 }
326 continue;
327 }
328
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000329 if ((err_ret->error =
330 PyParser_AddToken(ps, (int)type, str,
Ivan Levkivskyi9932a222019-01-22 11:18:22 +0000331 lineno, col_offset, tok->lineno, end_col_offset,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000332 &(err_ret->expected))) != E_OK) {
333 if (err_ret->error != E_DONE) {
334 PyObject_FREE(str);
335 err_ret->token = type;
336 }
337 break;
338 }
339 }
340
341 if (err_ret->error == E_DONE) {
342 n = ps->p_tree;
343 ps->p_tree = NULL;
Meador Ingefa21bf02012-01-19 01:08:41 -0600344
Guido van Rossumdcfcd142019-01-31 03:40:27 -0800345 if (n->n_type == file_input) {
346 /* Put type_ignore nodes in the ENDMARKER of file_input. */
347 int num;
348 node *ch;
349 size_t i;
350
351 num = NCH(n);
352 ch = CHILD(n, num - 1);
353 REQ(ch, ENDMARKER);
354
355 for (i = 0; i < type_ignores.num_items; i++) {
Michael J. Sullivan933e1502019-05-22 07:54:20 -0700356 int res = PyNode_AddChild(ch, TYPE_IGNORE, type_ignores.items[i].comment,
357 type_ignores.items[i].lineno, 0,
358 type_ignores.items[i].lineno, 0);
359 if (res != 0) {
360 err_ret->error = res;
361 PyNode_Free(n);
362 n = NULL;
363 break;
364 }
365 type_ignores.items[i].comment = NULL;
Guido van Rossumdcfcd142019-01-31 03:40:27 -0800366 }
367 }
Guido van Rossumdcfcd142019-01-31 03:40:27 -0800368
Meador Ingefa21bf02012-01-19 01:08:41 -0600369 /* Check that the source for a single input statement really
370 is a single statement by looking at what is left in the
371 buffer after parsing. Trailing whitespace and comments
372 are OK. */
Michael J. Sullivan933e1502019-05-22 07:54:20 -0700373 if (err_ret->error == E_DONE && start == single_input) {
Meador Ingefa21bf02012-01-19 01:08:41 -0600374 char *cur = tok->cur;
375 char c = *tok->cur;
376
Benjamin Petersoncff92372012-01-19 17:46:13 -0500377 for (;;) {
378 while (c == ' ' || c == '\t' || c == '\n' || c == '\014')
379 c = *++cur;
Meador Ingefa21bf02012-01-19 01:08:41 -0600380
Benjamin Petersoncff92372012-01-19 17:46:13 -0500381 if (!c)
382 break;
383
384 if (c != '#') {
385 err_ret->error = E_BADSINGLE;
386 PyNode_Free(n);
387 n = NULL;
388 break;
389 }
390
391 /* Suck up comment. */
392 while (c && c != '\n')
393 c = *++cur;
Meador Ingefa21bf02012-01-19 01:08:41 -0600394 }
395 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000396 }
397 else
398 n = NULL;
Christian Heimesb1b3efc2008-03-26 23:24:27 +0000399
Michael J. Sullivan933e1502019-05-22 07:54:20 -0700400 growable_comment_array_deallocate(&type_ignores);
Pablo Galindob9d2e972019-02-13 00:45:53 +0000401
Christian Heimes4d6ec852008-03-26 22:34:47 +0000402#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000403 *flags = ps->p_flags;
Christian Heimes4d6ec852008-03-26 22:34:47 +0000404#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000405 PyParser_Delete(ps);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000406
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000407 if (n == NULL) {
Benjamin Peterson758888d2011-05-30 11:12:38 -0500408 if (tok->done == E_EOF)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000409 err_ret->error = E_EOF;
410 err_ret->lineno = tok->lineno;
411 if (tok->buf != NULL) {
412 size_t len;
413 assert(tok->cur - tok->buf < INT_MAX);
Ammar Askar025eb982018-09-24 17:12:49 -0400414 /* if we've managed to parse a token, point the offset to its start,
415 * else use the current reading position of the tokenizer
416 */
417 err_ret->offset = col_offset != -1 ? col_offset + 1 : ((int)(tok->cur - tok->buf));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000418 len = tok->inp - tok->buf;
419 err_ret->text = (char *) PyObject_MALLOC(len + 1);
420 if (err_ret->text != NULL) {
421 if (len > 0)
422 strncpy(err_ret->text, tok->buf, len);
423 err_ret->text[len] = '\0';
424 }
425 }
426 } else if (tok->encoding != NULL) {
427 /* 'nodes->n_str' uses PyObject_*, while 'tok->encoding' was
428 * allocated using PyMem_
429 */
430 node* r = PyNode_New(encoding_decl);
431 if (r)
432 r->n_str = PyObject_MALLOC(strlen(tok->encoding)+1);
433 if (!r || !r->n_str) {
434 err_ret->error = E_NOMEM;
435 if (r)
436 PyObject_FREE(r);
437 n = NULL;
438 goto done;
439 }
440 strcpy(r->n_str, tok->encoding);
441 PyMem_FREE(tok->encoding);
442 tok->encoding = NULL;
443 r->n_nchildren = 1;
444 r->n_child = n;
445 n = r;
446 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000447
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000448done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000449 PyTokenizer_Free(tok);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000450
Ivan Levkivskyi9932a222019-01-22 11:18:22 +0000451 if (n != NULL) {
452 _PyNode_FinalizeEndPos(n);
453 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000454 return n;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000455}
Guido van Rossum0c156a52001-10-20 14:27:56 +0000456
Victor Stinner7f2fee32011-04-05 00:39:01 +0200457static int
Victor Stinner14e461d2013-08-26 22:28:21 +0200458initerr(perrdetail *err_ret, PyObject *filename)
Guido van Rossum0c156a52001-10-20 14:27:56 +0000459{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000460 err_ret->error = E_OK;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000461 err_ret->lineno = 0;
462 err_ret->offset = 0;
463 err_ret->text = NULL;
464 err_ret->token = -1;
465 err_ret->expected = -1;
Victor Stinner14e461d2013-08-26 22:28:21 +0200466 if (filename) {
467 Py_INCREF(filename);
468 err_ret->filename = filename;
469 }
470 else {
Victor Stinner7f2fee32011-04-05 00:39:01 +0200471 err_ret->filename = PyUnicode_FromString("<string>");
Victor Stinner14e461d2013-08-26 22:28:21 +0200472 if (err_ret->filename == NULL) {
473 err_ret->error = E_ERROR;
474 return -1;
475 }
Victor Stinner7f2fee32011-04-05 00:39:01 +0200476 }
Victor Stinner7f2fee32011-04-05 00:39:01 +0200477 return 0;
Guido van Rossum0c156a52001-10-20 14:27:56 +0000478}