Annotation of embedaddon/php/Zend/zend_language_scanner.l, revision 1.1.1.1

1.1       misho       1: /*
                      2:    +----------------------------------------------------------------------+
                      3:    | Zend Engine                                                          |
                      4:    +----------------------------------------------------------------------+
                      5:    | Copyright (c) 1998-2012 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: zend_language_scanner.l 321655 2012-01-01 22:45:58Z nlopess $ */
                     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: #include "zend_alloc.h"
                     37: #include <zend_language_parser.h>
                     38: #include "zend_compile.h"
                     39: #include "zend_language_scanner.h"
                     40: #include "zend_highlight.h"
                     41: #include "zend_constants.h"
                     42: #include "zend_variables.h"
                     43: #include "zend_operators.h"
                     44: #include "zend_API.h"
                     45: #include "zend_strtod.h"
                     46: #include "zend_exceptions.h"
                     47: #include "tsrm_virtual_cwd.h"
                     48: #include "tsrm_config_common.h"
                     49: 
                     50: #define YYCTYPE   unsigned char
                     51: #define YYFILL(n) { if ((YYCURSOR + n) >= (YYLIMIT + ZEND_MMAP_AHEAD)) { return 0; } }
                     52: #define YYCURSOR  SCNG(yy_cursor)
                     53: #define YYLIMIT   SCNG(yy_limit)
                     54: #define YYMARKER  SCNG(yy_marker)
                     55: 
                     56: #define YYGETCONDITION()  SCNG(yy_state)
                     57: #define YYSETCONDITION(s) SCNG(yy_state) = s
                     58: 
                     59: #define STATE(name)  yyc##name
                     60: 
                     61: /* emulate flex constructs */
                     62: #define BEGIN(state) YYSETCONDITION(STATE(state))
                     63: #define YYSTATE      YYGETCONDITION()
                     64: #define yytext       ((char*)SCNG(yy_text))
                     65: #define yyleng       SCNG(yy_leng)
                     66: #define yyless(x)    do { YYCURSOR = (unsigned char*)yytext + x; \
                     67:                           yyleng   = (unsigned int)x; } while(0)
                     68: #define yymore()     goto yymore_restart
                     69: 
                     70: /* perform sanity check. If this message is triggered you should
                     71:    increase the ZEND_MMAP_AHEAD value in the zend_streams.h file */
                     72: /*!max:re2c */
                     73: #if ZEND_MMAP_AHEAD < YYMAXFILL
                     74: # error ZEND_MMAP_AHEAD should be greater than or equal to YYMAXFILL
                     75: #endif
                     76: 
                     77: #ifdef HAVE_STDARG_H
                     78: # include <stdarg.h>
                     79: #endif
                     80: 
                     81: #ifdef HAVE_UNISTD_H
                     82: # include <unistd.h>
                     83: #endif
                     84: 
                     85: /* Globals Macros */
                     86: #define SCNG   LANG_SCNG
                     87: #ifdef ZTS
                     88: ZEND_API ts_rsrc_id language_scanner_globals_id;
                     89: #else
                     90: ZEND_API zend_php_scanner_globals language_scanner_globals;
                     91: #endif
                     92: 
                     93: #define HANDLE_NEWLINES(s, l)                                                                                                  \
                     94: do {                                                                                                                                                   \
                     95:        char *p = (s), *boundary = p+(l);                                                                                       \
                     96:                                                                                                                                                                \
                     97:        while (p<boundary) {                                                                                                            \
                     98:                if (*p == '\n' || (*p == '\r' && (*(p+1) != '\n'))) {                                   \
                     99:                        CG(zend_lineno)++;                                                                                                      \
                    100:                }                                                                                                                                               \
                    101:                p++;                                                                                                                                    \
                    102:        }                                                                                                                                                       \
                    103: } while (0)
                    104: 
                    105: #define HANDLE_NEWLINE(c) \
                    106: { \
                    107:        if (c == '\n' || c == '\r') { \
                    108:                CG(zend_lineno)++; \
                    109:        } \
                    110: }
                    111: 
                    112: /* To save initial string length after scanning to first variable, CG(doc_comment_len) can be reused */
                    113: #define SET_DOUBLE_QUOTES_SCANNED_LENGTH(len) CG(doc_comment_len) = (len)
                    114: #define GET_DOUBLE_QUOTES_SCANNED_LENGTH()    CG(doc_comment_len)
                    115: 
                    116: #define IS_LABEL_START(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z') || (c) == '_' || (c) >= 0x7F)
                    117: 
                    118: #define ZEND_IS_OCT(c)  ((c)>='0' && (c)<='7')
                    119: #define ZEND_IS_HEX(c)  (((c)>='0' && (c)<='9') || ((c)>='a' && (c)<='f') || ((c)>='A' && (c)<='F'))
                    120: 
                    121: BEGIN_EXTERN_C()
                    122: 
                    123: static void _yy_push_state(int new_state TSRMLS_DC)
                    124: {
                    125:        zend_stack_push(&SCNG(state_stack), (void *) &YYGETCONDITION(), sizeof(int));
                    126:        YYSETCONDITION(new_state);
                    127: }
                    128: 
                    129: #define yy_push_state(state_and_tsrm) _yy_push_state(yyc##state_and_tsrm)
                    130: 
                    131: static void yy_pop_state(TSRMLS_D)
                    132: {
                    133:        int *stack_state;
                    134:        zend_stack_top(&SCNG(state_stack), (void **) &stack_state);
                    135:        YYSETCONDITION(*stack_state);
                    136:        zend_stack_del_top(&SCNG(state_stack));
                    137: }
                    138: 
                    139: static void yy_scan_buffer(char *str, unsigned int len TSRMLS_DC)
                    140: {
                    141:        YYCURSOR       = (YYCTYPE*)str;
                    142:        YYLIMIT        = YYCURSOR + len;
                    143:        if (!SCNG(yy_start)) {
                    144:                SCNG(yy_start) = YYCURSOR;
                    145:        }
                    146: }
                    147: 
                    148: void startup_scanner(TSRMLS_D)
                    149: {
                    150:        CG(heredoc) = NULL;
                    151:        CG(heredoc_len) = 0;
                    152:        CG(doc_comment) = NULL;
                    153:        CG(doc_comment_len) = 0;
                    154:        zend_stack_init(&SCNG(state_stack));
                    155: }
                    156: 
                    157: void shutdown_scanner(TSRMLS_D)
                    158: {
                    159:        if (CG(heredoc)) {
                    160:                efree(CG(heredoc));
                    161:                CG(heredoc_len)=0;
                    162:        }
                    163:        zend_stack_destroy(&SCNG(state_stack));
                    164:        RESET_DOC_COMMENT();
                    165: }
                    166: 
                    167: ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
                    168: {
                    169:        lex_state->yy_leng   = SCNG(yy_leng);
                    170:        lex_state->yy_start  = SCNG(yy_start);
                    171:        lex_state->yy_text   = SCNG(yy_text);
                    172:        lex_state->yy_cursor = SCNG(yy_cursor);
                    173:        lex_state->yy_marker = SCNG(yy_marker);
                    174:        lex_state->yy_limit  = SCNG(yy_limit);
                    175: 
                    176:        lex_state->state_stack = SCNG(state_stack);
                    177:        zend_stack_init(&SCNG(state_stack));
                    178: 
                    179:        lex_state->in = SCNG(yy_in);
                    180:        lex_state->yy_state = YYSTATE;
                    181:        lex_state->filename = zend_get_compiled_filename(TSRMLS_C);
                    182:        lex_state->lineno = CG(zend_lineno);
                    183: 
                    184: #ifdef ZEND_MULTIBYTE
                    185:        lex_state->script_org = SCNG(script_org);
                    186:        lex_state->script_org_size = SCNG(script_org_size);
                    187:        lex_state->script_filtered = SCNG(script_filtered);
                    188:        lex_state->script_filtered_size = SCNG(script_filtered_size);
                    189:        lex_state->input_filter = SCNG(input_filter);
                    190:        lex_state->output_filter = SCNG(output_filter);
                    191:        lex_state->script_encoding = SCNG(script_encoding);
                    192:        lex_state->internal_encoding = SCNG(internal_encoding);
                    193: #endif /* ZEND_MULTIBYTE */
                    194: }
                    195: 
                    196: ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
                    197: {
                    198:        SCNG(yy_leng)   = lex_state->yy_leng;
                    199:        SCNG(yy_start)  = lex_state->yy_start;
                    200:        SCNG(yy_text)   = lex_state->yy_text;
                    201:        SCNG(yy_cursor) = lex_state->yy_cursor;
                    202:        SCNG(yy_marker) = lex_state->yy_marker;
                    203:        SCNG(yy_limit)  = lex_state->yy_limit;
                    204: 
                    205:        zend_stack_destroy(&SCNG(state_stack));
                    206:        SCNG(state_stack) = lex_state->state_stack;
                    207: 
                    208:        SCNG(yy_in) = lex_state->in;
                    209:        YYSETCONDITION(lex_state->yy_state);
                    210:        CG(zend_lineno) = lex_state->lineno;
                    211:        zend_restore_compiled_filename(lex_state->filename TSRMLS_CC);
                    212: #ifdef ZEND_MULTIBYTE
                    213:        if (SCNG(script_org)) {
                    214:                efree(SCNG(script_org));
                    215:                SCNG(script_org) = NULL;
                    216:        }
                    217:        if (SCNG(script_filtered)) {
                    218:                efree(SCNG(script_filtered));
                    219:                SCNG(script_filtered) = NULL;
                    220:        }
                    221:        SCNG(script_org) = lex_state->script_org;
                    222:        SCNG(script_org_size) = lex_state->script_org_size;
                    223:        SCNG(script_filtered) = lex_state->script_filtered;
                    224:        SCNG(script_filtered_size) = lex_state->script_filtered_size;
                    225:        SCNG(input_filter) = lex_state->input_filter;
                    226:        SCNG(output_filter) = lex_state->output_filter;
                    227:        SCNG(script_encoding) = lex_state->script_encoding;
                    228:        SCNG(internal_encoding) = lex_state->internal_encoding;
                    229: #endif /* ZEND_MULTIBYTE */
                    230: 
                    231:        if (CG(heredoc)) {
                    232:                efree(CG(heredoc));
                    233:                CG(heredoc) = NULL;
                    234:                CG(heredoc_len) = 0;
                    235:        }
                    236: }
                    237: 
                    238: ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC)
                    239: {
                    240:        zend_llist_del_element(&CG(open_files), file_handle, (int (*)(void *, void *)) zend_compare_file_handles);
                    241:        /* zend_file_handle_dtor() operates on the copy, so we have to NULLify the original here */
                    242:        file_handle->opened_path = NULL;
                    243:        if (file_handle->free_filename) {
                    244:                file_handle->filename = NULL;
                    245:        }
                    246: }
                    247: 
                    248: 
                    249: ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
                    250: {
                    251:        char *file_path = NULL, *buf;
                    252:        size_t size, offset = 0;
                    253:        
                    254:        /* The shebang line was read, get the current position to obtain the buffer start */
                    255:        if (CG(start_lineno) == 2 && file_handle->type == ZEND_HANDLE_FP && file_handle->handle.fp) {
                    256:                if ((offset = ftell(file_handle->handle.fp)) == -1) {
                    257:                        offset = 0;
                    258:                }
                    259:        }
                    260: 
                    261:        if (zend_stream_fixup(file_handle, &buf, &size TSRMLS_CC) == FAILURE) {
                    262:                return FAILURE;
                    263:        }
                    264: 
                    265:        zend_llist_add_element(&CG(open_files), file_handle);
                    266:        if (file_handle->handle.stream.handle >= (void*)file_handle && file_handle->handle.stream.handle <= (void*)(file_handle+1)) {
                    267:                zend_file_handle *fh = (zend_file_handle*)zend_llist_get_last(&CG(open_files));
                    268:                size_t diff = (char*)file_handle->handle.stream.handle - (char*)file_handle;
                    269:                fh->handle.stream.handle = (void*)(((char*)fh) + diff);
                    270:                file_handle->handle.stream.handle = fh->handle.stream.handle;
                    271:        }
                    272: 
                    273:        /* Reset the scanner for scanning the new file */
                    274:        SCNG(yy_in) = file_handle;
                    275:        SCNG(yy_start) = NULL;
                    276: 
                    277:        if (size != -1) {
                    278: #ifdef ZEND_MULTIBYTE
                    279:                if (zend_multibyte_read_script((unsigned char *)buf, size TSRMLS_CC) != 0) {
                    280:                        return FAILURE;
                    281:                }
                    282: 
                    283:                SCNG(yy_in) = NULL;
                    284: 
                    285:                zend_multibyte_set_filter(NULL TSRMLS_CC);
                    286: 
                    287:                if (!SCNG(input_filter)) {
                    288:                        SCNG(script_filtered) = (unsigned char*)emalloc(SCNG(script_org_size)+1);
                    289:                        memcpy(SCNG(script_filtered), SCNG(script_org), SCNG(script_org_size)+1);
                    290:                        SCNG(script_filtered_size) = SCNG(script_org_size);
                    291:                } else {
                    292:                        SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC);
                    293:                        if (SCNG(script_filtered) == NULL) {
                    294:                                zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
                    295:                                                "encoding \"%s\" to a compatible encoding", LANG_SCNG(script_encoding)->name);
                    296:                        }
                    297:                }
                    298:                SCNG(yy_start) = SCNG(script_filtered) - offset;
                    299:                yy_scan_buffer((char *)SCNG(script_filtered), SCNG(script_filtered_size) TSRMLS_CC);
                    300: #else /* !ZEND_MULTIBYTE */
                    301:                SCNG(yy_start) = buf - offset;
                    302:                yy_scan_buffer(buf, size TSRMLS_CC);
                    303: #endif /* ZEND_MULTIBYTE */
                    304:        } else {
                    305:                zend_error_noreturn(E_COMPILE_ERROR, "zend_stream_mmap() failed");
                    306:        }
                    307: 
                    308:        BEGIN(INITIAL);
                    309: 
                    310:        if (file_handle->opened_path) {
                    311:                file_path = file_handle->opened_path;
                    312:        } else {
                    313:                file_path = file_handle->filename;
                    314:        }
                    315: 
                    316:        zend_set_compiled_filename(file_path TSRMLS_CC);
                    317: 
                    318:        if (CG(start_lineno)) {
                    319:                CG(zend_lineno) = CG(start_lineno);
                    320:                CG(start_lineno) = 0;
                    321:        } else {
                    322:                CG(zend_lineno) = 1;
                    323:        }
                    324: 
                    325:        CG(increment_lineno) = 0;
                    326:        return SUCCESS;
                    327: }
                    328: END_EXTERN_C()
                    329: 
                    330: 
                    331: ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
                    332: {
                    333:        zend_lex_state original_lex_state;
                    334:        zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
                    335:        zend_op_array *original_active_op_array = CG(active_op_array);
                    336:        zend_op_array *retval=NULL;
                    337:        int compiler_result;
                    338:        zend_bool compilation_successful=0;
                    339:        znode retval_znode;
                    340:        zend_bool original_in_compilation = CG(in_compilation);
                    341: 
                    342:        retval_znode.op_type = IS_CONST;
                    343:        retval_znode.u.constant.type = IS_LONG;
                    344:        retval_znode.u.constant.value.lval = 1;
                    345:        Z_UNSET_ISREF(retval_znode.u.constant);
                    346:        Z_SET_REFCOUNT(retval_znode.u.constant, 1);
                    347: 
                    348:        zend_save_lexical_state(&original_lex_state TSRMLS_CC);
                    349: 
                    350:        retval = op_array; /* success oriented */
                    351: 
                    352:        if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) {
                    353:                if (type==ZEND_REQUIRE) {
                    354:                        zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
                    355:                        zend_bailout();
                    356:                } else {
                    357:                        zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
                    358:                }
                    359:                compilation_successful=0;
                    360:        } else {
                    361:                init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
                    362:                CG(in_compilation) = 1;
                    363:                CG(active_op_array) = op_array;
                    364:                compiler_result = zendparse(TSRMLS_C);
                    365:                zend_do_return(&retval_znode, 0 TSRMLS_CC);
                    366:                CG(in_compilation) = original_in_compilation;
                    367:                if (compiler_result==1) { /* parser error */
                    368:                        zend_bailout();
                    369:                }
                    370:                compilation_successful=1;
                    371:        }
                    372: 
                    373:        if (retval) {
                    374:                CG(active_op_array) = original_active_op_array;
                    375:                if (compilation_successful) {
                    376:                        pass_two(op_array TSRMLS_CC);
                    377:                        zend_release_labels(TSRMLS_C);
                    378:                } else {
                    379:                        efree(op_array);
                    380:                        retval = NULL;
                    381:                }
                    382:        }
                    383:        zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
                    384:        return retval;
                    385: }
                    386: 
                    387: 
                    388: zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC)
                    389: {
                    390:        zend_file_handle file_handle;
                    391:        zval tmp;
                    392:        zend_op_array *retval;
                    393:        char *opened_path = NULL;
                    394: 
                    395:        if (filename->type != IS_STRING) {
                    396:                tmp = *filename;
                    397:                zval_copy_ctor(&tmp);
                    398:                convert_to_string(&tmp);
                    399:                filename = &tmp;
                    400:        }
                    401:        file_handle.filename = filename->value.str.val;
                    402:        file_handle.free_filename = 0;
                    403:        file_handle.type = ZEND_HANDLE_FILENAME;
                    404:        file_handle.opened_path = NULL;
                    405:        file_handle.handle.fp = NULL;
                    406: 
                    407:        retval = zend_compile_file(&file_handle, type TSRMLS_CC);
                    408:        if (retval && file_handle.handle.stream.handle) {
                    409:                int dummy = 1;
                    410: 
                    411:                if (!file_handle.opened_path) {
                    412:                        file_handle.opened_path = opened_path = estrndup(filename->value.str.val, filename->value.str.len);
                    413:                }
                    414: 
                    415:                zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL);
                    416: 
                    417:                if (opened_path) {
                    418:                        efree(opened_path);
                    419:                }
                    420:        }
                    421:        zend_destroy_file_handle(&file_handle TSRMLS_CC);
                    422: 
                    423:        if (filename==&tmp) {
                    424:                zval_dtor(&tmp);
                    425:        }
                    426:        return retval;
                    427: }
                    428: 
                    429: ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_DC)
                    430: {
                    431:        /* enforce two trailing NULLs for flex... */
                    432:        str->value.str.val = safe_erealloc(str->value.str.val, 1, str->value.str.len, ZEND_MMAP_AHEAD);
                    433: 
                    434:        memset(str->value.str.val + str->value.str.len, 0, ZEND_MMAP_AHEAD);
                    435: 
                    436:        SCNG(yy_in)=NULL;
                    437:        SCNG(yy_start) = NULL;
                    438: 
                    439: #ifdef ZEND_MULTIBYTE
                    440:        SCNG(script_org) = (unsigned char *)estrdup(str->value.str.val);
                    441:        SCNG(script_org_size) = str->value.str.len;
                    442: 
                    443:        zend_multibyte_set_filter(CG(internal_encoding) TSRMLS_CC);
                    444: 
                    445:        if (!SCNG(input_filter)) {
                    446:                SCNG(script_filtered) = (unsigned char*)emalloc(SCNG(script_org_size)+1);
                    447:                memcpy(SCNG(script_filtered), SCNG(script_org), SCNG(script_org_size)+1);
                    448:                SCNG(script_filtered_size) = SCNG(script_org_size);
                    449:        } else {
                    450:                SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC);
                    451:        }
                    452: 
                    453:        yy_scan_buffer((char *)SCNG(script_filtered), SCNG(script_filtered_size) TSRMLS_CC);    
                    454: #else /* !ZEND_MULTIBYTE */
                    455:        yy_scan_buffer(str->value.str.val, str->value.str.len TSRMLS_CC);
                    456: #endif /* ZEND_MULTIBYTE */
                    457: 
                    458:        zend_set_compiled_filename(filename TSRMLS_CC);
                    459:        CG(zend_lineno) = 1;
                    460:        CG(increment_lineno) = 0;
                    461:        return SUCCESS;
                    462: }
                    463: 
                    464: 
                    465: ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D)
                    466: {
                    467:        size_t offset = SCNG(yy_cursor) - SCNG(yy_start);
                    468: #ifdef ZEND_MULTIBYTE
                    469:        if (SCNG(input_filter)) {
                    470:                size_t original_offset = offset, length = 0; do {
                    471:                        unsigned char *p = NULL;
                    472:                        SCNG(input_filter)(&p, &length, SCNG(script_org), offset TSRMLS_CC);
                    473:                        if (!p) {
                    474:                                break;
                    475:                        }
                    476:                        efree(p);
                    477:                        if (length > original_offset) {
                    478:                                offset--;
                    479:                        } else if (length < original_offset) {
                    480:                                offset++;
                    481:                        }
                    482:                } while (original_offset != length);
                    483:        }
                    484: #endif
                    485:        return offset;
                    486: }
                    487: 
                    488: 
                    489: zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
                    490: {
                    491:        zend_lex_state original_lex_state;
                    492:        zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
                    493:        zend_op_array *original_active_op_array = CG(active_op_array);
                    494:        zend_op_array *retval;
                    495:        zval tmp;
                    496:        int compiler_result;
                    497:        zend_bool original_in_compilation = CG(in_compilation);
                    498: 
                    499:        if (source_string->value.str.len==0) {
                    500:                efree(op_array);
                    501:                return NULL;
                    502:        }
                    503: 
                    504:        CG(in_compilation) = 1;
                    505: 
                    506:        tmp = *source_string;
                    507:        zval_copy_ctor(&tmp);
                    508:        convert_to_string(&tmp);
                    509:        source_string = &tmp;
                    510: 
                    511:        zend_save_lexical_state(&original_lex_state TSRMLS_CC);
                    512:        if (zend_prepare_string_for_scanning(source_string, filename TSRMLS_CC)==FAILURE) {
                    513:                efree(op_array);
                    514:                retval = NULL;
                    515:        } else {
                    516:                zend_bool orig_interactive = CG(interactive);
                    517: 
                    518:                CG(interactive) = 0;
                    519:                init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
                    520:                CG(interactive) = orig_interactive;
                    521:                CG(active_op_array) = op_array;
                    522:                BEGIN(ST_IN_SCRIPTING);
                    523:                compiler_result = zendparse(TSRMLS_C);
                    524: 
                    525: #ifdef ZEND_MULTIBYTE
                    526:                if (SCNG(script_org)) {
                    527:                        efree(SCNG(script_org));
                    528:                        SCNG(script_org) = NULL;
                    529:                }
                    530:                if (SCNG(script_filtered)) {
                    531:                        efree(SCNG(script_filtered));
                    532:                        SCNG(script_filtered) = NULL;
                    533:                }
                    534: #endif /* ZEND_MULTIBYTE */
                    535: 
                    536:                if (compiler_result==1) {
                    537:                        CG(active_op_array) = original_active_op_array;
                    538:                        CG(unclean_shutdown)=1;
                    539:                        destroy_op_array(op_array TSRMLS_CC);
                    540:                        efree(op_array);
                    541:                        retval = NULL;
                    542:                } else {
                    543:                        zend_do_return(NULL, 0 TSRMLS_CC);
                    544:                        CG(active_op_array) = original_active_op_array;
                    545:                        pass_two(op_array TSRMLS_CC);
                    546:                        zend_release_labels(TSRMLS_C);
                    547:                        retval = op_array;
                    548:                }
                    549:        }
                    550:        zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
                    551:        zval_dtor(&tmp);
                    552:        CG(in_compilation) = original_in_compilation;
                    553:        return retval;
                    554: }
                    555: 
                    556: 
                    557: BEGIN_EXTERN_C()
                    558: int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC)
                    559: {
                    560:        zend_lex_state original_lex_state;
                    561:        zend_file_handle file_handle;
                    562: 
                    563:        file_handle.type = ZEND_HANDLE_FILENAME;
                    564:        file_handle.filename = filename;
                    565:        file_handle.free_filename = 0;
                    566:        file_handle.opened_path = NULL;
                    567:        zend_save_lexical_state(&original_lex_state TSRMLS_CC);
                    568:        if (open_file_for_scanning(&file_handle TSRMLS_CC)==FAILURE) {
                    569:                zend_message_dispatcher(ZMSG_FAILED_HIGHLIGHT_FOPEN, filename TSRMLS_CC);
                    570:                zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
                    571:                return FAILURE;
                    572:        }
                    573:        zend_highlight(syntax_highlighter_ini TSRMLS_CC);
                    574: #ifdef ZEND_MULTIBYTE
                    575:        if (SCNG(script_org)) {
                    576:                efree(SCNG(script_org));
                    577:                SCNG(script_org) = NULL;
                    578:        }
                    579:        if (SCNG(script_filtered)) {
                    580:                efree(SCNG(script_filtered));
                    581:                SCNG(script_filtered) = NULL;
                    582:        }
                    583: #endif /* ZEND_MULTIBYTE */
                    584:        zend_destroy_file_handle(&file_handle TSRMLS_CC);
                    585:        zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
                    586:        return SUCCESS;
                    587: }
                    588: 
                    589: int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name TSRMLS_DC)
                    590: {
                    591:        zend_lex_state original_lex_state;
                    592:        zval tmp = *str;
                    593: 
                    594:        str = &tmp;
                    595:        zval_copy_ctor(str);
                    596:        zend_save_lexical_state(&original_lex_state TSRMLS_CC);
                    597:        if (zend_prepare_string_for_scanning(str, str_name TSRMLS_CC)==FAILURE) {
                    598:                zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
                    599:                return FAILURE;
                    600:        }
                    601:        BEGIN(INITIAL);
                    602:        zend_highlight(syntax_highlighter_ini TSRMLS_CC);
                    603: #ifdef ZEND_MULTIBYTE
                    604:        if (SCNG(script_org)) {
                    605:                efree(SCNG(script_org));
                    606:                SCNG(script_org) = NULL;
                    607:        }
                    608:        if (SCNG(script_filtered)) {
                    609:                efree(SCNG(script_filtered));
                    610:                SCNG(script_filtered) = NULL;
                    611:        }
                    612: #endif /* ZEND_MULTIBYTE */
                    613:        zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
                    614:        zval_dtor(str);
                    615:        return SUCCESS;
                    616: }
                    617: END_EXTERN_C()
                    618: 
                    619: #ifdef ZEND_MULTIBYTE
                    620: 
                    621: BEGIN_EXTERN_C()
                    622: ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, zend_encoding *old_encoding TSRMLS_DC)
                    623: {
                    624:        size_t original_offset, offset, free_flag, new_len, length;
                    625:        unsigned char *p;
                    626: 
                    627:        /* calculate current position */
                    628:        offset = original_offset = YYCURSOR - SCNG(yy_start);
                    629:        if (old_input_filter && offset > 0) {
                    630:                zend_encoding *new_encoding = SCNG(script_encoding);
                    631:                zend_encoding_filter new_filter = SCNG(input_filter);
                    632:                SCNG(script_encoding) = old_encoding;
                    633:                SCNG(input_filter) = old_input_filter;
                    634:                offset = zend_get_scanned_file_offset(TSRMLS_C);
                    635:                SCNG(script_encoding) = new_encoding;
                    636:                SCNG(input_filter) = new_filter;
                    637:        }
                    638: 
                    639:        /* convert and set */
                    640:        if (!SCNG(input_filter)) {
                    641:                length = SCNG(script_org_size) - offset;
                    642:                p = SCNG(script_org) + offset;
                    643:                free_flag = 0;
                    644:        } else {
                    645:                SCNG(input_filter)(&p, &length, SCNG(script_org) + offset, SCNG(script_org_size) - offset TSRMLS_CC);
                    646:                free_flag = 1;
                    647:        }
                    648: 
                    649:        new_len = original_offset + length;
                    650: 
                    651:        if (new_len > YYLIMIT - SCNG(yy_start)) {
                    652:                unsigned char *new_yy_start = erealloc(SCNG(yy_start), new_len);
                    653:                SCNG(yy_cursor) = new_yy_start + (SCNG(yy_cursor) - SCNG(yy_start));
                    654:                SCNG(yy_marker) = new_yy_start + (SCNG(yy_marker) - SCNG(yy_start));
                    655:                SCNG(yy_text) = new_yy_start + (SCNG(yy_text) - SCNG(yy_start));
                    656:                SCNG(yy_start) = new_yy_start;
                    657:                SCNG(script_filtered) = new_yy_start;
                    658:                SCNG(script_filtered_size) = new_len;
                    659:        }
                    660: 
                    661:        SCNG(yy_limit) = SCNG(yy_start) + new_len;
                    662:        memmove(SCNG(yy_start) + original_offset, p, length);
                    663: 
                    664:        if (free_flag) {
                    665:                efree(p);
                    666:        }
                    667: }
                    668: 
                    669: 
                    670: ZEND_API int zend_multibyte_yyinput(zend_file_handle *file_handle, char *buf, size_t len TSRMLS_DC)
                    671: {
                    672:        size_t n;
                    673: 
                    674:        if (CG(interactive) == 0) {
                    675:                if (zend_stream_fixup(file_handle, &buf, &len TSRMLS_CC) == FAILURE) {
                    676:                        return FAILURE;
                    677:                }
                    678:                n = len;
                    679:                return n;
                    680:        }
                    681: 
                    682:        /* interactive */
                    683:        if (SCNG(script_org)) {
                    684:                efree(SCNG(script_org));
                    685:        }
                    686:        if (SCNG(script_filtered)) {
                    687:                efree(SCNG(script_filtered));
                    688:        }
                    689:        SCNG(script_org) = NULL;
                    690:        SCNG(script_org_size) = 0;
                    691: 
                    692:        /* TODO: support widechars */
                    693:        if (zend_stream_fixup(file_handle, &buf, &len TSRMLS_CC) == FAILURE) {
                    694:                return FAILURE;
                    695:        }
                    696:        n = len;
                    697: 
                    698:        SCNG(script_org_size) = n;
                    699:        SCNG(script_org) = (unsigned char*)emalloc(SCNG(script_org_size) + 1);
                    700:        memcpy(SCNG(script_org), buf, n);
                    701: 
                    702:        return n;
                    703: }
                    704: 
                    705: 
                    706: ZEND_API int zend_multibyte_read_script(unsigned char *buf, size_t n TSRMLS_DC)
                    707: {
                    708:        if (SCNG(script_org)) {
                    709:                efree(SCNG(script_org));
                    710:                SCNG(script_org) = NULL;
                    711:        }
                    712:        SCNG(script_org_size) = n;      
                    713:        
                    714:        SCNG(script_org) = (unsigned char*)emalloc(SCNG(script_org_size) + 1);
                    715:        memcpy(SCNG(script_org), buf, n);
                    716:        *(SCNG(script_org)+SCNG(script_org_size)) = '\0';
                    717: 
                    718:        return 0;
                    719: }
                    720: 
                    721: 
                    722: # define zend_copy_value(zendlval, yytext, yyleng) \
                    723:        if (SCNG(output_filter)) { \
                    724:                size_t sz = 0; \
                    725:                SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)yytext, (size_t)yyleng TSRMLS_CC); \
                    726:                zendlval->value.str.len = sz; \
                    727:        } else { \
                    728:                zendlval->value.str.val = (char *) estrndup(yytext, yyleng); \
                    729:                zendlval->value.str.len = yyleng; \
                    730:        }
                    731: #else /* ZEND_MULTIBYTE */
                    732: # define zend_copy_value(zendlval, yytext, yyleng) \
                    733:        zendlval->value.str.val = (char *)estrndup(yytext, yyleng); \
                    734:        zendlval->value.str.len = yyleng;
                    735: #endif /* ZEND_MULTIBYTE */
                    736: 
                    737: static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type TSRMLS_DC)
                    738: {
                    739:        register char *s, *t;
                    740:        char *end;
                    741: 
                    742:        ZVAL_STRINGL(zendlval, str, len, 1);
                    743: 
                    744:        /* convert escape sequences */
                    745:        s = t = zendlval->value.str.val;
                    746:        end = s+zendlval->value.str.len;
                    747:        while (s<end) {
                    748:                if (*s=='\\') {
                    749:                        s++;
                    750:                        if (s >= end) {
                    751:                                *t++ = '\\';
                    752:                                break;
                    753:                        }
                    754: 
                    755:                        switch(*s) {
                    756:                                case 'n':
                    757:                                        *t++ = '\n';
                    758:                                        zendlval->value.str.len--;
                    759:                                        break;
                    760:                                case 'r':
                    761:                                        *t++ = '\r';
                    762:                                        zendlval->value.str.len--;
                    763:                                        break;
                    764:                                case 't':
                    765:                                        *t++ = '\t';
                    766:                                        zendlval->value.str.len--;
                    767:                                        break;
                    768:                                case 'f':
                    769:                                        *t++ = '\f';
                    770:                                        zendlval->value.str.len--;
                    771:                                        break;
                    772:                                case 'v':
                    773:                                        *t++ = '\v';
                    774:                                        zendlval->value.str.len--;
                    775:                                        break;
                    776:                                case '"':
                    777:                                case '`':
                    778:                                        if (*s != quote_type) {
                    779:                                                *t++ = '\\';
                    780:                                                *t++ = *s;
                    781:                                                break;
                    782:                                        }
                    783:                                case '\\':
                    784:                                case '$':
                    785:                                        *t++ = *s;
                    786:                                        zendlval->value.str.len--;
                    787:                                        break;
                    788:                                case 'x':
                    789:                                case 'X':
                    790:                                        if (ZEND_IS_HEX(*(s+1))) {
                    791:                                                char hex_buf[3] = { 0, 0, 0 };
                    792: 
                    793:                                                zendlval->value.str.len--; /* for the 'x' */
                    794: 
                    795:                                                hex_buf[0] = *(++s);
                    796:                                                zendlval->value.str.len--;
                    797:                                                if (ZEND_IS_HEX(*(s+1))) {
                    798:                                                        hex_buf[1] = *(++s);
                    799:                                                        zendlval->value.str.len--;
                    800:                                                }
                    801:                                                *t++ = (char) strtol(hex_buf, NULL, 16);
                    802:                                        } else {
                    803:                                                *t++ = '\\';
                    804:                                                *t++ = *s;
                    805:                                        }
                    806:                                        break;
                    807:                                default:
                    808:                                        /* check for an octal */
                    809:                                        if (ZEND_IS_OCT(*s)) {
                    810:                                                char octal_buf[4] = { 0, 0, 0, 0 };
                    811: 
                    812:                                                octal_buf[0] = *s;
                    813:                                                zendlval->value.str.len--;
                    814:                                                if (ZEND_IS_OCT(*(s+1))) {
                    815:                                                        octal_buf[1] = *(++s);
                    816:                                                        zendlval->value.str.len--;
                    817:                                                        if (ZEND_IS_OCT(*(s+1))) {
                    818:                                                                octal_buf[2] = *(++s);
                    819:                                                                zendlval->value.str.len--;
                    820:                                                        }
                    821:                                                }
                    822:                                                *t++ = (char) strtol(octal_buf, NULL, 8);
                    823:                                        } else {
                    824:                                                *t++ = '\\';
                    825:                                                *t++ = *s;
                    826:                                        }
                    827:                                        break;
                    828:                        }
                    829:                } else {
                    830:                        *t++ = *s;
                    831:                }
                    832: 
                    833:                if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) {
                    834:                        CG(zend_lineno)++;
                    835:                }
                    836:                s++;
                    837:        }
                    838:        *t = 0;
                    839: #ifdef ZEND_MULTIBYTE
                    840:        if (SCNG(output_filter)) {
                    841:                size_t sz = 0;
                    842:                s = zendlval->value.str.val;
                    843:                SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)s, (size_t)zendlval->value.str.len TSRMLS_CC);
                    844:                zendlval->value.str.len = sz;
                    845:                efree(s);
                    846:        }
                    847: #endif /* ZEND_MULTIBYTE */
                    848: }
                    849: 
                    850: 
                    851: int lex_scan(zval *zendlval TSRMLS_DC)
                    852: {
                    853: restart:
                    854:        SCNG(yy_text) = YYCURSOR;
                    855: 
                    856: yymore_restart:
                    857: 
                    858: /*!re2c
                    859: re2c:yyfill:check = 0;
                    860: LNUM   [0-9]+
                    861: DNUM   ([0-9]*"."[0-9]+)|([0-9]+"."[0-9]*)
                    862: EXPONENT_DNUM  (({LNUM}|{DNUM})[eE][+-]?{LNUM})
                    863: HNUM   "0x"[0-9a-fA-F]+
                    864: LABEL  [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
                    865: WHITESPACE [ \n\r\t]+
                    866: TABS_AND_SPACES [ \t]*
                    867: TOKENS [;:,.\[\]()|^&+-/*=%!~$<>?@]
                    868: ANY_CHAR [^]
                    869: NEWLINE ("\r"|"\n"|"\r\n")
                    870: 
                    871: /* compute yyleng before each rule */
                    872: <!*> := yyleng = YYCURSOR - SCNG(yy_text);
                    873: 
                    874: 
                    875: <ST_IN_SCRIPTING>"exit" {
                    876:        return T_EXIT;
                    877: }
                    878: 
                    879: <ST_IN_SCRIPTING>"die" {
                    880:        return T_EXIT;
                    881: }
                    882: 
                    883: <ST_IN_SCRIPTING>"function" {
                    884:        return T_FUNCTION;
                    885: }
                    886: 
                    887: <ST_IN_SCRIPTING>"const" {
                    888:        return T_CONST;
                    889: }
                    890: 
                    891: <ST_IN_SCRIPTING>"return" {
                    892:        return T_RETURN;
                    893: }
                    894: 
                    895: <ST_IN_SCRIPTING>"try" {
                    896:        return T_TRY;
                    897: }
                    898: 
                    899: <ST_IN_SCRIPTING>"catch" {
                    900:        return T_CATCH;
                    901: }
                    902: 
                    903: <ST_IN_SCRIPTING>"throw" {
                    904:        return T_THROW;
                    905: }
                    906: 
                    907: <ST_IN_SCRIPTING>"if" {
                    908:        return T_IF;
                    909: }
                    910: 
                    911: <ST_IN_SCRIPTING>"elseif" {
                    912:        return T_ELSEIF;
                    913: }
                    914: 
                    915: <ST_IN_SCRIPTING>"endif" {
                    916:        return T_ENDIF;
                    917: }
                    918: 
                    919: <ST_IN_SCRIPTING>"else" {
                    920:        return T_ELSE;
                    921: }
                    922: 
                    923: <ST_IN_SCRIPTING>"while" {
                    924:        return T_WHILE;
                    925: }
                    926: 
                    927: <ST_IN_SCRIPTING>"endwhile" {
                    928:        return T_ENDWHILE;
                    929: }
                    930: 
                    931: <ST_IN_SCRIPTING>"do" {
                    932:        return T_DO;
                    933: }
                    934: 
                    935: <ST_IN_SCRIPTING>"for" {
                    936:        return T_FOR;
                    937: }
                    938: 
                    939: <ST_IN_SCRIPTING>"endfor" {
                    940:        return T_ENDFOR;
                    941: }
                    942: 
                    943: <ST_IN_SCRIPTING>"foreach" {
                    944:        return T_FOREACH;
                    945: }
                    946: 
                    947: <ST_IN_SCRIPTING>"endforeach" {
                    948:        return T_ENDFOREACH;
                    949: }
                    950: 
                    951: <ST_IN_SCRIPTING>"declare" {
                    952:        return T_DECLARE;
                    953: }
                    954: 
                    955: <ST_IN_SCRIPTING>"enddeclare" {
                    956:        return T_ENDDECLARE;
                    957: }
                    958: 
                    959: <ST_IN_SCRIPTING>"instanceof" {
                    960:        return T_INSTANCEOF;
                    961: }
                    962: 
                    963: <ST_IN_SCRIPTING>"as" {
                    964:        return T_AS;
                    965: }
                    966: 
                    967: <ST_IN_SCRIPTING>"switch" {
                    968:        return T_SWITCH;
                    969: }
                    970: 
                    971: <ST_IN_SCRIPTING>"endswitch" {
                    972:        return T_ENDSWITCH;
                    973: }
                    974: 
                    975: <ST_IN_SCRIPTING>"case" {
                    976:        return T_CASE;
                    977: }
                    978: 
                    979: <ST_IN_SCRIPTING>"default" {
                    980:        return T_DEFAULT;
                    981: }
                    982: 
                    983: <ST_IN_SCRIPTING>"break" {
                    984:        return T_BREAK;
                    985: }
                    986: 
                    987: <ST_IN_SCRIPTING>"continue" {
                    988:        return T_CONTINUE;
                    989: }
                    990: 
                    991: <ST_IN_SCRIPTING>"goto" {
                    992:        return T_GOTO;
                    993: }
                    994: 
                    995: <ST_IN_SCRIPTING>"echo" {
                    996:        return T_ECHO;
                    997: }
                    998: 
                    999: <ST_IN_SCRIPTING>"print" {
                   1000:        return T_PRINT;
                   1001: }
                   1002: 
                   1003: <ST_IN_SCRIPTING>"class" {
                   1004:        return T_CLASS;
                   1005: }
                   1006: 
                   1007: <ST_IN_SCRIPTING>"interface" {
                   1008:        return T_INTERFACE;
                   1009: }
                   1010: 
                   1011: <ST_IN_SCRIPTING>"extends" {
                   1012:        return T_EXTENDS;
                   1013: }
                   1014: 
                   1015: <ST_IN_SCRIPTING>"implements" {
                   1016:        return T_IMPLEMENTS;
                   1017: }
                   1018: 
                   1019: <ST_IN_SCRIPTING>"->" {
                   1020:        yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
                   1021:        return T_OBJECT_OPERATOR;
                   1022: }
                   1023: 
                   1024: <ST_IN_SCRIPTING,ST_LOOKING_FOR_PROPERTY>{WHITESPACE}+ {
                   1025:        zendlval->value.str.val = yytext; /* no copying - intentional */
                   1026:        zendlval->value.str.len = yyleng;
                   1027:        zendlval->type = IS_STRING;
                   1028:        HANDLE_NEWLINES(yytext, yyleng);
                   1029:        return T_WHITESPACE;
                   1030: }
                   1031: 
                   1032: <ST_LOOKING_FOR_PROPERTY>"->" {
                   1033:        return T_OBJECT_OPERATOR;
                   1034: }
                   1035: 
                   1036: <ST_LOOKING_FOR_PROPERTY>{LABEL} {
                   1037:        yy_pop_state(TSRMLS_C);
                   1038:        zend_copy_value(zendlval, yytext, yyleng);
                   1039:        zendlval->type = IS_STRING;
                   1040:        return T_STRING;
                   1041: }
                   1042: 
                   1043: <ST_LOOKING_FOR_PROPERTY>{ANY_CHAR} {
                   1044:        yyless(0);
                   1045:        yy_pop_state(TSRMLS_C);
                   1046:        goto restart;
                   1047: }
                   1048: 
                   1049: <ST_IN_SCRIPTING>"::" {
                   1050:        return T_PAAMAYIM_NEKUDOTAYIM;
                   1051: }
                   1052: 
                   1053: <ST_IN_SCRIPTING>"\\" {
                   1054:        return T_NS_SEPARATOR;
                   1055: }
                   1056: 
                   1057: <ST_IN_SCRIPTING>"new" {
                   1058:        return T_NEW;
                   1059: }
                   1060: 
                   1061: <ST_IN_SCRIPTING>"clone" {
                   1062:        return T_CLONE;
                   1063: }
                   1064: 
                   1065: <ST_IN_SCRIPTING>"var" {
                   1066:        return T_VAR;
                   1067: }
                   1068: 
                   1069: <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("int"|"integer"){TABS_AND_SPACES}")" {
                   1070:        return T_INT_CAST;
                   1071: }
                   1072: 
                   1073: <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("real"|"double"|"float"){TABS_AND_SPACES}")" {
                   1074:        return T_DOUBLE_CAST;
                   1075: }
                   1076: 
                   1077: <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"string"{TABS_AND_SPACES}")" {
                   1078:        return T_STRING_CAST;
                   1079: }
                   1080: 
                   1081: <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"binary"{TABS_AND_SPACES}")" {
                   1082:        return T_STRING_CAST;
                   1083: }
                   1084: 
                   1085: <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"array"{TABS_AND_SPACES}")" {
                   1086:        return T_ARRAY_CAST;
                   1087: }
                   1088: 
                   1089: <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"object"{TABS_AND_SPACES}")" {
                   1090:        return T_OBJECT_CAST;
                   1091: }
                   1092: 
                   1093: <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("bool"|"boolean"){TABS_AND_SPACES}")" {
                   1094:        return T_BOOL_CAST;
                   1095: }
                   1096: 
                   1097: <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("unset"){TABS_AND_SPACES}")" {
                   1098:        return T_UNSET_CAST;
                   1099: }
                   1100: 
                   1101: <ST_IN_SCRIPTING>"eval" {
                   1102:        return T_EVAL;
                   1103: }
                   1104: 
                   1105: <ST_IN_SCRIPTING>"include" {
                   1106:        return T_INCLUDE;
                   1107: }
                   1108: 
                   1109: <ST_IN_SCRIPTING>"include_once" {
                   1110:        return T_INCLUDE_ONCE;
                   1111: }
                   1112: 
                   1113: <ST_IN_SCRIPTING>"require" {
                   1114:        return T_REQUIRE;
                   1115: }
                   1116: 
                   1117: <ST_IN_SCRIPTING>"require_once" {
                   1118:        return T_REQUIRE_ONCE;
                   1119: }
                   1120: 
                   1121: <ST_IN_SCRIPTING>"namespace" {
                   1122:        return T_NAMESPACE;
                   1123: }
                   1124: 
                   1125: <ST_IN_SCRIPTING>"use" {
                   1126:        return T_USE;
                   1127: }
                   1128: 
                   1129: <ST_IN_SCRIPTING>"global" {
                   1130:        return T_GLOBAL;
                   1131: }
                   1132: 
                   1133: <ST_IN_SCRIPTING>"isset" {
                   1134:        return T_ISSET;
                   1135: }
                   1136: 
                   1137: <ST_IN_SCRIPTING>"empty" {
                   1138:        return T_EMPTY;
                   1139: }
                   1140: 
                   1141: <ST_IN_SCRIPTING>"__halt_compiler" {
                   1142:        return T_HALT_COMPILER;
                   1143: }
                   1144: 
                   1145: <ST_IN_SCRIPTING>"static" {
                   1146:        return T_STATIC;
                   1147: }
                   1148: 
                   1149: <ST_IN_SCRIPTING>"abstract" {
                   1150:        return T_ABSTRACT;
                   1151: }
                   1152: 
                   1153: <ST_IN_SCRIPTING>"final" {
                   1154:        return T_FINAL;
                   1155: }
                   1156: 
                   1157: <ST_IN_SCRIPTING>"private" {
                   1158:        return T_PRIVATE;
                   1159: }
                   1160: 
                   1161: <ST_IN_SCRIPTING>"protected" {
                   1162:        return T_PROTECTED;
                   1163: }
                   1164: 
                   1165: <ST_IN_SCRIPTING>"public" {
                   1166:        return T_PUBLIC;
                   1167: }
                   1168: 
                   1169: <ST_IN_SCRIPTING>"unset" {
                   1170:        return T_UNSET;
                   1171: }
                   1172: 
                   1173: <ST_IN_SCRIPTING>"=>" {
                   1174:        return T_DOUBLE_ARROW;
                   1175: }
                   1176: 
                   1177: <ST_IN_SCRIPTING>"list" {
                   1178:        return T_LIST;
                   1179: }
                   1180: 
                   1181: <ST_IN_SCRIPTING>"array" {
                   1182:        return T_ARRAY;
                   1183: }
                   1184: 
                   1185: <ST_IN_SCRIPTING>"++" {
                   1186:        return T_INC;
                   1187: }
                   1188: 
                   1189: <ST_IN_SCRIPTING>"--" {
                   1190:        return T_DEC;
                   1191: }
                   1192: 
                   1193: <ST_IN_SCRIPTING>"===" {
                   1194:        return T_IS_IDENTICAL;
                   1195: }
                   1196: 
                   1197: <ST_IN_SCRIPTING>"!==" {
                   1198:        return T_IS_NOT_IDENTICAL;
                   1199: }
                   1200: 
                   1201: <ST_IN_SCRIPTING>"==" {
                   1202:        return T_IS_EQUAL;
                   1203: }
                   1204: 
                   1205: <ST_IN_SCRIPTING>"!="|"<>" {
                   1206:        return T_IS_NOT_EQUAL;
                   1207: }
                   1208: 
                   1209: <ST_IN_SCRIPTING>"<=" {
                   1210:        return T_IS_SMALLER_OR_EQUAL;
                   1211: }
                   1212: 
                   1213: <ST_IN_SCRIPTING>">=" {
                   1214:        return T_IS_GREATER_OR_EQUAL;
                   1215: }
                   1216: 
                   1217: <ST_IN_SCRIPTING>"+=" {
                   1218:        return T_PLUS_EQUAL;
                   1219: }
                   1220: 
                   1221: <ST_IN_SCRIPTING>"-=" {
                   1222:        return T_MINUS_EQUAL;
                   1223: }
                   1224: 
                   1225: <ST_IN_SCRIPTING>"*=" {
                   1226:        return T_MUL_EQUAL;
                   1227: }
                   1228: 
                   1229: <ST_IN_SCRIPTING>"/=" {
                   1230:        return T_DIV_EQUAL;
                   1231: }
                   1232: 
                   1233: <ST_IN_SCRIPTING>".=" {
                   1234:        return T_CONCAT_EQUAL;
                   1235: }
                   1236: 
                   1237: <ST_IN_SCRIPTING>"%=" {
                   1238:        return T_MOD_EQUAL;
                   1239: }
                   1240: 
                   1241: <ST_IN_SCRIPTING>"<<=" {
                   1242:        return T_SL_EQUAL;
                   1243: }
                   1244: 
                   1245: <ST_IN_SCRIPTING>">>=" {
                   1246:        return T_SR_EQUAL;
                   1247: }
                   1248: 
                   1249: <ST_IN_SCRIPTING>"&=" {
                   1250:        return T_AND_EQUAL;
                   1251: }
                   1252: 
                   1253: <ST_IN_SCRIPTING>"|=" {
                   1254:        return T_OR_EQUAL;
                   1255: }
                   1256: 
                   1257: <ST_IN_SCRIPTING>"^=" {
                   1258:        return T_XOR_EQUAL;
                   1259: }
                   1260: 
                   1261: <ST_IN_SCRIPTING>"||" {
                   1262:        return T_BOOLEAN_OR;
                   1263: }
                   1264: 
                   1265: <ST_IN_SCRIPTING>"&&" {
                   1266:        return T_BOOLEAN_AND;
                   1267: }
                   1268: 
                   1269: <ST_IN_SCRIPTING>"OR" {
                   1270:        return T_LOGICAL_OR;
                   1271: }
                   1272: 
                   1273: <ST_IN_SCRIPTING>"AND" {
                   1274:        return T_LOGICAL_AND;
                   1275: }
                   1276: 
                   1277: <ST_IN_SCRIPTING>"XOR" {
                   1278:        return T_LOGICAL_XOR;
                   1279: }
                   1280: 
                   1281: <ST_IN_SCRIPTING>"<<" {
                   1282:        return T_SL;
                   1283: }
                   1284: 
                   1285: <ST_IN_SCRIPTING>">>" {
                   1286:        return T_SR;
                   1287: }
                   1288: 
                   1289: <ST_IN_SCRIPTING>{TOKENS} {
                   1290:        return yytext[0];
                   1291: }
                   1292: 
                   1293: 
                   1294: <ST_IN_SCRIPTING>"{" {
                   1295:        yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
                   1296:        return '{';
                   1297: }
                   1298: 
                   1299: 
                   1300: <ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"${" {
                   1301:        yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC);
                   1302:        return T_DOLLAR_OPEN_CURLY_BRACES;
                   1303: }
                   1304: 
                   1305: 
                   1306: <ST_IN_SCRIPTING>"}" {
                   1307:        RESET_DOC_COMMENT();
                   1308:        if (!zend_stack_is_empty(&SCNG(state_stack))) {
                   1309:                yy_pop_state(TSRMLS_C);
                   1310:        }
                   1311:        return '}';
                   1312: }
                   1313: 
                   1314: 
                   1315: <ST_LOOKING_FOR_VARNAME>{LABEL} {
                   1316:        zend_copy_value(zendlval, yytext, yyleng);
                   1317:        zendlval->type = IS_STRING;
                   1318:        yy_pop_state(TSRMLS_C);
                   1319:        yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
                   1320:        return T_STRING_VARNAME;
                   1321: }
                   1322: 
                   1323: 
                   1324: <ST_LOOKING_FOR_VARNAME>{ANY_CHAR} {
                   1325:        yyless(0);
                   1326:        yy_pop_state(TSRMLS_C);
                   1327:        yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
                   1328:        goto restart;
                   1329: }
                   1330: 
                   1331: 
                   1332: <ST_IN_SCRIPTING>{LNUM} {
                   1333:        if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */
                   1334:                zendlval->value.lval = strtol(yytext, NULL, 0);
                   1335:        } else {
                   1336:                errno = 0;
                   1337:                zendlval->value.lval = strtol(yytext, NULL, 0);
                   1338:                if (errno == ERANGE) { /* Overflow */
                   1339:                        if (yytext[0] == '0') { /* octal overflow */
                   1340:                                zendlval->value.dval = zend_oct_strtod(yytext, NULL);
                   1341:                        } else {
                   1342:                                zendlval->value.dval = zend_strtod(yytext, NULL);
                   1343:                        }
                   1344:                        zendlval->type = IS_DOUBLE;
                   1345:                        return T_DNUMBER;
                   1346:                }
                   1347:        }
                   1348: 
                   1349:        zendlval->type = IS_LONG;
                   1350:        return T_LNUMBER;
                   1351: }
                   1352: 
                   1353: <ST_IN_SCRIPTING>{HNUM} {
                   1354:        char *hex = yytext + 2; /* Skip "0x" */
                   1355:        int len = yyleng - 2;
                   1356: 
                   1357:        /* Skip any leading 0s */
                   1358:        while (*hex == '0') {
                   1359:                hex++;
                   1360:                len--;
                   1361:        }
                   1362: 
                   1363:        if (len < SIZEOF_LONG * 2 || (len == SIZEOF_LONG * 2 && *hex <= '7')) {
                   1364:                zendlval->value.lval = strtol(hex, NULL, 16);
                   1365:                zendlval->type = IS_LONG;
                   1366:                return T_LNUMBER;
                   1367:        } else {
                   1368:                zendlval->value.dval = zend_hex_strtod(hex, NULL);
                   1369:                zendlval->type = IS_DOUBLE;
                   1370:                return T_DNUMBER;
                   1371:        }
                   1372: }
                   1373: 
                   1374: <ST_VAR_OFFSET>[0]|([1-9][0-9]*) { /* Offset could be treated as a long */
                   1375:        if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) {
                   1376:                zendlval->value.lval = strtol(yytext, NULL, 10);
                   1377:                zendlval->type = IS_LONG;
                   1378:        } else {
                   1379:                zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
                   1380:                zendlval->value.str.len = yyleng;
                   1381:                zendlval->type = IS_STRING;
                   1382:        }
                   1383:        return T_NUM_STRING;
                   1384: }
                   1385: 
                   1386: <ST_VAR_OFFSET>{LNUM}|{HNUM} { /* Offset must be treated as a string */
                   1387:        zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
                   1388:        zendlval->value.str.len = yyleng;
                   1389:        zendlval->type = IS_STRING;
                   1390:        return T_NUM_STRING;
                   1391: }
                   1392: 
                   1393: <ST_IN_SCRIPTING>{DNUM}|{EXPONENT_DNUM} {
                   1394:        zendlval->value.dval = zend_strtod(yytext, NULL);
                   1395:        zendlval->type = IS_DOUBLE;
                   1396:        return T_DNUMBER;
                   1397: }
                   1398: 
                   1399: <ST_IN_SCRIPTING>"__CLASS__" {
                   1400:        char *class_name = NULL;
                   1401: 
                   1402:        if (CG(active_class_entry)) {
                   1403:                class_name = CG(active_class_entry)->name;
                   1404:        }
                   1405: 
                   1406:        if (!class_name) {
                   1407:                class_name = "";
                   1408:        }
                   1409:        zendlval->value.str.len = strlen(class_name);
                   1410:        zendlval->value.str.val = estrndup(class_name, zendlval->value.str.len);
                   1411:        zendlval->type = IS_STRING;
                   1412:        return T_CLASS_C;
                   1413: }
                   1414: 
                   1415: <ST_IN_SCRIPTING>"__FUNCTION__" {
                   1416:        char *func_name = NULL;
                   1417: 
                   1418:        if (CG(active_op_array)) {
                   1419:                func_name = CG(active_op_array)->function_name;
                   1420:        }
                   1421: 
                   1422:        if (!func_name) {
                   1423:                func_name = "";
                   1424:        }
                   1425:        zendlval->value.str.len = strlen(func_name);
                   1426:        zendlval->value.str.val = estrndup(func_name, zendlval->value.str.len);
                   1427:        zendlval->type = IS_STRING;
                   1428:        return T_FUNC_C;
                   1429: }
                   1430: 
                   1431: <ST_IN_SCRIPTING>"__METHOD__" {
                   1432:        char *class_name = CG(active_class_entry) ? CG(active_class_entry)->name : NULL;
                   1433:        char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL;
                   1434:        size_t len = 0;
                   1435: 
                   1436:        if (class_name) {
                   1437:                len += strlen(class_name) + 2;
                   1438:        }
                   1439:        if (func_name) {
                   1440:                len += strlen(func_name);
                   1441:        }
                   1442: 
                   1443:        zendlval->value.str.len = zend_spprintf(&zendlval->value.str.val, 0, "%s%s%s", 
                   1444:                class_name ? class_name : "",
                   1445:                class_name && func_name ? "::" : "",
                   1446:                func_name ? func_name : ""
                   1447:                );
                   1448:        zendlval->type = IS_STRING;
                   1449:        return T_METHOD_C;
                   1450: }
                   1451: 
                   1452: <ST_IN_SCRIPTING>"__LINE__" {
                   1453:        zendlval->value.lval = CG(zend_lineno);
                   1454:        zendlval->type = IS_LONG;
                   1455:        return T_LINE;
                   1456: }
                   1457: 
                   1458: <ST_IN_SCRIPTING>"__FILE__" {
                   1459:        char *filename = zend_get_compiled_filename(TSRMLS_C);
                   1460: 
                   1461:        if (!filename) {
                   1462:                filename = "";
                   1463:        }
                   1464:        zendlval->value.str.len = strlen(filename);
                   1465:        zendlval->value.str.val = estrndup(filename, zendlval->value.str.len);
                   1466:        zendlval->type = IS_STRING;
                   1467:        return T_FILE;
                   1468: }
                   1469: 
                   1470: <ST_IN_SCRIPTING>"__DIR__" {
                   1471:        char *filename = zend_get_compiled_filename(TSRMLS_C);
                   1472:        const size_t filename_len = strlen(filename);
                   1473:        char *dirname;
                   1474: 
                   1475:        if (!filename) {
                   1476:                filename = "";
                   1477:        }
                   1478: 
                   1479:        dirname = estrndup(filename, filename_len);
                   1480:        zend_dirname(dirname, filename_len);
                   1481: 
                   1482:        if (strcmp(dirname, ".") == 0) {
                   1483:                dirname = erealloc(dirname, MAXPATHLEN);
                   1484: #if HAVE_GETCWD
                   1485:                VCWD_GETCWD(dirname, MAXPATHLEN);
                   1486: #elif HAVE_GETWD
                   1487:                VCWD_GETWD(dirname);
                   1488: #endif
                   1489:        }
                   1490: 
                   1491:        zendlval->value.str.len = strlen(dirname);
                   1492:        zendlval->value.str.val = dirname;
                   1493:        zendlval->type = IS_STRING;
                   1494:        return T_DIR;
                   1495: }
                   1496: 
                   1497: <ST_IN_SCRIPTING>"__NAMESPACE__" {
                   1498:        if (CG(current_namespace)) {
                   1499:                *zendlval = *CG(current_namespace);
                   1500:                zval_copy_ctor(zendlval);
                   1501:        } else {
                   1502:                ZVAL_EMPTY_STRING(zendlval);
                   1503:        }
                   1504:        return T_NS_C;
                   1505: }
                   1506: 
                   1507: <INITIAL>"<script"{WHITESPACE}+"language"{WHITESPACE}*"="{WHITESPACE}*("php"|"\"php\""|"'php'"){WHITESPACE}*">" {
                   1508:        YYCTYPE *bracket = zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1));
                   1509: 
                   1510:        if (bracket != SCNG(yy_text)) {
                   1511:                /* Handle previously scanned HTML, as possible <script> tags found are assumed to not be PHP's */
                   1512:                YYCURSOR = bracket;
                   1513:                goto inline_html;
                   1514:        }
                   1515: 
                   1516:        HANDLE_NEWLINES(yytext, yyleng);
                   1517:        zendlval->value.str.val = yytext; /* no copying - intentional */
                   1518:        zendlval->value.str.len = yyleng;
                   1519:        zendlval->type = IS_STRING;
                   1520:        BEGIN(ST_IN_SCRIPTING);
                   1521:        return T_OPEN_TAG;
                   1522: }
                   1523: 
                   1524: 
                   1525: <INITIAL>"<%=" {
                   1526:        if (CG(asp_tags)) {
                   1527:                zendlval->value.str.val = yytext; /* no copying - intentional */
                   1528:                zendlval->value.str.len = yyleng;
                   1529:                zendlval->type = IS_STRING;
                   1530:                BEGIN(ST_IN_SCRIPTING);
                   1531:                return T_OPEN_TAG_WITH_ECHO;
                   1532:        } else {
                   1533:                goto inline_char_handler;
                   1534:        }
                   1535: }
                   1536: 
                   1537: 
                   1538: <INITIAL>"<?=" {
                   1539:        if (CG(short_tags)) {
                   1540:                zendlval->value.str.val = yytext; /* no copying - intentional */
                   1541:                zendlval->value.str.len = yyleng;
                   1542:                zendlval->type = IS_STRING;
                   1543:                BEGIN(ST_IN_SCRIPTING);
                   1544:                return T_OPEN_TAG_WITH_ECHO;
                   1545:        } else {
                   1546:                goto inline_char_handler;
                   1547:        }
                   1548: }
                   1549: 
                   1550: 
                   1551: <INITIAL>"<%" {
                   1552:        if (CG(asp_tags)) {
                   1553:                zendlval->value.str.val = yytext; /* no copying - intentional */
                   1554:                zendlval->value.str.len = yyleng;
                   1555:                zendlval->type = IS_STRING;
                   1556:                BEGIN(ST_IN_SCRIPTING);
                   1557:                return T_OPEN_TAG;
                   1558:        } else {
                   1559:                goto inline_char_handler;
                   1560:        }
                   1561: }
                   1562: 
                   1563: 
                   1564: <INITIAL>"<?php"([ \t]|{NEWLINE}) {
                   1565:        zendlval->value.str.val = yytext; /* no copying - intentional */
                   1566:        zendlval->value.str.len = yyleng;
                   1567:        zendlval->type = IS_STRING;
                   1568:        HANDLE_NEWLINE(yytext[yyleng-1]);
                   1569:        BEGIN(ST_IN_SCRIPTING);
                   1570:        return T_OPEN_TAG;
                   1571: }
                   1572: 
                   1573: 
                   1574: <INITIAL>"<?" {
                   1575:        if (CG(short_tags)) {
                   1576:                zendlval->value.str.val = yytext; /* no copying - intentional */
                   1577:                zendlval->value.str.len = yyleng;
                   1578:                zendlval->type = IS_STRING;
                   1579:                BEGIN(ST_IN_SCRIPTING);
                   1580:                return T_OPEN_TAG;
                   1581:        } else {
                   1582:                goto inline_char_handler;
                   1583:        }
                   1584: }
                   1585: 
                   1586: <INITIAL>{ANY_CHAR} {
                   1587:        if (YYCURSOR > YYLIMIT) {
                   1588:                return 0;
                   1589:        }
                   1590: 
                   1591: inline_char_handler:
                   1592: 
                   1593:        while (1) {
                   1594:                YYCTYPE *ptr = memchr(YYCURSOR, '<', YYLIMIT - YYCURSOR);
                   1595: 
                   1596:                YYCURSOR = ptr ? ptr + 1 : YYLIMIT;
                   1597: 
                   1598:                if (YYCURSOR < YYLIMIT) {
                   1599:                        switch (*YYCURSOR) {
                   1600:                                case '?':
                   1601:                                        if (CG(short_tags) || !strncasecmp(YYCURSOR + 1, "php", 3)) { /* Assume [ \t\n\r] follows "php" */
                   1602:                                                break;
                   1603:                                        }
                   1604:                                        continue;
                   1605:                                case '%':
                   1606:                                        if (CG(asp_tags)) {
                   1607:                                                break;
                   1608:                                        }
                   1609:                                        continue;
                   1610:                                case 's':
                   1611:                                case 'S':
                   1612:                                        /* Probably NOT an opening PHP <script> tag, so don't end the HTML chunk yet
                   1613:                                         * If it is, the PHP <script> tag rule checks for any HTML scanned before it */
                   1614:                                        YYCURSOR--;
                   1615:                                        yymore();
                   1616:                                default:
                   1617:                                        continue;
                   1618:                        }
                   1619: 
                   1620:                        YYCURSOR--;
                   1621:                }
                   1622: 
                   1623:                break;
                   1624:        }
                   1625: 
                   1626: inline_html:
                   1627:        yyleng = YYCURSOR - SCNG(yy_text);
                   1628: 
                   1629: #ifdef ZEND_MULTIBYTE
                   1630:        if (SCNG(output_filter)) {
                   1631:                int readsize;
                   1632:                size_t sz = 0;
                   1633:                readsize = SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)yytext, (size_t)yyleng TSRMLS_CC);
                   1634:                zendlval->value.str.len = sz;
                   1635:                if (readsize < yyleng) {
                   1636:                        yyless(readsize);
                   1637:                }
                   1638:        } else {
                   1639:          zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
                   1640:          zendlval->value.str.len = yyleng;
                   1641:        }
                   1642: #else /* !ZEND_MULTIBYTE */
                   1643:        zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
                   1644:        zendlval->value.str.len = yyleng;
                   1645: #endif
                   1646:        zendlval->type = IS_STRING;
                   1647:        HANDLE_NEWLINES(yytext, yyleng);
                   1648:        return T_INLINE_HTML;
                   1649: }
                   1650: 
                   1651: 
                   1652: /* Make sure a label character follows "->", otherwise there is no property
                   1653:  * and "->" will be taken literally
                   1654:  */
                   1655: <ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE>"$"{LABEL}"->"[a-zA-Z_\x7f-\xff] {
                   1656:        yyless(yyleng - 3);
                   1657:        yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
                   1658:        zend_copy_value(zendlval, (yytext+1), (yyleng-1));
                   1659:        zendlval->type = IS_STRING;
                   1660:        return T_VARIABLE;
                   1661: }
                   1662: 
                   1663: /* A [ always designates a variable offset, regardless of what follows
                   1664:  */
                   1665: <ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE>"$"{LABEL}"[" {
                   1666:        yyless(yyleng - 1);
                   1667:        yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
                   1668:        zend_copy_value(zendlval, (yytext+1), (yyleng-1));
                   1669:        zendlval->type = IS_STRING;
                   1670:        return T_VARIABLE;
                   1671: }
                   1672: 
                   1673: <ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>"$"{LABEL} {
                   1674:        zend_copy_value(zendlval, (yytext+1), (yyleng-1));
                   1675:        zendlval->type = IS_STRING;
                   1676:        return T_VARIABLE;
                   1677: }
                   1678: 
                   1679: <ST_VAR_OFFSET>"]" {
                   1680:        yy_pop_state(TSRMLS_C);
                   1681:        return ']';
                   1682: }
                   1683: 
                   1684: <ST_VAR_OFFSET>{TOKENS}|[{}"`] {
                   1685:        /* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */
                   1686:        return yytext[0];
                   1687: }
                   1688: 
                   1689: <ST_VAR_OFFSET>[ \n\r\t\\'#] {
                   1690:        /* Invalid rule to return a more explicit parse error with proper line number */
                   1691:        yyless(0);
                   1692:        yy_pop_state(TSRMLS_C);
                   1693:        return T_ENCAPSED_AND_WHITESPACE;
                   1694: }
                   1695: 
                   1696: <ST_IN_SCRIPTING,ST_VAR_OFFSET>{LABEL} {
                   1697:        zend_copy_value(zendlval, yytext, yyleng);
                   1698:        zendlval->type = IS_STRING;
                   1699:        return T_STRING;
                   1700: }
                   1701: 
                   1702: 
                   1703: <ST_IN_SCRIPTING>"#"|"//" {
                   1704:        while (YYCURSOR < YYLIMIT) {
                   1705:                switch (*YYCURSOR++) {
                   1706:                        case '\r':
                   1707:                                if (*YYCURSOR == '\n') {
                   1708:                                        YYCURSOR++;
                   1709:                                }
                   1710:                                /* fall through */
                   1711:                        case '\n':
                   1712:                                CG(zend_lineno)++;
                   1713:                                break;
                   1714:                        case '%':
                   1715:                                if (!CG(asp_tags)) {
                   1716:                                        continue;
                   1717:                                }
                   1718:                                /* fall through */
                   1719:                        case '?':
                   1720:                                if (*YYCURSOR == '>') {
                   1721:                                        YYCURSOR--;
                   1722:                                        break;
                   1723:                                }
                   1724:                                /* fall through */
                   1725:                        default:
                   1726:                                continue;
                   1727:                }
                   1728: 
                   1729:                break;
                   1730:        }
                   1731: 
                   1732:        yyleng = YYCURSOR - SCNG(yy_text);
                   1733: 
                   1734:        return T_COMMENT;
                   1735: }
                   1736: 
                   1737: <ST_IN_SCRIPTING>"/*"|"/**"{WHITESPACE} {
                   1738:        int doc_com;
                   1739: 
                   1740:        if (yyleng > 2) {
                   1741:                doc_com = 1;
                   1742:                RESET_DOC_COMMENT();
                   1743:        } else {
                   1744:                doc_com = 0;
                   1745:        }
                   1746: 
                   1747:        while (YYCURSOR < YYLIMIT) {
                   1748:                if (*YYCURSOR++ == '*' && *YYCURSOR == '/') {
                   1749:                        break;
                   1750:                }
                   1751:        }
                   1752: 
                   1753:        if (YYCURSOR < YYLIMIT) {
                   1754:                YYCURSOR++;
                   1755:        } else {
                   1756:                zend_error(E_COMPILE_WARNING, "Unterminated comment starting line %d", CG(zend_lineno));
                   1757:        }
                   1758: 
                   1759:        yyleng = YYCURSOR - SCNG(yy_text);
                   1760:        HANDLE_NEWLINES(yytext, yyleng);
                   1761: 
                   1762:        if (doc_com) {
                   1763:                CG(doc_comment) = estrndup(yytext, yyleng);
                   1764:                CG(doc_comment_len) = yyleng;
                   1765:                return T_DOC_COMMENT;
                   1766:        }
                   1767: 
                   1768:        return T_COMMENT;
                   1769: }
                   1770: 
                   1771: <ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*">"){NEWLINE}? {
                   1772:        zendlval->value.str.val = yytext; /* no copying - intentional */
                   1773:        zendlval->value.str.len = yyleng;
                   1774:        zendlval->type = IS_STRING;
                   1775:        BEGIN(INITIAL);
                   1776:        return T_CLOSE_TAG;  /* implicit ';' at php-end tag */
                   1777: }
                   1778: 
                   1779: 
                   1780: <ST_IN_SCRIPTING>"%>"{NEWLINE}? {
                   1781:        if (CG(asp_tags)) {
                   1782:                BEGIN(INITIAL);
                   1783:                zendlval->value.str.len = yyleng;
                   1784:                zendlval->type = IS_STRING;
                   1785:                zendlval->value.str.val = yytext; /* no copying - intentional */
                   1786:                return T_CLOSE_TAG;  /* implicit ';' at php-end tag */
                   1787:        } else {
                   1788:                yyless(1);
                   1789:                return yytext[0];
                   1790:        }
                   1791: }
                   1792: 
                   1793: 
                   1794: <ST_IN_SCRIPTING>b?['] {
                   1795:        register char *s, *t;
                   1796:        char *end;
                   1797:        int bprefix = (yytext[0] != '\'') ? 1 : 0;
                   1798: 
                   1799:        while (1) {
                   1800:                if (YYCURSOR < YYLIMIT) {
                   1801:                        if (*YYCURSOR == '\'') {
                   1802:                                YYCURSOR++;
                   1803:                                yyleng = YYCURSOR - SCNG(yy_text);
                   1804: 
                   1805:                                break;
                   1806:                        } else if (*YYCURSOR++ == '\\' && YYCURSOR < YYLIMIT) {
                   1807:                                YYCURSOR++;
                   1808:                        }
                   1809:                } else {
                   1810:                        yyleng = YYLIMIT - SCNG(yy_text);
                   1811: 
                   1812:                        /* Unclosed single quotes; treat similar to double quotes, but without a separate token
                   1813:                         * for ' (unrecognized by parser), instead of old flex fallback to "Unexpected character..."
                   1814:                         * rule, which continued in ST_IN_SCRIPTING state after the quote */
                   1815:                        return T_ENCAPSED_AND_WHITESPACE;
                   1816:                }
                   1817:        }
                   1818: 
                   1819:        zendlval->value.str.val = estrndup(yytext+bprefix+1, yyleng-bprefix-2);
                   1820:        zendlval->value.str.len = yyleng-bprefix-2;
                   1821:        zendlval->type = IS_STRING;
                   1822: 
                   1823:        /* convert escape sequences */
                   1824:        s = t = zendlval->value.str.val;
                   1825:        end = s+zendlval->value.str.len;
                   1826:        while (s<end) {
                   1827:                if (*s=='\\') {
                   1828:                        s++;
                   1829: 
                   1830:                        switch(*s) {
                   1831:                                case '\\':
                   1832:                                case '\'':
                   1833:                                        *t++ = *s;
                   1834:                                        zendlval->value.str.len--;
                   1835:                                        break;
                   1836:                                default:
                   1837:                                        *t++ = '\\';
                   1838:                                        *t++ = *s;
                   1839:                                        break;
                   1840:                        }
                   1841:                } else {
                   1842:                        *t++ = *s;
                   1843:                }
                   1844: 
                   1845:                if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) {
                   1846:                        CG(zend_lineno)++;
                   1847:                }
                   1848:                s++;
                   1849:        }
                   1850:        *t = 0;
                   1851: 
                   1852: #ifdef ZEND_MULTIBYTE
                   1853:        if (SCNG(output_filter)) {
                   1854:                size_t sz = 0;
                   1855:                s = zendlval->value.str.val;
                   1856:                SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)s, (size_t)zendlval->value.str.len TSRMLS_CC);
                   1857:                zendlval->value.str.len = sz;
                   1858:                efree(s);
                   1859:        }
                   1860: #endif /* ZEND_MULTIBYTE */
                   1861:        return T_CONSTANT_ENCAPSED_STRING;
                   1862: }
                   1863: 
                   1864: 
                   1865: <ST_IN_SCRIPTING>b?["] {
                   1866:        int bprefix = (yytext[0] != '"') ? 1 : 0;
                   1867: 
                   1868:        while (YYCURSOR < YYLIMIT) {
                   1869:                switch (*YYCURSOR++) {
                   1870:                        case '"':
                   1871:                                yyleng = YYCURSOR - SCNG(yy_text);
                   1872:                                zend_scan_escape_string(zendlval, yytext+bprefix+1, yyleng-bprefix-2, '"' TSRMLS_CC);
                   1873:                                return T_CONSTANT_ENCAPSED_STRING;
                   1874:                        case '$':
                   1875:                                if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
                   1876:                                        break;
                   1877:                                }
                   1878:                                continue;
                   1879:                        case '{':
                   1880:                                if (*YYCURSOR == '$') {
                   1881:                                        break;
                   1882:                                }
                   1883:                                continue;
                   1884:                        case '\\':
                   1885:                                if (YYCURSOR < YYLIMIT) {
                   1886:                                        YYCURSOR++;
                   1887:                                }
                   1888:                                /* fall through */
                   1889:                        default:
                   1890:                                continue;
                   1891:                }
                   1892: 
                   1893:                YYCURSOR--;
                   1894:                break;
                   1895:        }
                   1896: 
                   1897:        /* Remember how much was scanned to save rescanning */
                   1898:        SET_DOUBLE_QUOTES_SCANNED_LENGTH(YYCURSOR - SCNG(yy_text) - yyleng);
                   1899: 
                   1900:        YYCURSOR = SCNG(yy_text) + yyleng;
                   1901: 
                   1902:        BEGIN(ST_DOUBLE_QUOTES);
                   1903:        return '"';
                   1904: }
                   1905: 
                   1906: 
                   1907: <ST_IN_SCRIPTING>b?"<<<"{TABS_AND_SPACES}({LABEL}|([']{LABEL}['])|(["]{LABEL}["])){NEWLINE} {
                   1908:        char *s;
                   1909:        int bprefix = (yytext[0] != '<') ? 1 : 0;
                   1910: 
                   1911:        /* save old heredoc label */
                   1912:        Z_STRVAL_P(zendlval) = CG(heredoc);
                   1913:        Z_STRLEN_P(zendlval) = CG(heredoc_len);
                   1914: 
                   1915:        CG(zend_lineno)++;
                   1916:        CG(heredoc_len) = yyleng-bprefix-3-1-(yytext[yyleng-2]=='\r'?1:0);
                   1917:        s = yytext+bprefix+3;
                   1918:        while ((*s == ' ') || (*s == '\t')) {
                   1919:                s++;
                   1920:                CG(heredoc_len)--;
                   1921:        }
                   1922: 
                   1923:        if (*s == '\'') {
                   1924:                s++;
                   1925:                CG(heredoc_len) -= 2;
                   1926: 
                   1927:                BEGIN(ST_NOWDOC);
                   1928:        } else {
                   1929:                if (*s == '"') {
                   1930:                        s++;
                   1931:                        CG(heredoc_len) -= 2;
                   1932:                }
                   1933: 
                   1934:                BEGIN(ST_HEREDOC);
                   1935:        }
                   1936: 
                   1937:        CG(heredoc) = estrndup(s, CG(heredoc_len));
                   1938: 
                   1939:        /* Check for ending label on the next line */
                   1940:        if (CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, s, CG(heredoc_len))) {
                   1941:                YYCTYPE *end = YYCURSOR + CG(heredoc_len);
                   1942: 
                   1943:                if (*end == ';') {
                   1944:                        end++;
                   1945:                }
                   1946: 
                   1947:                if (*end == '\n' || *end == '\r') {
                   1948:                        BEGIN(ST_END_HEREDOC);
                   1949:                }
                   1950:        }
                   1951: 
                   1952:        return T_START_HEREDOC;
                   1953: }
                   1954: 
                   1955: 
                   1956: <ST_IN_SCRIPTING>[`] {
                   1957:        BEGIN(ST_BACKQUOTE);
                   1958:        return '`';
                   1959: }
                   1960: 
                   1961: 
                   1962: <ST_END_HEREDOC>{ANY_CHAR} {
                   1963:        YYCURSOR += CG(heredoc_len) - 1;
                   1964:        yyleng = CG(heredoc_len);
                   1965: 
                   1966:        Z_STRVAL_P(zendlval) = CG(heredoc);
                   1967:        Z_STRLEN_P(zendlval) = CG(heredoc_len);
                   1968:        CG(heredoc) = NULL;
                   1969:        CG(heredoc_len) = 0;
                   1970:        BEGIN(ST_IN_SCRIPTING);
                   1971:        return T_END_HEREDOC;
                   1972: }
                   1973: 
                   1974: 
                   1975: <ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"{$" {
                   1976:        zendlval->value.lval = (long) '{';
                   1977:        yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
                   1978:        yyless(1);
                   1979:        return T_CURLY_OPEN;
                   1980: }
                   1981: 
                   1982: 
                   1983: <ST_DOUBLE_QUOTES>["] {
                   1984:        BEGIN(ST_IN_SCRIPTING);
                   1985:        return '"';
                   1986: }
                   1987: 
                   1988: <ST_BACKQUOTE>[`] {
                   1989:        BEGIN(ST_IN_SCRIPTING);
                   1990:        return '`';
                   1991: }
                   1992: 
                   1993: 
                   1994: <ST_DOUBLE_QUOTES>{ANY_CHAR} {
                   1995:        if (GET_DOUBLE_QUOTES_SCANNED_LENGTH()) {
                   1996:                YYCURSOR += GET_DOUBLE_QUOTES_SCANNED_LENGTH() - 1;
                   1997:                SET_DOUBLE_QUOTES_SCANNED_LENGTH(0);
                   1998: 
                   1999:                goto double_quotes_scan_done;
                   2000:        }
                   2001: 
                   2002:        if (YYCURSOR > YYLIMIT) {
                   2003:                return 0;
                   2004:        }
                   2005:        if (yytext[0] == '\\' && YYCURSOR < YYLIMIT) {
                   2006:                YYCURSOR++;
                   2007:        }
                   2008: 
                   2009:        while (YYCURSOR < YYLIMIT) {
                   2010:                switch (*YYCURSOR++) {
                   2011:                        case '"':
                   2012:                                break;
                   2013:                        case '$':
                   2014:                                if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
                   2015:                                        break;
                   2016:                                }
                   2017:                                continue;
                   2018:                        case '{':
                   2019:                                if (*YYCURSOR == '$') {
                   2020:                                        break;
                   2021:                                }
                   2022:                                continue;
                   2023:                        case '\\':
                   2024:                                if (YYCURSOR < YYLIMIT) {
                   2025:                                        YYCURSOR++;
                   2026:                                }
                   2027:                                /* fall through */
                   2028:                        default:
                   2029:                                continue;
                   2030:                }
                   2031: 
                   2032:                YYCURSOR--;
                   2033:                break;
                   2034:        }
                   2035: 
                   2036: double_quotes_scan_done:
                   2037:        yyleng = YYCURSOR - SCNG(yy_text);
                   2038: 
                   2039:        zend_scan_escape_string(zendlval, yytext, yyleng, '"' TSRMLS_CC);
                   2040:        return T_ENCAPSED_AND_WHITESPACE;
                   2041: }
                   2042: 
                   2043: 
                   2044: <ST_BACKQUOTE>{ANY_CHAR} {
                   2045:        if (YYCURSOR > YYLIMIT) {
                   2046:                return 0;
                   2047:        }
                   2048:        if (yytext[0] == '\\' && YYCURSOR < YYLIMIT) {
                   2049:                YYCURSOR++;
                   2050:        }
                   2051: 
                   2052:        while (YYCURSOR < YYLIMIT) {
                   2053:                switch (*YYCURSOR++) {
                   2054:                        case '`':
                   2055:                                break;
                   2056:                        case '$':
                   2057:                                if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
                   2058:                                        break;
                   2059:                                }
                   2060:                                continue;
                   2061:                        case '{':
                   2062:                                if (*YYCURSOR == '$') {
                   2063:                                        break;
                   2064:                                }
                   2065:                                continue;
                   2066:                        case '\\':
                   2067:                                if (YYCURSOR < YYLIMIT) {
                   2068:                                        YYCURSOR++;
                   2069:                                }
                   2070:                                /* fall through */
                   2071:                        default:
                   2072:                                continue;
                   2073:                }
                   2074: 
                   2075:                YYCURSOR--;
                   2076:                break;
                   2077:        }
                   2078: 
                   2079:        yyleng = YYCURSOR - SCNG(yy_text);
                   2080: 
                   2081:        zend_scan_escape_string(zendlval, yytext, yyleng, '`' TSRMLS_CC);
                   2082:        return T_ENCAPSED_AND_WHITESPACE;
                   2083: }
                   2084: 
                   2085: 
                   2086: <ST_HEREDOC>{ANY_CHAR} {
                   2087:        int newline = 0;
                   2088: 
                   2089:        if (YYCURSOR > YYLIMIT) {
                   2090:                return 0;
                   2091:        }
                   2092: 
                   2093:        YYCURSOR--;
                   2094: 
                   2095:        while (YYCURSOR < YYLIMIT) {
                   2096:                switch (*YYCURSOR++) {
                   2097:                        case '\r':
                   2098:                                if (*YYCURSOR == '\n') {
                   2099:                                        YYCURSOR++;
                   2100:                                }
                   2101:                                /* fall through */
                   2102:                        case '\n':
                   2103:                                /* Check for ending label on the next line */
                   2104:                                if (IS_LABEL_START(*YYCURSOR) && CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, CG(heredoc), CG(heredoc_len))) {
                   2105:                                        YYCTYPE *end = YYCURSOR + CG(heredoc_len);
                   2106: 
                   2107:                                        if (*end == ';') {
                   2108:                                                end++;
                   2109:                                        }
                   2110: 
                   2111:                                        if (*end == '\n' || *end == '\r') {
                   2112:                                                /* newline before label will be subtracted from returned text, but
                   2113:                                                 * yyleng/yytext will include it, for zend_highlight/strip, tokenizer, etc. */
                   2114:                                                if (YYCURSOR[-2] == '\r' && YYCURSOR[-1] == '\n') {
                   2115:                                                        newline = 2; /* Windows newline */
                   2116:                                                } else {
                   2117:                                                        newline = 1;
                   2118:                                                }
                   2119: 
                   2120:                                                CG(increment_lineno) = 1; /* For newline before label */
                   2121:                                                BEGIN(ST_END_HEREDOC);
                   2122: 
                   2123:                                                goto heredoc_scan_done;
                   2124:                                        }
                   2125:                                }
                   2126:                                continue;
                   2127:                        case '$':
                   2128:                                if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
                   2129:                                        break;
                   2130:                                }
                   2131:                                continue;
                   2132:                        case '{':
                   2133:                                if (*YYCURSOR == '$') {
                   2134:                                        break;
                   2135:                                }
                   2136:                                continue;
                   2137:                        case '\\':
                   2138:                                if (YYCURSOR < YYLIMIT && *YYCURSOR != '\n' && *YYCURSOR != '\r') {
                   2139:                                        YYCURSOR++;
                   2140:                                }
                   2141:                                /* fall through */
                   2142:                        default:
                   2143:                                continue;
                   2144:                }
                   2145: 
                   2146:                YYCURSOR--;
                   2147:                break;
                   2148:        }
                   2149: 
                   2150: heredoc_scan_done:
                   2151:        yyleng = YYCURSOR - SCNG(yy_text);
                   2152: 
                   2153:        zend_scan_escape_string(zendlval, yytext, yyleng - newline, 0 TSRMLS_CC);
                   2154:        return T_ENCAPSED_AND_WHITESPACE;
                   2155: }
                   2156: 
                   2157: 
                   2158: <ST_NOWDOC>{ANY_CHAR} {
                   2159:        int newline = 0;
                   2160: 
                   2161:        if (YYCURSOR > YYLIMIT) {
                   2162:                return 0;
                   2163:        }
                   2164: 
                   2165:        YYCURSOR--;
                   2166: 
                   2167:        while (YYCURSOR < YYLIMIT) {
                   2168:                switch (*YYCURSOR++) {
                   2169:                        case '\r':
                   2170:                                if (*YYCURSOR == '\n') {
                   2171:                                        YYCURSOR++;
                   2172:                                }
                   2173:                                /* fall through */
                   2174:                        case '\n':
                   2175:                                /* Check for ending label on the next line */
                   2176:                                if (IS_LABEL_START(*YYCURSOR) && CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, CG(heredoc), CG(heredoc_len))) {
                   2177:                                        YYCTYPE *end = YYCURSOR + CG(heredoc_len);
                   2178: 
                   2179:                                        if (*end == ';') {
                   2180:                                                end++;
                   2181:                                        }
                   2182: 
                   2183:                                        if (*end == '\n' || *end == '\r') {
                   2184:                                                /* newline before label will be subtracted from returned text, but
                   2185:                                                 * yyleng/yytext will include it, for zend_highlight/strip, tokenizer, etc. */
                   2186:                                                if (YYCURSOR[-2] == '\r' && YYCURSOR[-1] == '\n') {
                   2187:                                                        newline = 2; /* Windows newline */
                   2188:                                                } else {
                   2189:                                                        newline = 1;
                   2190:                                                }
                   2191: 
                   2192:                                                CG(increment_lineno) = 1; /* For newline before label */
                   2193:                                                BEGIN(ST_END_HEREDOC);
                   2194: 
                   2195:                                                goto nowdoc_scan_done;
                   2196:                                        }
                   2197:                                }
                   2198:                                /* fall through */
                   2199:                        default:
                   2200:                                continue;
                   2201:                }
                   2202:        }
                   2203: 
                   2204: nowdoc_scan_done:
                   2205:        yyleng = YYCURSOR - SCNG(yy_text);
                   2206: 
                   2207:        zend_copy_value(zendlval, yytext, yyleng - newline);
                   2208:        zendlval->type = IS_STRING;
                   2209:        HANDLE_NEWLINES(yytext, yyleng - newline);
                   2210:        return T_ENCAPSED_AND_WHITESPACE;
                   2211: }
                   2212: 
                   2213: 
                   2214: <ST_IN_SCRIPTING,ST_VAR_OFFSET>{ANY_CHAR} {
                   2215:        if (YYCURSOR > YYLIMIT) {
                   2216:                return 0;
                   2217:        }
                   2218: 
                   2219:        zend_error(E_COMPILE_WARNING,"Unexpected character in input:  '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
                   2220:        goto restart;
                   2221: }
                   2222: 
                   2223: */
                   2224: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>