PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - lcov_data/Zend - zend_language_scanner.l (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 934 1060 88.1 %
Date: 2016-09-27 Functions: 28 30 93.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2016 Zend Technologies Ltd. (http://www.zend.com) |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 2.00 of the Zend license,     |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.zend.com/license/2_00.txt.                                |
      11             :    | If you did not receive a copy of the Zend license and are unable to  |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@zend.com so we can mail you a copy immediately.              |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Marcus Boerger <helly@php.net>                              |
      16             :    |          Nuno Lopes <nlopess@php.net>                                |
      17             :    |          Scott MacVicar <scottmac@php.net>                           |
      18             :    | Flex version authors:                                                |
      19             :    |          Andi Gutmans <andi@zend.com>                                |
      20             :    |          Zeev Suraski <zeev@zend.com>                                |
      21             :    +----------------------------------------------------------------------+
      22             : */
      23             : 
      24             : /* $Id$ */
      25             : 
      26             : #if 0
      27             : # define YYDEBUG(s, c) printf("state: %d char: %c\n", s, c)
      28             : #else
      29             : # define YYDEBUG(s, c)
      30             : #endif
      31             : 
      32             : #include "zend_language_scanner_defs.h"
      33             : 
      34             : #include <errno.h>
      35             : #include "zend.h"
      36             : #ifdef ZEND_WIN32
      37             : # include <Winuser.h>
      38             : #endif
      39             : #include "zend_alloc.h"
      40             : #include <zend_language_parser.h>
      41             : #include "zend_compile.h"
      42             : #include "zend_language_scanner.h"
      43             : #include "zend_highlight.h"
      44             : #include "zend_constants.h"
      45             : #include "zend_variables.h"
      46             : #include "zend_operators.h"
      47             : #include "zend_API.h"
      48             : #include "zend_strtod.h"
      49             : #include "zend_exceptions.h"
      50             : #include "zend_virtual_cwd.h"
      51             : #include "tsrm_config_common.h"
      52             : 
      53             : #define YYCTYPE   unsigned char
      54             : #define YYFILL(n) { if ((YYCURSOR + n) >= (YYLIMIT + ZEND_MMAP_AHEAD)) { return 0; } }
      55             : #define YYCURSOR  SCNG(yy_cursor)
      56             : #define YYLIMIT   SCNG(yy_limit)
      57             : #define YYMARKER  SCNG(yy_marker)
      58             : 
      59             : #define YYGETCONDITION()  SCNG(yy_state)
      60             : #define YYSETCONDITION(s) SCNG(yy_state) = s
      61             : 
      62             : #define STATE(name)  yyc##name
      63             : 
      64             : /* emulate flex constructs */
      65             : #define BEGIN(state) YYSETCONDITION(STATE(state))
      66             : #define YYSTATE      YYGETCONDITION()
      67             : #define yytext       ((char*)SCNG(yy_text))
      68             : #define yyleng       SCNG(yy_leng)
      69             : #define yyless(x)    do { YYCURSOR = (unsigned char*)yytext + x; \
      70             :                           yyleng   = (unsigned int)x; } while(0)
      71             : #define yymore()     goto yymore_restart
      72             : 
      73             : /* perform sanity check. If this message is triggered you should
      74             :    increase the ZEND_MMAP_AHEAD value in the zend_streams.h file */
      75             : /*!max:re2c */
      76             : #if ZEND_MMAP_AHEAD < YYMAXFILL
      77             : # error ZEND_MMAP_AHEAD should be greater than or equal to YYMAXFILL
      78             : #endif
      79             : 
      80             : #ifdef HAVE_STDARG_H
      81             : # include <stdarg.h>
      82             : #endif
      83             : 
      84             : #ifdef HAVE_UNISTD_H
      85             : # include <unistd.h>
      86             : #endif
      87             : 
      88             : /* Globals Macros */
      89             : #define SCNG    LANG_SCNG
      90             : #ifdef ZTS
      91             : ZEND_API ts_rsrc_id language_scanner_globals_id;
      92             : #else
      93             : ZEND_API zend_php_scanner_globals language_scanner_globals;
      94             : #endif
      95             : 
      96             : #define HANDLE_NEWLINES(s, l)                                                                                                   \
      97             : do {                                                                                                                                                    \
      98             :         char *p = (s), *boundary = p+(l);                                                                                       \
      99             :                                                                                                                                                                 \
     100             :         while (p<boundary) {                                                                                                         \
     101             :                 if (*p == '\n' || (*p == '\r' && (*(p+1) != '\n'))) {                                   \
     102             :                         CG(zend_lineno)++;                                                                                                      \
     103             :                 }                                                                                                                                               \
     104             :                 p++;                                                                                                                                    \
     105             :         }                                                                                                                                                       \
     106             : } while (0)
     107             : 
     108             : #define HANDLE_NEWLINE(c) \
     109             : { \
     110             :         if (c == '\n' || c == '\r') { \
     111             :                 CG(zend_lineno)++; \
     112             :         } \
     113             : }
     114             : 
     115             : /* To save initial string length after scanning to first variable */
     116             : #define SET_DOUBLE_QUOTES_SCANNED_LENGTH(len) SCNG(scanned_string_len) = (len)
     117             : #define GET_DOUBLE_QUOTES_SCANNED_LENGTH()    SCNG(scanned_string_len)
     118             : 
     119             : #define IS_LABEL_START(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z') || (c) == '_' || (c) >= 0x80)
     120             : 
     121             : #define ZEND_IS_OCT(c)  ((c)>='0' && (c)<='7')
     122             : #define ZEND_IS_HEX(c)  (((c)>='0' && (c)<='9') || ((c)>='a' && (c)<='f') || ((c)>='A' && (c)<='F'))
     123             : 
     124             : BEGIN_EXTERN_C()
     125             : 
     126          44 : static size_t encoding_filter_script_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length)
     127             : {
     128          44 :         const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding();
     129             :         ZEND_ASSERT(internal_encoding);
     130          44 :         return zend_multibyte_encoding_converter(to, to_length, from, from_length, internal_encoding, LANG_SCNG(script_encoding));
     131             : }
     132             : 
     133           4 : static size_t encoding_filter_script_to_intermediate(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length)
     134             : {
     135           4 :         return zend_multibyte_encoding_converter(to, to_length, from, from_length, zend_multibyte_encoding_utf8, LANG_SCNG(script_encoding));
     136             : }
     137             : 
     138          27 : static size_t encoding_filter_intermediate_to_script(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length)
     139             : {
     140          27 :         return zend_multibyte_encoding_converter(to, to_length, from, from_length,
     141             : LANG_SCNG(script_encoding), zend_multibyte_encoding_utf8);
     142             : }
     143             : 
     144           0 : static size_t encoding_filter_intermediate_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length)
     145             : {
     146           0 :         const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding();
     147             :         ZEND_ASSERT(internal_encoding);
     148           0 :         return zend_multibyte_encoding_converter(to, to_length, from, from_length,
     149             : internal_encoding, zend_multibyte_encoding_utf8);
     150             : }
     151             : 
     152             : 
     153      199003 : static void _yy_push_state(int new_state)
     154             : {
     155      199003 :         zend_stack_push(&SCNG(state_stack), (void *) &YYGETCONDITION());
     156      199003 :         YYSETCONDITION(new_state);
     157      199003 : }
     158             : 
     159             : #define yy_push_state(state_and_tsrm) _yy_push_state(yyc##state_and_tsrm)
     160             : 
     161      198971 : static void yy_pop_state(void)
     162             : {
     163      198971 :         int *stack_state = zend_stack_top(&SCNG(state_stack));
     164      198971 :         YYSETCONDITION(*stack_state);
     165      198971 :         zend_stack_del_top(&SCNG(state_stack));
     166      198971 : }
     167             : 
     168       35367 : static void yy_scan_buffer(char *str, unsigned int len)
     169             : {
     170       35367 :         YYCURSOR       = (YYCTYPE*)str;
     171       35367 :         YYLIMIT        = YYCURSOR + len;
     172       35367 :         if (!SCNG(yy_start)) {
     173        1316 :                 SCNG(yy_start) = YYCURSOR;
     174             :         }
     175       35367 : }
     176             : 
     177       23904 : void startup_scanner(void)
     178             : {
     179       23904 :         CG(parse_error) = 0;
     180       23904 :         CG(doc_comment) = NULL;
     181       23904 :         CG(extra_fn_flags) = 0;
     182       23904 :         zend_stack_init(&SCNG(state_stack), sizeof(int));
     183       23904 :         zend_ptr_stack_init(&SCNG(heredoc_label_stack));
     184       23904 : }
     185             : 
     186        1616 : static void heredoc_label_dtor(zend_heredoc_label *heredoc_label) {
     187        1616 :     efree(heredoc_label->label);
     188        1616 : }
     189             : 
     190       23925 : void shutdown_scanner(void)
     191             : {
     192       23925 :         CG(parse_error) = 0;
     193       23925 :         RESET_DOC_COMMENT();
     194       23925 :         zend_stack_destroy(&SCNG(state_stack));
     195       23925 :         zend_ptr_stack_clean(&SCNG(heredoc_label_stack), (void (*)(void *)) &heredoc_label_dtor, 1);
     196       23925 :         zend_ptr_stack_destroy(&SCNG(heredoc_label_stack));
     197       23925 :         SCNG(on_event) = NULL;
     198       23925 : }
     199             : 
     200       35392 : ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state)
     201             : {
     202       35392 :         lex_state->yy_leng   = SCNG(yy_leng);
     203       35392 :         lex_state->yy_start  = SCNG(yy_start);
     204       35392 :         lex_state->yy_text   = SCNG(yy_text);
     205       35392 :         lex_state->yy_cursor = SCNG(yy_cursor);
     206       35392 :         lex_state->yy_marker = SCNG(yy_marker);
     207       35392 :         lex_state->yy_limit  = SCNG(yy_limit);
     208             : 
     209       35392 :         lex_state->state_stack = SCNG(state_stack);
     210       35392 :         zend_stack_init(&SCNG(state_stack), sizeof(int));
     211             : 
     212       35392 :         lex_state->heredoc_label_stack = SCNG(heredoc_label_stack);
     213       35392 :         zend_ptr_stack_init(&SCNG(heredoc_label_stack));
     214             : 
     215       35392 :         lex_state->in = SCNG(yy_in);
     216       35392 :         lex_state->yy_state = YYSTATE;
     217       35392 :         lex_state->filename = zend_get_compiled_filename();
     218       35392 :         lex_state->lineno = CG(zend_lineno);
     219             : 
     220       35392 :         lex_state->script_org = SCNG(script_org);
     221       35392 :         lex_state->script_org_size = SCNG(script_org_size);
     222       35392 :         lex_state->script_filtered = SCNG(script_filtered);
     223       35392 :         lex_state->script_filtered_size = SCNG(script_filtered_size);
     224       35392 :         lex_state->input_filter = SCNG(input_filter);
     225       35392 :         lex_state->output_filter = SCNG(output_filter);
     226       35392 :         lex_state->script_encoding = SCNG(script_encoding);
     227             : 
     228       35392 :         lex_state->on_event = SCNG(on_event);
     229       35392 :         lex_state->on_event_context = SCNG(on_event_context);
     230             : 
     231       35392 :         lex_state->ast = CG(ast);
     232       35392 :         lex_state->ast_arena = CG(ast_arena);
     233       35392 : }
     234             : 
     235       35097 : ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state)
     236             : {
     237       35097 :         SCNG(yy_leng)   = lex_state->yy_leng;
     238       35097 :         SCNG(yy_start)  = lex_state->yy_start;
     239       35097 :         SCNG(yy_text)   = lex_state->yy_text;
     240       35097 :         SCNG(yy_cursor) = lex_state->yy_cursor;
     241       35097 :         SCNG(yy_marker) = lex_state->yy_marker;
     242       35097 :         SCNG(yy_limit)  = lex_state->yy_limit;
     243             : 
     244       35097 :         zend_stack_destroy(&SCNG(state_stack));
     245       35097 :         SCNG(state_stack) = lex_state->state_stack;
     246             : 
     247       35097 :         zend_ptr_stack_clean(&SCNG(heredoc_label_stack), (void (*)(void *)) &heredoc_label_dtor, 1);
     248       35097 :         zend_ptr_stack_destroy(&SCNG(heredoc_label_stack));
     249       35097 :         SCNG(heredoc_label_stack) = lex_state->heredoc_label_stack;
     250             : 
     251       35097 :         SCNG(yy_in) = lex_state->in;
     252       35097 :         YYSETCONDITION(lex_state->yy_state);
     253       35097 :         CG(zend_lineno) = lex_state->lineno;
     254       35097 :         zend_restore_compiled_filename(lex_state->filename);
     255             : 
     256       35097 :         if (SCNG(script_filtered)) {
     257          24 :                 efree(SCNG(script_filtered));
     258          24 :                 SCNG(script_filtered) = NULL;
     259             :         }
     260       35097 :         SCNG(script_org) = lex_state->script_org;
     261       35097 :         SCNG(script_org_size) = lex_state->script_org_size;
     262       35097 :         SCNG(script_filtered) = lex_state->script_filtered;
     263       35097 :         SCNG(script_filtered_size) = lex_state->script_filtered_size;
     264       35097 :         SCNG(input_filter) = lex_state->input_filter;
     265       35097 :         SCNG(output_filter) = lex_state->output_filter;
     266       35097 :         SCNG(script_encoding) = lex_state->script_encoding;
     267             : 
     268       35097 :         SCNG(on_event) = lex_state->on_event;
     269       35097 :         SCNG(on_event_context) = lex_state->on_event_context;
     270             : 
     271       35097 :         CG(ast) = lex_state->ast;
     272       35097 :         CG(ast_arena) = lex_state->ast_arena;
     273             : 
     274       35113 :         RESET_DOC_COMMENT();
     275       35097 : }
     276             : 
     277       33784 : ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle)
     278             : {
     279       33784 :         zend_llist_del_element(&CG(open_files), file_handle, (int (*)(void *, void *)) zend_compare_file_handles);
     280             :         /* zend_file_handle_dtor() operates on the copy, so we have to NULLify the original here */
     281       33784 :         file_handle->opened_path = NULL;
     282       33784 :         if (file_handle->free_filename) {
     283           0 :                 file_handle->filename = NULL;
     284             :         }
     285       33784 : }
     286             : 
     287         509 : ZEND_API void zend_lex_tstring(zval *zv)
     288             : {
     289         509 :         if (SCNG(on_event)) {
     290          10 :                 SCNG(on_event)(ON_FEEDBACK, T_STRING, 0, SCNG(on_event_context));
     291             :         }
     292             : 
     293        1018 :         ZVAL_STRINGL(zv, (char*)SCNG(yy_text), SCNG(yy_leng));
     294         509 : }
     295             : 
     296             : #define BOM_UTF32_BE    "\x00\x00\xfe\xff"
     297             : #define BOM_UTF32_LE    "\xff\xfe\x00\x00"
     298             : #define BOM_UTF16_BE    "\xfe\xff"
     299             : #define BOM_UTF16_LE    "\xff\xfe"
     300             : #define BOM_UTF8                "\xef\xbb\xbf"
     301             : 
     302           0 : static const zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned char *script, size_t script_size)
     303             : {
     304             :         const unsigned char *p;
     305           0 :         int wchar_size = 2;
     306           0 :         int le = 0;
     307             : 
     308             :         /* utf-16 or utf-32? */
     309           0 :         p = script;
     310           0 :         assert(p >= script);
     311           0 :         while ((size_t)(p-script) < script_size) {
     312           0 :                 p = memchr(p, 0, script_size-(p-script)-2);
     313           0 :                 if (!p) {
     314           0 :                         break;
     315             :                 }
     316           0 :                 if (*(p+1) == '\0' && *(p+2) == '\0') {
     317           0 :                         wchar_size = 4;
     318           0 :                         break;
     319             :                 }
     320             : 
     321             :                 /* searching for UTF-32 specific byte orders, so this will do */
     322           0 :                 p += 4;
     323             :         }
     324             : 
     325             :         /* BE or LE? */
     326           0 :         p = script;
     327           0 :         assert(p >= script);
     328           0 :         while ((size_t)(p-script) < script_size) {
     329           0 :                 if (*p == '\0' && *(p+wchar_size-1) != '\0') {
     330             :                         /* BE */
     331           0 :                         le = 0;
     332           0 :                         break;
     333           0 :                 } else if (*p != '\0' && *(p+wchar_size-1) == '\0') {
     334             :                         /* LE* */
     335           0 :                         le = 1;
     336           0 :                         break;
     337             :                 }
     338           0 :                 p += wchar_size;
     339             :         }
     340             : 
     341           0 :         if (wchar_size == 2) {
     342           0 :                 return le ? zend_multibyte_encoding_utf16le : zend_multibyte_encoding_utf16be;
     343             :         } else {
     344           0 :                 return le ? zend_multibyte_encoding_utf32le : zend_multibyte_encoding_utf32be;
     345             :         }
     346             : 
     347             :         return NULL;
     348             : }
     349             : 
     350          49 : static const zend_encoding* zend_multibyte_detect_unicode(void)
     351             : {
     352          49 :         const zend_encoding *script_encoding = NULL;
     353             :         int bom_size;
     354             :         unsigned char *pos1, *pos2;
     355             : 
     356          49 :         if (LANG_SCNG(script_org_size) < sizeof(BOM_UTF32_LE)-1) {
     357           0 :                 return NULL;
     358             :         }
     359             : 
     360             :         /* check out BOM */
     361          49 :         if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_BE, sizeof(BOM_UTF32_BE)-1)) {
     362           0 :                 script_encoding = zend_multibyte_encoding_utf32be;
     363           0 :                 bom_size = sizeof(BOM_UTF32_BE)-1;
     364          49 :         } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_LE, sizeof(BOM_UTF32_LE)-1)) {
     365           0 :                 script_encoding = zend_multibyte_encoding_utf32le;
     366           0 :                 bom_size = sizeof(BOM_UTF32_LE)-1;
     367          49 :         } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_BE, sizeof(BOM_UTF16_BE)-1)) {
     368           0 :                 script_encoding = zend_multibyte_encoding_utf16be;
     369           0 :                 bom_size = sizeof(BOM_UTF16_BE)-1;
     370          49 :         } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_LE, sizeof(BOM_UTF16_LE)-1)) {
     371           1 :                 script_encoding = zend_multibyte_encoding_utf16le;
     372           1 :                 bom_size = sizeof(BOM_UTF16_LE)-1;
     373          48 :         } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF8, sizeof(BOM_UTF8)-1)) {
     374           1 :                 script_encoding = zend_multibyte_encoding_utf8;
     375           1 :                 bom_size = sizeof(BOM_UTF8)-1;
     376             :         }
     377             : 
     378          49 :         if (script_encoding) {
     379             :                 /* remove BOM */
     380           2 :                 LANG_SCNG(script_org) += bom_size;
     381           2 :                 LANG_SCNG(script_org_size) -= bom_size;
     382             : 
     383           2 :                 return script_encoding;
     384             :         }
     385             : 
     386             :         /* script contains NULL bytes -> auto-detection */
     387          47 :         if ((pos1 = memchr(LANG_SCNG(script_org), 0, LANG_SCNG(script_org_size)))) {
     388             :                 /* check if the NULL byte is after the __HALT_COMPILER(); */
     389           0 :                 pos2 = LANG_SCNG(script_org);
     390             : 
     391           0 :                 while ((size_t)(pos1 - pos2) >= sizeof("__HALT_COMPILER();")-1) {
     392           0 :                         pos2 = memchr(pos2, '_', pos1 - pos2);
     393           0 :                         if (!pos2) break;
     394           0 :                         pos2++;
     395           0 :                         if (strncasecmp((char*)pos2, "_HALT_COMPILER", sizeof("_HALT_COMPILER")-1) == 0) {
     396           0 :                                 pos2 += sizeof("_HALT_COMPILER")-1;
     397           0 :                                 while (*pos2 == ' '  ||
     398           0 :                                            *pos2 == '\t' ||
     399           0 :                                            *pos2 == '\r' ||
     400           0 :                                            *pos2 == '\n') {
     401           0 :                                         pos2++;
     402             :                                 }
     403           0 :                                 if (*pos2 == '(') {
     404           0 :                                         pos2++;
     405           0 :                                         while (*pos2 == ' '  ||
     406           0 :                                                    *pos2 == '\t' ||
     407           0 :                                                    *pos2 == '\r' ||
     408           0 :                                                    *pos2 == '\n') {
     409           0 :                                                 pos2++;
     410             :                                         }
     411           0 :                                         if (*pos2 == ')') {
     412           0 :                                                 pos2++;
     413           0 :                                                 while (*pos2 == ' '  ||
     414           0 :                                                            *pos2 == '\t' ||
     415           0 :                                                            *pos2 == '\r' ||
     416           0 :                                                            *pos2 == '\n') {
     417           0 :                                                         pos2++;
     418             :                                                 }
     419           0 :                                                 if (*pos2 == ';') {
     420           0 :                                                         return NULL;
     421             :                                                 }
     422             :                                         }
     423             :                                 }
     424             :                         }
     425             :                 }
     426             :                 /* make best effort if BOM is missing */
     427           0 :                 return zend_multibyte_detect_utf_encoding(LANG_SCNG(script_org), LANG_SCNG(script_org_size));
     428             :         }
     429             : 
     430          47 :         return NULL;
     431             : }
     432             : 
     433          49 : static const zend_encoding* zend_multibyte_find_script_encoding(void)
     434             : {
     435             :         const zend_encoding *script_encoding;
     436             : 
     437          49 :         if (CG(detect_unicode)) {
     438             :                 /* check out bom(byte order mark) and see if containing wchars */
     439          49 :                 script_encoding = zend_multibyte_detect_unicode();
     440          49 :                 if (script_encoding != NULL) {
     441             :                         /* bom or wchar detection is prior to 'script_encoding' option */
     442           2 :                         return script_encoding;
     443             :                 }
     444             :         }
     445             : 
     446             :         /* if no script_encoding specified, just leave alone */
     447          47 :         if (!CG(script_encoding_list) || !CG(script_encoding_list_size)) {
     448          26 :                 return NULL;
     449             :         }
     450             : 
     451             :         /* if multiple encodings specified, detect automagically */
     452          21 :         if (CG(script_encoding_list_size) > 1) {
     453           0 :                 return zend_multibyte_encoding_detector(LANG_SCNG(script_org), LANG_SCNG(script_org_size), CG(script_encoding_list), CG(script_encoding_list_size));
     454             :         }
     455             : 
     456          21 :         return CG(script_encoding_list)[0];
     457             : }
     458             : 
     459          69 : ZEND_API int zend_multibyte_set_filter(const zend_encoding *onetime_encoding)
     460             : {
     461          69 :         const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding();
     462          69 :         const zend_encoding *script_encoding = onetime_encoding ? onetime_encoding: zend_multibyte_find_script_encoding();
     463             : 
     464          69 :         if (!script_encoding) {
     465          26 :                 return FAILURE;
     466             :         }
     467             : 
     468             :         /* judge input/output filter */
     469          43 :         LANG_SCNG(script_encoding) = script_encoding;
     470          43 :         LANG_SCNG(input_filter) = NULL;
     471          43 :         LANG_SCNG(output_filter) = NULL;
     472             : 
     473          43 :         if (!internal_encoding || LANG_SCNG(script_encoding) == internal_encoding) {
     474          11 :                 if (!zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) {
     475             :                         /* and if not, work around w/ script_encoding -> utf-8 -> script_encoding conversion */
     476           4 :                         LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate;
     477           4 :                         LANG_SCNG(output_filter) = encoding_filter_intermediate_to_script;
     478             :                 } else {
     479           7 :                         LANG_SCNG(input_filter) = NULL;
     480           7 :                         LANG_SCNG(output_filter) = NULL;
     481             :                 }
     482          11 :                 return SUCCESS;
     483             :         }
     484             : 
     485          32 :         if (zend_multibyte_check_lexer_compatibility(internal_encoding)) {
     486          29 :                 LANG_SCNG(input_filter) = encoding_filter_script_to_internal;
     487          29 :                 LANG_SCNG(output_filter) = NULL;
     488           3 :         } else if (zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) {
     489           3 :                 LANG_SCNG(input_filter) = NULL;
     490           3 :                 LANG_SCNG(output_filter) = encoding_filter_script_to_internal;
     491             :         } else {
     492             :                 /* both script and internal encodings are incompatible w/ flex */
     493           0 :                 LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate;
     494           0 :                 LANG_SCNG(output_filter) = encoding_filter_intermediate_to_internal;
     495             :         }
     496             : 
     497          32 :         return 0;
     498             : }
     499             : 
     500       34082 : ZEND_API int open_file_for_scanning(zend_file_handle *file_handle)
     501             : {
     502             :         char *buf;
     503       34082 :         size_t size, offset = 0;
     504             :         zend_string *compiled_filename;
     505             : 
     506             :         /* The shebang line was read, get the current position to obtain the buffer start */
     507       34082 :         if (CG(start_lineno) == 2 && file_handle->type == ZEND_HANDLE_FP && file_handle->handle.fp) {
     508           5 :                 if ((offset = ftell(file_handle->handle.fp)) == (size_t)-1) {
     509           0 :                         offset = 0;
     510             :                 }
     511             :         }
     512             : 
     513       34082 :         if (zend_stream_fixup(file_handle, &buf, &size) == FAILURE) {
     514          31 :                 return FAILURE;
     515             :         }
     516             : 
     517       34051 :         zend_llist_add_element(&CG(open_files), file_handle);
     518       34051 :         if (file_handle->handle.stream.handle >= (void*)file_handle && file_handle->handle.stream.handle <= (void*)(file_handle+1)) {
     519       23672 :                 zend_file_handle *fh = (zend_file_handle*)zend_llist_get_last(&CG(open_files));
     520       23672 :                 size_t diff = (char*)file_handle->handle.stream.handle - (char*)file_handle;
     521       23672 :                 fh->handle.stream.handle = (void*)(((char*)fh) + diff);
     522       23672 :                 file_handle->handle.stream.handle = fh->handle.stream.handle;
     523             :         }
     524             : 
     525             :         /* Reset the scanner for scanning the new file */
     526       34051 :         SCNG(yy_in) = file_handle;
     527       34051 :         SCNG(yy_start) = NULL;
     528             : 
     529       34051 :         if (size != (size_t)-1) {
     530       34051 :                 if (CG(multibyte)) {
     531          49 :                         SCNG(script_org) = (unsigned char*)buf;
     532          49 :                         SCNG(script_org_size) = size;
     533          49 :                         SCNG(script_filtered) = NULL;
     534             : 
     535          49 :                         zend_multibyte_set_filter(NULL);
     536             : 
     537          49 :                         if (SCNG(input_filter)) {
     538          20 :                                 if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size))) {
     539           0 :                                         zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
     540             :                                                         "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
     541             :                                 }
     542          20 :                                 buf = (char*)SCNG(script_filtered);
     543          20 :                                 size = SCNG(script_filtered_size);
     544             :                         }
     545             :                 }
     546       34051 :                 SCNG(yy_start) = (unsigned char *)buf - offset;
     547       34051 :                 yy_scan_buffer(buf, (unsigned int)size);
     548             :         } else {
     549           0 :                 zend_error_noreturn(E_COMPILE_ERROR, "zend_stream_mmap() failed");
     550             :         }
     551             : 
     552       34051 :         BEGIN(INITIAL);
     553             : 
     554       34051 :         if (file_handle->opened_path) {
     555       68028 :                 compiled_filename = zend_string_copy(file_handle->opened_path);
     556             :         } else {
     557          74 :                 compiled_filename = zend_string_init(file_handle->filename, strlen(file_handle->filename), 0);
     558             :         }
     559             : 
     560       34051 :         zend_set_compiled_filename(compiled_filename);
     561             :         zend_string_release(compiled_filename);
     562             : 
     563       34051 :         if (CG(start_lineno)) {
     564       23382 :                 CG(zend_lineno) = CG(start_lineno);
     565       23382 :                 CG(start_lineno) = 0;
     566             :         } else {
     567       10669 :                 CG(zend_lineno) = 1;
     568             :         }
     569             : 
     570       34051 :         RESET_DOC_COMMENT();
     571       34051 :         CG(increment_lineno) = 0;
     572       34051 :         return SUCCESS;
     573             : }
     574             : END_EXTERN_C()
     575             : 
     576       35233 : static zend_op_array *zend_compile(int type)
     577             : {
     578       35233 :         zend_op_array *op_array = NULL;
     579       35233 :         zend_bool original_in_compilation = CG(in_compilation);
     580             : 
     581       35233 :         CG(in_compilation) = 1;
     582       35233 :         CG(ast) = NULL;
     583       35233 :         CG(ast_arena) = zend_arena_create(1024 * 32);
     584             : 
     585       35233 :         if (!zendparse()) {
     586             :                 zend_file_context original_file_context;
     587             :                 zend_oparray_context original_oparray_context;
     588       35155 :                 zend_op_array *original_active_op_array = CG(active_op_array);
     589             : 
     590       35155 :                 op_array = emalloc(sizeof(zend_op_array));
     591       35155 :                 init_op_array(op_array, type, INITIAL_OP_ARRAY_SIZE);
     592       35155 :                 CG(active_op_array) = op_array;
     593             : 
     594       35155 :                 if (zend_ast_process) {
     595           0 :                         zend_ast_process(CG(ast));
     596             :                 }
     597             : 
     598       35155 :                 zend_file_context_begin(&original_file_context);
     599       35155 :                 zend_oparray_context_begin(&original_oparray_context);
     600       35155 :                 zend_compile_top_stmt(CG(ast));
     601       34884 :                 zend_emit_final_return(type == ZEND_USER_FUNCTION);
     602       34884 :                 op_array->line_start = 1;
     603       34884 :                 op_array->line_end = CG(zend_lineno);
     604       34884 :                 pass_two(op_array);
     605       34879 :                 zend_oparray_context_end(&original_oparray_context);
     606       34879 :                 zend_file_context_end(&original_file_context);
     607             : 
     608       34879 :                 CG(active_op_array) = original_active_op_array;
     609             :         }
     610             : 
     611       34939 :         zend_ast_destroy(CG(ast));
     612       34939 :         zend_arena_destroy(CG(ast_arena));
     613             : 
     614       34939 :         CG(in_compilation) = original_in_compilation;
     615             : 
     616       34939 :         return op_array;
     617             : }
     618             : 
     619       34048 : ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type)
     620             : {
     621             :         zend_lex_state original_lex_state;
     622       34048 :         zend_op_array *op_array = NULL;
     623       34048 :         zend_save_lexical_state(&original_lex_state);
     624             : 
     625       34048 :         if (open_file_for_scanning(file_handle)==FAILURE) {
     626          27 :                 if (type==ZEND_REQUIRE) {
     627           1 :                         zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
     628           0 :                         zend_bailout();
     629             :                 } else {
     630          26 :                         zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
     631             :                 }
     632             :         } else {
     633       34021 :                 op_array = zend_compile(ZEND_USER_FUNCTION);
     634             :         }
     635             : 
     636       33755 :         zend_restore_lexical_state(&original_lex_state);
     637       33755 :         return op_array;
     638             : }
     639             : 
     640             : 
     641        4540 : zend_op_array *compile_filename(int type, zval *filename)
     642             : {
     643             :         zend_file_handle file_handle;
     644             :         zval tmp;
     645             :         zend_op_array *retval;
     646        4540 :         zend_string *opened_path = NULL;
     647             : 
     648        4540 :         if (Z_TYPE_P(filename) != IS_STRING) {
     649           0 :                 tmp = *filename;
     650             :                 zval_copy_ctor(&tmp);
     651           0 :                 convert_to_string(&tmp);
     652           0 :                 filename = &tmp;
     653             :         }
     654        4540 :         file_handle.filename = Z_STRVAL_P(filename);
     655        4540 :         file_handle.free_filename = 0;
     656        4540 :         file_handle.type = ZEND_HANDLE_FILENAME;
     657        4540 :         file_handle.opened_path = NULL;
     658        4540 :         file_handle.handle.fp = NULL;
     659             : 
     660        4540 :         retval = zend_compile_file(&file_handle, type);
     661        4537 :         if (retval && file_handle.handle.stream.handle) {
     662        4496 :                 if (!file_handle.opened_path) {
     663          36 :                         file_handle.opened_path = opened_path = zend_string_copy(Z_STR_P(filename));
     664             :                 }
     665             : 
     666        4496 :                 zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path);
     667             : 
     668        4496 :                 if (opened_path) {
     669             :                         zend_string_release(opened_path);
     670             :                 }
     671             :         }
     672        4537 :         zend_destroy_file_handle(&file_handle);
     673             : 
     674        4537 :         if (filename==&tmp) {
     675             :                 zval_dtor(&tmp);
     676             :         }
     677        4537 :         return retval;
     678             : }
     679             : 
     680        1316 : ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename)
     681             : {
     682             :         char *buf;
     683             :         size_t size, old_len;
     684             :         zend_string *new_compiled_filename;
     685             : 
     686             :         /* enforce ZEND_MMAP_AHEAD trailing NULLs for flex... */
     687        1316 :         old_len = Z_STRLEN_P(str);
     688        2632 :         Z_STR_P(str) = zend_string_extend(Z_STR_P(str), old_len + ZEND_MMAP_AHEAD, 0);
     689        1316 :         Z_TYPE_INFO_P(str) = IS_STRING_EX;
     690        1316 :         memset(Z_STRVAL_P(str) + old_len, 0, ZEND_MMAP_AHEAD + 1);
     691             : 
     692        1316 :         SCNG(yy_in) = NULL;
     693        1316 :         SCNG(yy_start) = NULL;
     694             : 
     695        1316 :         buf = Z_STRVAL_P(str);
     696        1316 :         size = old_len;
     697             : 
     698        1316 :         if (CG(multibyte)) {
     699           0 :                 SCNG(script_org) = (unsigned char*)buf;
     700           0 :                 SCNG(script_org_size) = size;
     701           0 :                 SCNG(script_filtered) = NULL;
     702             : 
     703           0 :                 zend_multibyte_set_filter(zend_multibyte_get_internal_encoding());
     704             : 
     705           0 :                 if (SCNG(input_filter)) {
     706           0 :                         if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size))) {
     707           0 :                                 zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
     708             :                                                 "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
     709             :                         }
     710           0 :                         buf = (char*)SCNG(script_filtered);
     711           0 :                         size = SCNG(script_filtered_size);
     712             :                 }
     713             :         }
     714             : 
     715        1316 :         yy_scan_buffer(buf, (unsigned int)size);
     716             : 
     717        2632 :         new_compiled_filename = zend_string_init(filename, strlen(filename), 0);
     718        1316 :         zend_set_compiled_filename(new_compiled_filename);
     719             :         zend_string_release(new_compiled_filename);
     720        1316 :         CG(zend_lineno) = 1;
     721        1316 :         CG(increment_lineno) = 0;
     722        1316 :         RESET_DOC_COMMENT();
     723        1316 :         return SUCCESS;
     724             : }
     725             : 
     726             : 
     727         277 : ZEND_API size_t zend_get_scanned_file_offset(void)
     728             : {
     729         277 :         size_t offset = SCNG(yy_cursor) - SCNG(yy_start);
     730         277 :         if (SCNG(input_filter)) {
     731           1 :                 size_t original_offset = offset, length = 0;
     732             :                 do {
     733           7 :                         unsigned char *p = NULL;
     734           7 :                         if ((size_t)-1 == SCNG(input_filter)(&p, &length, SCNG(script_org), offset)) {
     735           0 :                                 return (size_t)-1;
     736             :                         }
     737           7 :                         efree(p);
     738           7 :                         if (length > original_offset) {
     739           0 :                                 offset--;
     740           7 :                         } else if (length < original_offset) {
     741           6 :                                 offset++;
     742             :                         }
     743           7 :                 } while (original_offset != length);
     744             :         }
     745         277 :         return offset;
     746             : }
     747             : 
     748        1212 : zend_op_array *compile_string(zval *source_string, char *filename)
     749             : {
     750             :         zend_lex_state original_lex_state;
     751        1212 :         zend_op_array *op_array = NULL;
     752             :         zval tmp;
     753             : 
     754        1212 :         if (Z_STRLEN_P(source_string)==0) {
     755           0 :                 return NULL;
     756             :         }
     757             : 
     758        1212 :         ZVAL_DUP(&tmp, source_string);
     759        1212 :         convert_to_string(&tmp);
     760        1212 :         source_string = &tmp;
     761             : 
     762        1212 :         zend_save_lexical_state(&original_lex_state);
     763        1212 :         if (zend_prepare_string_for_scanning(source_string, filename) == SUCCESS) {
     764        1212 :                 BEGIN(ST_IN_SCRIPTING);
     765        1212 :                 op_array = zend_compile(ZEND_EVAL_CODE);
     766             :         }
     767             : 
     768        1210 :         zend_restore_lexical_state(&original_lex_state);
     769             :         zval_dtor(&tmp);
     770             : 
     771        1210 :         return op_array;
     772             : }
     773             : 
     774             : 
     775             : BEGIN_EXTERN_C()
     776          20 : int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini)
     777             : {
     778             :         zend_lex_state original_lex_state;
     779             :         zend_file_handle file_handle;
     780             : 
     781          20 :         file_handle.type = ZEND_HANDLE_FILENAME;
     782          20 :         file_handle.filename = filename;
     783          20 :         file_handle.free_filename = 0;
     784          20 :         file_handle.opened_path = NULL;
     785          20 :         zend_save_lexical_state(&original_lex_state);
     786          20 :         if (open_file_for_scanning(&file_handle)==FAILURE) {
     787           2 :                 zend_message_dispatcher(ZMSG_FAILED_HIGHLIGHT_FOPEN, filename);
     788           2 :                 zend_restore_lexical_state(&original_lex_state);
     789           2 :                 return FAILURE;
     790             :         }
     791          18 :         zend_highlight(syntax_highlighter_ini);
     792          18 :         if (SCNG(script_filtered)) {
     793           0 :                 efree(SCNG(script_filtered));
     794           0 :                 SCNG(script_filtered) = NULL;
     795             :         }
     796          18 :         zend_destroy_file_handle(&file_handle);
     797          18 :         zend_restore_lexical_state(&original_lex_state);
     798          18 :         return SUCCESS;
     799             : }
     800             : 
     801          15 : int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name)
     802             : {
     803             :         zend_lex_state original_lex_state;
     804          15 :         zval tmp = *str;
     805             : 
     806          15 :         str = &tmp;
     807             :         zval_copy_ctor(str);
     808          15 :         zend_save_lexical_state(&original_lex_state);
     809          15 :         if (zend_prepare_string_for_scanning(str, str_name)==FAILURE) {
     810           0 :                 zend_restore_lexical_state(&original_lex_state);
     811           0 :                 return FAILURE;
     812             :         }
     813          15 :         BEGIN(INITIAL);
     814          15 :         zend_highlight(syntax_highlighter_ini);
     815          15 :         if (SCNG(script_filtered)) {
     816           0 :                 efree(SCNG(script_filtered));
     817           0 :                 SCNG(script_filtered) = NULL;
     818             :         }
     819          15 :         zend_restore_lexical_state(&original_lex_state);
     820             :         zval_dtor(str);
     821          15 :         return SUCCESS;
     822             : }
     823             : 
     824          14 : ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, const zend_encoding *old_encoding)
     825             : {
     826             :         size_t length;
     827             :         unsigned char *new_yy_start;
     828             : 
     829             :         /* convert and set */
     830          14 :         if (!SCNG(input_filter)) {
     831           1 :                 if (SCNG(script_filtered)) {
     832           1 :                         efree(SCNG(script_filtered));
     833           1 :                         SCNG(script_filtered) = NULL;
     834             :                 }
     835           1 :                 SCNG(script_filtered_size) = 0;
     836           1 :                 length = SCNG(script_org_size);
     837           1 :                 new_yy_start = SCNG(script_org);
     838             :         } else {
     839          13 :                 if ((size_t)-1 == SCNG(input_filter)(&new_yy_start, &length, SCNG(script_org), SCNG(script_org_size))) {
     840           0 :                         zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
     841             :                                         "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
     842             :                 }
     843          13 :                 if (SCNG(script_filtered)) {
     844           6 :                         efree(SCNG(script_filtered));
     845             :                 }
     846          13 :                 SCNG(script_filtered) = new_yy_start;
     847          13 :                 SCNG(script_filtered_size) = length;
     848             :         }
     849             : 
     850          14 :         SCNG(yy_cursor) = new_yy_start + (SCNG(yy_cursor) - SCNG(yy_start));
     851          14 :         SCNG(yy_marker) = new_yy_start + (SCNG(yy_marker) - SCNG(yy_start));
     852          14 :         SCNG(yy_text) = new_yy_start + (SCNG(yy_text) - SCNG(yy_start));
     853          14 :         SCNG(yy_limit) = new_yy_start + length;
     854             : 
     855          14 :         SCNG(yy_start) = new_yy_start;
     856          14 : }
     857             : 
     858             : 
     859             : // TODO: avoid reallocation ???
     860             : # define zend_copy_value(zendlval, yytext, yyleng) \
     861             :         if (SCNG(output_filter)) { \
     862             :                 size_t sz = 0; \
     863             :                 char *s = NULL; \
     864             :                 SCNG(output_filter)((unsigned char **)&s, &sz, (unsigned char *)yytext, (size_t)yyleng); \
     865             :                 ZVAL_STRINGL(zendlval, s, sz); \
     866             :                 efree(s); \
     867             :         } else { \
     868             :                 ZVAL_STRINGL(zendlval, yytext, yyleng); \
     869             :         }
     870             : 
     871      225863 : static int zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type)
     872             : {
     873             :         register char *s, *t;
     874             :         char *end;
     875             : 
     876      451726 :         ZVAL_STRINGL(zendlval, str, len);
     877             : 
     878             :         /* convert escape sequences */
     879      225863 :         s = t = Z_STRVAL_P(zendlval);
     880      225863 :         end = s+Z_STRLEN_P(zendlval);
     881     4203670 :         while (s<end) {
     882     3751960 :                 if (*s=='\\') {
     883       67135 :                         s++;
     884       67135 :                         if (s >= end) {
     885           4 :                                 *t++ = '\\';
     886           4 :                                 break;
     887             :                         }
     888             : 
     889       67131 :                         switch(*s) {
     890             :                                 case 'n':
     891       52862 :                                         *t++ = '\n';
     892       52862 :                                         Z_STRLEN_P(zendlval)--;
     893       52862 :                                         break;
     894             :                                 case 'r':
     895        5073 :                                         *t++ = '\r';
     896        5073 :                                         Z_STRLEN_P(zendlval)--;
     897        5073 :                                         break;
     898             :                                 case 't':
     899         973 :                                         *t++ = '\t';
     900         973 :                                         Z_STRLEN_P(zendlval)--;
     901         973 :                                         break;
     902             :                                 case 'f':
     903          73 :                                         *t++ = '\f';
     904          73 :                                         Z_STRLEN_P(zendlval)--;
     905          73 :                                         break;
     906             :                                 case 'v':
     907         106 :                                         *t++ = '\v';
     908         106 :                                         Z_STRLEN_P(zendlval)--;
     909         106 :                                         break;
     910             :                                 case 'e':
     911             : #ifdef ZEND_WIN32
     912             :                                         *t++ = VK_ESCAPE;
     913             : #else
     914          15 :                                         *t++ = '\e';
     915             : #endif
     916          15 :                                         Z_STRLEN_P(zendlval)--;
     917          15 :                                         break;
     918             :                                 case '"':
     919             :                                 case '`':
     920        1850 :                                         if (*s != quote_type) {
     921          10 :                                                 *t++ = '\\';
     922          10 :                                                 *t++ = *s;
     923          10 :                                                 break;
     924             :                                         }
     925             :                                 case '\\':
     926             :                                 case '$':
     927        3029 :                                         *t++ = *s;
     928        3029 :                                         Z_STRLEN_P(zendlval)--;
     929        3029 :                                         break;
     930             :                                 case 'x':
     931             :                                 case 'X':
     932        6029 :                                         if (ZEND_IS_HEX(*(s+1))) {
     933        3004 :                                                 char hex_buf[3] = { 0, 0, 0 };
     934             : 
     935        3004 :                                                 Z_STRLEN_P(zendlval)--; /* for the 'x' */
     936             : 
     937        3004 :                                                 hex_buf[0] = *(++s);
     938        3004 :                                                 Z_STRLEN_P(zendlval)--;
     939        3004 :                                                 if (ZEND_IS_HEX(*(s+1))) {
     940        2973 :                                                         hex_buf[1] = *(++s);
     941        2973 :                                                         Z_STRLEN_P(zendlval)--;
     942             :                                                 }
     943        3004 :                                                 *t++ = (char) ZEND_STRTOL(hex_buf, NULL, 16);
     944             :                                         } else {
     945          21 :                                                 *t++ = '\\';
     946          21 :                                                 *t++ = *s;
     947             :                                         }
     948        3025 :                                         break;
     949             :                                 /* UTF-8 codepoint escape, format: /\\u\{\x+\}/ */
     950             :                                 case 'u':
     951             :                                         {
     952             :                                                 /* cache where we started so we can parse after validating */
     953          34 :                                                 char *start = s + 1;
     954          34 :                                                 size_t len = 0;
     955          34 :                                                 zend_bool valid = 1;
     956             :                                                 unsigned long codepoint;
     957          34 :                                                 size_t byte_len = 0;
     958             : 
     959          34 :                                                 if (*start != '{') {
     960             :                                                         /* we silently let this pass to avoid breaking code
     961             :                                                          * with JSON in string literals (e.g. "\"\u202e\""
     962             :                                                          */
     963           3 :                                                         *t++ = '\\';
     964           3 :                                                         *t++ = 'u';
     965           3 :                                                         break;
     966             :                                                 } else {
     967             :                                                         /* on the other hand, invalid \u{blah} errors */
     968          31 :                                                         s++;
     969          31 :                                                         len++;
     970          31 :                                                         s++;
     971         172 :                                                         while (*s != '}') {
     972         117 :                                                                 if (!ZEND_IS_HEX(*s)) {
     973           7 :                                                                         valid = 0;
     974           7 :                                                                         break;
     975             :                                                                 } else {
     976         110 :                                                                         len++;
     977             :                                                                 }
     978         110 :                                                                 s++;
     979             :                                                         }
     980          31 :                                                         if (*s == '}') {
     981          24 :                                                                 valid = 1;
     982          24 :                                                                 len++;
     983             :                                                         }
     984             :                                                 }
     985             : 
     986             :                                                 /* \u{} is invalid */
     987          31 :                                                 if (len <= 2) {
     988           7 :                                                         valid = 0;
     989             :                                                 }
     990             : 
     991          31 :                                                 if (!valid) {
     992           8 :                                                         zend_throw_exception(zend_ce_parse_error,
     993             :                                                                 "Invalid UTF-8 codepoint escape sequence", 0);
     994           8 :                                                         zval_ptr_dtor(zendlval);
     995           8 :                                                         ZVAL_UNDEF(zendlval);
     996           8 :                                                         return FAILURE;
     997             :                                                 }
     998             : 
     999          23 :                                                 errno = 0;
    1000          23 :                                                 codepoint = strtoul(start + 1, NULL, 16);
    1001             : 
    1002             :                                                 /* per RFC 3629, UTF-8 can only represent 21 bits */
    1003          23 :                                                 if (codepoint > 0x10FFFF || errno) {
    1004           4 :                                                         zend_throw_exception(zend_ce_parse_error,
    1005             :                                                                 "Invalid UTF-8 codepoint escape sequence: Codepoint too large", 0);
    1006           4 :                                                         zval_ptr_dtor(zendlval);
    1007           4 :                                                         ZVAL_UNDEF(zendlval);
    1008           4 :                                                         return FAILURE;
    1009             :                                                 }
    1010             : 
    1011             :                                                 /* based on https://en.wikipedia.org/wiki/UTF-8#Sample_code */
    1012          19 :                                                 if (codepoint < 0x80) {
    1013           1 :                                                         byte_len = 1;
    1014           1 :                                                         *t++ = codepoint;
    1015          18 :                                                 } else if (codepoint <= 0x7FF) {
    1016           2 :                                                         byte_len = 2;
    1017           2 :                                                         *t++ = (codepoint >> 6) + 0xC0;
    1018           2 :                                                         *t++ = (codepoint & 0x3F) + 0x80;
    1019          16 :                                                 } else if (codepoint <= 0xFFFF) {
    1020          12 :                                                         byte_len = 3;
    1021          12 :                                                         *t++ = (codepoint >> 12) + 0xE0;
    1022          12 :                                                         *t++ = ((codepoint >> 6) & 0x3F) + 0x80;
    1023          12 :                                                         *t++ = (codepoint & 0x3F) + 0x80;
    1024           4 :                                                 } else if (codepoint <= 0x10FFFF) {
    1025           4 :                                                         byte_len = 4;
    1026           4 :                                                         *t++ = (codepoint >> 18) + 0xF0;
    1027           4 :                                                         *t++ = ((codepoint >> 12) & 0x3F) + 0x80;
    1028           4 :                                                         *t++ = ((codepoint >> 6) & 0x3F) + 0x80;
    1029           4 :                                                         *t++ = (codepoint & 0x3F) + 0x80;
    1030             :                                                 }
    1031             : 
    1032          19 :                                                 Z_STRLEN_P(zendlval) -= 2; /* \u */
    1033          19 :                                                 Z_STRLEN_P(zendlval) -= (len - byte_len);
    1034             :                                         }
    1035          19 :                                         break;
    1036             :                                 default:
    1037             :                                         /* check for an octal */
    1038        3020 :                                         if (ZEND_IS_OCT(*s)) {
    1039        1089 :                                                 char octal_buf[4] = { 0, 0, 0, 0 };
    1040             : 
    1041        1089 :                                                 octal_buf[0] = *s;
    1042        1089 :                                                 Z_STRLEN_P(zendlval)--;
    1043        1089 :                                                 if (ZEND_IS_OCT(*(s+1))) {
    1044         261 :                                                         octal_buf[1] = *(++s);
    1045         261 :                                                         Z_STRLEN_P(zendlval)--;
    1046         261 :                                                         if (ZEND_IS_OCT(*(s+1))) {
    1047         237 :                                                                 octal_buf[2] = *(++s);
    1048         237 :                                                                 Z_STRLEN_P(zendlval)--;
    1049             :                                                         }
    1050             :                                                 }
    1051        1326 :                                                 if (octal_buf[2] &&
    1052         237 :                                                     (octal_buf[0] > '3')) {
    1053             :                                                         /* 3 octit values must not overflow 0xFF (\377) */
    1054           1 :                                                         zend_error(E_COMPILE_WARNING, "Octal escape sequence overflow \\%s is greater than \\377", octal_buf);
    1055             :                                                 }
    1056             : 
    1057        1089 :                                                 *t++ = (char) ZEND_STRTOL(octal_buf, NULL, 8);
    1058             :                                         } else {
    1059         842 :                                                 *t++ = '\\';
    1060         842 :                                                 *t++ = *s;
    1061             :                                         }
    1062             :                                         break;
    1063             :                         }
    1064             :                 } else {
    1065     3684825 :                         *t++ = *s;
    1066             :                 }
    1067             : 
    1068     3751944 :                 if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) {
    1069       11716 :                         CG(zend_lineno)++;
    1070             :                 }
    1071     3751944 :                 s++;
    1072             :         }
    1073      225851 :         *t = 0;
    1074      225851 :         if (SCNG(output_filter)) {
    1075          11 :                 size_t sz = 0;
    1076             :                 unsigned char *str;
    1077             :                 // TODO: avoid realocation ???
    1078          11 :                 s = Z_STRVAL_P(zendlval);
    1079          11 :                 SCNG(output_filter)(&str, &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval));
    1080          11 :                 zval_ptr_dtor(zendlval);
    1081          22 :                 ZVAL_STRINGL(zendlval, (char *) str, sz);
    1082          11 :                 efree(str);
    1083             :         }
    1084      225851 :         return SUCCESS;
    1085             : }
    1086             : 
    1087             : static zend_always_inline int emit_token(int token, int token_line)
    1088             : {
    1089     8261893 :         if (SCNG(on_event)) {
    1090         160 :                 SCNG(on_event)(ON_TOKEN, token, token_line, SCNG(on_event_context));
    1091             :         }
    1092             : 
    1093     8261893 :         return token;
    1094             : }
    1095             : 
    1096             : #define RETURN_TOKEN(token) return emit_token(token, start_line);
    1097             : 
    1098     8261893 : int lex_scan(zval *zendlval)
    1099             : {
    1100             : 
    1101     8261893 : int start_line = CG(zend_lineno);
    1102             : 
    1103             : restart:
    1104     8262145 :         SCNG(yy_text) = YYCURSOR;
    1105             : 
    1106             : /*!re2c
    1107             : re2c:yyfill:check = 0;
    1108             : LNUM    [0-9]+
    1109             : DNUM    ([0-9]*"."[0-9]+)|([0-9]+"."[0-9]*)
    1110             : EXPONENT_DNUM   (({LNUM}|{DNUM})[eE][+-]?{LNUM})
    1111             : HNUM    "0x"[0-9a-fA-F]+
    1112             : BNUM    "0b"[01]+
    1113             : LABEL   [a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*
    1114             : WHITESPACE [ \n\r\t]+
    1115             : TABS_AND_SPACES [ \t]*
    1116             : TOKENS [;:,.\[\]()|^&+-/*=%!~$<>?@]
    1117             : ANY_CHAR [^]
    1118             : NEWLINE ("\r"|"\n"|"\r\n")
    1119             : 
    1120             : /* compute yyleng before each rule */
    1121             : <!*> := yyleng = YYCURSOR - SCNG(yy_text);
    1122             : 
    1123             : <ST_IN_SCRIPTING>"exit" {
    1124        1631 :         RETURN_TOKEN(T_EXIT);
    1125             : }
    1126             : 
    1127             : <ST_IN_SCRIPTING>"die" {
    1128       16476 :         RETURN_TOKEN(T_EXIT);
    1129             : }
    1130             : 
    1131             : <ST_IN_SCRIPTING>"function" {
    1132       41192 :         RETURN_TOKEN(T_FUNCTION);
    1133             : }
    1134             : 
    1135             : <ST_IN_SCRIPTING>"const" {
    1136         644 :         RETURN_TOKEN(T_CONST);
    1137             : }
    1138             : 
    1139             : <ST_IN_SCRIPTING>"return" {
    1140       47026 :         RETURN_TOKEN(T_RETURN);
    1141             : }
    1142             : 
    1143             : <ST_IN_SCRIPTING>"yield"{WHITESPACE}"from" {
    1144          42 :         HANDLE_NEWLINES(yytext, yyleng);
    1145          42 :         RETURN_TOKEN(T_YIELD_FROM);
    1146             : }
    1147             : 
    1148             : <ST_IN_SCRIPTING>"yield" {
    1149         269 :         RETURN_TOKEN(T_YIELD);
    1150             : }
    1151             : 
    1152             : <ST_IN_SCRIPTING>"try" {
    1153        3104 :         RETURN_TOKEN(T_TRY);
    1154             : }
    1155             : 
    1156             : <ST_IN_SCRIPTING>"catch" {
    1157        3020 :         RETURN_TOKEN(T_CATCH);
    1158             : }
    1159             : 
    1160             : <ST_IN_SCRIPTING>"finally" {
    1161         167 :         RETURN_TOKEN(T_FINALLY);
    1162             : }
    1163             : 
    1164             : <ST_IN_SCRIPTING>"throw" {
    1165         473 :         RETURN_TOKEN(T_THROW);
    1166             : }
    1167             : 
    1168             : <ST_IN_SCRIPTING>"if" {
    1169       82002 :         RETURN_TOKEN(T_IF);
    1170             : }
    1171             : 
    1172             : <ST_IN_SCRIPTING>"elseif" {
    1173        2263 :         RETURN_TOKEN(T_ELSEIF);
    1174             : }
    1175             : 
    1176             : <ST_IN_SCRIPTING>"endif" {
    1177          10 :         RETURN_TOKEN(T_ENDIF);
    1178             : }
    1179             : 
    1180             : <ST_IN_SCRIPTING>"else" {
    1181       21629 :         RETURN_TOKEN(T_ELSE);
    1182             : }
    1183             : 
    1184             : <ST_IN_SCRIPTING>"while" {
    1185        2633 :         RETURN_TOKEN(T_WHILE);
    1186             : }
    1187             : 
    1188             : <ST_IN_SCRIPTING>"endwhile" {
    1189           6 :         RETURN_TOKEN(T_ENDWHILE);
    1190             : }
    1191             : 
    1192             : <ST_IN_SCRIPTING>"do" {
    1193         320 :         RETURN_TOKEN(T_DO);
    1194             : }
    1195             : 
    1196             : <ST_IN_SCRIPTING>"for" {
    1197        2305 :         RETURN_TOKEN(T_FOR);
    1198             : }
    1199             : 
    1200             : <ST_IN_SCRIPTING>"endfor" {
    1201           8 :         RETURN_TOKEN(T_ENDFOR);
    1202             : }
    1203             : 
    1204             : <ST_IN_SCRIPTING>"foreach" {
    1205       12366 :         RETURN_TOKEN(T_FOREACH);
    1206             : }
    1207             : 
    1208             : <ST_IN_SCRIPTING>"endforeach" {
    1209           5 :         RETURN_TOKEN(T_ENDFOREACH);
    1210             : }
    1211             : 
    1212             : <ST_IN_SCRIPTING>"declare" {
    1213          81 :         RETURN_TOKEN(T_DECLARE);
    1214             : }
    1215             : 
    1216             : <ST_IN_SCRIPTING>"enddeclare" {
    1217           5 :         RETURN_TOKEN(T_ENDDECLARE);
    1218             : }
    1219             : 
    1220             : <ST_IN_SCRIPTING>"instanceof" {
    1221          81 :         RETURN_TOKEN(T_INSTANCEOF);
    1222             : }
    1223             : 
    1224             : <ST_IN_SCRIPTING>"as" {
    1225       12506 :         RETURN_TOKEN(T_AS);
    1226             : }
    1227             : 
    1228             : <ST_IN_SCRIPTING>"switch" {
    1229         524 :         RETURN_TOKEN(T_SWITCH);
    1230             : }
    1231             : 
    1232             : <ST_IN_SCRIPTING>"endswitch" {
    1233           6 :         RETURN_TOKEN(T_ENDSWITCH);
    1234             : }
    1235             : 
    1236             : <ST_IN_SCRIPTING>"case" {
    1237        1758 :         RETURN_TOKEN(T_CASE);
    1238             : }
    1239             : 
    1240             : <ST_IN_SCRIPTING>"default" {
    1241         314 :         RETURN_TOKEN(T_DEFAULT);
    1242             : }
    1243             : 
    1244             : <ST_IN_SCRIPTING>"break" {
    1245        2095 :         RETURN_TOKEN(T_BREAK);
    1246             : }
    1247             : 
    1248             : <ST_IN_SCRIPTING>"continue" {
    1249         319 :         RETURN_TOKEN(T_CONTINUE);
    1250             : }
    1251             : 
    1252             : <ST_IN_SCRIPTING>"goto" {
    1253          56 :         RETURN_TOKEN(T_GOTO);
    1254             : }
    1255             : 
    1256             : <ST_IN_SCRIPTING>"echo" {
    1257       35638 :         RETURN_TOKEN(T_ECHO);
    1258             : }
    1259             : 
    1260             : <ST_IN_SCRIPTING>"print" {
    1261        3601 :         RETURN_TOKEN(T_PRINT);
    1262             : }
    1263             : 
    1264             : <ST_IN_SCRIPTING>"class" {
    1265        7929 :         RETURN_TOKEN(T_CLASS);
    1266             : }
    1267             : 
    1268             : <ST_IN_SCRIPTING>"interface" {
    1269         229 :         RETURN_TOKEN(T_INTERFACE);
    1270             : }
    1271             : 
    1272             : <ST_IN_SCRIPTING>"trait" {
    1273         245 :         RETURN_TOKEN(T_TRAIT);
    1274             : }
    1275             : 
    1276             : <ST_IN_SCRIPTING>"extends" {
    1277        2571 :         RETURN_TOKEN(T_EXTENDS);
    1278             : }
    1279             : 
    1280             : <ST_IN_SCRIPTING>"implements" {
    1281         352 :         RETURN_TOKEN(T_IMPLEMENTS);
    1282             : }
    1283             : 
    1284             : <ST_IN_SCRIPTING>"->" {
    1285       50981 :         yy_push_state(ST_LOOKING_FOR_PROPERTY);
    1286       50981 :         RETURN_TOKEN(T_OBJECT_OPERATOR);
    1287             : }
    1288             : 
    1289             : <ST_IN_SCRIPTING,ST_LOOKING_FOR_PROPERTY>{WHITESPACE}+ {
    1290     2465178 :         HANDLE_NEWLINES(yytext, yyleng);
    1291     2465178 :         RETURN_TOKEN(T_WHITESPACE);
    1292             : }
    1293             : 
    1294             : <ST_LOOKING_FOR_PROPERTY>"->" {
    1295         115 :         RETURN_TOKEN(T_OBJECT_OPERATOR);
    1296             : }
    1297             : 
    1298             : <ST_LOOKING_FOR_PROPERTY>{LABEL} {
    1299       50848 :         yy_pop_state();
    1300      101696 :         zend_copy_value(zendlval, yytext, yyleng);
    1301       50848 :         RETURN_TOKEN(T_STRING);
    1302             : }
    1303             : 
    1304             : <ST_LOOKING_FOR_PROPERTY>{ANY_CHAR} {
    1305         247 :         yyless(0);
    1306         247 :         yy_pop_state();
    1307         247 :         goto restart;
    1308             : }
    1309             : 
    1310             : <ST_IN_SCRIPTING>"::" {
    1311       24441 :         RETURN_TOKEN(T_PAAMAYIM_NEKUDOTAYIM);
    1312             : }
    1313             : 
    1314             : <ST_IN_SCRIPTING>"\\" {
    1315         970 :         RETURN_TOKEN(T_NS_SEPARATOR);
    1316             : }
    1317             : 
    1318             : <ST_IN_SCRIPTING>"..." {
    1319         117 :         RETURN_TOKEN(T_ELLIPSIS);
    1320             : }
    1321             : 
    1322             : <ST_IN_SCRIPTING>"??" {
    1323          53 :         RETURN_TOKEN(T_COALESCE);
    1324             : }
    1325             : 
    1326             : <ST_IN_SCRIPTING>"new" {
    1327       15726 :         RETURN_TOKEN(T_NEW);
    1328             : }
    1329             : 
    1330             : <ST_IN_SCRIPTING>"clone" {
    1331         129 :         RETURN_TOKEN(T_CLONE);
    1332             : }
    1333             : 
    1334             : <ST_IN_SCRIPTING>"var" {
    1335         208 :         RETURN_TOKEN(T_VAR);
    1336             : }
    1337             : 
    1338             : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("int"|"integer"){TABS_AND_SPACES}")" {
    1339        4941 :         RETURN_TOKEN(T_INT_CAST);
    1340             : }
    1341             : 
    1342             : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("real"|"double"|"float"){TABS_AND_SPACES}")" {
    1343          86 :         RETURN_TOKEN(T_DOUBLE_CAST);
    1344             : }
    1345             : 
    1346             : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("string"|"binary"){TABS_AND_SPACES}")" {
    1347        1360 :         RETURN_TOKEN(T_STRING_CAST);
    1348             : }
    1349             : 
    1350             : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"array"{TABS_AND_SPACES}")" {
    1351          34 :         RETURN_TOKEN(T_ARRAY_CAST);
    1352             : }
    1353             : 
    1354             : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"object"{TABS_AND_SPACES}")" {
    1355         180 :         RETURN_TOKEN(T_OBJECT_CAST);
    1356             : }
    1357             : 
    1358             : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("bool"|"boolean"){TABS_AND_SPACES}")" {
    1359          78 :         RETURN_TOKEN(T_BOOL_CAST);
    1360             : }
    1361             : 
    1362             : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("unset"){TABS_AND_SPACES}")" {
    1363           1 :         RETURN_TOKEN(T_UNSET_CAST);
    1364             : }
    1365             : 
    1366             : <ST_IN_SCRIPTING>"eval" {
    1367        2579 :         RETURN_TOKEN(T_EVAL);
    1368             : }
    1369             : 
    1370             : <ST_IN_SCRIPTING>"include" {
    1371        2779 :         RETURN_TOKEN(T_INCLUDE);
    1372             : }
    1373             : 
    1374             : <ST_IN_SCRIPTING>"include_once" {
    1375         554 :         RETURN_TOKEN(T_INCLUDE_ONCE);
    1376             : }
    1377             : 
    1378             : <ST_IN_SCRIPTING>"require" {
    1379        2366 :         RETURN_TOKEN(T_REQUIRE);
    1380             : }
    1381             : 
    1382             : <ST_IN_SCRIPTING>"require_once" {
    1383        5802 :         RETURN_TOKEN(T_REQUIRE_ONCE);
    1384             : }
    1385             : 
    1386             : <ST_IN_SCRIPTING>"namespace" {
    1387         337 :         RETURN_TOKEN(T_NAMESPACE);
    1388             : }
    1389             : 
    1390             : <ST_IN_SCRIPTING>"use" {
    1391         551 :         RETURN_TOKEN(T_USE);
    1392             : }
    1393             : 
    1394             : <ST_IN_SCRIPTING>"insteadof" {
    1395          32 :     RETURN_TOKEN(T_INSTEADOF);
    1396             : }
    1397             : 
    1398             : <ST_IN_SCRIPTING>"global" {
    1399        4388 :         RETURN_TOKEN(T_GLOBAL);
    1400             : }
    1401             : 
    1402             : <ST_IN_SCRIPTING>"isset" {
    1403        5851 :         RETURN_TOKEN(T_ISSET);
    1404             : }
    1405             : 
    1406             : <ST_IN_SCRIPTING>"empty" {
    1407        8136 :         RETURN_TOKEN(T_EMPTY);
    1408             : }
    1409             : 
    1410             : <ST_IN_SCRIPTING>"__halt_compiler" {
    1411         284 :         RETURN_TOKEN(T_HALT_COMPILER);
    1412             : }
    1413             : 
    1414             : <ST_IN_SCRIPTING>"static" {
    1415       10930 :         RETURN_TOKEN(T_STATIC);
    1416             : }
    1417             : 
    1418             : <ST_IN_SCRIPTING>"abstract" {
    1419         191 :         RETURN_TOKEN(T_ABSTRACT);
    1420             : }
    1421             : 
    1422             : <ST_IN_SCRIPTING>"final" {
    1423          55 :         RETURN_TOKEN(T_FINAL);
    1424             : }
    1425             : 
    1426             : <ST_IN_SCRIPTING>"private" {
    1427        1285 :         RETURN_TOKEN(T_PRIVATE);
    1428             : }
    1429             : 
    1430             : <ST_IN_SCRIPTING>"protected" {
    1431         634 :         RETURN_TOKEN(T_PROTECTED);
    1432             : }
    1433             : 
    1434             : <ST_IN_SCRIPTING>"public" {
    1435        5154 :         RETURN_TOKEN(T_PUBLIC);
    1436             : }
    1437             : 
    1438             : <ST_IN_SCRIPTING>"unset" {
    1439        1608 :         RETURN_TOKEN(T_UNSET);
    1440             : }
    1441             : 
    1442             : <ST_IN_SCRIPTING>"=>" {
    1443       34655 :         RETURN_TOKEN(T_DOUBLE_ARROW);
    1444             : }
    1445             : 
    1446             : <ST_IN_SCRIPTING>"list" {
    1447         254 :         RETURN_TOKEN(T_LIST);
    1448             : }
    1449             : 
    1450             : <ST_IN_SCRIPTING>"array" {
    1451       28907 :         RETURN_TOKEN(T_ARRAY);
    1452             : }
    1453             : 
    1454             : <ST_IN_SCRIPTING>"callable" {
    1455          26 :         RETURN_TOKEN(T_CALLABLE);
    1456             : }
    1457             : 
    1458             : <ST_IN_SCRIPTING>"++" {
    1459        6521 :         RETURN_TOKEN(T_INC);
    1460             : }
    1461             : 
    1462             : <ST_IN_SCRIPTING>"--" {
    1463         200 :         RETURN_TOKEN(T_DEC);
    1464             : }
    1465             : 
    1466             : <ST_IN_SCRIPTING>"===" {
    1467        7350 :         RETURN_TOKEN(T_IS_IDENTICAL);
    1468             : }
    1469             : 
    1470             : <ST_IN_SCRIPTING>"!==" {
    1471        8998 :         RETURN_TOKEN(T_IS_NOT_IDENTICAL);
    1472             : }
    1473             : 
    1474             : <ST_IN_SCRIPTING>"==" {
    1475       17835 :         RETURN_TOKEN(T_IS_EQUAL);
    1476             : }
    1477             : 
    1478             : <ST_IN_SCRIPTING>"!="|"<>" {
    1479        3560 :         RETURN_TOKEN(T_IS_NOT_EQUAL);
    1480             : }
    1481             : 
    1482             : <ST_IN_SCRIPTING>"<=>" {
    1483          19 :         RETURN_TOKEN(T_SPACESHIP);
    1484             : }
    1485             : 
    1486             : <ST_IN_SCRIPTING>"<=" {
    1487        1780 :         RETURN_TOKEN(T_IS_SMALLER_OR_EQUAL);
    1488             : }
    1489             : 
    1490             : <ST_IN_SCRIPTING>">=" {
    1491         617 :         RETURN_TOKEN(T_IS_GREATER_OR_EQUAL);
    1492             : }
    1493             : 
    1494             : <ST_IN_SCRIPTING>"+=" {
    1495         735 :         RETURN_TOKEN(T_PLUS_EQUAL);
    1496             : }
    1497             : 
    1498             : <ST_IN_SCRIPTING>"-=" {
    1499         145 :         RETURN_TOKEN(T_MINUS_EQUAL);
    1500             : }
    1501             : 
    1502             : <ST_IN_SCRIPTING>"*=" {
    1503          20 :         RETURN_TOKEN(T_MUL_EQUAL);
    1504             : }
    1505             : 
    1506             : <ST_IN_SCRIPTING>"*\*" {
    1507          15 :         RETURN_TOKEN(T_POW);
    1508             : }
    1509             : 
    1510             : <ST_IN_SCRIPTING>"*\*=" {
    1511           7 :         RETURN_TOKEN(T_POW_EQUAL);
    1512             : }
    1513             : 
    1514             : <ST_IN_SCRIPTING>"/=" {
    1515           8 :         RETURN_TOKEN(T_DIV_EQUAL);
    1516             : }
    1517             : 
    1518             : <ST_IN_SCRIPTING>".=" {
    1519        3405 :         RETURN_TOKEN(T_CONCAT_EQUAL);
    1520             : }
    1521             : 
    1522             : <ST_IN_SCRIPTING>"%=" {
    1523           8 :         RETURN_TOKEN(T_MOD_EQUAL);
    1524             : }
    1525             : 
    1526             : <ST_IN_SCRIPTING>"<<=" {
    1527          10 :         RETURN_TOKEN(T_SL_EQUAL);
    1528             : }
    1529             : 
    1530             : <ST_IN_SCRIPTING>">>=" {
    1531          19 :         RETURN_TOKEN(T_SR_EQUAL);
    1532             : }
    1533             : 
    1534             : <ST_IN_SCRIPTING>"&=" {
    1535          10 :         RETURN_TOKEN(T_AND_EQUAL);
    1536             : }
    1537             : 
    1538             : <ST_IN_SCRIPTING>"|=" {
    1539         103 :         RETURN_TOKEN(T_OR_EQUAL);
    1540             : }
    1541             : 
    1542             : <ST_IN_SCRIPTING>"^=" {
    1543          11 :         RETURN_TOKEN(T_XOR_EQUAL);
    1544             : }
    1545             : 
    1546             : <ST_IN_SCRIPTING>"||" {
    1547        4847 :         RETURN_TOKEN(T_BOOLEAN_OR);
    1548             : }
    1549             : 
    1550             : <ST_IN_SCRIPTING>"&&" {
    1551        8272 :         RETURN_TOKEN(T_BOOLEAN_AND);
    1552             : }
    1553             : 
    1554             : <ST_IN_SCRIPTING>"OR" {
    1555         949 :         RETURN_TOKEN(T_LOGICAL_OR);
    1556             : }
    1557             : 
    1558             : <ST_IN_SCRIPTING>"AND" {
    1559          20 :         RETURN_TOKEN(T_LOGICAL_AND);
    1560             : }
    1561             : 
    1562             : <ST_IN_SCRIPTING>"XOR" {
    1563           8 :         RETURN_TOKEN(T_LOGICAL_XOR);
    1564             : }
    1565             : 
    1566             : <ST_IN_SCRIPTING>"<<" {
    1567         163 :         RETURN_TOKEN(T_SL);
    1568             : }
    1569             : 
    1570             : <ST_IN_SCRIPTING>">>" {
    1571          81 :         RETURN_TOKEN(T_SR);
    1572             : }
    1573             : 
    1574             : <ST_IN_SCRIPTING>{TOKENS} {
    1575     5359486 :         RETURN_TOKEN(yytext[0]);
    1576             : }
    1577             : 
    1578             : 
    1579             : <ST_IN_SCRIPTING>"{" {
    1580      144310 :         yy_push_state(ST_IN_SCRIPTING);
    1581      144310 :         RETURN_TOKEN('{');
    1582             : }
    1583             : 
    1584             : 
    1585             : <ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"${" {
    1586         404 :         yy_push_state(ST_LOOKING_FOR_VARNAME);
    1587         404 :         RETURN_TOKEN(T_DOLLAR_OPEN_CURLY_BRACES);
    1588             : }
    1589             : 
    1590             : 
    1591             : <ST_IN_SCRIPTING>"}" {
    1592      146462 :         RESET_DOC_COMMENT();
    1593      146450 :         if (!zend_stack_is_empty(&SCNG(state_stack))) {
    1594      146449 :                 yy_pop_state();
    1595             :         }
    1596      146450 :         RETURN_TOKEN('}');
    1597             : }
    1598             : 
    1599             : 
    1600             : <ST_LOOKING_FOR_VARNAME>{LABEL}[[}] {
    1601         400 :         yyless(yyleng - 1);
    1602         800 :         zend_copy_value(zendlval, yytext, yyleng);
    1603         400 :         yy_pop_state();
    1604         400 :         yy_push_state(ST_IN_SCRIPTING);
    1605         400 :         RETURN_TOKEN(T_STRING_VARNAME);
    1606             : }
    1607             : 
    1608             : 
    1609             : <ST_LOOKING_FOR_VARNAME>{ANY_CHAR} {
    1610           4 :         yyless(0);
    1611           4 :         yy_pop_state();
    1612           4 :         yy_push_state(ST_IN_SCRIPTING);
    1613           4 :         goto restart;
    1614             : }
    1615             : 
    1616             : <ST_IN_SCRIPTING>{BNUM} {
    1617          73 :         char *bin = yytext + 2; /* Skip "0b" */
    1618          73 :         int len = yyleng - 2;
    1619             :         char *end;
    1620             : 
    1621             :         /* Skip any leading 0s */
    1622         148 :         while (*bin == '0') {
    1623           2 :                 ++bin;
    1624           2 :                 --len;
    1625             :         }
    1626             : 
    1627          73 :         if (len < SIZEOF_ZEND_LONG * 8) {
    1628          68 :                 if (len == 0) {
    1629           1 :                         ZVAL_LONG(zendlval, 0);
    1630             :                 } else {
    1631          67 :                         errno = 0;
    1632          67 :                         ZVAL_LONG(zendlval, ZEND_STRTOL(bin, &end, 2));
    1633             :                         ZEND_ASSERT(!errno && end == yytext + yyleng);
    1634             :                 }
    1635          68 :                 RETURN_TOKEN(T_LNUMBER);
    1636             :         } else {
    1637           5 :                 ZVAL_DOUBLE(zendlval, zend_bin_strtod(bin, (const char **)&end));
    1638             :                 /* errno isn't checked since we allow HUGE_VAL/INF overflow */
    1639             :                 ZEND_ASSERT(end == yytext + yyleng);
    1640           5 :                 RETURN_TOKEN(T_DNUMBER);
    1641             :         }
    1642             : }
    1643             : 
    1644             : <ST_IN_SCRIPTING>{LNUM} {
    1645             :         char *end;
    1646      177603 :         if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */
    1647      177421 :                 errno = 0;
    1648      177421 :                 ZVAL_LONG(zendlval, ZEND_STRTOL(yytext, &end, 0));
    1649             :                 /* This isn't an assert, we need to ensure 019 isn't valid octal
    1650             :                  * Because the lexing itself doesn't do that for us
    1651             :                  */
    1652      177421 :                 if (end != yytext + yyleng) {
    1653          11 :                         zend_throw_exception(zend_ce_parse_error, "Invalid numeric literal", 0);
    1654          11 :                         ZVAL_UNDEF(zendlval);
    1655          11 :                         RETURN_TOKEN(T_LNUMBER);
    1656             :                 }
    1657             :         } else {
    1658         182 :                 errno = 0;
    1659         182 :                 ZVAL_LONG(zendlval, ZEND_STRTOL(yytext, &end, 0));
    1660         182 :                 if (errno == ERANGE) { /* Overflow */
    1661          43 :                         errno = 0;
    1662          43 :                         if (yytext[0] == '0') { /* octal overflow */
    1663           1 :                                 errno = 0;
    1664           1 :                                 ZVAL_DOUBLE(zendlval, zend_oct_strtod(yytext, (const char **)&end));
    1665             :                         } else {
    1666          42 :                                 ZVAL_DOUBLE(zendlval, zend_strtod(yytext, (const char **)&end));
    1667             :                         }
    1668             :                         /* Also not an assert for the same reason */
    1669          43 :                         if (end != yytext + yyleng) {
    1670           0 :                                 zend_throw_exception(zend_ce_parse_error,
    1671             :                                         "Invalid numeric literal", 0);
    1672           0 :                                 ZVAL_UNDEF(zendlval);
    1673           0 :                                 RETURN_TOKEN(T_DNUMBER);
    1674             :                         }
    1675             :                         ZEND_ASSERT(!errno);
    1676          43 :                         RETURN_TOKEN(T_DNUMBER);
    1677             :                 }
    1678             :                 /* Also not an assert for the same reason */
    1679         139 :                 if (end != yytext + yyleng) {
    1680           0 :                         zend_throw_exception(zend_ce_parse_error, "Invalid numeric literal", 0);
    1681           0 :                         ZVAL_UNDEF(zendlval);
    1682           0 :                         RETURN_TOKEN(T_DNUMBER);
    1683             :                 }
    1684             :         }
    1685             :         ZEND_ASSERT(!errno);
    1686      177549 :         RETURN_TOKEN(T_LNUMBER);
    1687             : }
    1688             : 
    1689             : <ST_IN_SCRIPTING>{HNUM} {
    1690        3316 :         char *hex = yytext + 2; /* Skip "0x" */
    1691        3316 :         int len = yyleng - 2;
    1692             :         char *end;
    1693             : 
    1694             :         /* Skip any leading 0s */
    1695        8250 :         while (*hex == '0') {
    1696        1618 :                 hex++;
    1697        1618 :                 len--;
    1698             :         }
    1699             : 
    1700        3316 :         if (len < SIZEOF_ZEND_LONG * 2 || (len == SIZEOF_ZEND_LONG * 2 && *hex <= '7')) {
    1701        3308 :                 if (len == 0) {
    1702          62 :                         ZVAL_LONG(zendlval, 0);
    1703             :                 } else {
    1704        3246 :                         errno = 0;
    1705        3246 :                         ZVAL_LONG(zendlval, ZEND_STRTOL(hex, &end, 16));
    1706             :                         ZEND_ASSERT(!errno && end == hex + len);
    1707             :                 }
    1708        3308 :                 RETURN_TOKEN(T_LNUMBER);
    1709             :         } else {
    1710           8 :                 ZVAL_DOUBLE(zendlval, zend_hex_strtod(hex, (const char **)&end));
    1711             :                 /* errno isn't checked since we allow HUGE_VAL/INF overflow */
    1712             :                 ZEND_ASSERT(end == hex + len);
    1713           8 :                 RETURN_TOKEN(T_DNUMBER);
    1714             :         }
    1715             : }
    1716             : 
    1717             : <ST_VAR_OFFSET>[0]|([1-9][0-9]*) { /* Offset could be treated as a long */
    1718         838 :         if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) {
    1719             :                 char *end;
    1720         419 :                 errno = 0;
    1721         419 :                 ZVAL_LONG(zendlval, ZEND_STRTOL(yytext, &end, 10));
    1722         419 :                 if (errno == ERANGE) {
    1723           0 :                         goto string;
    1724             :                 }
    1725             :                 ZEND_ASSERT(end == yytext + yyleng);
    1726             :         } else {
    1727             : string:
    1728           0 :                 ZVAL_STRINGL(zendlval, yytext, yyleng);
    1729             :         }
    1730         419 :         RETURN_TOKEN(T_NUM_STRING);
    1731             : }
    1732             : 
    1733             : <ST_VAR_OFFSET>{LNUM}|{HNUM}|{BNUM} { /* Offset must be treated as a string */
    1734           0 :         ZVAL_STRINGL(zendlval, yytext, yyleng);
    1735           0 :         RETURN_TOKEN(T_NUM_STRING);
    1736             : }
    1737             : 
    1738             : <ST_IN_SCRIPTING>{DNUM}|{EXPONENT_DNUM} {
    1739             :         const char *end;
    1740             : 
    1741        6717 :         ZVAL_DOUBLE(zendlval, zend_strtod(yytext, &end));
    1742             :         /* errno isn't checked since we allow HUGE_VAL/INF overflow */
    1743             :         ZEND_ASSERT(end == yytext + yyleng);
    1744        6717 :         RETURN_TOKEN(T_DNUMBER);
    1745             : }
    1746             : 
    1747             : <ST_IN_SCRIPTING>"__CLASS__" {
    1748         108 :         RETURN_TOKEN(T_CLASS_C);
    1749             : }
    1750             : 
    1751             : <ST_IN_SCRIPTING>"__TRAIT__" {
    1752          11 :         RETURN_TOKEN(T_TRAIT_C);
    1753             : }
    1754             : 
    1755             : <ST_IN_SCRIPTING>"__FUNCTION__" {
    1756         139 :         RETURN_TOKEN(T_FUNC_C);
    1757             : }
    1758             : 
    1759             : <ST_IN_SCRIPTING>"__METHOD__" {
    1760         993 :         RETURN_TOKEN(T_METHOD_C);
    1761             : }
    1762             : 
    1763             : <ST_IN_SCRIPTING>"__LINE__" {
    1764          31 :         RETURN_TOKEN(T_LINE);
    1765             : }
    1766             : 
    1767             : <ST_IN_SCRIPTING>"__FILE__" {
    1768       10064 :         RETURN_TOKEN(T_FILE);
    1769             : }
    1770             : 
    1771             : <ST_IN_SCRIPTING>"__DIR__" {
    1772         950 :         RETURN_TOKEN(T_DIR);
    1773             : }
    1774             : 
    1775             : <ST_IN_SCRIPTING>"__NAMESPACE__" {
    1776          41 :         RETURN_TOKEN(T_NS_C);
    1777             : }
    1778             : 
    1779             : 
    1780             : <INITIAL>"<?=" {
    1781           4 :         BEGIN(ST_IN_SCRIPTING);
    1782           4 :         RETURN_TOKEN(T_OPEN_TAG_WITH_ECHO);
    1783             : }
    1784             : 
    1785             : 
    1786             : <INITIAL>"<?php"([ \t]|{NEWLINE}) {
    1787       34672 :         HANDLE_NEWLINE(yytext[yyleng-1]);
    1788       34672 :         BEGIN(ST_IN_SCRIPTING);
    1789       34672 :         RETURN_TOKEN(T_OPEN_TAG);
    1790             : }
    1791             : 
    1792             : 
    1793             : <INITIAL>"<?" {
    1794           4 :         if (CG(short_tags)) {
    1795           3 :                 BEGIN(ST_IN_SCRIPTING);
    1796           3 :                 RETURN_TOKEN(T_OPEN_TAG);
    1797             :         } else {
    1798           1 :                 goto inline_char_handler;
    1799             :         }
    1800             : }
    1801             : 
    1802             : <INITIAL>{ANY_CHAR} {
    1803       35467 :         if (YYCURSOR > YYLIMIT) {
    1804       31361 :                 RETURN_TOKEN(END);
    1805             :         }
    1806             : 
    1807             : inline_char_handler:
    1808             : 
    1809             :         while (1) {
    1810        4510 :                 YYCTYPE *ptr = memchr(YYCURSOR, '<', YYLIMIT - YYCURSOR);
    1811             : 
    1812        4510 :                 YYCURSOR = ptr ? ptr + 1 : YYLIMIT;
    1813             : 
    1814        4510 :                 if (YYCURSOR >= YYLIMIT) {
    1815        3879 :                         break;
    1816             :                 }
    1817             : 
    1818         631 :                 if (*YYCURSOR == '?') {
    1819         229 :                         if (CG(short_tags) || !strncasecmp((char*)YYCURSOR + 1, "php", 3) || (*(YYCURSOR + 1) == '=')) { /* Assume [ \t\n\r] follows "php" */
    1820             : 
    1821         228 :                                 YYCURSOR--;
    1822         228 :                                 break;
    1823             :                         }
    1824             :                 }
    1825         403 :         }
    1826             : 
    1827        4107 :         yyleng = YYCURSOR - SCNG(yy_text);
    1828             : 
    1829        4107 :         if (SCNG(output_filter)) {
    1830             :                 size_t readsize;
    1831           1 :                 char *s = NULL;
    1832           1 :                 size_t sz = 0;
    1833             :                 // TODO: avoid reallocation ???
    1834           1 :                 readsize = SCNG(output_filter)((unsigned char **)&s, &sz, (unsigned char *)yytext, (size_t)yyleng);
    1835           2 :                 ZVAL_STRINGL(zendlval, s, sz);
    1836           1 :                 efree(s);
    1837           1 :                 if (readsize < yyleng) {
    1838           0 :                         yyless(readsize);
    1839             :                 }
    1840             :         } else {
    1841        8212 :           ZVAL_STRINGL(zendlval, yytext, yyleng);
    1842             :         }
    1843        4107 :         HANDLE_NEWLINES(yytext, yyleng);
    1844        4107 :         RETURN_TOKEN(T_INLINE_HTML);
    1845             : }
    1846             : 
    1847             : 
    1848             : /* Make sure a label character follows "->", otherwise there is no property
    1849             :  * and "->" will be taken literally
    1850             :  */
    1851             : <ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE>"$"{LABEL}"->"[a-zA-Z_\x80-\xff] {
    1852         115 :         yyless(yyleng - 3);
    1853         115 :         yy_push_state(ST_LOOKING_FOR_PROPERTY);
    1854         230 :         zend_copy_value(zendlval, (yytext+1), (yyleng-1));
    1855         115 :         RETURN_TOKEN(T_VARIABLE);
    1856             : }
    1857             : 
    1858             : /* A [ always designates a variable offset, regardless of what follows
    1859             :  */
    1860             : <ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE>"$"{LABEL}"[" {
    1861        1023 :         yyless(yyleng - 1);
    1862        1023 :         yy_push_state(ST_VAR_OFFSET);
    1863        2046 :         zend_copy_value(zendlval, (yytext+1), (yyleng-1));
    1864        1023 :         RETURN_TOKEN(T_VARIABLE);
    1865             : }
    1866             : 
    1867             : <ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>"$"{LABEL} {
    1868     1626126 :         zend_copy_value(zendlval, (yytext+1), (yyleng-1));
    1869      813063 :         RETURN_TOKEN(T_VARIABLE);
    1870             : }
    1871             : 
    1872             : <ST_VAR_OFFSET>"]" {
    1873        1021 :         yy_pop_state();
    1874        1021 :         RETURN_TOKEN(']');
    1875             : }
    1876             : 
    1877             : <ST_VAR_OFFSET>{TOKENS}|[{}"`] {
    1878             :         /* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */
    1879        2046 :         RETURN_TOKEN(yytext[0]);
    1880             : }
    1881             : 
    1882             : <ST_VAR_OFFSET>[ \n\r\t\\'#] {
    1883             :         /* Invalid rule to return a more explicit parse error with proper line number */
    1884           2 :         yyless(0);
    1885           2 :         yy_pop_state();
    1886           2 :         ZVAL_NULL(zendlval);
    1887           2 :         RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
    1888             : }
    1889             : 
    1890             : <ST_IN_SCRIPTING,ST_VAR_OFFSET>{LABEL} {
    1891     1012296 :         zend_copy_value(zendlval, yytext, yyleng);
    1892      506148 :         RETURN_TOKEN(T_STRING);
    1893             : }
    1894             : 
    1895             : 
    1896             : <ST_IN_SCRIPTING>"#"|"//" {
    1897     1765669 :         while (YYCURSOR < YYLIMIT) {
    1898     1711845 :                 switch (*YYCURSOR++) {
    1899             :                         case '\r':
    1900         138 :                                 if (*YYCURSOR == '\n') {
    1901         138 :                                         YYCURSOR++;
    1902             :                                 }
    1903             :                                 /* fall through */
    1904             :                         case '\n':
    1905       53812 :                                 CG(zend_lineno)++;
    1906       53812 :                                 break;
    1907             :                         case '?':
    1908         595 :                                 if (*YYCURSOR == '>') {
    1909           2 :                                         YYCURSOR--;
    1910           2 :                                         break;
    1911             :                                 }
    1912             :                                 /* fall through */
    1913             :                         default:
    1914     1658031 :                                 continue;
    1915             :                 }
    1916             : 
    1917       53814 :                 break;
    1918             :         }
    1919             : 
    1920       53819 :         yyleng = YYCURSOR - SCNG(yy_text);
    1921             : 
    1922       53819 :         RETURN_TOKEN(T_COMMENT);
    1923             : }
    1924             : 
    1925             : <ST_IN_SCRIPTING>"/*"|"/**"{WHITESPACE} {
    1926             :         int doc_com;
    1927             : 
    1928       27055 :         if (yyleng > 2) {
    1929        2728 :                 doc_com = 1;
    1930        2781 :                 RESET_DOC_COMMENT();
    1931             :         } else {
    1932       24327 :                 doc_com = 0;
    1933             :         }
    1934             : 
    1935     4114622 :         while (YYCURSOR < YYLIMIT) {
    1936     4087566 :                 if (*YYCURSOR++ == '*' && *YYCURSOR == '/') {
    1937       27054 :                         break;
    1938             :                 }
    1939             :         }
    1940             : 
    1941       27055 :         if (YYCURSOR < YYLIMIT) {
    1942       27054 :                 YYCURSOR++;
    1943             :         } else {
    1944           1 :                 zend_error(E_COMPILE_WARNING, "Unterminated comment starting line %d", CG(zend_lineno));
    1945             :         }
    1946             : 
    1947       27055 :         yyleng = YYCURSOR - SCNG(yy_text);
    1948       27055 :         HANDLE_NEWLINES(yytext, yyleng);
    1949             : 
    1950       27055 :         if (doc_com) {
    1951        5456 :                 CG(doc_comment) = zend_string_init(yytext, yyleng, 0);
    1952        2728 :                 RETURN_TOKEN(T_DOC_COMMENT);
    1953             :         }
    1954             : 
    1955       24327 :         RETURN_TOKEN(T_COMMENT);
    1956             : }
    1957             : 
    1958             : <ST_IN_SCRIPTING>"?>"{NEWLINE}? {
    1959       31885 :         BEGIN(INITIAL);
    1960       31885 :         RETURN_TOKEN(T_CLOSE_TAG);  /* implicit ';' at php-end tag */
    1961             : }
    1962             : 
    1963             : 
    1964             : <ST_IN_SCRIPTING>b?['] {
    1965             :         register char *s, *t;
    1966             :         char *end;
    1967      205672 :         int bprefix = (yytext[0] != '\'') ? 1 : 0;
    1968             : 
    1969             :         while (1) {
    1970     2463287 :                 if (YYCURSOR < YYLIMIT) {
    1971     2463287 :                         if (*YYCURSOR == '\'') {
    1972      205672 :                                 YYCURSOR++;
    1973      205672 :                                 yyleng = YYCURSOR - SCNG(yy_text);
    1974             : 
    1975      205672 :                                 break;
    1976     2257615 :                         } else if (*YYCURSOR++ == '\\' && YYCURSOR < YYLIMIT) {
    1977       14632 :                                 YYCURSOR++;
    1978             :                         }
    1979             :                 } else {
    1980           0 :                         yyleng = YYLIMIT - SCNG(yy_text);
    1981             : 
    1982             :                         /* Unclosed single quotes; treat similar to double quotes, but without a separate token
    1983             :                          * for ' (unrecognized by parser), instead of old flex fallback to "Unexpected character..."
    1984             :                          * rule, which continued in ST_IN_SCRIPTING state after the quote */
    1985           0 :                         ZVAL_NULL(zendlval);
    1986           0 :                         RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
    1987             :                 }
    1988     2257615 :         }
    1989             : 
    1990      411344 :         ZVAL_STRINGL(zendlval, yytext+bprefix+1, yyleng-bprefix-2);
    1991             : 
    1992             :         /* convert escape sequences */
    1993      205672 :         s = t = Z_STRVAL_P(zendlval);
    1994      205672 :         end = s+Z_STRLEN_P(zendlval);
    1995     2668959 :         while (s<end) {
    1996     2257615 :                 if (*s=='\\') {
    1997       14632 :                         s++;
    1998             : 
    1999       14632 :                         switch(*s) {
    2000             :                                 case '\\':
    2001             :                                 case '\'':
    2002        2265 :                                         *t++ = *s;
    2003        2265 :                                         Z_STRLEN_P(zendlval)--;
    2004        2265 :                                         break;
    2005             :                                 default:
    2006       12367 :                                         *t++ = '\\';
    2007       12367 :                                         *t++ = *s;
    2008             :                                         break;
    2009             :                         }
    2010             :                 } else {
    2011     2242983 :                         *t++ = *s;
    2012             :                 }
    2013             : 
    2014     2257615 :                 if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) {
    2015        2593 :                         CG(zend_lineno)++;
    2016             :                 }
    2017     2257615 :                 s++;
    2018             :         }
    2019      205672 :         *t = 0;
    2020             : 
    2021      205672 :         if (SCNG(output_filter)) {
    2022           0 :                 size_t sz = 0;
    2023           0 :                 char *str = NULL;
    2024           0 :                 s = Z_STRVAL_P(zendlval);
    2025             :                 // TODO: avoid reallocation ???
    2026           0 :                 SCNG(output_filter)((unsigned char **)&str, &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval));
    2027           0 :                 ZVAL_STRINGL(zendlval, str, sz);
    2028             :         }
    2029      205672 :         RETURN_TOKEN(T_CONSTANT_ENCAPSED_STRING);
    2030             : }
    2031             : 
    2032             : 
    2033             : <ST_IN_SCRIPTING>b?["] {
    2034      209933 :         int bprefix = (yytext[0] != '"') ? 1 : 0;
    2035             : 
    2036     3715704 :         while (YYCURSOR < YYLIMIT) {
    2037     3505769 :                 switch (*YYCURSOR++) {
    2038             :                         case '"':
    2039      190144 :                                 yyleng = YYCURSOR - SCNG(yy_text);
    2040      190144 :                                 zend_scan_escape_string(zendlval, yytext+bprefix+1, yyleng-bprefix-2, '"');
    2041      190144 :                                 RETURN_TOKEN(T_CONSTANT_ENCAPSED_STRING);
    2042             :                         case '$':
    2043       19229 :                                 if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
    2044             :                                         break;
    2045             :                                 }
    2046         460 :                                 continue;
    2047             :                         case '{':
    2048        1228 :                                 if (*YYCURSOR == '$') {
    2049        1018 :                                         break;
    2050             :                                 }
    2051         210 :                                 continue;
    2052             :                         case '\\':
    2053       57330 :                                 if (YYCURSOR < YYLIMIT) {
    2054       57330 :                                         YYCURSOR++;
    2055             :                                 }
    2056             :                                 /* fall through */
    2057             :                         default:
    2058     3295168 :                                 continue;
    2059             :                 }
    2060             : 
    2061       19787 :                 YYCURSOR--;
    2062       19787 :                 break;
    2063             :         }
    2064             : 
    2065             :         /* Remember how much was scanned to save rescanning */
    2066       19789 :         SET_DOUBLE_QUOTES_SCANNED_LENGTH(YYCURSOR - SCNG(yy_text) - yyleng);
    2067             : 
    2068       19789 :         YYCURSOR = SCNG(yy_text) + yyleng;
    2069             : 
    2070       19789 :         BEGIN(ST_DOUBLE_QUOTES);
    2071       19789 :         RETURN_TOKEN('"');
    2072             : }
    2073             : 
    2074             : 
    2075             : <ST_IN_SCRIPTING>b?"<<<"{TABS_AND_SPACES}({LABEL}|([']{LABEL}['])|(["]{LABEL}["])){NEWLINE} {
    2076             :         char *s;
    2077        1616 :         int bprefix = (yytext[0] != '<') ? 1 : 0;
    2078        1616 :         zend_heredoc_label *heredoc_label = emalloc(sizeof(zend_heredoc_label));
    2079             : 
    2080        1616 :         CG(zend_lineno)++;
    2081        1616 :         heredoc_label->length = yyleng-bprefix-3-1-(yytext[yyleng-2]=='\r'?1:0);
    2082        1616 :         s = yytext+bprefix+3;
    2083        3268 :         while ((*s == ' ') || (*s == '\t')) {
    2084          36 :                 s++;
    2085          36 :                 heredoc_label->length--;
    2086             :         }
    2087             : 
    2088        1616 :         if (*s == '\'') {
    2089         122 :                 s++;
    2090         122 :                 heredoc_label->length -= 2;
    2091             : 
    2092         122 :                 BEGIN(ST_NOWDOC);
    2093             :         } else {
    2094        1494 :                 if (*s == '"') {
    2095           7 :                         s++;
    2096           7 :                         heredoc_label->length -= 2;
    2097             :                 }
    2098             : 
    2099        1494 :                 BEGIN(ST_HEREDOC);
    2100             :         }
    2101             : 
    2102        1616 :         heredoc_label->label = estrndup(s, heredoc_label->length);
    2103             : 
    2104             :         /* Check for ending label on the next line */
    2105        1616 :         if (heredoc_label->length < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, s, heredoc_label->length)) {
    2106          65 :                 YYCTYPE *end = YYCURSOR + heredoc_label->length;
    2107             : 
    2108          65 :                 if (*end == ';') {
    2109          59 :                         end++;
    2110             :                 }
    2111             : 
    2112          65 :                 if (*end == '\n' || *end == '\r') {
    2113          61 :                         BEGIN(ST_END_HEREDOC);
    2114             :                 }
    2115             :         }
    2116             : 
    2117             :         zend_ptr_stack_push(&SCNG(heredoc_label_stack), (void *) heredoc_label);
    2118             : 
    2119        1616 :         RETURN_TOKEN(T_START_HEREDOC);
    2120             : }
    2121             : 
    2122             : 
    2123             : <ST_IN_SCRIPTING>[`] {
    2124         125 :         BEGIN(ST_BACKQUOTE);
    2125         125 :         RETURN_TOKEN('`');
    2126             : }
    2127             : 
    2128             : 
    2129             : <ST_END_HEREDOC>{ANY_CHAR} {
    2130        1613 :         zend_heredoc_label *heredoc_label = zend_ptr_stack_pop(&SCNG(heredoc_label_stack));
    2131             : 
    2132        1613 :         YYCURSOR += heredoc_label->length - 1;
    2133        1613 :         yyleng = heredoc_label->length;
    2134             : 
    2135        1613 :         heredoc_label_dtor(heredoc_label);
    2136        1613 :         efree(heredoc_label);
    2137             : 
    2138        1613 :         BEGIN(ST_IN_SCRIPTING);
    2139        1613 :         RETURN_TOKEN(T_END_HEREDOC);
    2140             : }
    2141             : 
    2142             : 
    2143             : <ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"{$" {
    2144        1766 :         Z_LVAL_P(zendlval) = (zend_long) '{';
    2145        1766 :         yy_push_state(ST_IN_SCRIPTING);
    2146        1766 :         yyless(1);
    2147        1766 :         RETURN_TOKEN(T_CURLY_OPEN);
    2148             : }
    2149             : 
    2150             : 
    2151             : <ST_DOUBLE_QUOTES>["] {
    2152       19786 :         BEGIN(ST_IN_SCRIPTING);
    2153       19786 :         RETURN_TOKEN('"');
    2154             : }
    2155             : 
    2156             : <ST_BACKQUOTE>[`] {
    2157         125 :         BEGIN(ST_IN_SCRIPTING);
    2158         125 :         RETURN_TOKEN('`');
    2159             : }
    2160             : 
    2161             : 
    2162             : <ST_DOUBLE_QUOTES>{ANY_CHAR} {
    2163       33567 :         if (GET_DOUBLE_QUOTES_SCANNED_LENGTH()) {
    2164       14295 :                 YYCURSOR += GET_DOUBLE_QUOTES_SCANNED_LENGTH() - 1;
    2165       14295 :                 SET_DOUBLE_QUOTES_SCANNED_LENGTH(0);
    2166             : 
    2167       14295 :                 goto double_quotes_scan_done;
    2168             :         }
    2169             : 
    2170       19272 :         if (YYCURSOR > YYLIMIT) {
    2171           1 :                 RETURN_TOKEN(END);
    2172             :         }
    2173       19271 :         if (yytext[0] == '\\' && YYCURSOR < YYLIMIT) {
    2174        2745 :                 YYCURSOR++;
    2175             :         }
    2176             : 
    2177      128146 :         while (YYCURSOR < YYLIMIT) {
    2178      108875 :                 switch (*YYCURSOR++) {
    2179             :                         case '"':
    2180       11427 :                                 break;
    2181             :                         case '$':
    2182        7177 :                                 if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
    2183             :                                         break;
    2184             :                                 }
    2185           3 :                                 continue;
    2186             :                         case '{':
    2187         693 :                                 if (*YYCURSOR == '$') {
    2188         670 :                                         break;
    2189             :                                 }
    2190          23 :                                 continue;
    2191             :                         case '\\':
    2192        6342 :                                 if (YYCURSOR < YYLIMIT) {
    2193        6342 :                                         YYCURSOR++;
    2194             :                                 }
    2195             :                                 /* fall through */
    2196             :                         default:
    2197       89578 :                                 continue;
    2198             :                 }
    2199             : 
    2200       19271 :                 YYCURSOR--;
    2201       19271 :                 break;
    2202             :         }
    2203             : 
    2204             : double_quotes_scan_done:
    2205       33566 :         yyleng = YYCURSOR - SCNG(yy_text);
    2206             : 
    2207       33566 :         zend_scan_escape_string(zendlval, yytext, yyleng, '"');
    2208       33566 :         RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
    2209             : }
    2210             : 
    2211             : 
    2212             : <ST_BACKQUOTE>{ANY_CHAR} {
    2213         206 :         if (YYCURSOR > YYLIMIT) {
    2214           0 :                 RETURN_TOKEN(END);
    2215             :         }
    2216         206 :         if (yytext[0] == '\\' && YYCURSOR < YYLIMIT) {
    2217           0 :                 YYCURSOR++;
    2218             :         }
    2219             : 
    2220        2838 :         while (YYCURSOR < YYLIMIT) {
    2221        2632 :                 switch (*YYCURSOR++) {
    2222             :                         case '`':
    2223         108 :                                 break;
    2224             :                         case '$':
    2225          98 :                                 if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
    2226             :                                         break;
    2227             :                                 }
    2228           0 :                                 continue;
    2229             :                         case '{':
    2230           4 :                                 if (*YYCURSOR == '$') {
    2231           0 :                                         break;
    2232             :                                 }
    2233           4 :                                 continue;
    2234             :                         case '\\':
    2235           7 :                                 if (YYCURSOR < YYLIMIT) {
    2236           7 :                                         YYCURSOR++;
    2237             :                                 }
    2238             :                                 /* fall through */
    2239             :                         default:
    2240        2422 :                                 continue;
    2241             :                 }
    2242             : 
    2243         206 :                 YYCURSOR--;
    2244         206 :                 break;
    2245             :         }
    2246             : 
    2247         206 :         yyleng = YYCURSOR - SCNG(yy_text);
    2248             : 
    2249         206 :         zend_scan_escape_string(zendlval, yytext, yyleng, '`');
    2250         206 :         RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
    2251             : }
    2252             : 
    2253             : 
    2254             : <ST_HEREDOC>{ANY_CHAR} {
    2255        1948 :         int newline = 0;
    2256             : 
    2257        1948 :         zend_heredoc_label *heredoc_label = zend_ptr_stack_top(&SCNG(heredoc_label_stack));
    2258             : 
    2259        1948 :         if (YYCURSOR > YYLIMIT) {
    2260           1 :                 RETURN_TOKEN(END);
    2261             :         }
    2262             : 
    2263        1947 :         YYCURSOR--;
    2264             : 
    2265      355189 :         while (YYCURSOR < YYLIMIT) {
    2266      353241 :                 switch (*YYCURSOR++) {
    2267             :                         case '\r':
    2268           0 :                                 if (*YYCURSOR == '\n') {
    2269           0 :                                         YYCURSOR++;
    2270             :                                 }
    2271             :                                 /* fall through */
    2272             :                         case '\n':
    2273             :                                 /* Check for ending label on the next line */
    2274       10645 :                                 if (IS_LABEL_START(*YYCURSOR) && heredoc_label->length < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, heredoc_label->label, heredoc_label->length)) {
    2275        1439 :                                         YYCTYPE *end = YYCURSOR + heredoc_label->length;
    2276             : 
    2277        1439 :                                         if (*end == ';') {
    2278        1372 :                                                 end++;
    2279             :                                         }
    2280             : 
    2281        1439 :                                         if (*end == '\n' || *end == '\r') {
    2282             :                                                 /* newline before label will be subtracted from returned text, but
    2283             :                                                  * yyleng/yytext will include it, for zend_highlight/strip, tokenizer, etc. */
    2284        1435 :                                                 if (YYCURSOR[-2] == '\r' && YYCURSOR[-1] == '\n') {
    2285           0 :                                                         newline = 2; /* Windows newline */
    2286             :                                                 } else {
    2287        1435 :                                                         newline = 1;
    2288             :                                                 }
    2289             : 
    2290        1435 :                                                 CG(increment_lineno) = 1; /* For newline before label */
    2291        1435 :                                                 BEGIN(ST_END_HEREDOC);
    2292             : 
    2293        1435 :                                                 goto heredoc_scan_done;
    2294             :                                         }
    2295             :                                 }
    2296        9210 :                                 continue;
    2297             :                         case '$':
    2298         529 :                                 if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
    2299             :                                         break;
    2300             :                                 }
    2301          79 :                                 continue;
    2302             :                         case '{':
    2303         116 :                                 if (*YYCURSOR == '$') {
    2304          61 :                                         break;
    2305             :                                 }
    2306          55 :                                 continue;
    2307             :                         case '\\':
    2308         711 :                                 if (YYCURSOR < YYLIMIT && *YYCURSOR != '\n' && *YYCURSOR != '\r') {
    2309         703 :                                         YYCURSOR++;
    2310             :                                 }
    2311             :                                 /* fall through */
    2312             :                         default:
    2313      341951 :                                 continue;
    2314             :                 }
    2315             : 
    2316         511 :                 YYCURSOR--;
    2317         511 :                 break;
    2318             :         }
    2319             : 
    2320             : heredoc_scan_done:
    2321        1947 :         yyleng = YYCURSOR - SCNG(yy_text);
    2322             : 
    2323        1947 :         zend_scan_escape_string(zendlval, yytext, yyleng - newline, 0);
    2324        1947 :         RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
    2325             : }
    2326             : 
    2327             : 
    2328             : <ST_NOWDOC>{ANY_CHAR} {
    2329         117 :         int newline = 0;
    2330             : 
    2331         117 :         zend_heredoc_label *heredoc_label = zend_ptr_stack_top(&SCNG(heredoc_label_stack));
    2332             : 
    2333         117 :         if (YYCURSOR > YYLIMIT) {
    2334           0 :                 RETURN_TOKEN(END);
    2335             :         }
    2336             : 
    2337         117 :         YYCURSOR--;
    2338             : 
    2339       37344 :         while (YYCURSOR < YYLIMIT) {
    2340       37227 :                 switch (*YYCURSOR++) {
    2341             :                         case '\r':
    2342           0 :                                 if (*YYCURSOR == '\n') {
    2343           0 :                                         YYCURSOR++;
    2344             :                                 }
    2345             :                                 /* fall through */
    2346             :                         case '\n':
    2347             :                                 /* Check for ending label on the next line */
    2348        1102 :                                 if (IS_LABEL_START(*YYCURSOR) && heredoc_label->length < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, heredoc_label->label, heredoc_label->length)) {
    2349         122 :                                         YYCTYPE *end = YYCURSOR + heredoc_label->length;
    2350             : 
    2351         122 :                                         if (*end == ';') {
    2352          97 :                                                 end++;
    2353             :                                         }
    2354             : 
    2355         122 :                                         if (*end == '\n' || *end == '\r') {
    2356             :                                                 /* newline before label will be subtracted from returned text, but
    2357             :                                                  * yyleng/yytext will include it, for zend_highlight/strip, tokenizer, etc. */
    2358         117 :                                                 if (YYCURSOR[-2] == '\r' && YYCURSOR[-1] == '\n') {
    2359           0 :                                                         newline = 2; /* Windows newline */
    2360             :                                                 } else {
    2361         117 :                                                         newline = 1;
    2362             :                                                 }
    2363             : 
    2364         117 :                                                 CG(increment_lineno) = 1; /* For newline before label */
    2365         117 :                                                 BEGIN(ST_END_HEREDOC);
    2366             : 
    2367         117 :                                                 goto nowdoc_scan_done;
    2368             :                                         }
    2369             :                                 }
    2370             :                                 /* fall through */
    2371             :                         default:
    2372       37110 :                                 continue;
    2373             :                 }
    2374             :         }
    2375             : 
    2376             : nowdoc_scan_done:
    2377         117 :         yyleng = YYCURSOR - SCNG(yy_text);
    2378             : 
    2379         234 :         zend_copy_value(zendlval, yytext, yyleng - newline);
    2380         117 :         HANDLE_NEWLINES(yytext, yyleng - newline);
    2381         117 :         RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
    2382             : }
    2383             : 
    2384             : 
    2385             : <ST_IN_SCRIPTING,ST_VAR_OFFSET>{ANY_CHAR} {
    2386        3926 :         if (YYCURSOR > YYLIMIT) {
    2387        3925 :                 RETURN_TOKEN(END);
    2388             :         }
    2389             : 
    2390           1 :         zend_error(E_COMPILE_WARNING,"Unexpected character in input:  '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
    2391           1 :         goto restart;
    2392             : }
    2393             : 
    2394             : */
    2395             : }

Generated by: LCOV version 1.10

Generated at Tue, 27 Sep 2016 10:26:11 +0000 (4 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.