You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2399 lines
56 KiB

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