LCOV - code coverage report
Current view: top level - Parser - tokenizer.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 483 917 52.7 %
Date: 2017-04-19 Functions: 22 33 66.7 %

          Line data    Source code
       1             : 
       2             : /* Tokenizer implementation */
       3             : 
       4             : #include "Python.h"
       5             : #include "pgenheaders.h"
       6             : 
       7             : #include <ctype.h>
       8             : #include <assert.h>
       9             : 
      10             : #include "tokenizer.h"
      11             : #include "errcode.h"
      12             : 
      13             : #ifndef PGEN
      14             : #include "unicodeobject.h"
      15             : #include "stringobject.h"
      16             : #include "fileobject.h"
      17             : #include "codecs.h"
      18             : #include "abstract.h"
      19             : #include "pydebug.h"
      20             : #endif /* PGEN */
      21             : 
      22             : extern char *PyOS_Readline(FILE *, FILE *, char *);
      23             : /* Return malloc'ed string including trailing \n;
      24             :    empty malloc'ed string for EOF;
      25             :    NULL if interrupted */
      26             : 
      27             : /* Don't ever change this -- it would break the portability of Python code */
      28             : #define TABSIZE 8
      29             : 
      30             : /* Forward */
      31             : static struct tok_state *tok_new(void);
      32             : static int tok_nextc(struct tok_state *tok);
      33             : static void tok_backup(struct tok_state *tok, int c);
      34             : 
      35             : /* Token names */
      36             : 
      37             : char *_PyParser_TokenNames[] = {
      38             :     "ENDMARKER",
      39             :     "NAME",
      40             :     "NUMBER",
      41             :     "STRING",
      42             :     "NEWLINE",
      43             :     "INDENT",
      44             :     "DEDENT",
      45             :     "LPAR",
      46             :     "RPAR",
      47             :     "LSQB",
      48             :     "RSQB",
      49             :     "COLON",
      50             :     "COMMA",
      51             :     "SEMI",
      52             :     "PLUS",
      53             :     "MINUS",
      54             :     "STAR",
      55             :     "SLASH",
      56             :     "VBAR",
      57             :     "AMPER",
      58             :     "LESS",
      59             :     "GREATER",
      60             :     "EQUAL",
      61             :     "DOT",
      62             :     "PERCENT",
      63             :     "BACKQUOTE",
      64             :     "LBRACE",
      65             :     "RBRACE",
      66             :     "EQEQUAL",
      67             :     "NOTEQUAL",
      68             :     "LESSEQUAL",
      69             :     "GREATEREQUAL",
      70             :     "TILDE",
      71             :     "CIRCUMFLEX",
      72             :     "LEFTSHIFT",
      73             :     "RIGHTSHIFT",
      74             :     "DOUBLESTAR",
      75             :     "PLUSEQUAL",
      76             :     "MINEQUAL",
      77             :     "STAREQUAL",
      78             :     "SLASHEQUAL",
      79             :     "PERCENTEQUAL",
      80             :     "AMPEREQUAL",
      81             :     "VBAREQUAL",
      82             :     "CIRCUMFLEXEQUAL",
      83             :     "LEFTSHIFTEQUAL",
      84             :     "RIGHTSHIFTEQUAL",
      85             :     "DOUBLESTAREQUAL",
      86             :     "DOUBLESLASH",
      87             :     "DOUBLESLASHEQUAL",
      88             :     "AT",
      89             :     /* This table must match the #defines in token.h! */
      90             :     "OP",
      91             :     "<ERRORTOKEN>",
      92             :     "<N_TOKENS>"
      93             : };
      94             : 
      95             : /* Create and initialize a new tok_state structure */
      96             : 
      97             : static struct tok_state *
      98          63 : tok_new(void)
      99             : {
     100          63 :     struct tok_state *tok = (struct tok_state *)PyMem_MALLOC(
     101             :                                             sizeof(struct tok_state));
     102          63 :     if (tok == NULL)
     103           0 :         return NULL;
     104          63 :     tok->buf = tok->cur = tok->end = tok->inp = tok->start = NULL;
     105          63 :     tok->done = E_OK;
     106          63 :     tok->fp = NULL;
     107          63 :     tok->input = NULL;
     108          63 :     tok->tabsize = TABSIZE;
     109          63 :     tok->indent = 0;
     110          63 :     tok->indstack[0] = 0;
     111          63 :     tok->atbol = 1;
     112          63 :     tok->pendin = 0;
     113          63 :     tok->prompt = tok->nextprompt = NULL;
     114          63 :     tok->lineno = 0;
     115          63 :     tok->level = 0;
     116          63 :     tok->filename = NULL;
     117          63 :     tok->altwarning = 0;
     118          63 :     tok->alterror = 0;
     119          63 :     tok->alttabsize = 1;
     120          63 :     tok->altindstack[0] = 0;
     121          63 :     tok->decoding_state = 0;
     122          63 :     tok->decoding_erred = 0;
     123          63 :     tok->read_coding_spec = 0;
     124          63 :     tok->encoding = NULL;
     125          63 :     tok->cont_line = 0;
     126             : #ifndef PGEN
     127          63 :     tok->decoding_readline = NULL;
     128          63 :     tok->decoding_buffer = NULL;
     129             : #endif
     130          63 :     return tok;
     131             : }
     132             : 
     133             : static char *
     134           0 : new_string(const char *s, Py_ssize_t len)
     135             : {
     136           0 :     char* result = (char *)PyMem_MALLOC(len + 1);
     137           0 :     if (result != NULL) {
     138           0 :         memcpy(result, s, len);
     139           0 :         result[len] = '\0';
     140             :     }
     141           0 :     return result;
     142             : }
     143             : 
     144             : #ifdef PGEN
     145             : 
     146             : static char *
     147             : decoding_fgets(char *s, int size, struct tok_state *tok)
     148             : {
     149             :     return fgets(s, size, tok->fp);
     150             : }
     151             : 
     152             : static int
     153             : decoding_feof(struct tok_state *tok)
     154             : {
     155             :     return feof(tok->fp);
     156             : }
     157             : 
     158             : static char *
     159             : decode_str(const char *str, int exec_input, struct tok_state *tok)
     160             : {
     161             :     return new_string(str, strlen(str));
     162             : }
     163             : 
     164             : #else /* PGEN */
     165             : 
     166             : static char *
     167           0 : error_ret(struct tok_state *tok) /* XXX */
     168             : {
     169           0 :     tok->decoding_erred = 1;
     170           0 :     if (tok->fp != NULL && tok->buf != NULL) /* see PyTokenizer_Free */
     171           0 :         PyMem_FREE(tok->buf);
     172           0 :     tok->buf = tok->cur = tok->end = tok->inp = tok->start = NULL;
     173           0 :     tok->done = E_DECODE;
     174           0 :     return NULL;                /* as if it were EOF */
     175             : }
     176             : 
     177             : 
     178             : static char *
     179           0 : get_normal_name(char *s)        /* for utf-8 and latin-1 */
     180             : {
     181             :     char buf[13];
     182             :     int i;
     183           0 :     for (i = 0; i < 12; i++) {
     184           0 :         int c = s[i];
     185           0 :         if (c == '\0')
     186           0 :             break;
     187           0 :         else if (c == '_')
     188           0 :             buf[i] = '-';
     189             :         else
     190           0 :             buf[i] = tolower(c);
     191             :     }
     192           0 :     buf[i] = '\0';
     193           0 :     if (strcmp(buf, "utf-8") == 0 ||
     194           0 :         strncmp(buf, "utf-8-", 6) == 0)
     195           0 :         return "utf-8";
     196           0 :     else if (strcmp(buf, "latin-1") == 0 ||
     197           0 :              strcmp(buf, "iso-8859-1") == 0 ||
     198           0 :              strcmp(buf, "iso-latin-1") == 0 ||
     199           0 :              strncmp(buf, "latin-1-", 8) == 0 ||
     200           0 :              strncmp(buf, "iso-8859-1-", 11) == 0 ||
     201           0 :              strncmp(buf, "iso-latin-1-", 12) == 0)
     202           0 :         return "iso-8859-1";
     203             :     else
     204           0 :         return s;
     205             : }
     206             : 
     207             : /* Return the coding spec in S, or NULL if none is found.  */
     208             : 
     209             : static char *
     210          85 : get_coding_spec(const char *s, Py_ssize_t size)
     211             : {
     212             :     Py_ssize_t i;
     213             :     /* Coding spec must be in a comment, and that comment must be
     214             :      * the only statement on the source code line. */
     215          85 :     for (i = 0; i < size - 6; i++) {
     216          71 :         if (s[i] == '#')
     217          42 :             break;
     218          29 :         if (s[i] != ' ' && s[i] != '\t' && s[i] != '\014')
     219          29 :             return NULL;
     220             :     }
     221        1195 :     for (; i < size - 6; i++) { /* XXX inefficient search */
     222        1139 :         const char* t = s + i;
     223        1139 :         if (strncmp(t, "coding", 6) == 0) {
     224           0 :             const char* begin = NULL;
     225           0 :             t += 6;
     226           0 :             if (t[0] != ':' && t[0] != '=')
     227           0 :                 continue;
     228             :             do {
     229           0 :                 t++;
     230           0 :             } while (t[0] == '\x20' || t[0] == '\t');
     231             : 
     232           0 :             begin = t;
     233           0 :             while (Py_ISALNUM(t[0]) ||
     234           0 :                    t[0] == '-' || t[0] == '_' || t[0] == '.')
     235           0 :                 t++;
     236             : 
     237           0 :             if (begin < t) {
     238           0 :                 char* r = new_string(begin, t - begin);
     239             :                 char* q;
     240           0 :                 if (!r)
     241           0 :                     return NULL;
     242           0 :                 q = get_normal_name(r);
     243           0 :                 if (r != q) {
     244           0 :                     PyMem_FREE(r);
     245           0 :                     r = new_string(q, strlen(q));
     246             :                 }
     247           0 :                 return r;
     248             :             }
     249             :         }
     250             :     }
     251          56 :     return NULL;
     252             : }
     253             : 
     254             : /* Check whether the line contains a coding spec. If it does,
     255             :    invoke the set_readline function for the new encoding.
     256             :    This function receives the tok_state and the new encoding.
     257             :    Return 1 on success, 0 on failure.  */
     258             : 
     259             : static int
     260          85 : check_coding_spec(const char* line, Py_ssize_t size, struct tok_state *tok,
     261             :                   int set_readline(struct tok_state *, const char *))
     262             : {
     263             :     char * cs;
     264          85 :     int r = 1;
     265             : 
     266          85 :     if (tok->cont_line) {
     267             :         /* It's a continuation line, so it can't be a coding spec. */
     268           0 :         tok->read_coding_spec = 1;
     269           0 :         return 1;
     270             :     }
     271          85 :     cs = get_coding_spec(line, size);
     272          85 :     if (!cs) {
     273             :         Py_ssize_t i;
     274          85 :         for (i = 0; i < size; i++) {
     275          85 :             if (line[i] == '#' || line[i] == '\n' || line[i] == '\r')
     276             :                 break;
     277          43 :             if (line[i] != ' ' && line[i] != '\t' && line[i] != '\014') {
     278             :                 /* Stop checking coding spec after a line containing
     279             :                  * anything except a comment. */
     280          43 :                 tok->read_coding_spec = 1;
     281          43 :                 break;
     282             :             }
     283             :         }
     284             :     } else {
     285           0 :         tok->read_coding_spec = 1;
     286           0 :         if (tok->encoding == NULL) {
     287             :             assert(tok->decoding_state == 1); /* raw */
     288           0 :             if (strcmp(cs, "utf-8") == 0 ||
     289           0 :                 strcmp(cs, "iso-8859-1") == 0) {
     290           0 :                 tok->encoding = cs;
     291             :             } else {
     292             : #ifdef Py_USING_UNICODE
     293           0 :                 r = set_readline(tok, cs);
     294           0 :                 if (r) {
     295           0 :                     tok->encoding = cs;
     296           0 :                     tok->decoding_state = -1;
     297             :                 }
     298             :                 else {
     299           0 :                     PyErr_Format(PyExc_SyntaxError,
     300             :                                  "encoding problem: %s", cs);
     301           0 :                     PyMem_FREE(cs);
     302             :                 }
     303             : #else
     304             :                 /* Without Unicode support, we cannot
     305             :                    process the coding spec. Since there
     306             :                    won't be any Unicode literals, that
     307             :                    won't matter. */
     308             :                 PyMem_FREE(cs);
     309             : #endif
     310             :             }
     311             :         } else {                /* then, compare cs with BOM */
     312           0 :             r = (strcmp(tok->encoding, cs) == 0);
     313           0 :             if (!r)
     314           0 :                 PyErr_Format(PyExc_SyntaxError,
     315             :                              "encoding problem: %s with BOM", cs);
     316           0 :             PyMem_FREE(cs);
     317             :         }
     318             :     }
     319          85 :     return r;
     320             : }
     321             : 
     322             : /* See whether the file starts with a BOM. If it does,
     323             :    invoke the set_readline function with the new encoding.
     324             :    Return 1 on success, 0 on failure.  */
     325             : 
     326             : static int
     327          63 : check_bom(int get_char(struct tok_state *),
     328             :           void unget_char(int, struct tok_state *),
     329             :           int set_readline(struct tok_state *, const char *),
     330             :           struct tok_state *tok)
     331             : {
     332             :     int ch1, ch2, ch3;
     333          63 :     ch1 = get_char(tok);
     334          63 :     tok->decoding_state = 1;
     335          63 :     if (ch1 == EOF) {
     336           3 :         return 1;
     337          60 :     } else if (ch1 == 0xEF) {
     338           0 :         ch2 = get_char(tok);
     339           0 :         if (ch2 != 0xBB) {
     340           0 :             unget_char(ch2, tok);
     341           0 :             unget_char(ch1, tok);
     342           0 :             return 1;
     343             :         }
     344           0 :         ch3 = get_char(tok);
     345           0 :         if (ch3 != 0xBF) {
     346           0 :             unget_char(ch3, tok);
     347           0 :             unget_char(ch2, tok);
     348           0 :             unget_char(ch1, tok);
     349           0 :             return 1;
     350             :         }
     351             : #if 0
     352             :     /* Disable support for UTF-16 BOMs until a decision
     353             :        is made whether this needs to be supported.  */
     354             :     } else if (ch1 == 0xFE) {
     355             :         ch2 = get_char(tok);
     356             :         if (ch2 != 0xFF) {
     357             :             unget_char(ch2, tok);
     358             :             unget_char(ch1, tok);
     359             :             return 1;
     360             :         }
     361             :         if (!set_readline(tok, "utf-16-be"))
     362             :             return 0;
     363             :         tok->decoding_state = -1;
     364             :     } else if (ch1 == 0xFF) {
     365             :         ch2 = get_char(tok);
     366             :         if (ch2 != 0xFE) {
     367             :             unget_char(ch2, tok);
     368             :             unget_char(ch1, tok);
     369             :             return 1;
     370             :         }
     371             :         if (!set_readline(tok, "utf-16-le"))
     372             :             return 0;
     373             :         tok->decoding_state = -1;
     374             : #endif
     375             :     } else {
     376          60 :         unget_char(ch1, tok);
     377          60 :         return 1;
     378             :     }
     379           0 :     if (tok->encoding != NULL)
     380           0 :         PyMem_FREE(tok->encoding);
     381           0 :     tok->encoding = new_string("utf-8", 5);     /* resulting is in utf-8 */
     382           0 :     return 1;
     383             : }
     384             : 
     385             : /* Read a line of text from TOK into S, using the stream in TOK.
     386             :    Return NULL on failure, else S.
     387             : 
     388             :    On entry, tok->decoding_buffer will be one of:
     389             :      1) NULL: need to call tok->decoding_readline to get a new line
     390             :      2) PyUnicodeObject *: decoding_feof has called tok->decoding_readline and
     391             :        stored the result in tok->decoding_buffer
     392             :      3) PyStringObject *: previous call to fp_readl did not have enough room
     393             :        (in the s buffer) to copy entire contents of the line read
     394             :        by tok->decoding_readline.  tok->decoding_buffer has the overflow.
     395             :        In this case, fp_readl is called in a loop (with an expanded buffer)
     396             :        until the buffer ends with a '\n' (or until the end of the file is
     397             :        reached): see tok_nextc and its calls to decoding_fgets.
     398             : */
     399             : 
     400             : static char *
     401           0 : fp_readl(char *s, int size, struct tok_state *tok)
     402             : {
     403             : #ifndef Py_USING_UNICODE
     404             :     /* In a non-Unicode built, this should never be called. */
     405             :     Py_FatalError("fp_readl should not be called in this build.");
     406             :     return NULL; /* Keep compiler happy (not reachable) */
     407             : #else
     408           0 :     PyObject* utf8 = NULL;
     409           0 :     PyObject* buf = tok->decoding_buffer;
     410             :     char *str;
     411             :     Py_ssize_t utf8len;
     412             : 
     413             :     /* Ask for one less byte so we can terminate it */
     414             :     assert(size > 0);
     415           0 :     size--;
     416             : 
     417           0 :     if (buf == NULL) {
     418           0 :         buf = PyObject_CallObject(tok->decoding_readline, NULL);
     419           0 :         if (buf == NULL)
     420           0 :             return error_ret(tok);
     421           0 :         if (!PyUnicode_Check(buf)) {
     422           0 :             Py_DECREF(buf);
     423           0 :             PyErr_SetString(PyExc_SyntaxError,
     424             :                             "codec did not return a unicode object");
     425           0 :             return error_ret(tok);
     426             :         }
     427             :     } else {
     428           0 :         tok->decoding_buffer = NULL;
     429           0 :         if (PyString_CheckExact(buf))
     430           0 :             utf8 = buf;
     431             :     }
     432           0 :     if (utf8 == NULL) {
     433           0 :         utf8 = PyUnicode_AsUTF8String(buf);
     434           0 :         Py_DECREF(buf);
     435           0 :         if (utf8 == NULL)
     436           0 :             return error_ret(tok);
     437             :     }
     438           0 :     str = PyString_AsString(utf8);
     439           0 :     utf8len = PyString_GET_SIZE(utf8);
     440           0 :     if (utf8len > size) {
     441           0 :         tok->decoding_buffer = PyString_FromStringAndSize(str+size, utf8len-size);
     442           0 :         if (tok->decoding_buffer == NULL) {
     443           0 :             Py_DECREF(utf8);
     444           0 :             return error_ret(tok);
     445             :         }
     446           0 :         utf8len = size;
     447             :     }
     448           0 :     memcpy(s, str, utf8len);
     449           0 :     s[utf8len] = '\0';
     450           0 :     Py_DECREF(utf8);
     451           0 :     if (utf8len == 0)
     452           0 :         return NULL; /* EOF */
     453           0 :     return s;
     454             : #endif
     455             : }
     456             : 
     457             : /* Set the readline function for TOK to a StreamReader's
     458             :    readline function. The StreamReader is named ENC.
     459             : 
     460             :    This function is called from check_bom and check_coding_spec.
     461             : 
     462             :    ENC is usually identical to the future value of tok->encoding,
     463             :    except for the (currently unsupported) case of UTF-16.
     464             : 
     465             :    Return 1 on success, 0 on failure. */
     466             : 
     467             : static int
     468           0 : fp_setreadl(struct tok_state *tok, const char* enc)
     469             : {
     470             :     PyObject *reader, *stream, *readline;
     471             : 
     472             :     /* XXX: constify filename argument. */
     473           0 :     stream = PyFile_FromFile(tok->fp, (char*)tok->filename, "rb", NULL);
     474           0 :     if (stream == NULL)
     475           0 :         return 0;
     476             : 
     477           0 :     reader = PyCodec_StreamReader(enc, stream, NULL);
     478           0 :     Py_DECREF(stream);
     479           0 :     if (reader == NULL)
     480           0 :         return 0;
     481             : 
     482           0 :     readline = PyObject_GetAttrString(reader, "readline");
     483           0 :     Py_DECREF(reader);
     484           0 :     if (readline == NULL)
     485           0 :         return 0;
     486             : 
     487           0 :     tok->decoding_readline = readline;
     488           0 :     return 1;
     489             : }
     490             : 
     491             : /* Fetch the next byte from TOK. */
     492             : 
     493          36 : static int fp_getc(struct tok_state *tok) {
     494          36 :     return getc(tok->fp);
     495             : }
     496             : 
     497             : /* Unfetch the last byte back into TOK.  */
     498             : 
     499          33 : static void fp_ungetc(int c, struct tok_state *tok) {
     500          33 :     ungetc(c, tok->fp);
     501          33 : }
     502             : 
     503             : /* Read a line of input from TOK. Determine encoding
     504             :    if necessary.  */
     505             : 
     506             : static char *
     507       14686 : decoding_fgets(char *s, int size, struct tok_state *tok)
     508             : {
     509       14686 :     char *line = NULL;
     510       14686 :     int badchar = 0;
     511             :     for (;;) {
     512       14722 :         if (tok->decoding_state < 0) {
     513             :             /* We already have a codec associated with
     514             :                this input. */
     515           0 :             line = fp_readl(s, size, tok);
     516           0 :             break;
     517       14722 :         } else if (tok->decoding_state > 0) {
     518             :             /* We want a 'raw' read. */
     519       14686 :             line = Py_UniversalNewlineFgets(s, size,
     520             :                                             tok->fp, NULL);
     521       14686 :             break;
     522             :         } else {
     523             :             /* We have not yet determined the encoding.
     524             :                If an encoding is found, use the file-pointer
     525             :                reader functions from now on. */
     526          36 :             if (!check_bom(fp_getc, fp_ungetc, fp_setreadl, tok))
     527           0 :                 return error_ret(tok);
     528             :             assert(tok->decoding_state != 0);
     529             :         }
     530          36 :     }
     531       14686 :     if (line != NULL && tok->lineno < 2 && !tok->read_coding_spec) {
     532          58 :         if (!check_coding_spec(line, strlen(line), tok, fp_setreadl)) {
     533           0 :             return error_ret(tok);
     534             :         }
     535             :     }
     536             : #ifndef PGEN
     537             :     /* The default encoding is ASCII, so make sure we don't have any
     538             :        non-ASCII bytes in it. */
     539       14686 :     if (line && !tok->encoding) {
     540             :         unsigned char *c;
     541      441001 :         for (c = (unsigned char *)line; *c; c++)
     542      426351 :             if (*c > 127) {
     543           0 :                 badchar = *c;
     544           0 :                 break;
     545             :             }
     546             :     }
     547       14686 :     if (badchar) {
     548             :         char buf[500];
     549             :         /* Need to add 1 to the line number, since this line
     550             :            has not been counted, yet.  */
     551           0 :         sprintf(buf,
     552             :             "Non-ASCII character '\\x%.2x' "
     553             :             "in file %.200s on line %i, "
     554             :             "but no encoding declared; "
     555             :             "see http://python.org/dev/peps/pep-0263/ for details",
     556           0 :             badchar, tok->filename, tok->lineno + 1);
     557           0 :         PyErr_SetString(PyExc_SyntaxError, buf);
     558           0 :         return error_ret(tok);
     559             :     }
     560             : #endif
     561       14686 :     return line;
     562             : }
     563             : 
     564             : static int
     565        1734 : decoding_feof(struct tok_state *tok)
     566             : {
     567        1734 :     if (tok->decoding_state >= 0) {
     568        1734 :         return feof(tok->fp);
     569             :     } else {
     570           0 :         PyObject* buf = tok->decoding_buffer;
     571           0 :         if (buf == NULL) {
     572           0 :             buf = PyObject_CallObject(tok->decoding_readline, NULL);
     573           0 :             if (buf == NULL) {
     574           0 :                 error_ret(tok);
     575           0 :                 return 1;
     576             :             } else {
     577           0 :                 tok->decoding_buffer = buf;
     578             :             }
     579             :         }
     580           0 :         return PyObject_Length(buf) == 0;
     581             :     }
     582             : }
     583             : 
     584             : /* Fetch a byte from TOK, using the string buffer. */
     585             : 
     586             : static int
     587          27 : buf_getc(struct tok_state *tok) {
     588          27 :     return Py_CHARMASK(*tok->str++);
     589             : }
     590             : 
     591             : /* Unfetch a byte from TOK, using the string buffer. */
     592             : 
     593             : static void
     594          27 : buf_ungetc(int c, struct tok_state *tok) {
     595          27 :     tok->str--;
     596             :     assert(Py_CHARMASK(*tok->str) == c);        /* tok->cur may point to read-only segment */
     597          27 : }
     598             : 
     599             : /* Set the readline function for TOK to ENC. For the string-based
     600             :    tokenizer, this means to just record the encoding. */
     601             : 
     602             : static int
     603           0 : buf_setreadl(struct tok_state *tok, const char* enc) {
     604           0 :     tok->enc = enc;
     605           0 :     return 1;
     606             : }
     607             : 
     608             : /* Return a UTF-8 encoding Python string object from the
     609             :    C byte string STR, which is encoded with ENC. */
     610             : 
     611             : #ifdef Py_USING_UNICODE
     612             : static PyObject *
     613           0 : translate_into_utf8(const char* str, const char* enc) {
     614             :     PyObject *utf8;
     615           0 :     PyObject* buf = PyUnicode_Decode(str, strlen(str), enc, NULL);
     616           0 :     if (buf == NULL)
     617           0 :         return NULL;
     618           0 :     utf8 = PyUnicode_AsUTF8String(buf);
     619           0 :     Py_DECREF(buf);
     620           0 :     return utf8;
     621             : }
     622             : #endif
     623             : 
     624             : 
     625             : static char *
     626          27 : translate_newlines(const char *s, int exec_input, struct tok_state *tok) {
     627          27 :     int skip_next_lf = 0, needed_length = strlen(s) + 2, final_length;
     628             :     char *buf, *current;
     629          27 :     char c = '\0';
     630          27 :     buf = PyMem_MALLOC(needed_length);
     631          27 :     if (buf == NULL) {
     632           0 :         tok->done = E_NOMEM;
     633           0 :         return NULL;
     634             :     }
     635       50448 :     for (current = buf; *s; s++, current++) {
     636       50421 :         c = *s;
     637       50421 :         if (skip_next_lf) {
     638           0 :             skip_next_lf = 0;
     639           0 :             if (c == '\n') {
     640           0 :                 c = *++s;
     641           0 :                 if (!c)
     642           0 :                     break;
     643             :             }
     644             :         }
     645       50421 :         if (c == '\r') {
     646           0 :             skip_next_lf = 1;
     647           0 :             c = '\n';
     648             :         }
     649       50421 :         *current = c;
     650             :     }
     651             :     /* If this is exec input, add a newline to the end of the string if
     652             :        there isn't one already. */
     653          27 :     if (exec_input && c != '\n') {
     654           0 :         *current = '\n';
     655           0 :         current++;
     656             :     }
     657          27 :     *current = '\0';
     658          27 :     final_length = current - buf + 1;
     659          27 :     if (final_length < needed_length && final_length)
     660             :         /* should never fail */
     661          27 :         buf = PyMem_REALLOC(buf, final_length);
     662          27 :     return buf;
     663             : }
     664             : 
     665             : /* Decode a byte string STR for use as the buffer of TOK.
     666             :    Look for encoding declarations inside STR, and record them
     667             :    inside TOK.  */
     668             : 
     669             : static const char *
     670          27 : decode_str(const char *input, int single, struct tok_state *tok)
     671             : {
     672          27 :     PyObject* utf8 = NULL;
     673             :     const char *str;
     674             :     const char *s;
     675          27 :     const char *newl[2] = {NULL, NULL};
     676          27 :     int lineno = 0;
     677          27 :     tok->input = str = translate_newlines(input, single, tok);
     678          27 :     if (str == NULL)
     679           0 :         return NULL;
     680          27 :     tok->enc = NULL;
     681          27 :     tok->str = str;
     682          27 :     if (!check_bom(buf_getc, buf_ungetc, buf_setreadl, tok))
     683           0 :         return error_ret(tok);
     684          27 :     str = tok->str;             /* string after BOM if any */
     685             :     assert(str);
     686             : #ifdef Py_USING_UNICODE
     687          27 :     if (tok->enc != NULL) {
     688           0 :         utf8 = translate_into_utf8(str, tok->enc);
     689           0 :         if (utf8 == NULL)
     690           0 :             return error_ret(tok);
     691           0 :         str = PyString_AsString(utf8);
     692             :     }
     693             : #endif
     694        2016 :     for (s = str;; s++) {
     695        2016 :         if (*s == '\0') break;
     696        2016 :         else if (*s == '\n') {
     697             :             assert(lineno < 2);
     698          54 :             newl[lineno] = s;
     699          54 :             lineno++;
     700          54 :             if (lineno == 2) break;
     701             :         }
     702        1989 :     }
     703          27 :     tok->enc = NULL;
     704             :     /* need to check line 1 and 2 separately since check_coding_spec
     705             :        assumes a single line as input */
     706          27 :     if (newl[0]) {
     707          27 :         if (!check_coding_spec(str, newl[0] - str, tok, buf_setreadl))
     708           0 :             return error_ret(tok);
     709          27 :         if (tok->enc == NULL && !tok->read_coding_spec && newl[1]) {
     710           0 :             if (!check_coding_spec(newl[0]+1, newl[1] - newl[0],
     711             :                                    tok, buf_setreadl))
     712           0 :                 return error_ret(tok);
     713             :         }
     714             :     }
     715             : #ifdef Py_USING_UNICODE
     716          27 :     if (tok->enc != NULL) {
     717             :         assert(utf8 == NULL);
     718           0 :         utf8 = translate_into_utf8(str, tok->enc);
     719           0 :         if (utf8 == NULL)
     720           0 :             return error_ret(tok);
     721           0 :         str = PyString_AsString(utf8);
     722             :     }
     723             : #endif
     724             :     assert(tok->decoding_buffer == NULL);
     725          27 :     tok->decoding_buffer = utf8; /* CAUTION */
     726          27 :     return str;
     727             : }
     728             : 
     729             : #endif /* PGEN */
     730             : 
     731             : /* Set up tokenizer for string */
     732             : 
     733             : struct tok_state *
     734          27 : PyTokenizer_FromString(const char *str, int exec_input)
     735             : {
     736          27 :     struct tok_state *tok = tok_new();
     737          27 :     if (tok == NULL)
     738           0 :         return NULL;
     739          27 :     str = (char *)decode_str(str, exec_input, tok);
     740          27 :     if (str == NULL) {
     741           0 :         PyTokenizer_Free(tok);
     742           0 :         return NULL;
     743             :     }
     744             : 
     745             :     /* XXX: constify members. */
     746          27 :     tok->buf = tok->cur = tok->end = tok->inp = (char*)str;
     747          27 :     return tok;
     748             : }
     749             : 
     750             : 
     751             : /* Set up tokenizer for file */
     752             : 
     753             : struct tok_state *
     754          36 : PyTokenizer_FromFile(FILE *fp, char *ps1, char *ps2)
     755             : {
     756          36 :     struct tok_state *tok = tok_new();
     757          36 :     if (tok == NULL)
     758           0 :         return NULL;
     759          36 :     if ((tok->buf = (char *)PyMem_MALLOC(BUFSIZ)) == NULL) {
     760           0 :         PyTokenizer_Free(tok);
     761           0 :         return NULL;
     762             :     }
     763          36 :     tok->cur = tok->inp = tok->buf;
     764          36 :     tok->end = tok->buf + BUFSIZ;
     765          36 :     tok->fp = fp;
     766          36 :     tok->prompt = ps1;
     767          36 :     tok->nextprompt = ps2;
     768          36 :     return tok;
     769             : }
     770             : 
     771             : 
     772             : /* Free a tok_state structure */
     773             : 
     774             : void
     775          63 : PyTokenizer_Free(struct tok_state *tok)
     776             : {
     777          63 :     if (tok->encoding != NULL)
     778           0 :         PyMem_FREE(tok->encoding);
     779             : #ifndef PGEN
     780          63 :     Py_XDECREF(tok->decoding_readline);
     781          63 :     Py_XDECREF(tok->decoding_buffer);
     782             : #endif
     783          63 :     if (tok->fp != NULL && tok->buf != NULL)
     784          36 :         PyMem_FREE(tok->buf);
     785          63 :     if (tok->input)
     786          27 :         PyMem_FREE((char *)tok->input);
     787          63 :     PyMem_FREE(tok);
     788          63 : }
     789             : 
     790             : #if !defined(PGEN) && defined(Py_USING_UNICODE)
     791             : static int
     792           0 : tok_stdin_decode(struct tok_state *tok, char **inp)
     793             : {
     794             :     PyObject *enc, *sysstdin, *decoded, *utf8;
     795             :     const char *encoding;
     796             :     char *converted;
     797             : 
     798           0 :     if (PySys_GetFile((char *)"stdin", NULL) != stdin)
     799           0 :         return 0;
     800           0 :     sysstdin = PySys_GetObject("stdin");
     801           0 :     if (sysstdin == NULL || !PyFile_Check(sysstdin))
     802           0 :         return 0;
     803             : 
     804           0 :     enc = ((PyFileObject *)sysstdin)->f_encoding;
     805           0 :     if (enc == NULL || !PyString_Check(enc))
     806           0 :         return 0;
     807           0 :     Py_INCREF(enc);
     808             : 
     809           0 :     encoding = PyString_AsString(enc);
     810           0 :     decoded = PyUnicode_Decode(*inp, strlen(*inp), encoding, NULL);
     811           0 :     if (decoded == NULL)
     812           0 :         goto error_clear;
     813             : 
     814           0 :     utf8 = PyUnicode_AsEncodedString(decoded, "utf-8", NULL);
     815           0 :     Py_DECREF(decoded);
     816           0 :     if (utf8 == NULL)
     817           0 :         goto error_clear;
     818             : 
     819             :     assert(PyString_Check(utf8));
     820           0 :     converted = new_string(PyString_AS_STRING(utf8),
     821             :                            PyString_GET_SIZE(utf8));
     822           0 :     Py_DECREF(utf8);
     823           0 :     if (converted == NULL)
     824           0 :         goto error_nomem;
     825             : 
     826           0 :     PyMem_FREE(*inp);
     827           0 :     *inp = converted;
     828           0 :     if (tok->encoding != NULL)
     829           0 :         PyMem_FREE(tok->encoding);
     830           0 :     tok->encoding = new_string(encoding, strlen(encoding));
     831           0 :     if (tok->encoding == NULL)
     832           0 :         goto error_nomem;
     833             : 
     834           0 :     Py_DECREF(enc);
     835           0 :     return 0;
     836             : 
     837             : error_nomem:
     838           0 :     Py_DECREF(enc);
     839           0 :     tok->done = E_NOMEM;
     840           0 :     return -1;
     841             : 
     842             : error_clear:
     843           0 :     Py_DECREF(enc);
     844           0 :     if (!PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
     845           0 :         tok->done = E_ERROR;
     846           0 :         return -1;
     847             :     }
     848             :     /* Fallback to iso-8859-1: for backward compatibility */
     849           0 :     PyErr_Clear();
     850           0 :     return 0;
     851             : }
     852             : #endif
     853             : 
     854             : /* Get next char, updating state; error code goes into tok->done */
     855             : 
     856             : static int
     857      563929 : tok_nextc(register struct tok_state *tok)
     858             : {
     859             :     for (;;) {
     860      563929 :         if (tok->cur != tok->inp) {
     861      547677 :             return Py_CHARMASK(*tok->cur++); /* Fast path */
     862             :         }
     863       16252 :         if (tok->done != E_OK)
     864         123 :             return EOF;
     865       16129 :         if (tok->fp == NULL) {
     866        1443 :             char *end = strchr(tok->inp, '\n');
     867        1443 :             if (end != NULL)
     868        1416 :                 end++;
     869             :             else {
     870          27 :                 end = strchr(tok->inp, '\0');
     871          27 :                 if (end == tok->inp) {
     872          27 :                     tok->done = E_EOF;
     873          27 :                     return EOF;
     874             :                 }
     875             :             }
     876        1416 :             if (tok->start == NULL)
     877        1416 :                 tok->buf = tok->cur;
     878        1416 :             tok->line_start = tok->cur;
     879        1416 :             tok->lineno++;
     880        1416 :             tok->inp = end;
     881        1416 :             return Py_CHARMASK(*tok->cur++);
     882             :         }
     883       14686 :         if (tok->prompt != NULL) {
     884           0 :             char *newtok = PyOS_Readline(stdin, stdout, tok->prompt);
     885           0 :             if (tok->nextprompt != NULL)
     886           0 :                 tok->prompt = tok->nextprompt;
     887           0 :             if (newtok == NULL)
     888           0 :                 tok->done = E_INTR;
     889           0 :             else if (*newtok == '\0') {
     890           0 :                 PyMem_FREE(newtok);
     891           0 :                 tok->done = E_EOF;
     892             :             }
     893             : #if !defined(PGEN) && defined(Py_USING_UNICODE)
     894           0 :             else if (tok_stdin_decode(tok, &newtok) != 0)
     895           0 :                 PyMem_FREE(newtok);
     896             : #endif
     897           0 :             else if (tok->start != NULL) {
     898           0 :                 size_t start = tok->start - tok->buf;
     899           0 :                 size_t oldlen = tok->cur - tok->buf;
     900           0 :                 size_t newlen = oldlen + strlen(newtok);
     901           0 :                 char *buf = tok->buf;
     902           0 :                 buf = (char *)PyMem_REALLOC(buf, newlen+1);
     903           0 :                 tok->lineno++;
     904           0 :                 if (buf == NULL) {
     905           0 :                     PyMem_FREE(tok->buf);
     906           0 :                     tok->buf = NULL;
     907           0 :                     PyMem_FREE(newtok);
     908           0 :                     tok->done = E_NOMEM;
     909           0 :                     return EOF;
     910             :                 }
     911           0 :                 tok->buf = buf;
     912           0 :                 tok->cur = tok->buf + oldlen;
     913           0 :                 tok->line_start = tok->cur;
     914           0 :                 strcpy(tok->buf + oldlen, newtok);
     915           0 :                 PyMem_FREE(newtok);
     916           0 :                 tok->inp = tok->buf + newlen;
     917           0 :                 tok->end = tok->inp + 1;
     918           0 :                 tok->start = tok->buf + start;
     919             :             }
     920             :             else {
     921           0 :                 tok->lineno++;
     922           0 :                 if (tok->buf != NULL)
     923           0 :                     PyMem_FREE(tok->buf);
     924           0 :                 tok->buf = newtok;
     925           0 :                 tok->cur = tok->buf;
     926           0 :                 tok->line_start = tok->buf;
     927           0 :                 tok->inp = strchr(tok->buf, '\0');
     928           0 :                 tok->end = tok->inp + 1;
     929             :             }
     930             :         }
     931             :         else {
     932       14686 :             int done = 0;
     933       14686 :             Py_ssize_t cur = 0;
     934             :             char *pt;
     935       14686 :             if (tok->start == NULL) {
     936       12952 :                 if (tok->buf == NULL) {
     937           0 :                     tok->buf = (char *)
     938           0 :                         PyMem_MALLOC(BUFSIZ);
     939           0 :                     if (tok->buf == NULL) {
     940           0 :                         tok->done = E_NOMEM;
     941           0 :                         return EOF;
     942             :                     }
     943           0 :                     tok->end = tok->buf + BUFSIZ;
     944             :                 }
     945       12952 :                 if (decoding_fgets(tok->buf, (int)(tok->end - tok->buf),
     946             :                           tok) == NULL) {
     947          36 :                     if (!tok->decoding_erred)
     948          36 :                         tok->done = E_EOF;
     949          36 :                     done = 1;
     950             :                 }
     951             :                 else {
     952       12916 :                     tok->done = E_OK;
     953       12916 :                     tok->inp = strchr(tok->buf, '\0');
     954       12916 :                     done = tok->inp == tok->buf || tok->inp[-1] == '\n';
     955             :                 }
     956             :             }
     957             :             else {
     958        1734 :                 cur = tok->cur - tok->buf;
     959        1734 :                 if (decoding_feof(tok)) {
     960           0 :                     tok->done = E_EOF;
     961           0 :                     done = 1;
     962             :                 }
     963             :                 else
     964        1734 :                     tok->done = E_OK;
     965             :             }
     966       14686 :             tok->lineno++;
     967             :             /* Read until '\n' or EOF */
     968       31106 :             while (!done) {
     969        3468 :                 Py_ssize_t curstart = tok->start == NULL ? -1 :
     970        1734 :                           tok->start - tok->buf;
     971        1734 :                 Py_ssize_t curvalid = tok->inp - tok->buf;
     972        1734 :                 Py_ssize_t newsize = curvalid + BUFSIZ;
     973        1734 :                 char *newbuf = tok->buf;
     974        1734 :                 newbuf = (char *)PyMem_REALLOC(newbuf,
     975             :                                                newsize);
     976        1734 :                 if (newbuf == NULL) {
     977           0 :                     tok->done = E_NOMEM;
     978           0 :                     tok->cur = tok->inp;
     979           0 :                     return EOF;
     980             :                 }
     981        1734 :                 tok->buf = newbuf;
     982        1734 :                 tok->cur = tok->buf + cur;
     983        1734 :                 tok->line_start = tok->cur;
     984        1734 :                 tok->inp = tok->buf + curvalid;
     985        1734 :                 tok->end = tok->buf + newsize;
     986        3468 :                 tok->start = curstart < 0 ? NULL :
     987        1734 :                          tok->buf + curstart;
     988        1734 :                 if (decoding_fgets(tok->inp,
     989        1734 :                                (int)(tok->end - tok->inp),
     990             :                                tok) == NULL) {
     991             :                     /* Break out early on decoding
     992             :                        errors, as tok->buf will be NULL
     993             :                      */
     994           0 :                     if (tok->decoding_erred)
     995           0 :                         return EOF;
     996             :                     /* Last line does not end in \n,
     997             :                        fake one */
     998           0 :                     strcpy(tok->inp, "\n");
     999             :                 }
    1000        1734 :                 tok->inp = strchr(tok->inp, '\0');
    1001        1734 :                 done = tok->inp[-1] == '\n';
    1002             :             }
    1003       14686 :             if (tok->buf != NULL) {
    1004       14686 :                 tok->cur = tok->buf + cur;
    1005       14686 :                 tok->line_start = tok->cur;
    1006             :                 /* replace "\r\n" with "\n" */
    1007             :                 /* For Mac leave the \r, giving a syntax error */
    1008       14686 :                 pt = tok->inp - 2;
    1009       14686 :                 if (pt >= tok->buf && *pt == '\r') {
    1010           0 :                     *pt++ = '\n';
    1011           0 :                     *pt = '\0';
    1012           0 :                     tok->inp = pt;
    1013             :                 }
    1014             :             }
    1015             :         }
    1016       14686 :         if (tok->done != E_OK) {
    1017          36 :             if (tok->prompt != NULL)
    1018           0 :                 PySys_WriteStderr("\n");
    1019          36 :             tok->cur = tok->inp;
    1020          36 :             return EOF;
    1021             :         }
    1022       14650 :     }
    1023             :     /*NOTREACHED*/
    1024             : }
    1025             : 
    1026             : 
    1027             : /* Back-up one character */
    1028             : 
    1029             : static void
    1030       72384 : tok_backup(register struct tok_state *tok, register int c)
    1031             : {
    1032       72384 :     if (c != EOF) {
    1033       72321 :         if (--tok->cur < tok->buf)
    1034           0 :             Py_FatalError("tok_backup: beginning of buffer");
    1035       72321 :         if (*tok->cur != c)
    1036           0 :             *tok->cur = c;
    1037             :     }
    1038       72384 : }
    1039             : 
    1040             : 
    1041             : /* Return the token corresponding to a single character */
    1042             : 
    1043             : int
    1044       20938 : PyToken_OneChar(int c)
    1045             : {
    1046       20938 :     switch (c) {
    1047        4974 :     case '(':           return LPAR;
    1048        4974 :     case ')':           return RPAR;
    1049         516 :     case '[':           return LSQB;
    1050         516 :     case ']':           return RSQB;
    1051        2973 :     case ':':           return COLON;
    1052        3685 :     case ',':           return COMMA;
    1053           0 :     case ';':           return SEMI;
    1054         131 :     case '+':           return PLUS;
    1055         114 :     case '-':           return MINUS;
    1056          36 :     case '*':           return STAR;
    1057           1 :     case '/':           return SLASH;
    1058           4 :     case '|':           return VBAR;
    1059           3 :     case '&':           return AMPER;
    1060           5 :     case '<':           return LESS;
    1061           6 :     case '>':           return GREATER;
    1062        2686 :     case '=':           return EQUAL;
    1063           0 :     case '.':           return DOT;
    1064         193 :     case '%':           return PERCENT;
    1065           0 :     case '`':           return BACKQUOTE;
    1066          47 :     case '{':           return LBRACE;
    1067          47 :     case '}':           return RBRACE;
    1068           0 :     case '^':           return CIRCUMFLEX;
    1069           0 :     case '~':           return TILDE;
    1070          27 :     case '@':       return AT;
    1071           0 :     default:            return OP;
    1072             :     }
    1073             : }
    1074             : 
    1075             : 
    1076             : int
    1077       21762 : PyToken_TwoChars(int c1, int c2)
    1078             : {
    1079       21762 :     switch (c1) {
    1080             :     case '=':
    1081        3301 :         switch (c2) {
    1082         615 :         case '=':               return EQEQUAL;
    1083             :         }
    1084        2686 :         break;
    1085             :     case '!':
    1086         103 :         switch (c2) {
    1087         103 :         case '=':               return NOTEQUAL;
    1088             :         }
    1089           0 :         break;
    1090             :     case '<':
    1091          12 :         switch (c2) {
    1092           0 :         case '>':               return NOTEQUAL;
    1093           4 :         case '=':               return LESSEQUAL;
    1094           3 :         case '<':               return LEFTSHIFT;
    1095             :         }
    1096           5 :         break;
    1097             :     case '>':
    1098          18 :         switch (c2) {
    1099          10 :         case '=':               return GREATEREQUAL;
    1100           2 :         case '>':               return RIGHTSHIFT;
    1101             :         }
    1102           6 :         break;
    1103             :     case '+':
    1104         174 :         switch (c2) {
    1105          43 :         case '=':               return PLUSEQUAL;
    1106             :         }
    1107         131 :         break;
    1108             :     case '-':
    1109         116 :         switch (c2) {
    1110           2 :         case '=':               return MINEQUAL;
    1111             :         }
    1112         114 :         break;
    1113             :     case '*':
    1114          77 :         switch (c2) {
    1115          40 :         case '*':               return DOUBLESTAR;
    1116           1 :         case '=':               return STAREQUAL;
    1117             :         }
    1118          36 :         break;
    1119             :     case '/':
    1120           2 :         switch (c2) {
    1121           1 :         case '/':               return DOUBLESLASH;
    1122           0 :         case '=':               return SLASHEQUAL;
    1123             :         }
    1124           1 :         break;
    1125             :     case '|':
    1126           4 :         switch (c2) {
    1127           0 :         case '=':               return VBAREQUAL;
    1128             :         }
    1129           4 :         break;
    1130             :     case '%':
    1131         193 :         switch (c2) {
    1132           0 :         case '=':               return PERCENTEQUAL;
    1133             :         }
    1134         193 :         break;
    1135             :     case '&':
    1136           3 :         switch (c2) {
    1137           0 :         case '=':               return AMPEREQUAL;
    1138             :         }
    1139           3 :         break;
    1140             :     case '^':
    1141           0 :         switch (c2) {
    1142           0 :         case '=':               return CIRCUMFLEXEQUAL;
    1143             :         }
    1144           0 :         break;
    1145             :     }
    1146       20938 :     return OP;
    1147             : }
    1148             : 
    1149             : int
    1150         824 : PyToken_ThreeChars(int c1, int c2, int c3)
    1151             : {
    1152         824 :     switch (c1) {
    1153             :     case '<':
    1154           7 :         switch (c2) {
    1155             :         case '<':
    1156           3 :             switch (c3) {
    1157             :             case '=':
    1158           0 :                 return LEFTSHIFTEQUAL;
    1159             :             }
    1160           3 :             break;
    1161             :         }
    1162           7 :         break;
    1163             :     case '>':
    1164          12 :         switch (c2) {
    1165             :         case '>':
    1166           2 :             switch (c3) {
    1167             :             case '=':
    1168           2 :                 return RIGHTSHIFTEQUAL;
    1169             :             }
    1170           0 :             break;
    1171             :         }
    1172          10 :         break;
    1173             :     case '*':
    1174          41 :         switch (c2) {
    1175             :         case '*':
    1176          40 :             switch (c3) {
    1177             :             case '=':
    1178           0 :                 return DOUBLESTAREQUAL;
    1179             :             }
    1180          40 :             break;
    1181             :         }
    1182          41 :         break;
    1183             :     case '/':
    1184           1 :         switch (c2) {
    1185             :         case '/':
    1186           1 :             switch (c3) {
    1187             :             case '=':
    1188           0 :                 return DOUBLESLASHEQUAL;
    1189             :             }
    1190           1 :             break;
    1191             :         }
    1192           1 :         break;
    1193             :     }
    1194         822 :     return OP;
    1195             : }
    1196             : 
    1197             : static int
    1198           0 : indenterror(struct tok_state *tok)
    1199             : {
    1200           0 :     if (tok->alterror) {
    1201           0 :         tok->done = E_TABSPACE;
    1202           0 :         tok->cur = tok->inp;
    1203           0 :         return 1;
    1204             :     }
    1205           0 :     if (tok->altwarning) {
    1206           0 :         PySys_WriteStderr("%s: inconsistent use of tabs and spaces "
    1207             :                           "in indentation\n", tok->filename);
    1208           0 :         tok->altwarning = 0;
    1209             :     }
    1210           0 :     return 0;
    1211             : }
    1212             : 
    1213             : /* Get next token, after space stripping etc. */
    1214             : 
    1215             : static int
    1216       74459 : tok_get(register struct tok_state *tok, char **p_start, char **p_end)
    1217             : {
    1218             :     register int c;
    1219             :     int blankline;
    1220             : 
    1221       74459 :     *p_start = *p_end = NULL;
    1222             :   nextline:
    1223       80282 :     tok->start = NULL;
    1224       80282 :     blankline = 0;
    1225             : 
    1226             :     /* Get indentation level */
    1227       80282 :     if (tok->atbol) {
    1228       14384 :         register int col = 0;
    1229       14384 :         register int altcol = 0;
    1230       14384 :         tok->atbol = 0;
    1231             :         for (;;) {
    1232       67661 :             c = tok_nextc(tok);
    1233       67661 :             if (c == ' ')
    1234       53277 :                 col++, altcol++;
    1235       14384 :             else if (c == '\t') {
    1236           0 :                 col = (col/tok->tabsize + 1) * tok->tabsize;
    1237           0 :                 altcol = (altcol/tok->alttabsize + 1)
    1238           0 :                     * tok->alttabsize;
    1239             :             }
    1240       14384 :             else if (c == '\014') /* Control-L (formfeed) */
    1241           0 :                 col = altcol = 0; /* For Emacs users */
    1242             :             else
    1243       14384 :                 break;
    1244       53277 :         }
    1245       14384 :         tok_backup(tok, c);
    1246       14384 :         if (c == '#' || c == '\n') {
    1247             :             /* Lines with only whitespace and/or comments
    1248             :                shouldn't affect the indentation and are
    1249             :                not passed to the parser as NEWLINE tokens,
    1250             :                except *totally* empty lines in interactive
    1251             :                mode, which signal the end of a command group. */
    1252        5243 :             if (col == 0 && c == '\n' && tok->prompt != NULL)
    1253           0 :                 blankline = 0; /* Let it through */
    1254             :             else
    1255        5243 :                 blankline = 1; /* Ignore completely */
    1256             :             /* We can't jump back right here since we still
    1257             :                may need to skip to the end of a comment */
    1258             :         }
    1259       14384 :         if (!blankline && tok->level == 0) {
    1260        8561 :             if (col == tok->indstack[tok->indent]) {
    1261             :                 /* No change */
    1262        3508 :                 if (altcol != tok->altindstack[tok->indent]) {
    1263           0 :                     if (indenterror(tok))
    1264           0 :                         return ERRORTOKEN;
    1265             :                 }
    1266             :             }
    1267        5053 :             else if (col > tok->indstack[tok->indent]) {
    1268             :                 /* Indent -- always one */
    1269        2769 :                 if (tok->indent+1 >= MAXINDENT) {
    1270           0 :                     tok->done = E_TOODEEP;
    1271           0 :                     tok->cur = tok->inp;
    1272           0 :                     return ERRORTOKEN;
    1273             :                 }
    1274        2769 :                 if (altcol <= tok->altindstack[tok->indent]) {
    1275           0 :                     if (indenterror(tok))
    1276           0 :                         return ERRORTOKEN;
    1277             :                 }
    1278        2769 :                 tok->pendin++;
    1279        2769 :                 tok->indstack[++tok->indent] = col;
    1280        2769 :                 tok->altindstack[tok->indent] = altcol;
    1281             :             }
    1282             :             else /* col < tok->indstack[tok->indent] */ {
    1283             :                 /* Dedent -- any number, must be consistent */
    1284       12093 :                 while (tok->indent > 0 &&
    1285        4756 :                     col < tok->indstack[tok->indent]) {
    1286        2769 :                     tok->pendin--;
    1287        2769 :                     tok->indent--;
    1288             :                 }
    1289        2284 :                 if (col != tok->indstack[tok->indent]) {
    1290           0 :                     tok->done = E_DEDENT;
    1291           0 :                     tok->cur = tok->inp;
    1292           0 :                     return ERRORTOKEN;
    1293             :                 }
    1294        2284 :                 if (altcol != tok->altindstack[tok->indent]) {
    1295           0 :                     if (indenterror(tok))
    1296           0 :                         return ERRORTOKEN;
    1297             :                 }
    1298             :             }
    1299             :         }
    1300             :     }
    1301             : 
    1302       80282 :     tok->start = tok->cur;
    1303             : 
    1304             :     /* Return pending indents/dedents */
    1305       80282 :     if (tok->pendin != 0) {
    1306        5538 :         if (tok->pendin < 0) {
    1307        2769 :             tok->pendin++;
    1308        2769 :             return DEDENT;
    1309             :         }
    1310             :         else {
    1311        2769 :             tok->pendin--;
    1312        2769 :             return INDENT;
    1313             :         }
    1314             :     }
    1315             : 
    1316             :  again:
    1317       74755 :     tok->start = NULL;
    1318             :     /* Skip spaces */
    1319             :     do {
    1320       92272 :         c = tok_nextc(tok);
    1321       92272 :     } while (c == ' ' || c == '\t' || c == '\014');
    1322             : 
    1323             :     /* Set start of current token */
    1324       74755 :     tok->start = tok->cur - 1;
    1325             : 
    1326             :     /* Skip comment, while looking for tab-setting magic */
    1327       74755 :     if (c == '#') {
    1328             :         static char *tabforms[] = {
    1329             :             "tab-width:",                       /* Emacs */
    1330             :             ":tabstop=",                        /* vim, full form */
    1331             :             ":ts=",                             /* vim, abbreviated form */
    1332             :             "set tabsize=",                     /* will vi never die? */
    1333             :         /* more templates can be added here to support other editors */
    1334             :         };
    1335             :         char cbuf[80];
    1336             :         char *tp, **cp;
    1337        2786 :         tp = cbuf;
    1338             :         do {
    1339      100161 :             *tp++ = c = tok_nextc(tok);
    1340      197549 :         } while (c != EOF && c != '\n' &&
    1341      197549 :                  (size_t)(tp - cbuf + 1) < sizeof(cbuf));
    1342        2786 :         *tp = '\0';
    1343       16716 :         for (cp = tabforms;
    1344             :              cp < tabforms + sizeof(tabforms)/sizeof(tabforms[0]);
    1345       11144 :              cp++) {
    1346       11144 :             if ((tp = strstr(cbuf, *cp))) {
    1347           0 :                 int newsize = atoi(tp + strlen(*cp));
    1348             : 
    1349           0 :                 if (newsize >= 1 && newsize <= 40) {
    1350           0 :                     tok->tabsize = newsize;
    1351           0 :                     if (Py_VerboseFlag)
    1352           0 :                         PySys_WriteStderr(
    1353             :                         "Tab size set to %d\n",
    1354             :                         newsize);
    1355             :                 }
    1356             :             }
    1357             :         }
    1358        5660 :         while (c != EOF && c != '\n')
    1359          88 :             c = tok_nextc(tok);
    1360             :     }
    1361             : 
    1362             :     /* Check for EOF and errors now */
    1363       74755 :     if (c == EOF) {
    1364         123 :         return tok->done == E_EOF ? ENDMARKER : ERRORTOKEN;
    1365             :     }
    1366             : 
    1367             :     /* Identifier (most frequent token!) */
    1368       74632 :     if (Py_ISALPHA(c) || c == '_') {
    1369             :         /* Process r"", u"" and ur"" */
    1370       29247 :         switch (c) {
    1371             :         case 'b':
    1372             :         case 'B':
    1373         454 :             c = tok_nextc(tok);
    1374         454 :             if (c == 'r' || c == 'R')
    1375          93 :                 c = tok_nextc(tok);
    1376         454 :             if (c == '"' || c == '\'')
    1377             :                 goto letter_quote;
    1378         451 :             break;
    1379             :         case 'r':
    1380             :         case 'R':
    1381        2250 :             c = tok_nextc(tok);
    1382        2250 :             if (c == '"' || c == '\'')
    1383             :                 goto letter_quote;
    1384        2206 :             break;
    1385             :         case 'u':
    1386             :         case 'U':
    1387         194 :             c = tok_nextc(tok);
    1388         194 :             if (c == 'r' || c == 'R')
    1389           0 :                 c = tok_nextc(tok);
    1390         194 :             if (c == '"' || c == '\'')
    1391             :                 goto letter_quote;
    1392         194 :             break;
    1393             :         }
    1394      220786 :         while (c != EOF && (Py_ISALNUM(c) || c == '_')) {
    1395      162386 :             c = tok_nextc(tok);
    1396             :         }
    1397       29200 :         tok_backup(tok, c);
    1398       29200 :         *p_start = tok->start;
    1399       29200 :         *p_end = tok->cur;
    1400       29200 :         return NAME;
    1401             :     }
    1402             : 
    1403             :     /* Newline */
    1404       45385 :     if (c == '\n') {
    1405       14321 :         tok->atbol = 1;
    1406       14321 :         if (blankline || tok->level > 0)
    1407             :             goto nextline;
    1408        8498 :         *p_start = tok->start;
    1409        8498 :         *p_end = tok->cur - 1; /* Leave '\n' out of the string */
    1410        8498 :         tok->cont_line = 0;
    1411        8498 :         return NEWLINE;
    1412             :     }
    1413             : 
    1414             :     /* Period or number starting with period? */
    1415       31064 :     if (c == '.') {
    1416        6220 :         c = tok_nextc(tok);
    1417        6220 :         if (isdigit(c)) {
    1418           0 :             goto fraction;
    1419             :         }
    1420             :         else {
    1421        6220 :             tok_backup(tok, c);
    1422        6220 :             *p_start = tok->start;
    1423        6220 :             *p_end = tok->cur;
    1424        6220 :             return DOT;
    1425             :         }
    1426             :     }
    1427             : 
    1428             :     /* Number */
    1429       24844 :     if (isdigit(c)) {
    1430         759 :         if (c == '0') {
    1431             :             /* Hex, octal or binary -- maybe. */
    1432         268 :             c = tok_nextc(tok);
    1433         268 :             if (c == '.')
    1434           1 :                 goto fraction;
    1435             : #ifndef WITHOUT_COMPLEX
    1436         267 :             if (c == 'j' || c == 'J')
    1437             :                 goto imaginary;
    1438             : #endif
    1439         270 :             if (c == 'x' || c == 'X') {
    1440             : 
    1441             :                 /* Hex */
    1442           3 :                 c = tok_nextc(tok);
    1443           3 :                 if (!isxdigit(c)) {
    1444           0 :                     tok->done = E_TOKEN;
    1445           0 :                     tok_backup(tok, c);
    1446           0 :                     return ERRORTOKEN;
    1447             :                 }
    1448             :                 do {
    1449           6 :                     c = tok_nextc(tok);
    1450           6 :                 } while (isxdigit(c));
    1451             :             }
    1452         264 :             else if (c == 'o' || c == 'O') {
    1453             :                 /* Octal */
    1454           0 :                 c = tok_nextc(tok);
    1455           0 :                 if (c < '0' || c >= '8') {
    1456           0 :                     tok->done = E_TOKEN;
    1457           0 :                     tok_backup(tok, c);
    1458           0 :                     return ERRORTOKEN;
    1459             :                 }
    1460             :                 do {
    1461           0 :                     c = tok_nextc(tok);
    1462           0 :                 } while ('0' <= c && c < '8');
    1463             :             }
    1464         264 :             else if (c == 'b' || c == 'B') {
    1465             :                 /* Binary */
    1466           0 :                 c = tok_nextc(tok);
    1467           0 :                 if (c != '0' && c != '1') {
    1468           0 :                     tok->done = E_TOKEN;
    1469           0 :                     tok_backup(tok, c);
    1470           0 :                     return ERRORTOKEN;
    1471             :                 }
    1472             :                 do {
    1473           0 :                     c = tok_nextc(tok);
    1474           0 :                 } while (c == '0' || c == '1');
    1475             :             }
    1476             :             else {
    1477         264 :                 int found_decimal = 0;
    1478             :                 /* Octal; c is first char of it */
    1479             :                 /* There's no 'isoctdigit' macro, sigh */
    1480         528 :                 while ('0' <= c && c < '8') {
    1481           0 :                     c = tok_nextc(tok);
    1482             :                 }
    1483         264 :                 if (isdigit(c)) {
    1484           0 :                     found_decimal = 1;
    1485             :                     do {
    1486           0 :                         c = tok_nextc(tok);
    1487           0 :                     } while (isdigit(c));
    1488             :                 }
    1489         264 :                 if (c == '.')
    1490           0 :                     goto fraction;
    1491         264 :                 else if (c == 'e' || c == 'E')
    1492             :                     goto exponent;
    1493             : #ifndef WITHOUT_COMPLEX
    1494         264 :                 else if (c == 'j' || c == 'J')
    1495             :                     goto imaginary;
    1496             : #endif
    1497         264 :                 else if (found_decimal) {
    1498           0 :                     tok->done = E_TOKEN;
    1499           0 :                     tok_backup(tok, c);
    1500           0 :                     return ERRORTOKEN;
    1501             :                 }
    1502             :             }
    1503         267 :             if (c == 'l' || c == 'L')
    1504           0 :                 c = tok_nextc(tok);
    1505             :         }
    1506             :         else {
    1507             :             /* Decimal */
    1508             :             do {
    1509         526 :                 c = tok_nextc(tok);
    1510         526 :             } while (isdigit(c));
    1511         491 :             if (c == 'l' || c == 'L')
    1512           0 :                 c = tok_nextc(tok);
    1513             :             else {
    1514             :                 /* Accept floating point numbers. */
    1515         491 :                 if (c == '.') {
    1516             :         fraction:
    1517             :                     /* Fraction */
    1518             :                     do {
    1519           2 :                         c = tok_nextc(tok);
    1520           2 :                     } while (isdigit(c));
    1521             :                 }
    1522         492 :                 if (c == 'e' || c == 'E') {
    1523             :                     int e;
    1524             :                   exponent:
    1525           0 :                     e = c;
    1526             :                     /* Exponent part */
    1527           0 :                     c = tok_nextc(tok);
    1528           0 :                     if (c == '+' || c == '-') {
    1529           0 :                         c = tok_nextc(tok);
    1530           0 :                         if (!isdigit(c)) {
    1531           0 :                             tok->done = E_TOKEN;
    1532           0 :                             tok_backup(tok, c);
    1533           0 :                             return ERRORTOKEN;
    1534             :                         }
    1535           0 :                     } else if (!isdigit(c)) {
    1536           0 :                         tok_backup(tok, c);
    1537           0 :                         tok_backup(tok, e);
    1538           0 :                         *p_start = tok->start;
    1539           0 :                         *p_end = tok->cur;
    1540           0 :                         return NUMBER;
    1541             :                     }
    1542             :                     do {
    1543           0 :                         c = tok_nextc(tok);
    1544           0 :                     } while (isdigit(c));
    1545             :                 }
    1546             : #ifndef WITHOUT_COMPLEX
    1547         492 :                 if (c == 'j' || c == 'J')
    1548             :                     /* Imaginary part */
    1549             :         imaginary:
    1550           0 :                     c = tok_nextc(tok);
    1551             : #endif
    1552             :             }
    1553             :         }
    1554         759 :         tok_backup(tok, c);
    1555         759 :         *p_start = tok->start;
    1556         759 :         *p_end = tok->cur;
    1557         759 :         return NUMBER;
    1558             :     }
    1559             : 
    1560             :   letter_quote:
    1561             :     /* String */
    1562       24132 :     if (c == '\'' || c == '"') {
    1563        2359 :         Py_ssize_t quote2 = tok->cur - tok->start + 1;
    1564        2359 :         int quote = c;
    1565        2359 :         int triple = 0;
    1566        2359 :         int tripcount = 0;
    1567             :         for (;;) {
    1568       93572 :             c = tok_nextc(tok);
    1569       93572 :             if (c == '\n') {
    1570        1733 :                 if (!triple) {
    1571           0 :                     tok->done = E_EOLS;
    1572           0 :                     tok_backup(tok, c);
    1573           0 :                     return ERRORTOKEN;
    1574             :                 }
    1575        1733 :                 tripcount = 0;
    1576        1733 :                 tok->cont_line = 1; /* multiline string. */
    1577             :             }
    1578       91839 :             else if (c == EOF) {
    1579           0 :                 if (triple)
    1580           0 :                     tok->done = E_EOFS;
    1581             :                 else
    1582           0 :                     tok->done = E_EOLS;
    1583           0 :                 tok->cur = tok->inp;
    1584           0 :                 return ERRORTOKEN;
    1585             :             }
    1586       91839 :             else if (c == quote) {
    1587        3507 :                 tripcount++;
    1588        3507 :                 if (tok->cur - tok->start == quote2) {
    1589         418 :                     c = tok_nextc(tok);
    1590         418 :                     if (c == quote) {
    1591         357 :                         triple = 1;
    1592         357 :                         tripcount = 0;
    1593         357 :                         continue;
    1594             :                     }
    1595          61 :                     tok_backup(tok, c);
    1596             :                 }
    1597        3150 :                 if (!triple || tripcount == 3)
    1598             :                     break;
    1599             :             }
    1600       88332 :             else if (c == '\\') {
    1601         108 :                 tripcount = 0;
    1602         108 :                 c = tok_nextc(tok);
    1603         108 :                 if (c == EOF) {
    1604           0 :                     tok->done = E_EOLS;
    1605           0 :                     tok->cur = tok->inp;
    1606           0 :                     return ERRORTOKEN;
    1607             :                 }
    1608             :             }
    1609             :             else
    1610       88224 :                 tripcount = 0;
    1611       91213 :         }
    1612        2359 :         *p_start = tok->start;
    1613        2359 :         *p_end = tok->cur;
    1614        2359 :         return STRING;
    1615             :     }
    1616             : 
    1617             :     /* Line continuation */
    1618       21773 :     if (c == '\\') {
    1619          11 :         c = tok_nextc(tok);
    1620          11 :         if (c != '\n') {
    1621           0 :             tok->done = E_LINECONT;
    1622           0 :             tok->cur = tok->inp;
    1623           0 :             return ERRORTOKEN;
    1624             :         }
    1625          11 :         tok->cont_line = 1;
    1626          11 :         goto again; /* Read next line */
    1627             :     }
    1628             : 
    1629             :     /* Check for two-character token */
    1630             :     {
    1631       21762 :         int c2 = tok_nextc(tok);
    1632       21762 :         int token = PyToken_TwoChars(c, c2);
    1633             : #ifndef PGEN
    1634       21762 :         if (Py_Py3kWarningFlag && token == NOTEQUAL && c == '<') {
    1635           0 :             if (PyErr_WarnExplicit(PyExc_DeprecationWarning,
    1636             :                                    "<> not supported in 3.x; use !=",
    1637             :                                    tok->filename, tok->lineno,
    1638             :                                    NULL, NULL)) {
    1639           0 :                 return ERRORTOKEN;
    1640             :             }
    1641             :         }
    1642             : #endif
    1643       21762 :         if (token != OP) {
    1644         824 :             int c3 = tok_nextc(tok);
    1645         824 :             int token3 = PyToken_ThreeChars(c, c2, c3);
    1646         824 :             if (token3 != OP) {
    1647           2 :                 token = token3;
    1648             :             } else {
    1649         822 :                 tok_backup(tok, c3);
    1650             :             }
    1651         824 :             *p_start = tok->start;
    1652         824 :             *p_end = tok->cur;
    1653         824 :             return token;
    1654             :         }
    1655       20938 :         tok_backup(tok, c2);
    1656             :     }
    1657             : 
    1658             :     /* Keep track of parentheses nesting level */
    1659       20938 :     switch (c) {
    1660             :     case '(':
    1661             :     case '[':
    1662             :     case '{':
    1663        5537 :         tok->level++;
    1664        5537 :         break;
    1665             :     case ')':
    1666             :     case ']':
    1667             :     case '}':
    1668        5537 :         tok->level--;
    1669        5537 :         break;
    1670             :     }
    1671             : 
    1672             :     /* Punctuation character */
    1673       20938 :     *p_start = tok->start;
    1674       20938 :     *p_end = tok->cur;
    1675       20938 :     return PyToken_OneChar(c);
    1676             : }
    1677             : 
    1678             : int
    1679       74459 : PyTokenizer_Get(struct tok_state *tok, char **p_start, char **p_end)
    1680             : {
    1681       74459 :     int result = tok_get(tok, p_start, p_end);
    1682       74459 :     if (tok->decoding_erred) {
    1683           0 :         result = ERRORTOKEN;
    1684           0 :         tok->done = E_DECODE;
    1685             :     }
    1686       74459 :     return result;
    1687             : }
    1688             : 
    1689             : /* This function is only called from parsetok. However, it cannot live
    1690             :    there, as it must be empty for PGEN, and we can check for PGEN only
    1691             :    in this file. */
    1692             : 
    1693             : #if defined(PGEN) || !defined(Py_USING_UNICODE)
    1694             : char*
    1695             : PyTokenizer_RestoreEncoding(struct tok_state* tok, int len, int* offset)
    1696             : {
    1697             :     return NULL;
    1698             : }
    1699             : #else
    1700             : #ifdef Py_USING_UNICODE
    1701             : static PyObject *
    1702           0 : dec_utf8(const char *enc, const char *text, size_t len) {
    1703           0 :     PyObject *ret = NULL;
    1704           0 :     PyObject *unicode_text = PyUnicode_DecodeUTF8(text, len, "replace");
    1705           0 :     if (unicode_text) {
    1706           0 :         ret = PyUnicode_AsEncodedString(unicode_text, enc, "replace");
    1707           0 :         Py_DECREF(unicode_text);
    1708             :     }
    1709           0 :     if (!ret) {
    1710           0 :         PyErr_Clear();
    1711             :     }
    1712           0 :     return ret;
    1713             : }
    1714             : char *
    1715           0 : PyTokenizer_RestoreEncoding(struct tok_state* tok, int len, int *offset)
    1716             : {
    1717           0 :     char *text = NULL;
    1718           0 :     if (tok->encoding) {
    1719             :         /* convert source to original encondig */
    1720           0 :         PyObject *lineobj = dec_utf8(tok->encoding, tok->buf, len);
    1721           0 :         if (lineobj != NULL) {
    1722           0 :             int linelen = PyString_Size(lineobj);
    1723           0 :             const char *line = PyString_AsString(lineobj);
    1724           0 :             text = PyObject_MALLOC(linelen + 1);
    1725           0 :             if (text != NULL && line != NULL) {
    1726           0 :                 if (linelen)
    1727           0 :                     strncpy(text, line, linelen);
    1728           0 :                 text[linelen] = '\0';
    1729             :             }
    1730           0 :             Py_DECREF(lineobj);
    1731             : 
    1732             :             /* adjust error offset */
    1733           0 :             if (*offset > 1) {
    1734           0 :                 PyObject *offsetobj = dec_utf8(tok->encoding,
    1735           0 :                                                tok->buf, *offset-1);
    1736           0 :                 if (offsetobj) {
    1737           0 :                     *offset = PyString_Size(offsetobj) + 1;
    1738           0 :                     Py_DECREF(offsetobj);
    1739             :                 }
    1740             :             }
    1741             : 
    1742             :         }
    1743             :     }
    1744           0 :     return text;
    1745             : 
    1746             : }
    1747             : #endif /* defined(Py_USING_UNICODE) */
    1748             : #endif
    1749             : 
    1750             : 
    1751             : #ifdef Py_DEBUG
    1752             : 
    1753             : void
    1754             : tok_dump(int type, char *start, char *end)
    1755             : {
    1756             :     printf("%s", _PyParser_TokenNames[type]);
    1757             :     if (type == NAME || type == NUMBER || type == STRING || type == OP)
    1758             :         printf("(%.*s)", (int)(end - start), start);
    1759             : }
    1760             : 
    1761             : #endif

Generated by: LCOV version 1.10