LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Parser - parsetok.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 68 146 46.6 %
Date: 2012-12-17 Functions: 3 9 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : 
       2             : /* Parser-tokenizer link implementation */
       3             : 
       4             : #include "pgenheaders.h"
       5             : #include "tokenizer.h"
       6             : #include "node.h"
       7             : #include "grammar.h"
       8             : #include "parser.h"
       9             : #include "parsetok.h"
      10             : #include "errcode.h"
      11             : #include "graminit.h"
      12             : 
      13             : 
      14             : /* Forward */
      15             : static node *parsetok(struct tok_state *, grammar *, int, perrdetail *, int *);
      16             : static int initerr(perrdetail *err_ret, const char* filename);
      17             : 
      18             : /* Parse input coming from a string.  Return error code, print some errors. */
      19             : node *
      20           0 : PyParser_ParseString(const char *s, grammar *g, int start, perrdetail *err_ret)
      21             : {
      22           0 :     return PyParser_ParseStringFlagsFilename(s, NULL, g, start, err_ret, 0);
      23             : }
      24             : 
      25             : node *
      26           0 : PyParser_ParseStringFlags(const char *s, grammar *g, int start,
      27             :                           perrdetail *err_ret, int flags)
      28             : {
      29           0 :     return PyParser_ParseStringFlagsFilename(s, NULL,
      30             :                                              g, start, err_ret, flags);
      31             : }
      32             : 
      33             : node *
      34           0 : PyParser_ParseStringFlagsFilename(const char *s, const char *filename,
      35             :                           grammar *g, int start,
      36             :                           perrdetail *err_ret, int flags)
      37             : {
      38           0 :     int iflags = flags;
      39           0 :     return PyParser_ParseStringFlagsFilenameEx(s, filename, g, start,
      40             :                                                err_ret, &iflags);
      41             : }
      42             : 
      43             : node *
      44           3 : PyParser_ParseStringFlagsFilenameEx(const char *s, const char *filename,
      45             :                           grammar *g, int start,
      46             :                           perrdetail *err_ret, int *flags)
      47             : {
      48             :     struct tok_state *tok;
      49           3 :     int exec_input = start == file_input;
      50             : 
      51           3 :     if (initerr(err_ret, filename) < 0)
      52           0 :         return NULL;
      53             : 
      54           3 :     if (*flags & PyPARSE_IGNORE_COOKIE)
      55           3 :         tok = PyTokenizer_FromUTF8(s, exec_input);
      56             :     else
      57           0 :         tok = PyTokenizer_FromString(s, exec_input);
      58           3 :     if (tok == NULL) {
      59           0 :         err_ret->error = PyErr_Occurred() ? E_DECODE : E_NOMEM;
      60           0 :         return NULL;
      61             :     }
      62             : 
      63             : #ifndef PGEN
      64           3 :     Py_INCREF(err_ret->filename);
      65           3 :     tok->filename = err_ret->filename;
      66             : #endif
      67           3 :     return parsetok(tok, g, start, err_ret, flags);
      68             : }
      69             : 
      70             : /* Parse input coming from a file.  Return error code, print some errors. */
      71             : 
      72             : node *
      73           0 : PyParser_ParseFile(FILE *fp, const char *filename, grammar *g, int start,
      74             :                    char *ps1, char *ps2, perrdetail *err_ret)
      75             : {
      76           0 :     return PyParser_ParseFileFlags(fp, filename, NULL,
      77             :                                    g, start, ps1, ps2, err_ret, 0);
      78             : }
      79             : 
      80             : node *
      81           0 : PyParser_ParseFileFlags(FILE *fp, const char *filename, const char *enc,
      82             :                         grammar *g, int start,
      83             :                         char *ps1, char *ps2, perrdetail *err_ret, int flags)
      84             : {
      85           0 :     int iflags = flags;
      86           0 :     return PyParser_ParseFileFlagsEx(fp, filename, enc, g, start, ps1,
      87             :                                      ps2, err_ret, &iflags);
      88             : }
      89             : 
      90             : node *
      91           0 : PyParser_ParseFileFlagsEx(FILE *fp, const char *filename,
      92             :                           const char *enc, grammar *g, int start,
      93             :                           char *ps1, char *ps2, perrdetail *err_ret, int *flags)
      94             : {
      95             :     struct tok_state *tok;
      96             : 
      97           0 :     if (initerr(err_ret, filename) < 0)
      98           0 :         return NULL;
      99             : 
     100           0 :     if ((tok = PyTokenizer_FromFile(fp, (char *)enc, ps1, ps2)) == NULL) {
     101           0 :         err_ret->error = E_NOMEM;
     102           0 :         return NULL;
     103             :     }
     104             : #ifndef PGEN
     105           0 :     Py_INCREF(err_ret->filename);
     106           0 :     tok->filename = err_ret->filename;
     107             : #endif
     108           0 :     return parsetok(tok, g, start, err_ret, flags);
     109             : }
     110             : 
     111             : #ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
     112             : #if 0
     113             : static char with_msg[] =
     114             : "%s:%d: Warning: 'with' will become a reserved keyword in Python 2.6\n";
     115             : 
     116             : static char as_msg[] =
     117             : "%s:%d: Warning: 'as' will become a reserved keyword in Python 2.6\n";
     118             : 
     119             : static void
     120             : warn(const char *msg, const char *filename, int lineno)
     121             : {
     122             :     if (filename == NULL)
     123             :         filename = "<string>";
     124             :     PySys_WriteStderr(msg, filename, lineno);
     125             : }
     126             : #endif
     127             : #endif
     128             : 
     129             : /* Parse input coming from the given tokenizer structure.
     130             :    Return error code. */
     131             : 
     132             : static node *
     133           3 : parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret,
     134             :          int *flags)
     135             : {
     136             :     parser_state *ps;
     137             :     node *n;
     138           3 :     int started = 0;
     139             : 
     140           3 :     if ((ps = PyParser_New(g, start)) == NULL) {
     141           0 :         fprintf(stderr, "no mem for new parser\n");
     142           0 :         err_ret->error = E_NOMEM;
     143           0 :         PyTokenizer_Free(tok);
     144           0 :         return NULL;
     145             :     }
     146             : #ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
     147           3 :     if (*flags & PyPARSE_BARRY_AS_BDFL)
     148           0 :         ps->p_flags |= CO_FUTURE_BARRY_AS_BDFL;
     149             : #endif
     150             : 
     151             :     for (;;) {
     152             :         char *a, *b;
     153             :         int type;
     154             :         size_t len;
     155             :         char *str;
     156             :         int col_offset;
     157             : 
     158        1823 :         type = PyTokenizer_Get(tok, &a, &b);
     159        1823 :         if (type == ERRORTOKEN) {
     160           0 :             err_ret->error = tok->done;
     161             :             break;
     162             :         }
     163        1823 :         if (type == ENDMARKER && started) {
     164           3 :             type = NEWLINE; /* Add an extra newline */
     165           3 :             started = 0;
     166             :             /* Add the right number of dedent tokens,
     167             :                except if a certain flag is given --
     168             :                codeop.py uses this. */
     169           6 :             if (tok->indent &&
     170           0 :                 !(*flags & PyPARSE_DONT_IMPLY_DEDENT))
     171             :             {
     172           0 :                 tok->pendin = -tok->indent;
     173           0 :                 tok->indent = 0;
     174             :             }
     175             :         }
     176             :         else
     177        1820 :             started = 1;
     178        1823 :         len = b - a; /* XXX this may compute NULL - NULL */
     179        1823 :         str = (char *) PyObject_MALLOC(len + 1);
     180        1823 :         if (str == NULL) {
     181           0 :             fprintf(stderr, "no mem for next token\n");
     182           0 :             err_ret->error = E_NOMEM;
     183             :             break;
     184             :         }
     185        1823 :         if (len > 0)
     186        1511 :             strncpy(str, a, len);
     187        1823 :         str[len] = '\0';
     188             : 
     189             : #ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
     190        1823 :         if (type == NOTEQUAL) {
     191           6 :             if (!(ps->p_flags & CO_FUTURE_BARRY_AS_BDFL) &&
     192           3 :                             strcmp(str, "!=")) {
     193           0 :                 PyObject_FREE(str);
     194           0 :                 err_ret->error = E_SYNTAX;
     195             :                 break;
     196             :             }
     197           3 :             else if ((ps->p_flags & CO_FUTURE_BARRY_AS_BDFL) &&
     198           0 :                             strcmp(str, "<>")) {
     199           0 :                 PyObject_FREE(str);
     200           0 :                 err_ret->text = "with Barry as BDFL, use '<>' "
     201             :                                 "instead of '!='";
     202           0 :                 err_ret->error = E_SYNTAX;
     203             :                 break;
     204             :             }
     205             :         }
     206             : #endif
     207        1823 :         if (a >= tok->line_start)
     208        1705 :             col_offset = a - tok->line_start;
     209             :         else
     210         118 :             col_offset = -1;
     211             : 
     212        1823 :         if ((err_ret->error =
     213        1823 :              PyParser_AddToken(ps, (int)type, str,
     214             :                                tok->lineno, col_offset,
     215             :                                &(err_ret->expected))) != E_OK) {
     216           3 :             if (err_ret->error != E_DONE) {
     217           0 :                 PyObject_FREE(str);
     218           0 :                 err_ret->token = type;
     219             :             }
     220             :             break;
     221             :         }
     222        1820 :     }
     223             : 
     224           3 :     if (err_ret->error == E_DONE) {
     225           3 :         n = ps->p_tree;
     226           3 :         ps->p_tree = NULL;
     227             : 
     228             : #ifndef PGEN
     229             :         /* Check that the source for a single input statement really
     230             :            is a single statement by looking at what is left in the
     231             :            buffer after parsing.  Trailing whitespace and comments
     232             :            are OK.  */
     233           3 :         if (start == single_input) {
     234           0 :             char *cur = tok->cur;
     235           0 :             char c = *tok->cur;
     236             : 
     237             :             for (;;) {
     238           0 :                 while (c == ' ' || c == '\t' || c == '\n' || c == '\014')
     239           0 :                     c = *++cur;
     240             : 
     241           0 :                 if (!c)
     242           0 :                     break;
     243             : 
     244           0 :                 if (c != '#') {
     245           0 :                     err_ret->error = E_BADSINGLE;
     246           0 :                     PyNode_Free(n);
     247           0 :                     n = NULL;
     248           0 :                     break;
     249             :                 }
     250             : 
     251             :                 /* Suck up comment. */
     252           0 :                 while (c && c != '\n')
     253           0 :                     c = *++cur;
     254           0 :             }
     255             :         }
     256             : #endif
     257             :     }
     258             :     else
     259           0 :         n = NULL;
     260             : 
     261             : #ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
     262           3 :     *flags = ps->p_flags;
     263             : #endif
     264           3 :     PyParser_Delete(ps);
     265             : 
     266           3 :     if (n == NULL) {
     267           0 :         if (tok->done == E_EOF)
     268           0 :             err_ret->error = E_EOF;
     269           0 :         err_ret->lineno = tok->lineno;
     270           0 :         if (tok->buf != NULL) {
     271             :             size_t len;
     272             :             assert(tok->cur - tok->buf < INT_MAX);
     273           0 :             err_ret->offset = (int)(tok->cur - tok->buf);
     274           0 :             len = tok->inp - tok->buf;
     275           0 :             err_ret->text = (char *) PyObject_MALLOC(len + 1);
     276           0 :             if (err_ret->text != NULL) {
     277           0 :                 if (len > 0)
     278           0 :                     strncpy(err_ret->text, tok->buf, len);
     279           0 :                 err_ret->text[len] = '\0';
     280             :             }
     281             :         }
     282           3 :     } else if (tok->encoding != NULL) {
     283             :         /* 'nodes->n_str' uses PyObject_*, while 'tok->encoding' was
     284             :          * allocated using PyMem_
     285             :          */
     286           3 :         node* r = PyNode_New(encoding_decl);
     287           3 :         if (r)
     288           3 :             r->n_str = PyObject_MALLOC(strlen(tok->encoding)+1);
     289           3 :         if (!r || !r->n_str) {
     290           0 :             err_ret->error = E_NOMEM;
     291           0 :             if (r)
     292           0 :                 PyObject_FREE(r);
     293           0 :             n = NULL;
     294           0 :             goto done;
     295             :         }
     296           3 :         strcpy(r->n_str, tok->encoding);
     297           3 :         PyMem_FREE(tok->encoding);
     298           3 :         tok->encoding = NULL;
     299           3 :         r->n_nchildren = 1;
     300           3 :         r->n_child = n;
     301           3 :         n = r;
     302             :     }
     303             : 
     304             : done:
     305           3 :     PyTokenizer_Free(tok);
     306             : 
     307           3 :     return n;
     308             : }
     309             : 
     310             : static int
     311           3 : initerr(perrdetail *err_ret, const char *filename)
     312             : {
     313           3 :     err_ret->error = E_OK;
     314           3 :     err_ret->lineno = 0;
     315           3 :     err_ret->offset = 0;
     316           3 :     err_ret->text = NULL;
     317           3 :     err_ret->token = -1;
     318           3 :     err_ret->expected = -1;
     319             : #ifndef PGEN
     320           3 :     if (filename)
     321           3 :         err_ret->filename = PyUnicode_DecodeFSDefault(filename);
     322             :     else
     323           0 :         err_ret->filename = PyUnicode_FromString("<string>");
     324           3 :     if (err_ret->filename == NULL) {
     325           0 :         err_ret->error = E_ERROR;
     326           0 :         return -1;
     327             :     }
     328             : #endif
     329           3 :     return 0;
     330             : }

Generated by: LCOV version 1.10