PageRenderTime 69ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/docs/official-grammars/php/5.3.0/zend_language_scanner.l

http://github.com/facebook/pfff
LEX | 2200 lines | 1702 code | 377 blank | 121 comment | 0 complexity | 8617beea79988cac77f69fc670e09b54 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, LGPL-2.0, Apache-2.0

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file