2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2013 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 +----------------------------------------------------------------------+
27 # define YYDEBUG(s, c) printf("state: %d char: %c\n", s, c)
29 # define YYDEBUG(s, c)
32 #include "zend_language_scanner_defs.h"
39 #include "zend_alloc.h"
40 #include <zend_language_parser.h>
41 #include "zend_compile.h"
42 #include "zend_language_scanner.h"
43 #include "zend_highlight.h"
44 #include "zend_constants.h"
45 #include "zend_variables.h"
46 #include "zend_operators.h"
48 #include "zend_strtod.h"
49 #include "zend_exceptions.h"
50 #include "tsrm_virtual_cwd.h"
51 #include "tsrm_config_common.h"
53 #define YYCTYPE unsigned char
54 #define YYFILL(n) { if ((YYCURSOR + n) >= (YYLIMIT + ZEND_MMAP_AHEAD)) { return 0; } }
55 #define YYCURSOR SCNG(yy_cursor)
56 #define YYLIMIT SCNG(yy_limit)
57 #define YYMARKER SCNG(yy_marker)
59 #define YYGETCONDITION() SCNG(yy_state)
60 #define YYSETCONDITION(s) SCNG(yy_state) = s
62 #define STATE(name) yyc##name
64 /* emulate flex constructs */
65 #define BEGIN(state) YYSETCONDITION(STATE(state))
66 #define YYSTATE YYGETCONDITION()
67 #define yytext ((char*)SCNG(yy_text))
68 #define yyleng SCNG(yy_leng)
69 #define yyless(x) do { YYCURSOR = (unsigned char*)yytext + x; \
70 yyleng = (unsigned int)x; } while(0)
71 #define yymore() goto yymore_restart
73 /* perform sanity check. If this message is triggered you should
74 increase the ZEND_MMAP_AHEAD value in the zend_streams.h file */
76 #if ZEND_MMAP_AHEAD < YYMAXFILL
77 # error ZEND_MMAP_AHEAD should be greater than or equal to YYMAXFILL
89 #define SCNG LANG_SCNG
91 ZEND_API ts_rsrc_id language_scanner_globals_id;
93 ZEND_API zend_php_scanner_globals language_scanner_globals;
96 #define HANDLE_NEWLINES(s, l) \
98 char *p = (s), *boundary = p+(l); \
100 while (p<boundary) { \
101 if (*p == '\n' || (*p == '\r' && (*(p+1) != '\n'))) { \
108 #define HANDLE_NEWLINE(c) \
110 if (c == '\n' || c == '\r') { \
115 /* To save initial string length after scanning to first variable, CG(doc_comment_len) can be reused */
116 #define SET_DOUBLE_QUOTES_SCANNED_LENGTH(len) CG(doc_comment_len) = (len)
117 #define GET_DOUBLE_QUOTES_SCANNED_LENGTH() CG(doc_comment_len)
119 #define IS_LABEL_START(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z') || (c) == '_' || (c) >= 0x7F)
121 #define ZEND_IS_OCT(c) ((c)>='0' && (c)<='7')
122 #define ZEND_IS_HEX(c) (((c)>='0' && (c)<='9') || ((c)>='a' && (c)<='f') || ((c)>='A' && (c)<='F'))
126 static size_t encoding_filter_script_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
128 const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
129 assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding));
130 return zend_multibyte_encoding_converter(to, to_length, from, from_length, internal_encoding, LANG_SCNG(script_encoding) TSRMLS_CC);
133 static size_t encoding_filter_script_to_intermediate(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
135 return zend_multibyte_encoding_converter(to, to_length, from, from_length, zend_multibyte_encoding_utf8, LANG_SCNG(script_encoding) TSRMLS_CC);
138 static size_t encoding_filter_intermediate_to_script(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
140 return zend_multibyte_encoding_converter(to, to_length, from, from_length,
141 LANG_SCNG(script_encoding), zend_multibyte_encoding_utf8 TSRMLS_CC);
144 static size_t encoding_filter_intermediate_to_internal(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length TSRMLS_DC)
146 const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
147 assert(internal_encoding && zend_multibyte_check_lexer_compatibility(internal_encoding));
148 return zend_multibyte_encoding_converter(to, to_length, from, from_length,
149 internal_encoding, zend_multibyte_encoding_utf8 TSRMLS_CC);
153 static void _yy_push_state(int new_state TSRMLS_DC)
155 zend_stack_push(&SCNG(state_stack), (void *) &YYGETCONDITION(), sizeof(int));
156 YYSETCONDITION(new_state);
159 #define yy_push_state(state_and_tsrm) _yy_push_state(yyc##state_and_tsrm)
161 static void yy_pop_state(TSRMLS_D)
164 zend_stack_top(&SCNG(state_stack), (void **) &stack_state);
165 YYSETCONDITION(*stack_state);
166 zend_stack_del_top(&SCNG(state_stack));
169 static void yy_scan_buffer(char *str, unsigned int len TSRMLS_DC)
171 YYCURSOR = (YYCTYPE*)str;
172 YYLIMIT = YYCURSOR + len;
173 if (!SCNG(yy_start)) {
174 SCNG(yy_start) = YYCURSOR;
178 void startup_scanner(TSRMLS_D)
183 CG(doc_comment) = NULL;
184 CG(doc_comment_len) = 0;
185 zend_stack_init(&SCNG(state_stack));
188 void shutdown_scanner(TSRMLS_D)
195 zend_stack_destroy(&SCNG(state_stack));
199 ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
201 lex_state->yy_leng = SCNG(yy_leng);
202 lex_state->yy_start = SCNG(yy_start);
203 lex_state->yy_text = SCNG(yy_text);
204 lex_state->yy_cursor = SCNG(yy_cursor);
205 lex_state->yy_marker = SCNG(yy_marker);
206 lex_state->yy_limit = SCNG(yy_limit);
208 lex_state->state_stack = SCNG(state_stack);
209 zend_stack_init(&SCNG(state_stack));
211 lex_state->in = SCNG(yy_in);
212 lex_state->yy_state = YYSTATE;
213 lex_state->filename = zend_get_compiled_filename(TSRMLS_C);
214 lex_state->lineno = CG(zend_lineno);
216 lex_state->script_org = SCNG(script_org);
217 lex_state->script_org_size = SCNG(script_org_size);
218 lex_state->script_filtered = SCNG(script_filtered);
219 lex_state->script_filtered_size = SCNG(script_filtered_size);
220 lex_state->input_filter = SCNG(input_filter);
221 lex_state->output_filter = SCNG(output_filter);
222 lex_state->script_encoding = SCNG(script_encoding);
225 ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
227 SCNG(yy_leng) = lex_state->yy_leng;
228 SCNG(yy_start) = lex_state->yy_start;
229 SCNG(yy_text) = lex_state->yy_text;
230 SCNG(yy_cursor) = lex_state->yy_cursor;
231 SCNG(yy_marker) = lex_state->yy_marker;
232 SCNG(yy_limit) = lex_state->yy_limit;
234 zend_stack_destroy(&SCNG(state_stack));
235 SCNG(state_stack) = lex_state->state_stack;
237 SCNG(yy_in) = lex_state->in;
238 YYSETCONDITION(lex_state->yy_state);
239 CG(zend_lineno) = lex_state->lineno;
240 zend_restore_compiled_filename(lex_state->filename TSRMLS_CC);
242 if (SCNG(script_filtered)) {
243 efree(SCNG(script_filtered));
244 SCNG(script_filtered) = NULL;
246 SCNG(script_org) = lex_state->script_org;
247 SCNG(script_org_size) = lex_state->script_org_size;
248 SCNG(script_filtered) = lex_state->script_filtered;
249 SCNG(script_filtered_size) = lex_state->script_filtered_size;
250 SCNG(input_filter) = lex_state->input_filter;
251 SCNG(output_filter) = lex_state->output_filter;
252 SCNG(script_encoding) = lex_state->script_encoding;
261 ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC)
263 zend_llist_del_element(&CG(open_files), file_handle, (int (*)(void *, void *)) zend_compare_file_handles);
264 /* zend_file_handle_dtor() operates on the copy, so we have to NULLify the original here */
265 file_handle->opened_path = NULL;
266 if (file_handle->free_filename) {
267 file_handle->filename = NULL;
271 #define BOM_UTF32_BE "\x00\x00\xfe\xff"
272 #define BOM_UTF32_LE "\xff\xfe\x00\x00"
273 #define BOM_UTF16_BE "\xfe\xff"
274 #define BOM_UTF16_LE "\xff\xfe"
275 #define BOM_UTF8 "\xef\xbb\xbf"
277 static const zend_encoding *zend_multibyte_detect_utf_encoding(const unsigned char *script, size_t script_size TSRMLS_DC)
279 const unsigned char *p;
283 /* utf-16 or utf-32? */
285 while ((p-script) < script_size) {
286 p = memchr(p, 0, script_size-(p-script)-2);
290 if (*(p+1) == '\0' && *(p+2) == '\0') {
295 /* searching for UTF-32 specific byte orders, so this will do */
301 while ((p-script) < script_size) {
302 if (*p == '\0' && *(p+wchar_size-1) != '\0') {
306 } else if (*p != '\0' && *(p+wchar_size-1) == '\0') {
314 if (wchar_size == 2) {
315 return le ? zend_multibyte_encoding_utf16le : zend_multibyte_encoding_utf16be;
317 return le ? zend_multibyte_encoding_utf32le : zend_multibyte_encoding_utf32be;
323 static const zend_encoding* zend_multibyte_detect_unicode(TSRMLS_D)
325 const zend_encoding *script_encoding = NULL;
327 unsigned char *pos1, *pos2;
329 if (LANG_SCNG(script_org_size) < sizeof(BOM_UTF32_LE)-1) {
334 if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_BE, sizeof(BOM_UTF32_BE)-1)) {
335 script_encoding = zend_multibyte_encoding_utf32be;
336 bom_size = sizeof(BOM_UTF32_BE)-1;
337 } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF32_LE, sizeof(BOM_UTF32_LE)-1)) {
338 script_encoding = zend_multibyte_encoding_utf32le;
339 bom_size = sizeof(BOM_UTF32_LE)-1;
340 } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_BE, sizeof(BOM_UTF16_BE)-1)) {
341 script_encoding = zend_multibyte_encoding_utf16be;
342 bom_size = sizeof(BOM_UTF16_BE)-1;
343 } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF16_LE, sizeof(BOM_UTF16_LE)-1)) {
344 script_encoding = zend_multibyte_encoding_utf16le;
345 bom_size = sizeof(BOM_UTF16_LE)-1;
346 } else if (!memcmp(LANG_SCNG(script_org), BOM_UTF8, sizeof(BOM_UTF8)-1)) {
347 script_encoding = zend_multibyte_encoding_utf8;
348 bom_size = sizeof(BOM_UTF8)-1;
351 if (script_encoding) {
353 LANG_SCNG(script_org) += bom_size;
354 LANG_SCNG(script_org_size) -= bom_size;
356 return script_encoding;
359 /* script contains NULL bytes -> auto-detection */
360 if ((pos1 = memchr(LANG_SCNG(script_org), 0, LANG_SCNG(script_org_size)))) {
361 /* check if the NULL byte is after the __HALT_COMPILER(); */
362 pos2 = LANG_SCNG(script_org);
364 while (pos1 - pos2 >= sizeof("__HALT_COMPILER();")-1) {
365 pos2 = memchr(pos2, '_', pos1 - pos2);
368 if (strncasecmp((char*)pos2, "_HALT_COMPILER", sizeof("_HALT_COMPILER")-1) == 0) {
369 pos2 += sizeof("_HALT_COMPILER")-1;
370 while (*pos2 == ' ' ||
378 while (*pos2 == ' ' ||
386 while (*pos2 == ' ' ||
399 /* make best effort if BOM is missing */
400 return zend_multibyte_detect_utf_encoding(LANG_SCNG(script_org), LANG_SCNG(script_org_size) TSRMLS_CC);
406 static const zend_encoding* zend_multibyte_find_script_encoding(TSRMLS_D)
408 const zend_encoding *script_encoding;
410 if (CG(detect_unicode)) {
411 /* check out bom(byte order mark) and see if containing wchars */
412 script_encoding = zend_multibyte_detect_unicode(TSRMLS_C);
413 if (script_encoding != NULL) {
414 /* bom or wchar detection is prior to 'script_encoding' option */
415 return script_encoding;
419 /* if no script_encoding specified, just leave alone */
420 if (!CG(script_encoding_list) || !CG(script_encoding_list_size)) {
424 /* if multiple encodings specified, detect automagically */
425 if (CG(script_encoding_list_size) > 1) {
426 return zend_multibyte_encoding_detector(LANG_SCNG(script_org), LANG_SCNG(script_org_size), CG(script_encoding_list), CG(script_encoding_list_size) TSRMLS_CC);
429 return CG(script_encoding_list)[0];
432 ZEND_API int zend_multibyte_set_filter(const zend_encoding *onetime_encoding TSRMLS_DC)
434 const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
435 const zend_encoding *script_encoding = onetime_encoding ? onetime_encoding: zend_multibyte_find_script_encoding(TSRMLS_C);
437 if (!script_encoding) {
441 /* judge input/output filter */
442 LANG_SCNG(script_encoding) = script_encoding;
443 LANG_SCNG(input_filter) = NULL;
444 LANG_SCNG(output_filter) = NULL;
446 if (!internal_encoding || LANG_SCNG(script_encoding) == internal_encoding) {
447 if (!zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) {
448 /* and if not, work around w/ script_encoding -> utf-8 -> script_encoding conversion */
449 LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate;
450 LANG_SCNG(output_filter) = encoding_filter_intermediate_to_script;
452 LANG_SCNG(input_filter) = NULL;
453 LANG_SCNG(output_filter) = NULL;
458 if (zend_multibyte_check_lexer_compatibility(internal_encoding)) {
459 LANG_SCNG(input_filter) = encoding_filter_script_to_internal;
460 LANG_SCNG(output_filter) = NULL;
461 } else if (zend_multibyte_check_lexer_compatibility(LANG_SCNG(script_encoding))) {
462 LANG_SCNG(input_filter) = NULL;
463 LANG_SCNG(output_filter) = encoding_filter_script_to_internal;
465 /* both script and internal encodings are incompatible w/ flex */
466 LANG_SCNG(input_filter) = encoding_filter_script_to_intermediate;
467 LANG_SCNG(output_filter) = encoding_filter_intermediate_to_internal;
473 ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
475 const char *file_path = NULL;
477 size_t size, offset = 0;
479 /* The shebang line was read, get the current position to obtain the buffer start */
480 if (CG(start_lineno) == 2 && file_handle->type == ZEND_HANDLE_FP && file_handle->handle.fp) {
481 if ((offset = ftell(file_handle->handle.fp)) == -1) {
486 if (zend_stream_fixup(file_handle, &buf, &size TSRMLS_CC) == FAILURE) {
490 zend_llist_add_element(&CG(open_files), file_handle);
491 if (file_handle->handle.stream.handle >= (void*)file_handle && file_handle->handle.stream.handle <= (void*)(file_handle+1)) {
492 zend_file_handle *fh = (zend_file_handle*)zend_llist_get_last(&CG(open_files));
493 size_t diff = (char*)file_handle->handle.stream.handle - (char*)file_handle;
494 fh->handle.stream.handle = (void*)(((char*)fh) + diff);
495 file_handle->handle.stream.handle = fh->handle.stream.handle;
498 /* Reset the scanner for scanning the new file */
499 SCNG(yy_in) = file_handle;
500 SCNG(yy_start) = NULL;
504 SCNG(script_org) = (unsigned char*)buf;
505 SCNG(script_org_size) = size;
506 SCNG(script_filtered) = NULL;
508 zend_multibyte_set_filter(NULL TSRMLS_CC);
510 if (SCNG(input_filter)) {
511 if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) {
512 zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
513 "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
515 buf = (char*)SCNG(script_filtered);
516 size = SCNG(script_filtered_size);
519 SCNG(yy_start) = (unsigned char *)buf - offset;
520 yy_scan_buffer(buf, size TSRMLS_CC);
522 zend_error_noreturn(E_COMPILE_ERROR, "zend_stream_mmap() failed");
527 if (file_handle->opened_path) {
528 file_path = file_handle->opened_path;
530 file_path = file_handle->filename;
533 zend_set_compiled_filename(file_path TSRMLS_CC);
535 if (CG(start_lineno)) {
536 CG(zend_lineno) = CG(start_lineno);
537 CG(start_lineno) = 0;
542 CG(increment_lineno) = 0;
548 ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
550 zend_lex_state original_lex_state;
551 zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
552 zend_op_array *original_active_op_array = CG(active_op_array);
553 zend_op_array *retval=NULL;
555 zend_bool compilation_successful=0;
557 zend_bool original_in_compilation = CG(in_compilation);
559 retval_znode.op_type = IS_CONST;
560 retval_znode.u.constant.type = IS_LONG;
561 retval_znode.u.constant.value.lval = 1;
562 Z_UNSET_ISREF(retval_znode.u.constant);
563 Z_SET_REFCOUNT(retval_znode.u.constant, 1);
565 zend_save_lexical_state(&original_lex_state TSRMLS_CC);
567 retval = op_array; /* success oriented */
569 if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) {
570 if (type==ZEND_REQUIRE) {
571 zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
574 zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
576 compilation_successful=0;
578 init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
579 CG(in_compilation) = 1;
580 CG(active_op_array) = op_array;
581 zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
582 zend_init_compiler_context(TSRMLS_C);
583 compiler_result = zendparse(TSRMLS_C);
584 zend_do_return(&retval_znode, 0 TSRMLS_CC);
585 CG(in_compilation) = original_in_compilation;
586 if (compiler_result==1) { /* parser error */
589 compilation_successful=1;
593 CG(active_op_array) = original_active_op_array;
594 if (compilation_successful) {
595 pass_two(op_array TSRMLS_CC);
596 zend_release_labels(0 TSRMLS_CC);
602 zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
607 zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC)
609 zend_file_handle file_handle;
611 zend_op_array *retval;
612 char *opened_path = NULL;
614 if (filename->type != IS_STRING) {
616 zval_copy_ctor(&tmp);
617 convert_to_string(&tmp);
620 file_handle.filename = filename->value.str.val;
621 file_handle.free_filename = 0;
622 file_handle.type = ZEND_HANDLE_FILENAME;
623 file_handle.opened_path = NULL;
624 file_handle.handle.fp = NULL;
626 retval = zend_compile_file(&file_handle, type TSRMLS_CC);
627 if (retval && file_handle.handle.stream.handle) {
630 if (!file_handle.opened_path) {
631 file_handle.opened_path = opened_path = estrndup(filename->value.str.val, filename->value.str.len);
634 zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL);
640 zend_destroy_file_handle(&file_handle TSRMLS_CC);
642 if (filename==&tmp) {
648 ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_DC)
653 /* enforce two trailing NULLs for flex... */
654 if (IS_INTERNED(str->value.str.val)) {
655 char *tmp = safe_emalloc(1, str->value.str.len, ZEND_MMAP_AHEAD);
656 memcpy(tmp, str->value.str.val, str->value.str.len + ZEND_MMAP_AHEAD);
657 str->value.str.val = tmp;
659 str->value.str.val = safe_erealloc(str->value.str.val, 1, str->value.str.len, ZEND_MMAP_AHEAD);
662 memset(str->value.str.val + str->value.str.len, 0, ZEND_MMAP_AHEAD);
665 SCNG(yy_start) = NULL;
667 buf = str->value.str.val;
668 size = str->value.str.len;
671 SCNG(script_org) = (unsigned char*)buf;
672 SCNG(script_org_size) = size;
673 SCNG(script_filtered) = NULL;
675 zend_multibyte_set_filter(zend_multibyte_get_internal_encoding(TSRMLS_C) TSRMLS_CC);
677 if (SCNG(input_filter)) {
678 if ((size_t)-1 == SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) {
679 zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
680 "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
682 buf = (char*)SCNG(script_filtered);
683 size = SCNG(script_filtered_size);
687 yy_scan_buffer(buf, size TSRMLS_CC);
689 zend_set_compiled_filename(filename TSRMLS_CC);
691 CG(increment_lineno) = 0;
696 ZEND_API size_t zend_get_scanned_file_offset(TSRMLS_D)
698 size_t offset = SCNG(yy_cursor) - SCNG(yy_start);
699 if (SCNG(input_filter)) {
700 size_t original_offset = offset, length = 0;
702 unsigned char *p = NULL;
703 if ((size_t)-1 == SCNG(input_filter)(&p, &length, SCNG(script_org), offset TSRMLS_CC)) {
707 if (length > original_offset) {
709 } else if (length < original_offset) {
712 } while (original_offset != length);
718 zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
720 zend_lex_state original_lex_state;
721 zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
722 zend_op_array *original_active_op_array = CG(active_op_array);
723 zend_op_array *retval;
726 zend_bool original_in_compilation = CG(in_compilation);
728 if (source_string->value.str.len==0) {
733 CG(in_compilation) = 1;
735 tmp = *source_string;
736 zval_copy_ctor(&tmp);
737 convert_to_string(&tmp);
738 source_string = &tmp;
740 zend_save_lexical_state(&original_lex_state TSRMLS_CC);
741 if (zend_prepare_string_for_scanning(source_string, filename TSRMLS_CC)==FAILURE) {
745 zend_bool orig_interactive = CG(interactive);
748 init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
749 CG(interactive) = orig_interactive;
750 CG(active_op_array) = op_array;
751 zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
752 zend_init_compiler_context(TSRMLS_C);
753 BEGIN(ST_IN_SCRIPTING);
754 compiler_result = zendparse(TSRMLS_C);
756 if (SCNG(script_filtered)) {
757 efree(SCNG(script_filtered));
758 SCNG(script_filtered) = NULL;
761 if (compiler_result==1) {
762 CG(active_op_array) = original_active_op_array;
763 CG(unclean_shutdown)=1;
764 destroy_op_array(op_array TSRMLS_CC);
768 zend_do_return(NULL, 0 TSRMLS_CC);
769 CG(active_op_array) = original_active_op_array;
770 pass_two(op_array TSRMLS_CC);
771 zend_release_labels(0 TSRMLS_CC);
775 zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
777 CG(in_compilation) = original_in_compilation;
783 int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC)
785 zend_lex_state original_lex_state;
786 zend_file_handle file_handle;
788 file_handle.type = ZEND_HANDLE_FILENAME;
789 file_handle.filename = filename;
790 file_handle.free_filename = 0;
791 file_handle.opened_path = NULL;
792 zend_save_lexical_state(&original_lex_state TSRMLS_CC);
793 if (open_file_for_scanning(&file_handle TSRMLS_CC)==FAILURE) {
794 zend_message_dispatcher(ZMSG_FAILED_HIGHLIGHT_FOPEN, filename TSRMLS_CC);
795 zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
798 zend_highlight(syntax_highlighter_ini TSRMLS_CC);
799 if (SCNG(script_filtered)) {
800 efree(SCNG(script_filtered));
801 SCNG(script_filtered) = NULL;
803 zend_destroy_file_handle(&file_handle TSRMLS_CC);
804 zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
808 int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name TSRMLS_DC)
810 zend_lex_state original_lex_state;
815 zend_save_lexical_state(&original_lex_state TSRMLS_CC);
816 if (zend_prepare_string_for_scanning(str, str_name TSRMLS_CC)==FAILURE) {
817 zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
821 zend_highlight(syntax_highlighter_ini TSRMLS_CC);
822 if (SCNG(script_filtered)) {
823 efree(SCNG(script_filtered));
824 SCNG(script_filtered) = NULL;
826 zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
831 ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, const zend_encoding *old_encoding TSRMLS_DC)
834 unsigned char *new_yy_start;
836 /* convert and set */
837 if (!SCNG(input_filter)) {
838 if (SCNG(script_filtered)) {
839 efree(SCNG(script_filtered));
840 SCNG(script_filtered) = NULL;
842 SCNG(script_filtered_size) = 0;
843 length = SCNG(script_org_size);
844 new_yy_start = SCNG(script_org);
846 if ((size_t)-1 == SCNG(input_filter)(&new_yy_start, &length, SCNG(script_org), SCNG(script_org_size) TSRMLS_CC)) {
847 zend_error_noreturn(E_COMPILE_ERROR, "Could not convert the script from the detected "
848 "encoding \"%s\" to a compatible encoding", zend_multibyte_get_encoding_name(LANG_SCNG(script_encoding)));
850 SCNG(script_filtered) = new_yy_start;
851 SCNG(script_filtered_size) = length;
854 SCNG(yy_cursor) = new_yy_start + (SCNG(yy_cursor) - SCNG(yy_start));
855 SCNG(yy_marker) = new_yy_start + (SCNG(yy_marker) - SCNG(yy_start));
856 SCNG(yy_text) = new_yy_start + (SCNG(yy_text) - SCNG(yy_start));
857 SCNG(yy_limit) = new_yy_start + (SCNG(yy_limit) - SCNG(yy_start));
859 SCNG(yy_start) = new_yy_start;
863 # define zend_copy_value(zendlval, yytext, yyleng) \
864 if (SCNG(output_filter)) { \
866 SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)yytext, (size_t)yyleng TSRMLS_CC); \
867 zendlval->value.str.len = sz; \
869 zendlval->value.str.val = (char *) estrndup(yytext, yyleng); \
870 zendlval->value.str.len = yyleng; \
873 static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type TSRMLS_DC)
875 register char *s, *t;
878 ZVAL_STRINGL(zendlval, str, len, 1);
880 /* convert escape sequences */
881 s = t = zendlval->value.str.val;
882 end = s+zendlval->value.str.len;
894 zendlval->value.str.len--;
898 zendlval->value.str.len--;
902 zendlval->value.str.len--;
906 zendlval->value.str.len--;
910 zendlval->value.str.len--;
918 zendlval->value.str.len--;
922 if (*s != quote_type) {
930 zendlval->value.str.len--;
934 if (ZEND_IS_HEX(*(s+1))) {
935 char hex_buf[3] = { 0, 0, 0 };
937 zendlval->value.str.len--; /* for the 'x' */
940 zendlval->value.str.len--;
941 if (ZEND_IS_HEX(*(s+1))) {
943 zendlval->value.str.len--;
945 *t++ = (char) strtol(hex_buf, NULL, 16);
952 /* check for an octal */
953 if (ZEND_IS_OCT(*s)) {
954 char octal_buf[4] = { 0, 0, 0, 0 };
957 zendlval->value.str.len--;
958 if (ZEND_IS_OCT(*(s+1))) {
959 octal_buf[1] = *(++s);
960 zendlval->value.str.len--;
961 if (ZEND_IS_OCT(*(s+1))) {
962 octal_buf[2] = *(++s);
963 zendlval->value.str.len--;
966 *t++ = (char) strtol(octal_buf, NULL, 8);
977 if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) {
983 if (SCNG(output_filter)) {
985 s = zendlval->value.str.val;
986 SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)s, (size_t)zendlval->value.str.len TSRMLS_CC);
987 zendlval->value.str.len = sz;
993 int lex_scan(zval *zendlval TSRMLS_DC)
996 SCNG(yy_text) = YYCURSOR;
1001 re2c:yyfill:check = 0;
1003 DNUM ([0-9]*"."[0-9]+)|([0-9]+"."[0-9]*)
1004 EXPONENT_DNUM (({LNUM}|{DNUM})[eE][+-]?{LNUM})
1005 HNUM "0x"[0-9a-fA-F]+
1007 LABEL [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
1008 WHITESPACE [ \n\r\t]+
1009 TABS_AND_SPACES [ \t]*
1010 TOKENS [;:,.\[\]()|^&+-/*=%!~$<>?@]
1012 NEWLINE ("\r"|"\n"|"\r\n")
1014 /* compute yyleng before each rule */
1015 <!*> := yyleng = YYCURSOR - SCNG(yy_text);
1018 <ST_IN_SCRIPTING>"exit" {
1022 <ST_IN_SCRIPTING>"die" {
1026 <ST_IN_SCRIPTING>"function" {
1030 <ST_IN_SCRIPTING>"const" {
1034 <ST_IN_SCRIPTING>"return" {
1038 <ST_IN_SCRIPTING>"try" {
1042 <ST_IN_SCRIPTING>"catch" {
1046 <ST_IN_SCRIPTING>"throw" {
1050 <ST_IN_SCRIPTING>"if" {
1054 <ST_IN_SCRIPTING>"elseif" {
1058 <ST_IN_SCRIPTING>"endif" {
1062 <ST_IN_SCRIPTING>"else" {
1066 <ST_IN_SCRIPTING>"while" {
1070 <ST_IN_SCRIPTING>"endwhile" {
1074 <ST_IN_SCRIPTING>"do" {
1078 <ST_IN_SCRIPTING>"for" {
1082 <ST_IN_SCRIPTING>"endfor" {
1086 <ST_IN_SCRIPTING>"foreach" {
1090 <ST_IN_SCRIPTING>"endforeach" {
1091 return T_ENDFOREACH;
1094 <ST_IN_SCRIPTING>"declare" {
1098 <ST_IN_SCRIPTING>"enddeclare" {
1099 return T_ENDDECLARE;
1102 <ST_IN_SCRIPTING>"instanceof" {
1103 return T_INSTANCEOF;
1106 <ST_IN_SCRIPTING>"as" {
1110 <ST_IN_SCRIPTING>"switch" {
1114 <ST_IN_SCRIPTING>"endswitch" {
1118 <ST_IN_SCRIPTING>"case" {
1122 <ST_IN_SCRIPTING>"default" {
1126 <ST_IN_SCRIPTING>"break" {
1130 <ST_IN_SCRIPTING>"continue" {
1134 <ST_IN_SCRIPTING>"goto" {
1138 <ST_IN_SCRIPTING>"echo" {
1142 <ST_IN_SCRIPTING>"print" {
1146 <ST_IN_SCRIPTING>"class" {
1150 <ST_IN_SCRIPTING>"interface" {
1154 <ST_IN_SCRIPTING>"trait" {
1158 <ST_IN_SCRIPTING>"extends" {
1162 <ST_IN_SCRIPTING>"implements" {
1163 return T_IMPLEMENTS;
1166 <ST_IN_SCRIPTING>"->" {
1167 yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
1168 return T_OBJECT_OPERATOR;
1171 <ST_IN_SCRIPTING,ST_LOOKING_FOR_PROPERTY>{WHITESPACE}+ {
1172 zendlval->value.str.val = yytext; /* no copying - intentional */
1173 zendlval->value.str.len = yyleng;
1174 zendlval->type = IS_STRING;
1175 HANDLE_NEWLINES(yytext, yyleng);
1176 return T_WHITESPACE;
1179 <ST_LOOKING_FOR_PROPERTY>"->" {
1180 return T_OBJECT_OPERATOR;
1183 <ST_LOOKING_FOR_PROPERTY>{LABEL} {
1184 yy_pop_state(TSRMLS_C);
1185 zend_copy_value(zendlval, yytext, yyleng);
1186 zendlval->type = IS_STRING;
1190 <ST_LOOKING_FOR_PROPERTY>{ANY_CHAR} {
1192 yy_pop_state(TSRMLS_C);
1196 <ST_IN_SCRIPTING>"::" {
1197 return T_PAAMAYIM_NEKUDOTAYIM;
1200 <ST_IN_SCRIPTING>"\\" {
1201 return T_NS_SEPARATOR;
1204 <ST_IN_SCRIPTING>"new" {
1208 <ST_IN_SCRIPTING>"clone" {
1212 <ST_IN_SCRIPTING>"var" {
1216 <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("int"|"integer"){TABS_AND_SPACES}")" {
1220 <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("real"|"double"|"float"){TABS_AND_SPACES}")" {
1221 return T_DOUBLE_CAST;
1224 <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("string"|"binary"){TABS_AND_SPACES}")" {
1225 return T_STRING_CAST;
1228 <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"array"{TABS_AND_SPACES}")" {
1229 return T_ARRAY_CAST;
1232 <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"object"{TABS_AND_SPACES}")" {
1233 return T_OBJECT_CAST;
1236 <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("bool"|"boolean"){TABS_AND_SPACES}")" {
1240 <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("unset"){TABS_AND_SPACES}")" {
1241 return T_UNSET_CAST;
1244 <ST_IN_SCRIPTING>"eval" {
1248 <ST_IN_SCRIPTING>"include" {
1252 <ST_IN_SCRIPTING>"include_once" {
1253 return T_INCLUDE_ONCE;
1256 <ST_IN_SCRIPTING>"require" {
1260 <ST_IN_SCRIPTING>"require_once" {
1261 return T_REQUIRE_ONCE;
1264 <ST_IN_SCRIPTING>"namespace" {
1268 <ST_IN_SCRIPTING>"use" {
1272 <ST_IN_SCRIPTING>"insteadof" {
1276 <ST_IN_SCRIPTING>"global" {
1280 <ST_IN_SCRIPTING>"isset" {
1284 <ST_IN_SCRIPTING>"empty" {
1288 <ST_IN_SCRIPTING>"__halt_compiler" {
1289 return T_HALT_COMPILER;
1292 <ST_IN_SCRIPTING>"static" {
1296 <ST_IN_SCRIPTING>"abstract" {
1300 <ST_IN_SCRIPTING>"final" {
1304 <ST_IN_SCRIPTING>"private" {
1308 <ST_IN_SCRIPTING>"protected" {
1312 <ST_IN_SCRIPTING>"public" {
1316 <ST_IN_SCRIPTING>"unset" {
1320 <ST_IN_SCRIPTING>"=>" {
1321 return T_DOUBLE_ARROW;
1324 <ST_IN_SCRIPTING>"list" {
1328 <ST_IN_SCRIPTING>"array" {
1332 <ST_IN_SCRIPTING>"callable" {
1336 <ST_IN_SCRIPTING>"++" {
1340 <ST_IN_SCRIPTING>"--" {
1344 <ST_IN_SCRIPTING>"===" {
1345 return T_IS_IDENTICAL;
1348 <ST_IN_SCRIPTING>"!==" {
1349 return T_IS_NOT_IDENTICAL;
1352 <ST_IN_SCRIPTING>"==" {
1356 <ST_IN_SCRIPTING>"!="|"<>" {
1357 return T_IS_NOT_EQUAL;
1360 <ST_IN_SCRIPTING>"<=" {
1361 return T_IS_SMALLER_OR_EQUAL;
1364 <ST_IN_SCRIPTING>">=" {
1365 return T_IS_GREATER_OR_EQUAL;
1368 <ST_IN_SCRIPTING>"+=" {
1369 return T_PLUS_EQUAL;
1372 <ST_IN_SCRIPTING>"-=" {
1373 return T_MINUS_EQUAL;
1376 <ST_IN_SCRIPTING>"*=" {
1380 <ST_IN_SCRIPTING>"/=" {
1384 <ST_IN_SCRIPTING>".=" {
1385 return T_CONCAT_EQUAL;
1388 <ST_IN_SCRIPTING>"%=" {
1392 <ST_IN_SCRIPTING>"<<=" {
1396 <ST_IN_SCRIPTING>">>=" {
1400 <ST_IN_SCRIPTING>"&=" {
1404 <ST_IN_SCRIPTING>"|=" {
1408 <ST_IN_SCRIPTING>"^=" {
1412 <ST_IN_SCRIPTING>"||" {
1413 return T_BOOLEAN_OR;
1416 <ST_IN_SCRIPTING>"&&" {
1417 return T_BOOLEAN_AND;
1420 <ST_IN_SCRIPTING>"OR" {
1421 return T_LOGICAL_OR;
1424 <ST_IN_SCRIPTING>"AND" {
1425 return T_LOGICAL_AND;
1428 <ST_IN_SCRIPTING>"XOR" {
1429 return T_LOGICAL_XOR;
1432 <ST_IN_SCRIPTING>"<<" {
1436 <ST_IN_SCRIPTING>">>" {
1440 <ST_IN_SCRIPTING>{TOKENS} {
1445 <ST_IN_SCRIPTING>"{" {
1446 yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
1451 <ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"${" {
1452 yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC);
1453 return T_DOLLAR_OPEN_CURLY_BRACES;
1457 <ST_IN_SCRIPTING>"}" {
1458 RESET_DOC_COMMENT();
1459 if (!zend_stack_is_empty(&SCNG(state_stack))) {
1460 yy_pop_state(TSRMLS_C);
1466 <ST_LOOKING_FOR_VARNAME>{LABEL} {
1467 zend_copy_value(zendlval, yytext, yyleng);
1468 zendlval->type = IS_STRING;
1469 yy_pop_state(TSRMLS_C);
1470 yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
1471 return T_STRING_VARNAME;
1475 <ST_LOOKING_FOR_VARNAME>{ANY_CHAR} {
1477 yy_pop_state(TSRMLS_C);
1478 yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
1482 <ST_IN_SCRIPTING>{BNUM} {
1483 char *bin = yytext + 2; /* Skip "0b" */
1484 int len = yyleng - 2;
1486 /* Skip any leading 0s */
1487 while (*bin == '0') {
1492 if (len < SIZEOF_LONG * 8) {
1494 zendlval->value.lval = 0;
1496 zendlval->value.lval = strtol(bin, NULL, 2);
1498 zendlval->type = IS_LONG;
1501 zendlval->value.dval = zend_bin_strtod(bin, NULL);
1502 zendlval->type = IS_DOUBLE;
1507 <ST_IN_SCRIPTING>{LNUM} {
1508 if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */
1509 zendlval->value.lval = strtol(yytext, NULL, 0);
1512 zendlval->value.lval = strtol(yytext, NULL, 0);
1513 if (errno == ERANGE) { /* Overflow */
1514 if (yytext[0] == '0') { /* octal overflow */
1515 zendlval->value.dval = zend_oct_strtod(yytext, NULL);
1517 zendlval->value.dval = zend_strtod(yytext, NULL);
1519 zendlval->type = IS_DOUBLE;
1524 zendlval->type = IS_LONG;
1528 <ST_IN_SCRIPTING>{HNUM} {
1529 char *hex = yytext + 2; /* Skip "0x" */
1530 int len = yyleng - 2;
1532 /* Skip any leading 0s */
1533 while (*hex == '0') {
1538 if (len < SIZEOF_LONG * 2 || (len == SIZEOF_LONG * 2 && *hex <= '7')) {
1540 zendlval->value.lval = 0;
1542 zendlval->value.lval = strtol(hex, NULL, 16);
1544 zendlval->type = IS_LONG;
1547 zendlval->value.dval = zend_hex_strtod(hex, NULL);
1548 zendlval->type = IS_DOUBLE;
1553 <ST_VAR_OFFSET>[0]|([1-9][0-9]*) { /* Offset could be treated as a long */
1554 if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) {
1555 zendlval->value.lval = strtol(yytext, NULL, 10);
1556 zendlval->type = IS_LONG;
1558 zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
1559 zendlval->value.str.len = yyleng;
1560 zendlval->type = IS_STRING;
1562 return T_NUM_STRING;
1565 <ST_VAR_OFFSET>{LNUM}|{HNUM}|{BNUM} { /* Offset must be treated as a string */
1566 zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
1567 zendlval->value.str.len = yyleng;
1568 zendlval->type = IS_STRING;
1569 return T_NUM_STRING;
1572 <ST_IN_SCRIPTING>{DNUM}|{EXPONENT_DNUM} {
1573 zendlval->value.dval = zend_strtod(yytext, NULL);
1574 zendlval->type = IS_DOUBLE;
1578 <ST_IN_SCRIPTING>"__CLASS__" {
1579 const char *class_name = NULL;
1581 if (CG(active_class_entry)
1582 && (ZEND_ACC_TRAIT ==
1583 (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT))) {
1584 /* We create a special __CLASS__ constant that is going to be resolved
1586 zendlval->value.str.len = sizeof("__CLASS__")-1;
1587 zendlval->value.str.val = estrndup("__CLASS__", zendlval->value.str.len);
1588 zendlval->type = IS_CONSTANT;
1590 if (CG(active_class_entry)) {
1591 class_name = CG(active_class_entry)->name;
1598 zendlval->value.str.len = strlen(class_name);
1599 zendlval->value.str.val = estrndup(class_name, zendlval->value.str.len);
1600 zendlval->type = IS_STRING;
1605 <ST_IN_SCRIPTING>"__TRAIT__" {
1606 const char *trait_name = NULL;
1608 if (CG(active_class_entry)
1609 && (ZEND_ACC_TRAIT ==
1610 (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT))) {
1611 trait_name = CG(active_class_entry)->name;
1618 zendlval->value.str.len = strlen(trait_name);
1619 zendlval->value.str.val = estrndup(trait_name, zendlval->value.str.len);
1620 zendlval->type = IS_STRING;
1625 <ST_IN_SCRIPTING>"__FUNCTION__" {
1626 const char *func_name = NULL;
1628 if (CG(active_op_array)) {
1629 func_name = CG(active_op_array)->function_name;
1635 zendlval->value.str.len = strlen(func_name);
1636 zendlval->value.str.val = estrndup(func_name, zendlval->value.str.len);
1637 zendlval->type = IS_STRING;
1641 <ST_IN_SCRIPTING>"__METHOD__" {
1642 const char *class_name = CG(active_class_entry) ? CG(active_class_entry)->name : NULL;
1643 const char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL;
1647 len += strlen(class_name) + 2;
1650 len += strlen(func_name);
1653 zendlval->value.str.len = zend_spprintf(&zendlval->value.str.val, 0, "%s%s%s",
1654 class_name ? class_name : "",
1655 class_name && func_name ? "::" : "",
1656 func_name ? func_name : ""
1658 zendlval->type = IS_STRING;
1662 <ST_IN_SCRIPTING>"__LINE__" {
1663 zendlval->value.lval = CG(zend_lineno);
1664 zendlval->type = IS_LONG;
1668 <ST_IN_SCRIPTING>"__FILE__" {
1669 char *filename = zend_get_compiled_filename(TSRMLS_C);
1674 zendlval->value.str.len = strlen(filename);
1675 zendlval->value.str.val = estrndup(filename, zendlval->value.str.len);
1676 zendlval->type = IS_STRING;
1680 <ST_IN_SCRIPTING>"__DIR__" {
1681 char *filename = zend_get_compiled_filename(TSRMLS_C);
1682 const size_t filename_len = strlen(filename);
1689 dirname = estrndup(filename, filename_len);
1690 zend_dirname(dirname, filename_len);
1692 if (strcmp(dirname, ".") == 0) {
1693 dirname = erealloc(dirname, MAXPATHLEN);
1695 VCWD_GETCWD(dirname, MAXPATHLEN);
1697 VCWD_GETWD(dirname);
1701 zendlval->value.str.len = strlen(dirname);
1702 zendlval->value.str.val = dirname;
1703 zendlval->type = IS_STRING;
1707 <ST_IN_SCRIPTING>"__NAMESPACE__" {
1708 if (CG(current_namespace)) {
1709 *zendlval = *CG(current_namespace);
1710 zval_copy_ctor(zendlval);
1712 ZVAL_EMPTY_STRING(zendlval);
1717 <INITIAL>"<script"{WHITESPACE}+"language"{WHITESPACE}*"="{WHITESPACE}*("php"|"\"php\""|"'php'"){WHITESPACE}*">" {
1718 YYCTYPE *bracket = (YYCTYPE*)zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1));
1720 if (bracket != SCNG(yy_text)) {
1721 /* Handle previously scanned HTML, as possible <script> tags found are assumed to not be PHP's */
1726 HANDLE_NEWLINES(yytext, yyleng);
1727 zendlval->value.str.val = yytext; /* no copying - intentional */
1728 zendlval->value.str.len = yyleng;
1729 zendlval->type = IS_STRING;
1730 BEGIN(ST_IN_SCRIPTING);
1737 zendlval->value.str.val = yytext; /* no copying - intentional */
1738 zendlval->value.str.len = yyleng;
1739 zendlval->type = IS_STRING;
1740 BEGIN(ST_IN_SCRIPTING);
1741 return T_OPEN_TAG_WITH_ECHO;
1743 goto inline_char_handler;
1749 zendlval->value.str.val = yytext; /* no copying - intentional */
1750 zendlval->value.str.len = yyleng;
1751 zendlval->type = IS_STRING;
1752 BEGIN(ST_IN_SCRIPTING);
1753 return T_OPEN_TAG_WITH_ECHO;
1759 zendlval->value.str.val = yytext; /* no copying - intentional */
1760 zendlval->value.str.len = yyleng;
1761 zendlval->type = IS_STRING;
1762 BEGIN(ST_IN_SCRIPTING);
1765 goto inline_char_handler;
1770 <INITIAL>"<?php"([ \t]|{NEWLINE}) {
1771 zendlval->value.str.val = yytext; /* no copying - intentional */
1772 zendlval->value.str.len = yyleng;
1773 zendlval->type = IS_STRING;
1774 HANDLE_NEWLINE(yytext[yyleng-1]);
1775 BEGIN(ST_IN_SCRIPTING);
1781 if (CG(short_tags)) {
1782 zendlval->value.str.val = yytext; /* no copying - intentional */
1783 zendlval->value.str.len = yyleng;
1784 zendlval->type = IS_STRING;
1785 BEGIN(ST_IN_SCRIPTING);
1788 goto inline_char_handler;
1792 <INITIAL>{ANY_CHAR} {
1793 if (YYCURSOR > YYLIMIT) {
1797 inline_char_handler:
1800 YYCTYPE *ptr = memchr(YYCURSOR, '<', YYLIMIT - YYCURSOR);
1802 YYCURSOR = ptr ? ptr + 1 : YYLIMIT;
1804 if (YYCURSOR < YYLIMIT) {
1805 switch (*YYCURSOR) {
1807 if (CG(short_tags) || !strncasecmp((char*)YYCURSOR + 1, "php", 3) || (*(YYCURSOR + 1) == '=')) { /* Assume [ \t\n\r] follows "php" */
1818 /* Probably NOT an opening PHP <script> tag, so don't end the HTML chunk yet
1819 * If it is, the PHP <script> tag rule checks for any HTML scanned before it */
1833 yyleng = YYCURSOR - SCNG(yy_text);
1835 if (SCNG(output_filter)) {
1838 readsize = SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)yytext, (size_t)yyleng TSRMLS_CC);
1839 zendlval->value.str.len = sz;
1840 if (readsize < yyleng) {
1844 zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
1845 zendlval->value.str.len = yyleng;
1847 zendlval->type = IS_STRING;
1848 HANDLE_NEWLINES(yytext, yyleng);
1849 return T_INLINE_HTML;
1853 /* Make sure a label character follows "->", otherwise there is no property
1854 * and "->" will be taken literally
1856 <ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE>"$"{LABEL}"->"[a-zA-Z_\x7f-\xff] {
1858 yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
1859 zend_copy_value(zendlval, (yytext+1), (yyleng-1));
1860 zendlval->type = IS_STRING;
1864 /* A [ always designates a variable offset, regardless of what follows
1866 <ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE>"$"{LABEL}"[" {
1868 yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
1869 zend_copy_value(zendlval, (yytext+1), (yyleng-1));
1870 zendlval->type = IS_STRING;
1874 <ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>"$"{LABEL} {
1875 zend_copy_value(zendlval, (yytext+1), (yyleng-1));
1876 zendlval->type = IS_STRING;
1880 <ST_VAR_OFFSET>"]" {
1881 yy_pop_state(TSRMLS_C);
1885 <ST_VAR_OFFSET>{TOKENS}|[{}"`] {
1886 /* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */
1890 <ST_VAR_OFFSET>[ \n\r\t\\'#] {
1891 /* Invalid rule to return a more explicit parse error with proper line number */
1893 yy_pop_state(TSRMLS_C);
1894 return T_ENCAPSED_AND_WHITESPACE;
1897 <ST_IN_SCRIPTING,ST_VAR_OFFSET>{LABEL} {
1898 zend_copy_value(zendlval, yytext, yyleng);
1899 zendlval->type = IS_STRING;
1904 <ST_IN_SCRIPTING>"#"|"//" {
1905 while (YYCURSOR < YYLIMIT) {
1906 switch (*YYCURSOR++) {
1908 if (*YYCURSOR == '\n') {
1916 if (!CG(asp_tags)) {
1921 if (*YYCURSOR == '>') {
1933 yyleng = YYCURSOR - SCNG(yy_text);
1938 <ST_IN_SCRIPTING>"/*"|"/**"{WHITESPACE} {
1943 RESET_DOC_COMMENT();
1948 while (YYCURSOR < YYLIMIT) {
1949 if (*YYCURSOR++ == '*' && *YYCURSOR == '/') {
1954 if (YYCURSOR < YYLIMIT) {
1957 zend_error(E_COMPILE_WARNING, "Unterminated comment starting line %d", CG(zend_lineno));
1960 yyleng = YYCURSOR - SCNG(yy_text);
1961 HANDLE_NEWLINES(yytext, yyleng);
1964 CG(doc_comment) = estrndup(yytext, yyleng);
1965 CG(doc_comment_len) = yyleng;
1966 return T_DOC_COMMENT;
1972 <ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*">"){NEWLINE}? {
1973 zendlval->value.str.val = yytext; /* no copying - intentional */
1974 zendlval->value.str.len = yyleng;
1975 zendlval->type = IS_STRING;
1977 return T_CLOSE_TAG; /* implicit ';' at php-end tag */
1981 <ST_IN_SCRIPTING>"%>"{NEWLINE}? {
1984 zendlval->value.str.len = yyleng;
1985 zendlval->type = IS_STRING;
1986 zendlval->value.str.val = yytext; /* no copying - intentional */
1987 return T_CLOSE_TAG; /* implicit ';' at php-end tag */
1995 <ST_IN_SCRIPTING>b?['] {
1996 register char *s, *t;
1998 int bprefix = (yytext[0] != '\'') ? 1 : 0;
2001 if (YYCURSOR < YYLIMIT) {
2002 if (*YYCURSOR == '\'') {
2004 yyleng = YYCURSOR - SCNG(yy_text);
2007 } else if (*YYCURSOR++ == '\\' && YYCURSOR < YYLIMIT) {
2011 yyleng = YYLIMIT - SCNG(yy_text);
2013 /* Unclosed single quotes; treat similar to double quotes, but without a separate token
2014 * for ' (unrecognized by parser), instead of old flex fallback to "Unexpected character..."
2015 * rule, which continued in ST_IN_SCRIPTING state after the quote */
2016 return T_ENCAPSED_AND_WHITESPACE;
2020 zendlval->value.str.val = estrndup(yytext+bprefix+1, yyleng-bprefix-2);
2021 zendlval->value.str.len = yyleng-bprefix-2;
2022 zendlval->type = IS_STRING;
2024 /* convert escape sequences */
2025 s = t = zendlval->value.str.val;
2026 end = s+zendlval->value.str.len;
2035 zendlval->value.str.len--;
2046 if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) {
2053 if (SCNG(output_filter)) {
2055 s = zendlval->value.str.val;
2056 SCNG(output_filter)((unsigned char **)&(zendlval->value.str.val), &sz, (unsigned char *)s, (size_t)zendlval->value.str.len TSRMLS_CC);
2057 zendlval->value.str.len = sz;
2060 return T_CONSTANT_ENCAPSED_STRING;
2064 <ST_IN_SCRIPTING>b?["] {
2065 int bprefix = (yytext[0] != '"') ? 1 : 0;
2067 while (YYCURSOR < YYLIMIT) {
2068 switch (*YYCURSOR++) {
2070 yyleng = YYCURSOR - SCNG(yy_text);
2071 zend_scan_escape_string(zendlval, yytext+bprefix+1, yyleng-bprefix-2, '"' TSRMLS_CC);
2072 return T_CONSTANT_ENCAPSED_STRING;
2074 if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
2079 if (*YYCURSOR == '$') {
2084 if (YYCURSOR < YYLIMIT) {
2096 /* Remember how much was scanned to save rescanning */
2097 SET_DOUBLE_QUOTES_SCANNED_LENGTH(YYCURSOR - SCNG(yy_text) - yyleng);
2099 YYCURSOR = SCNG(yy_text) + yyleng;
2101 BEGIN(ST_DOUBLE_QUOTES);
2106 <ST_IN_SCRIPTING>b?"<<<"{TABS_AND_SPACES}({LABEL}|([']{LABEL}['])|(["]{LABEL}["])){NEWLINE} {
2108 int bprefix = (yytext[0] != '<') ? 1 : 0;
2110 /* save old heredoc label */
2111 Z_STRVAL_P(zendlval) = CG(heredoc);
2112 Z_STRLEN_P(zendlval) = CG(heredoc_len);
2115 CG(heredoc_len) = yyleng-bprefix-3-1-(yytext[yyleng-2]=='\r'?1:0);
2116 s = yytext+bprefix+3;
2117 while ((*s == ' ') || (*s == '\t')) {
2124 CG(heredoc_len) -= 2;
2130 CG(heredoc_len) -= 2;
2136 CG(heredoc) = estrndup(s, CG(heredoc_len));
2138 /* Check for ending label on the next line */
2139 if (CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, s, CG(heredoc_len))) {
2140 YYCTYPE *end = YYCURSOR + CG(heredoc_len);
2146 if (*end == '\n' || *end == '\r') {
2147 BEGIN(ST_END_HEREDOC);
2151 return T_START_HEREDOC;
2155 <ST_IN_SCRIPTING>[`] {
2156 BEGIN(ST_BACKQUOTE);
2161 <ST_END_HEREDOC>{ANY_CHAR} {
2162 YYCURSOR += CG(heredoc_len) - 1;
2163 yyleng = CG(heredoc_len);
2165 Z_STRVAL_P(zendlval) = CG(heredoc);
2166 Z_STRLEN_P(zendlval) = CG(heredoc_len);
2168 CG(heredoc_len) = 0;
2169 BEGIN(ST_IN_SCRIPTING);
2170 return T_END_HEREDOC;
2174 <ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"{$" {
2175 zendlval->value.lval = (long) '{';
2176 yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
2178 return T_CURLY_OPEN;
2182 <ST_DOUBLE_QUOTES>["] {
2183 BEGIN(ST_IN_SCRIPTING);
2188 BEGIN(ST_IN_SCRIPTING);
2193 <ST_DOUBLE_QUOTES>{ANY_CHAR} {
2194 if (GET_DOUBLE_QUOTES_SCANNED_LENGTH()) {
2195 YYCURSOR += GET_DOUBLE_QUOTES_SCANNED_LENGTH() - 1;
2196 SET_DOUBLE_QUOTES_SCANNED_LENGTH(0);
2198 goto double_quotes_scan_done;
2201 if (YYCURSOR > YYLIMIT) {
2204 if (yytext[0] == '\\' && YYCURSOR < YYLIMIT) {
2208 while (YYCURSOR < YYLIMIT) {
2209 switch (*YYCURSOR++) {
2213 if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
2218 if (*YYCURSOR == '$') {
2223 if (YYCURSOR < YYLIMIT) {
2235 double_quotes_scan_done:
2236 yyleng = YYCURSOR - SCNG(yy_text);
2238 zend_scan_escape_string(zendlval, yytext, yyleng, '"' TSRMLS_CC);
2239 return T_ENCAPSED_AND_WHITESPACE;
2243 <ST_BACKQUOTE>{ANY_CHAR} {
2244 if (YYCURSOR > YYLIMIT) {
2247 if (yytext[0] == '\\' && YYCURSOR < YYLIMIT) {
2251 while (YYCURSOR < YYLIMIT) {
2252 switch (*YYCURSOR++) {
2256 if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
2261 if (*YYCURSOR == '$') {
2266 if (YYCURSOR < YYLIMIT) {
2278 yyleng = YYCURSOR - SCNG(yy_text);
2280 zend_scan_escape_string(zendlval, yytext, yyleng, '`' TSRMLS_CC);
2281 return T_ENCAPSED_AND_WHITESPACE;
2285 <ST_HEREDOC>{ANY_CHAR} {
2288 if (YYCURSOR > YYLIMIT) {
2294 while (YYCURSOR < YYLIMIT) {
2295 switch (*YYCURSOR++) {
2297 if (*YYCURSOR == '\n') {
2302 /* Check for ending label on the next line */
2303 if (IS_LABEL_START(*YYCURSOR) && CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, CG(heredoc), CG(heredoc_len))) {
2304 YYCTYPE *end = YYCURSOR + CG(heredoc_len);
2310 if (*end == '\n' || *end == '\r') {
2311 /* newline before label will be subtracted from returned text, but
2312 * yyleng/yytext will include it, for zend_highlight/strip, tokenizer, etc. */
2313 if (YYCURSOR[-2] == '\r' && YYCURSOR[-1] == '\n') {
2314 newline = 2; /* Windows newline */
2319 CG(increment_lineno) = 1; /* For newline before label */
2320 BEGIN(ST_END_HEREDOC);
2322 goto heredoc_scan_done;
2327 if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
2332 if (*YYCURSOR == '$') {
2337 if (YYCURSOR < YYLIMIT && *YYCURSOR != '\n' && *YYCURSOR != '\r') {
2350 yyleng = YYCURSOR - SCNG(yy_text);
2352 zend_scan_escape_string(zendlval, yytext, yyleng - newline, 0 TSRMLS_CC);
2353 return T_ENCAPSED_AND_WHITESPACE;
2357 <ST_NOWDOC>{ANY_CHAR} {
2360 if (YYCURSOR > YYLIMIT) {
2366 while (YYCURSOR < YYLIMIT) {
2367 switch (*YYCURSOR++) {
2369 if (*YYCURSOR == '\n') {
2374 /* Check for ending label on the next line */
2375 if (IS_LABEL_START(*YYCURSOR) && CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, CG(heredoc), CG(heredoc_len))) {
2376 YYCTYPE *end = YYCURSOR + CG(heredoc_len);
2382 if (*end == '\n' || *end == '\r') {
2383 /* newline before label will be subtracted from returned text, but
2384 * yyleng/yytext will include it, for zend_highlight/strip, tokenizer, etc. */
2385 if (YYCURSOR[-2] == '\r' && YYCURSOR[-1] == '\n') {
2386 newline = 2; /* Windows newline */
2391 CG(increment_lineno) = 1; /* For newline before label */
2392 BEGIN(ST_END_HEREDOC);
2394 goto nowdoc_scan_done;
2404 yyleng = YYCURSOR - SCNG(yy_text);
2406 zend_copy_value(zendlval, yytext, yyleng - newline);
2407 zendlval->type = IS_STRING;
2408 HANDLE_NEWLINES(yytext, yyleng - newline);
2409 return T_ENCAPSED_AND_WHITESPACE;
2413 <ST_IN_SCRIPTING,ST_VAR_OFFSET>{ANY_CHAR} {
2414 if (YYCURSOR > YYLIMIT) {
2418 zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);