1 : %{
2 :
3 : /*
4 : +----------------------------------------------------------------------+
5 : | Zend Engine |
6 : +----------------------------------------------------------------------+
7 : | Copyright (c) 1998-2006 Zend Technologies Ltd. (http://www.zend.com) |
8 : +----------------------------------------------------------------------+
9 : | This source file is subject to version 2.00 of the Zend license, |
10 : | that is bundled with this package in the file LICENSE, and is |
11 : | available through the world-wide-web at the following url: |
12 : | http://www.zend.com/license/2_00.txt. |
13 : | If you did not receive a copy of the Zend license and are unable to |
14 : | obtain it through the world-wide-web, please send a note to |
15 : | license@zend.com so we can mail you a copy immediately. |
16 : +----------------------------------------------------------------------+
17 : | Authors: Andi Gutmans <andi@zend.com> |
18 : | Zeev Suraski <zeev@zend.com> |
19 : +----------------------------------------------------------------------+
20 : */
21 :
22 : /* $Id: zend_language_scanner.l 280170 2009-05-08 17:50:58Z mattwil $ */
23 :
24 : #define yyleng SCNG(yy_leng)
25 : #define yytext SCNG(yy_text)
26 : #define yytext_ptr SCNG(yy_text)
27 : #define yyin SCNG(yy_in)
28 : #define yyout SCNG(yy_out)
29 : #define yy_last_accepting_state SCNG(_yy_last_accepting_state)
30 : #define yy_last_accepting_cpos SCNG(_yy_last_accepting_cpos)
31 : #define yy_more_flag SCNG(_yy_more_flag)
32 : #define yy_more_len SCNG(_yy_more_len)
33 :
34 : %}
35 :
36 : %x ST_IN_SCRIPTING
37 : %x ST_DOUBLE_QUOTES
38 : %x ST_BACKQUOTE
39 : %x ST_HEREDOC
40 : %x ST_START_HEREDOC
41 : %x ST_END_HEREDOC
42 : %x ST_LOOKING_FOR_PROPERTY
43 : %x ST_LOOKING_FOR_VARNAME
44 : %x ST_VAR_OFFSET
45 : %x ST_COMMENT
46 : %x ST_DOC_COMMENT
47 : %x ST_ONE_LINE_COMMENT
48 : %option stack
49 :
50 : %{
51 :
52 : #include <errno.h>
53 : #include "zend.h"
54 : #include "zend_alloc.h"
55 : #include <zend_language_parser.h>
56 : #include "zend_compile.h"
57 : #include "zend_language_scanner.h"
58 : #include "zend_highlight.h"
59 : #include "zend_constants.h"
60 : #include "zend_variables.h"
61 : #include "zend_operators.h"
62 : #include "zend_API.h"
63 : #include "zend_strtod.h"
64 : #include "zend_exceptions.h"
65 :
66 : #ifdef HAVE_STDARG_H
67 : # include <stdarg.h>
68 : #endif
69 :
70 : #ifdef HAVE_UNISTD_H
71 : # include <unistd.h>
72 : #endif
73 :
74 : #define YY_DECL int lex_scan(zval *zendlval TSRMLS_DC)
75 :
76 : #define ECHO { ZEND_WRITE( yytext, yyleng ); }
77 :
78 : #ifdef ZTS
79 : # define MY_INPUT yyinput
80 : #else
81 : # define MY_INPUT input
82 : #endif
83 :
84 :
85 : /* Globals Macros */
86 : #define SCNG LANG_SCNG
87 : #ifdef ZTS
88 : ZEND_API ts_rsrc_id language_scanner_globals_id;
89 : #else
90 : ZEND_API zend_scanner_globals language_scanner_globals;
91 : #endif
92 :
93 :
94 : #define YY_FATAL_ERROR zend_fatal_scanner_error
95 :
96 : #define HANDLE_NEWLINES(s, l) \
97 : do { \
98 : char *p = (s), *boundary = p+(l); \
99 : \
100 : while (p<boundary) { \
101 : if (*p == '\n' || (*p == '\r' && (*(p+1) != '\n'))) { \
102 : CG(zend_lineno)++; \
103 : } \
104 : p++; \
105 : } \
106 : } while (0)
107 :
108 : #define HANDLE_NEWLINE(c) \
109 : { \
110 : if (c == '\n' || c == '\r') { \
111 : CG(zend_lineno)++; \
112 : } \
113 : }
114 :
115 :
116 : #define ZEND_IS_OCT(c) ((c)>='0' && (c)<='7')
117 : #define ZEND_IS_HEX(c) (((c)>='0' && (c)<='9') || ((c)>='a' && (c)<='f') || ((c)>='A' && (c)<='F'))
118 :
119 :
120 : void zend_fatal_scanner_error(char *message)
121 0 : {
122 0 : zend_error(E_COMPILE_ERROR, "%s", message);
123 0 : }
124 :
125 : BEGIN_EXTERN_C()
126 : void startup_scanner(TSRMLS_D)
127 13551 : {
128 13551 : CG(heredoc) = NULL;
129 13551 : CG(heredoc_len) = 0;
130 13551 : CG(doc_comment) = NULL;
131 13551 : CG(doc_comment_len) = 0;
132 13551 : SCNG(yy_start_stack_ptr) = 0;
133 13551 : SCNG(yy_start_stack_depth) = 0;
134 13551 : SCNG(current_buffer) = NULL;
135 : #ifdef ZEND_MULTIBYTE
136 : SCNG(script_org) = NULL;
137 : SCNG(script_org_size) = 0;
138 : SCNG(script_filtered) = NULL;
139 : SCNG(script_filtered_size) = 0;
140 : SCNG(input_filter) = NULL;
141 : SCNG(output_filter) = NULL;
142 : SCNG(script_encoding) = NULL;
143 : SCNG(internal_encoding) = NULL;
144 : #endif /* ZEND_MULTIBYTE */
145 13551 : }
146 :
147 :
148 : void shutdown_scanner(TSRMLS_D)
149 13584 : {
150 13584 : if (CG(heredoc)) {
151 0 : efree(CG(heredoc));
152 0 : CG(heredoc_len)=0;
153 : }
154 13584 : if (SCNG(yy_start_stack)) {
155 7435 : yy_flex_free(SCNG(yy_start_stack));
156 7435 : SCNG(yy_start_stack) = NULL;
157 : }
158 13584 : RESET_DOC_COMMENT();
159 :
160 : #ifdef ZEND_MULTIBYTE
161 : if (SCNG(script_org)) {
162 : efree(SCNG(script_org));
163 : SCNG(script_org) = NULL;
164 : }
165 : if (SCNG(script_filtered)) {
166 : efree(SCNG(script_filtered));
167 : SCNG(script_filtered) = NULL;
168 : }
169 : SCNG(script_org_size) = 0;
170 : SCNG(script_filtered_size) = 0;
171 : SCNG(input_filter) = NULL;
172 : SCNG(output_filter) = NULL;
173 : SCNG(script_encoding) = NULL;
174 : SCNG(internal_encoding) = NULL;
175 : #endif /* ZEND_MULTIBYTE */
176 13584 : }
177 : END_EXTERN_C()
178 :
179 :
180 : ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
181 18515 : {
182 18515 : memcpy(&lex_state->buffer_state, &YY_CURRENT_BUFFER, sizeof(YY_BUFFER_STATE));
183 18515 : lex_state->in = SCNG(yy_in);
184 18515 : lex_state->state = YYSTATE;
185 18515 : lex_state->filename = zend_get_compiled_filename(TSRMLS_C);
186 18515 : lex_state->lineno = CG(zend_lineno);
187 :
188 : #ifdef ZEND_MULTIBYTE
189 : lex_state->script_org = SCNG(script_org);
190 : lex_state->script_org_size = SCNG(script_org_size);
191 : lex_state->script_filtered = SCNG(script_filtered);
192 : lex_state->script_filtered_size = SCNG(script_filtered_size);
193 : lex_state->input_filter = SCNG(input_filter);
194 : lex_state->output_filter = SCNG(output_filter);
195 : lex_state->script_encoding = SCNG(script_encoding);
196 : lex_state->internal_encoding = SCNG(internal_encoding);
197 : #endif /* ZEND_MULTIBYTE */
198 18515 : }
199 :
200 : ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
201 18381 : {
202 18381 : YY_BUFFER_STATE original_buffer_state = YY_CURRENT_BUFFER;
203 :
204 18381 : if (lex_state->buffer_state) {
205 1 : yy_switch_to_buffer(lex_state->buffer_state TSRMLS_CC);
206 : } else {
207 18380 : YY_CURRENT_BUFFER = NULL;
208 : }
209 :
210 18381 : yy_delete_buffer(original_buffer_state TSRMLS_CC);
211 18381 : SCNG(yy_in) = lex_state->in;
212 18381 : BEGIN(lex_state->state);
213 18381 : CG(zend_lineno) = lex_state->lineno;
214 18381 : zend_restore_compiled_filename(lex_state->filename TSRMLS_CC);
215 :
216 : #ifdef ZEND_MULTIBYTE
217 : if (SCNG(script_org)) {
218 : efree(SCNG(script_org));
219 : SCNG(script_org) = NULL;
220 : }
221 : if (SCNG(script_filtered)) {
222 : efree(SCNG(script_filtered));
223 : SCNG(script_filtered) = NULL;
224 : }
225 : SCNG(script_org) = lex_state->script_org;
226 : SCNG(script_org_size) = lex_state->script_org_size;
227 : SCNG(script_filtered) = lex_state->script_filtered;
228 : SCNG(script_filtered_size) = lex_state->script_filtered_size;
229 : SCNG(input_filter) = lex_state->input_filter;
230 : SCNG(output_filter) = lex_state->output_filter;
231 : SCNG(script_encoding) = lex_state->script_encoding;
232 : SCNG(internal_encoding) = lex_state->internal_encoding;
233 : #endif /* ZEND_MULTIBYTE */
234 18381 : }
235 :
236 :
237 : BEGIN_EXTERN_C()
238 :
239 :
240 : ZEND_API void zend_file_handle_dtor(zend_file_handle *fh)
241 31038 : {
242 : TSRMLS_FETCH();
243 :
244 31038 : switch (fh->type) {
245 : case ZEND_HANDLE_FP:
246 26958 : fclose(fh->handle.fp);
247 26958 : break;
248 : case ZEND_HANDLE_STREAM:
249 4080 : if (fh->handle.stream.closer) {
250 4080 : fh->handle.stream.closer(fh->handle.stream.handle TSRMLS_CC);
251 : }
252 : break;
253 : case ZEND_HANDLE_FILENAME:
254 : /* We're only supposed to get here when destructing the used_files hash,
255 : * which doesn't really contain open files, but references to their names/paths
256 : */
257 : break;
258 : }
259 31038 : if (fh->opened_path) {
260 17562 : efree(fh->opened_path);
261 17562 : fh->opened_path = NULL;
262 : }
263 31038 : if (fh->free_filename && fh->filename) {
264 0 : efree(fh->filename);
265 0 : fh->filename = NULL;
266 : }
267 31038 : }
268 :
269 :
270 : int zend_compare_file_handles(zend_file_handle *fh1, zend_file_handle *fh2)
271 17377 : {
272 17377 : if (fh1->type != fh2->type) {
273 0 : return 0;
274 : }
275 17377 : switch (fh1->type) {
276 : case ZEND_HANDLE_FP:
277 13366 : return fh1->handle.fp==fh2->handle.fp;
278 : break;
279 : case ZEND_HANDLE_STREAM:
280 4011 : return fh1->handle.stream.handle == fh2->handle.stream.handle;
281 : break;
282 : }
283 0 : return 0;
284 : }
285 :
286 :
287 : ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC)
288 17382 : {
289 17382 : zend_llist_del_element(&CG(open_files), file_handle, (int (*)(void *, void *)) zend_compare_file_handles);
290 : /* zend_file_handle_dtor() operates on the copy, so we have to NULLify the original here */
291 17382 : file_handle->opened_path = NULL;
292 17382 : if (file_handle->free_filename) {
293 0 : file_handle->filename = NULL;
294 : }
295 17382 : }
296 :
297 :
298 : ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
299 17517 : {
300 17517 : char *file_path=NULL;
301 :
302 17517 : if (FAILURE == zend_stream_fixup(file_handle TSRMLS_CC)) {
303 10 : return FAILURE;
304 : }
305 :
306 17507 : zend_llist_add_element(&CG(open_files), file_handle);
307 :
308 : /* Reset the scanner for scanning the new file */
309 17507 : SCNG(yy_in) = file_handle;
310 :
311 : #ifdef ZEND_MULTIBYTE
312 : if (file_handle->handle.stream.interactive == 0) {
313 : if (zend_multibyte_read_script(TSRMLS_C) != 0) {
314 : return FAILURE;
315 : }
316 :
317 : /* force flex to use buffer only */
318 : SCNG(yy_in) = NULL;
319 : SCNG(init) = 0;
320 : SCNG(start) = 1;
321 :
322 : zend_multibyte_set_filter(NULL TSRMLS_CC);
323 :
324 : if (!SCNG(input_filter)) {
325 : SCNG(script_filtered) = (char*)emalloc(SCNG(script_org_size)+1);
326 : memcpy(SCNG(script_filtered), SCNG(script_org), SCNG(script_org_size)+1);
327 : SCNG(script_filtered_size) = SCNG(script_org_size);
328 : } else {
329 : SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC);
330 : }
331 :
332 : /* flex requires doubled null */
333 : SCNG(script_filtered) = (char*)erealloc(SCNG(script_filtered), SCNG(script_filtered_size)+2);
334 : *(SCNG(script_filtered)+SCNG(script_filtered_size)) = (char)NULL;
335 : *(SCNG(script_filtered)+SCNG(script_filtered_size)+1) = (char)NULL;
336 : yy_scan_buffer(SCNG(script_filtered), SCNG(script_filtered_size)+2 TSRMLS_CC);
337 : } else {
338 : yy_switch_to_buffer(yy_create_buffer(SCNG(yy_in), YY_BUF_SIZE TSRMLS_CC) TSRMLS_CC);
339 : }
340 : #else /* !ZEND_MULTIBYTE */
341 17507 : yy_switch_to_buffer(yy_create_buffer(SCNG(yy_in), YY_BUF_SIZE TSRMLS_CC) TSRMLS_CC);
342 : #endif /* ZEND_MULTIBYTE */
343 :
344 17507 : BEGIN(INITIAL);
345 :
346 17507 : if (file_handle->opened_path) {
347 17497 : file_path = file_handle->opened_path;
348 : } else {
349 10 : file_path = file_handle->filename;
350 : }
351 :
352 17507 : zend_set_compiled_filename(file_path TSRMLS_CC);
353 :
354 17507 : if (CG(start_lineno)) {
355 13401 : CG(zend_lineno) = CG(start_lineno);
356 13401 : CG(start_lineno) = 0;
357 : } else {
358 4106 : CG(zend_lineno) = 1;
359 : }
360 :
361 17507 : CG(increment_lineno) = 0;
362 17507 : return SUCCESS;
363 : }
364 : END_EXTERN_C()
365 :
366 :
367 : ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
368 17498 : {
369 : zend_lex_state original_lex_state;
370 17498 : zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
371 17498 : zend_op_array *original_active_op_array = CG(active_op_array);
372 17498 : zend_op_array *retval=NULL;
373 : int compiler_result;
374 17498 : zend_bool compilation_successful=0;
375 : znode retval_znode;
376 17498 : zend_bool original_in_compilation = CG(in_compilation);
377 :
378 17498 : retval_znode.op_type = IS_CONST;
379 17498 : retval_znode.u.constant.type = IS_LONG;
380 17498 : retval_znode.u.constant.value.lval = 1;
381 17498 : retval_znode.u.constant.is_ref = 0;
382 17498 : retval_znode.u.constant.refcount = 1;
383 :
384 17498 : zend_save_lexical_state(&original_lex_state TSRMLS_CC);
385 :
386 17498 : retval = op_array; /* success oriented */
387 :
388 17498 : if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) {
389 6 : if (type==ZEND_REQUIRE) {
390 0 : zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
391 0 : zend_bailout();
392 : } else {
393 6 : zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
394 : }
395 6 : compilation_successful=0;
396 : } else {
397 17492 : init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
398 17492 : CG(in_compilation) = 1;
399 17492 : CG(active_op_array) = op_array;
400 17492 : compiler_result = zendparse(TSRMLS_C);
401 17380 : zend_do_return(&retval_znode, 0 TSRMLS_CC);
402 17380 : zend_do_handle_exception(TSRMLS_C);
403 17380 : CG(in_compilation) = original_in_compilation;
404 17380 : if (compiler_result==1) { /* parser error */
405 13 : zend_bailout();
406 : }
407 17367 : compilation_successful=1;
408 : }
409 :
410 17373 : if (retval) {
411 17373 : CG(active_op_array) = original_active_op_array;
412 17373 : if (compilation_successful) {
413 17367 : pass_two(op_array TSRMLS_CC);
414 : } else {
415 6 : efree(op_array);
416 6 : retval = NULL;
417 : }
418 : }
419 17373 : if (compilation_successful) {
420 17367 : zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
421 : }
422 17373 : return retval;
423 : }
424 :
425 :
426 : zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC)
427 2194 : {
428 : zend_file_handle file_handle;
429 : zval tmp;
430 : zend_op_array *retval;
431 2194 : char *opened_path = NULL;
432 :
433 2194 : if (filename->type != IS_STRING) {
434 0 : tmp = *filename;
435 0 : zval_copy_ctor(&tmp);
436 0 : convert_to_string(&tmp);
437 0 : filename = &tmp;
438 : }
439 2194 : file_handle.filename = filename->value.str.val;
440 2194 : file_handle.free_filename = 0;
441 2194 : file_handle.type = ZEND_HANDLE_FILENAME;
442 2194 : file_handle.opened_path = NULL;
443 2194 : file_handle.handle.fp = NULL;
444 :
445 2194 : retval = zend_compile_file(&file_handle, type TSRMLS_CC);
446 2191 : if (retval && file_handle.handle.stream.handle) {
447 2185 : int dummy = 1;
448 :
449 2185 : if (!file_handle.opened_path) {
450 2 : file_handle.opened_path = opened_path = estrndup(filename->value.str.val, filename->value.str.len);
451 : }
452 :
453 2185 : zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL);
454 :
455 2185 : if (opened_path) {
456 2 : efree(opened_path);
457 : }
458 : }
459 2191 : zend_destroy_file_handle(&file_handle TSRMLS_CC);
460 :
461 2191 : if (filename==&tmp) {
462 0 : zval_dtor(&tmp);
463 : }
464 2191 : return retval;
465 : }
466 :
467 : ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_DC)
468 1004 : {
469 : /* enforce two trailing NULLs for flex... */
470 1004 : STR_REALLOC(str->value.str.val, str->value.str.len+2);
471 :
472 1004 : str->value.str.val[str->value.str.len+1]=0;
473 :
474 1004 : SCNG(yy_in)=NULL;
475 :
476 : #ifdef ZEND_MULTIBYTE
477 : SCNG(script_org) = estrdup(str->value.str.val);
478 : SCNG(script_org_size) = str->value.str.len;
479 :
480 : zend_multibyte_set_filter(CG(internal_encoding) TSRMLS_CC);
481 :
482 : if (!SCNG(input_filter)) {
483 : SCNG(script_filtered) = (char*)emalloc(SCNG(script_org_size)+1);
484 : memcpy(SCNG(script_filtered), SCNG(script_org), SCNG(script_org_size)+1);
485 : SCNG(script_filtered_size) = SCNG(script_org_size);
486 : } else {
487 : SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC);
488 : }
489 :
490 : /* flex requires doubled null */
491 : SCNG(script_filtered) = (char*)erealloc(SCNG(script_filtered), SCNG(script_filtered_size)+2);
492 : *(SCNG(script_filtered)+SCNG(script_filtered_size)) = (char)NULL;
493 : *(SCNG(script_filtered)+SCNG(script_filtered_size)+1) = (char)NULL;
494 : yy_scan_buffer(SCNG(script_filtered), SCNG(script_filtered_size)+2 TSRMLS_CC);
495 : #else /* !ZEND_MULTIBYTE */
496 1004 : yy_scan_buffer(str->value.str.val, str->value.str.len+2 TSRMLS_CC);
497 : #endif /* ZEND_MULTIBYTE */
498 :
499 1004 : zend_set_compiled_filename(filename TSRMLS_CC);
500 1004 : CG(zend_lineno) = 1;
501 1004 : CG(increment_lineno) = 0;
502 1004 : return SUCCESS;
503 : }
504 :
505 :
506 : ZEND_API int zend_get_scanned_file_offset(TSRMLS_D)
507 7 : {
508 7 : if (yyin) {
509 7 : int offset_in_buffer = (yy_c_buf_p - (YY_CURRENT_BUFFER)->yy_ch_buf);
510 7 : int read_bytes = SCNG(yy_n_chars);
511 7 : int offset_from_the_end = read_bytes - offset_in_buffer;
512 :
513 7 : return zend_stream_ftell(yyin TSRMLS_CC) - offset_from_the_end;
514 : } else {
515 : /* The entire file is in the buffer; probably zend multibyte
516 : is enabled */
517 0 : return (yy_c_buf_p - (YY_CURRENT_BUFFER)->yy_ch_buf);
518 : }
519 : }
520 :
521 :
522 : zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
523 927 : {
524 : zend_lex_state original_lex_state;
525 927 : zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
526 927 : zend_op_array *original_active_op_array = CG(active_op_array);
527 : zend_op_array *retval;
528 : zval tmp;
529 : int compiler_result;
530 927 : zend_bool original_in_compilation = CG(in_compilation);
531 :
532 927 : if (source_string->value.str.len==0) {
533 0 : efree(op_array);
534 0 : return NULL;
535 : }
536 :
537 927 : CG(in_compilation) = 1;
538 :
539 927 : tmp = *source_string;
540 927 : zval_copy_ctor(&tmp);
541 927 : convert_to_string(&tmp);
542 927 : source_string = &tmp;
543 :
544 927 : zend_save_lexical_state(&original_lex_state TSRMLS_CC);
545 927 : if (zend_prepare_string_for_scanning(source_string, filename TSRMLS_CC)==FAILURE) {
546 0 : efree(op_array);
547 0 : retval = NULL;
548 : } else {
549 927 : zend_bool orig_interactive = CG(interactive);
550 :
551 927 : CG(interactive) = 0;
552 927 : init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
553 927 : CG(interactive) = orig_interactive;
554 927 : CG(active_op_array) = op_array;
555 927 : BEGIN(ST_IN_SCRIPTING);
556 927 : compiler_result = zendparse(TSRMLS_C);
557 :
558 : #ifdef ZEND_MULTIBYTE
559 : if (SCNG(script_org)) {
560 : efree(SCNG(script_org));
561 : SCNG(script_org) = NULL;
562 : }
563 : if (SCNG(script_filtered)) {
564 : efree(SCNG(script_filtered));
565 : SCNG(script_filtered) = NULL;
566 : }
567 : #endif /* ZEND_MULTIBYTE */
568 :
569 926 : if (compiler_result==1) {
570 7 : CG(active_op_array) = original_active_op_array;
571 7 : CG(unclean_shutdown)=1;
572 7 : retval = NULL;
573 : } else {
574 919 : zend_do_return(NULL, 0 TSRMLS_CC);
575 919 : zend_do_handle_exception(TSRMLS_C);
576 919 : CG(active_op_array) = original_active_op_array;
577 919 : pass_two(op_array TSRMLS_CC);
578 919 : retval = op_array;
579 : }
580 926 : zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
581 : }
582 926 : zval_dtor(&tmp);
583 926 : CG(in_compilation) = original_in_compilation;
584 926 : return retval;
585 : }
586 :
587 :
588 : BEGIN_EXTERN_C()
589 : int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC)
590 8 : {
591 : zend_lex_state original_lex_state;
592 : zend_file_handle file_handle;
593 :
594 8 : file_handle.type = ZEND_HANDLE_FILENAME;
595 8 : file_handle.filename = filename;
596 8 : file_handle.free_filename = 0;
597 8 : file_handle.opened_path = NULL;
598 8 : zend_save_lexical_state(&original_lex_state TSRMLS_CC);
599 8 : if (open_file_for_scanning(&file_handle TSRMLS_CC)==FAILURE) {
600 2 : zend_message_dispatcher(ZMSG_FAILED_HIGHLIGHT_FOPEN, filename);
601 2 : return FAILURE;
602 : }
603 6 : zend_highlight(syntax_highlighter_ini TSRMLS_CC);
604 : #ifdef ZEND_MULTIBYTE
605 : if (SCNG(script_org)) {
606 : efree(SCNG(script_org));
607 : SCNG(script_org) = NULL;
608 : }
609 : if (SCNG(script_filtered)) {
610 : efree(SCNG(script_filtered));
611 : SCNG(script_filtered) = NULL;
612 : }
613 : #endif /* ZEND_MULTIBYTE */
614 6 : zend_destroy_file_handle(&file_handle TSRMLS_CC);
615 6 : zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
616 6 : return SUCCESS;
617 : }
618 :
619 : int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name TSRMLS_DC)
620 10 : {
621 : zend_lex_state original_lex_state;
622 10 : zval tmp = *str;
623 :
624 10 : str = &tmp;
625 10 : zval_copy_ctor(str);
626 10 : zend_save_lexical_state(&original_lex_state TSRMLS_CC);
627 10 : if (zend_prepare_string_for_scanning(str, str_name TSRMLS_CC)==FAILURE) {
628 0 : return FAILURE;
629 : }
630 10 : BEGIN(INITIAL);
631 10 : zend_highlight(syntax_highlighter_ini TSRMLS_CC);
632 : #ifdef ZEND_MULTIBYTE
633 : if (SCNG(script_org)) {
634 : efree(SCNG(script_org));
635 : SCNG(script_org) = NULL;
636 : }
637 : if (SCNG(script_filtered)) {
638 : efree(SCNG(script_filtered));
639 : SCNG(script_filtered) = NULL;
640 : }
641 : #endif /* ZEND_MULTIBYTE */
642 10 : zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
643 10 : zval_dtor(str);
644 10 : return SUCCESS;
645 : }
646 : END_EXTERN_C()
647 :
648 : #ifdef ZEND_MULTIBYTE
649 : BEGIN_EXTERN_C()
650 : ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, zend_encoding *old_encoding TSRMLS_DC)
651 : {
652 : YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
653 : int offset, original_offset, length, free_flag;
654 : char *p;
655 : zend_encoding *new_encoding;
656 :
657 : /* calculate current position */
658 : offset = original_offset = yy_c_buf_p - b->yy_ch_buf;
659 : if (old_input_filter && original_offset > 0) {
660 : new_encoding = SCNG(script_encoding);
661 : SCNG(script_encoding) = old_encoding;
662 : do {
663 : (old_input_filter)(&p, &length, SCNG(script_org), offset TSRMLS_CC);
664 : if (!p) {
665 : SCNG(script_encoding) = new_encoding;
666 : return;
667 : }
668 : efree(p);
669 : if (length > original_offset) {
670 : offset--;
671 : } else if (length < original_offset) {
672 : offset++;
673 : }
674 : } while (original_offset != length);
675 : SCNG(script_encoding) = new_encoding;
676 : }
677 :
678 : /* convert and set */
679 : if (!SCNG(input_filter)) {
680 : length = SCNG(script_org_size)-offset-1;
681 : p = SCNG(script_org)+offset+1;
682 : free_flag = 0;
683 : } else {
684 : SCNG(input_filter)(&p, &length, SCNG(script_org)+offset+1, SCNG(script_org_size)-offset-1 TSRMLS_CC);
685 : free_flag = 1;
686 : }
687 : if (original_offset+length+1 > (int)b->yy_buf_size) {
688 : b->yy_buf_size = original_offset+length+1;
689 : b->yy_ch_buf = (char*)erealloc(b->yy_ch_buf, b->yy_buf_size+2);
690 : SCNG(script_filtered) = b->yy_ch_buf;
691 : SCNG(script_filtered_size) = b->yy_buf_size;
692 : }
693 : yy_c_buf_p = b->yy_ch_buf + original_offset;
694 : strncpy(yy_c_buf_p+1, p, length);
695 : b->yy_n_chars = original_offset + length + 1;
696 : SCNG(yy_n_chars) = b->yy_n_chars;
697 : b->yy_ch_buf[SCNG(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
698 : b->yy_ch_buf[SCNG(yy_n_chars)+1] = YY_END_OF_BUFFER_CHAR;
699 :
700 : if (free_flag) {
701 : efree(p);
702 : }
703 : }
704 :
705 :
706 : ZEND_API int zend_multibyte_yyinput(zend_file_handle *file_handle, char *buf, size_t len TSRMLS_DC)
707 : {
708 : int c = '*', n;
709 :
710 : if (file_handle->handle.stream.interactive == 0) {
711 : return zend_stream_read(file_handle, buf, len TSRMLS_CC);
712 : }
713 :
714 : /* interactive */
715 : if (SCNG(script_org)) {
716 : efree(SCNG(script_org));
717 : }
718 : if (SCNG(script_filtered)) {
719 : efree(SCNG(script_filtered));
720 : }
721 : SCNG(script_org) = NULL;
722 : SCNG(script_org_size) = 0;
723 :
724 : /* TODO: support widechars */
725 :
726 : for (n = 0; n < len && (c = zend_stream_getc(yyin TSRMLS_CC)) != EOF && c != '\n'; ++n) {
727 : buf[n] = (char)c;
728 : }
729 : if (c == '\n') {
730 : buf[n++] = (char) c;
731 : }
732 :
733 : SCNG(script_org_size) = n;
734 : SCNG(script_org) = (char*)emalloc(SCNG(script_org_size) + 1);
735 : memcpy(SCNG(script_org), buf, n);
736 :
737 : return n;
738 : }
739 :
740 :
741 : ZEND_API int zend_multibyte_read_script(TSRMLS_D)
742 : {
743 : char buf[8192];
744 : int n;
745 :
746 : if (SCNG(script_org)) {
747 : efree(SCNG(script_org));
748 : }
749 : SCNG(script_org) = NULL;
750 : SCNG(script_org_size) = 0;
751 :
752 : for (; (n = zend_stream_read(yyin, buf, sizeof(buf) TSRMLS_CC)) > 0; ) {
753 : SCNG(script_org_size) += n;
754 : SCNG(script_org) = (char*)erealloc(SCNG(script_org), SCNG(script_org_size));
755 : memcpy(SCNG(script_org) + SCNG(script_org_size) - n, buf, n);
756 : }
757 :
758 : if (n < 0) {
759 : return -1;
760 : }
761 :
762 : SCNG(script_org) = (char*)erealloc(SCNG(script_org), SCNG(script_org_size) + 1);
763 : *(SCNG(script_org)+SCNG(script_org_size)) = '\0';
764 :
765 : return 0;
766 : }
767 :
768 :
769 : # define zend_copy_value(zendlval, yytext, yyleng) \
770 : if (SCNG(output_filter)) { \
771 : SCNG(output_filter)(&(zendlval->value.str.val), &(zendlval->value.str.len), yytext, yyleng TSRMLS_CC); \
772 : } else { \
773 : zendlval->value.str.val = (char *) estrndup(yytext, yyleng); \
774 : zendlval->value.str.len = yyleng; \
775 : }
776 : #else /* ZEND_MULTIBYTE */
777 : # define zend_copy_value(zendlval, yytext, yyleng) \
778 : zendlval->value.str.val = (char *)estrndup(yytext, yyleng); \
779 : zendlval->value.str.len = yyleng;
780 : #endif /* ZEND_MULTIBYTE */
781 :
782 : static void zend_scan_escape_string(zval *zendlval, char *str, int len, char quote_type TSRMLS_DC)
783 123302 : {
784 : register char *s, *t;
785 : char *end;
786 :
787 123302 : ZVAL_STRINGL(zendlval, str, len, 1);
788 :
789 : /* convert escape sequences */
790 123302 : s = t = zendlval->value.str.val;
791 123302 : end = s+zendlval->value.str.len;
792 2194705 : while (s<end) {
793 1948103 : if (*s=='\\') {
794 40151 : s++;
795 40151 : if (s >= end) {
796 2 : *t++ = '\\';
797 2 : break;
798 : }
799 :
800 40149 : switch(*s) {
801 : case 'n':
802 31547 : *t++ = '\n';
803 31547 : zendlval->value.str.len--;
804 31547 : break;
805 : case 'r':
806 3439 : *t++ = '\r';
807 3439 : zendlval->value.str.len--;
808 3439 : break;
809 : case 't':
810 615 : *t++ = '\t';
811 615 : zendlval->value.str.len--;
812 615 : break;
813 : case 'f':
814 72 : *t++ = '\f';
815 72 : zendlval->value.str.len--;
816 72 : break;
817 : case 'v':
818 106 : *t++ = '\v';
819 106 : zendlval->value.str.len--;
820 106 : break;
821 : case '"':
822 : case '`':
823 1002 : if (*s != quote_type) {
824 3 : *t++ = '\\';
825 3 : *t++ = *s;
826 3 : break;
827 : }
828 : case '\\':
829 : case '$':
830 1915 : *t++ = *s;
831 1915 : zendlval->value.str.len--;
832 1915 : break;
833 : case 'x':
834 : case 'X':
835 2403 : if (ZEND_IS_HEX(*(s+1))) {
836 1191 : char hex_buf[3] = { 0, 0, 0 };
837 :
838 1191 : zendlval->value.str.len--; /* for the 'x' */
839 :
840 1191 : hex_buf[0] = *(++s);
841 1191 : zendlval->value.str.len--;
842 1191 : if (ZEND_IS_HEX(*(s+1))) {
843 1163 : hex_buf[1] = *(++s);
844 1163 : zendlval->value.str.len--;
845 : }
846 1191 : *t++ = (char) strtol(hex_buf, NULL, 16);
847 : } else {
848 21 : *t++ = '\\';
849 21 : *t++ = *s;
850 : }
851 1212 : break;
852 : default:
853 : /* check for an octal */
854 1887 : if (ZEND_IS_OCT(*s)) {
855 647 : char octal_buf[4] = { 0, 0, 0, 0 };
856 :
857 647 : octal_buf[0] = *s;
858 647 : zendlval->value.str.len--;
859 647 : if (ZEND_IS_OCT(*(s+1))) {
860 159 : octal_buf[1] = *(++s);
861 159 : zendlval->value.str.len--;
862 159 : if (ZEND_IS_OCT(*(s+1))) {
863 134 : octal_buf[2] = *(++s);
864 134 : zendlval->value.str.len--;
865 : }
866 : }
867 647 : *t++ = (char) strtol(octal_buf, NULL, 8);
868 : } else {
869 593 : *t++ = '\\';
870 593 : *t++ = *s;
871 : }
872 : break;
873 : }
874 : } else {
875 1907952 : *t++ = *s;
876 : }
877 :
878 1948101 : if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) {
879 9909 : CG(zend_lineno)++;
880 : }
881 1948101 : s++;
882 : }
883 123302 : *t = 0;
884 :
885 : #ifdef ZEND_MULTIBYTE
886 : if (SCNG(output_filter)) {
887 : s = zendlval->value.str.val;
888 : SCNG(output_filter)(&(zendlval->value.str.val), &(zendlval->value.str.len), s, zendlval->value.str.len TSRMLS_CC);
889 : efree(s);
890 : }
891 : #endif /* ZEND_MULTIBYTE */
892 123302 : }
893 :
894 : %}
895 :
896 : LNUM [0-9]+
897 : DNUM ([0-9]*[\.][0-9]+)|([0-9]+[\.][0-9]*)
898 : EXPONENT_DNUM (({LNUM}|{DNUM})[eE][+-]?{LNUM})
899 : HNUM "0x"[0-9a-fA-F]+
900 : LABEL [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
901 : WHITESPACE [ \n\r\t]+
902 : TABS_AND_SPACES [ \t]*
903 : TOKENS [;:,.\[\]()|^&+-/*=%!~$<>?@]
904 : ANY_CHAR (.|[\n])
905 : NEWLINE ("\r"|"\n"|"\r\n")
906 :
907 : /*
908 : * LITERAL_DOLLAR matches unescaped $ that aren't followed by a label character
909 : * or a { and therefore will be taken literally. The case of literal $ before
910 : * a variable or "${" is handled in a rule for each string type
911 : */
912 : DOUBLE_QUOTES_LITERAL_DOLLAR ("$"+([^a-zA-Z_\x7f-\xff$"\\{]|("\\"{ANY_CHAR})))
913 : BACKQUOTE_LITERAL_DOLLAR ("$"+([^a-zA-Z_\x7f-\xff$`\\{]|("\\"{ANY_CHAR})))
914 : HEREDOC_LITERAL_DOLLAR ("$"+([^a-zA-Z_\x7f-\xff$\n\r\\{]|("\\"[^\n\r])))
915 :
916 : /*
917 : * Usually, HEREDOC_NEWLINE will just function like a simple NEWLINE, but some
918 : * special cases need to be handled. HEREDOC_CHARS doesn't allow a line to
919 : * match when { or $, and/or \ is at the end. (("{"*|"$"*)"\\"?) handles that,
920 : * along with cases where { or $, and/or \ is the ONLY thing on a line
921 : *
922 : * The other case is when a line contains a label, followed by ONLY
923 : * { or $, and/or \ Handled by ({LABEL}";"?((("{"+|"$"+)"\\"?)|"\\"))
924 : */
925 : HEREDOC_NEWLINE ((({LABEL}";"?((("{"+|"$"+)"\\"?)|"\\"))|(("{"*|"$"*)"\\"?)){NEWLINE})
926 :
927 : /*
928 : * This pattern is just used in the next 2 for matching { or literal $, and/or
929 : * \ escape sequence immediately at the beginning of a line or after a label
930 : */
931 : HEREDOC_CURLY_OR_ESCAPE_OR_DOLLAR (("{"+[^$\n\r\\{])|("{"*"\\"[^\n\r])|{HEREDOC_LITERAL_DOLLAR})
932 :
933 : /*
934 : * These 2 label-related patterns allow HEREDOC_CHARS to continue "regular"
935 : * matching after a newline that starts with either a non-label character or a
936 : * label that isn't followed by a newline. Like HEREDOC_CHARS, they won't match
937 : * a variable or "{$" Matching a newline, and possibly label, up TO a variable
938 : * or "{$", is handled in the heredoc rules
939 : *
940 : * The HEREDOC_LABEL_NO_NEWLINE pattern (";"[^$\n\r\\{]) handles cases where ;
941 : * follows a label. [^a-zA-Z0-9_\x7f-\xff;$\n\r\\{] is needed to prevent a label
942 : * character or ; from matching on a possible (real) ending label
943 : */
944 : HEREDOC_NON_LABEL ([^a-zA-Z_\x7f-\xff$\n\r\\{]|{HEREDOC_CURLY_OR_ESCAPE_OR_DOLLAR})
945 : HEREDOC_LABEL_NO_NEWLINE ({LABEL}([^a-zA-Z0-9_\x7f-\xff;$\n\r\\{]|(";"[^$\n\r\\{])|(";"?{HEREDOC_CURLY_OR_ESCAPE_OR_DOLLAR})))
946 :
947 : /*
948 : * CHARS matches everything up to a variable or "{$"
949 : * {'s are matched as long as they aren't followed by a $
950 : * The case of { before "{$" is handled in a rule for each string type
951 : *
952 : * For heredocs, matching continues across/after newlines if/when it's known
953 : * that the next line doesn't contain a possible ending label
954 : */
955 : DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"{ANY_CHAR}))|{DOUBLE_QUOTES_LITERAL_DOLLAR})
956 : BACKQUOTE_CHARS ("{"*([^$`\\{]|("\\"{ANY_CHAR}))|{BACKQUOTE_LITERAL_DOLLAR})
957 : HEREDOC_CHARS ("{"*([^$\n\r\\{]|("\\"[^\n\r]))|{HEREDOC_LITERAL_DOLLAR}|({HEREDOC_NEWLINE}+({HEREDOC_NON_LABEL}|{HEREDOC_LABEL_NO_NEWLINE})))
958 :
959 : %option noyylineno
960 : %option noyywrap
961 : %%
962 :
963 : <ST_IN_SCRIPTING>"exit" {
964 746 : return T_EXIT;
965 : }
966 :
967 : <ST_IN_SCRIPTING>"die" {
968 7131 : return T_EXIT;
969 : }
970 :
971 : <ST_IN_SCRIPTING>"function" {
972 15254 : return T_FUNCTION;
973 : }
974 :
975 : <ST_IN_SCRIPTING>"const" {
976 136 : return T_CONST;
977 : }
978 :
979 : <ST_IN_SCRIPTING>"return" {
980 14269 : return T_RETURN;
981 : }
982 :
983 : <ST_IN_SCRIPTING>"try" {
984 960 : return T_TRY;
985 : }
986 :
987 : <ST_IN_SCRIPTING>"catch" {
988 967 : return T_CATCH;
989 : }
990 :
991 : <ST_IN_SCRIPTING>"throw" {
992 137 : return T_THROW;
993 : }
994 :
995 : <ST_IN_SCRIPTING>"if" {
996 24707 : return T_IF;
997 : }
998 :
999 : <ST_IN_SCRIPTING>"elseif" {
1000 1277 : return T_ELSEIF;
1001 : }
1002 :
1003 : <ST_IN_SCRIPTING>"endif" {
1004 2 : return T_ENDIF;
1005 : }
1006 :
1007 : <ST_IN_SCRIPTING>"else" {
1008 6845 : return T_ELSE;
1009 : }
1010 :
1011 : <ST_IN_SCRIPTING>"while" {
1012 722 : return T_WHILE;
1013 : }
1014 :
1015 : <ST_IN_SCRIPTING>"endwhile" {
1016 0 : return T_ENDWHILE;
1017 : }
1018 :
1019 : <ST_IN_SCRIPTING>"do" {
1020 206 : return T_DO;
1021 : }
1022 :
1023 : <ST_IN_SCRIPTING>"for" {
1024 1790 : return T_FOR;
1025 : }
1026 :
1027 : <ST_IN_SCRIPTING>"endfor" {
1028 1 : return T_ENDFOR;
1029 : }
1030 :
1031 : <ST_IN_SCRIPTING>"foreach" {
1032 5924 : return T_FOREACH;
1033 : }
1034 :
1035 : <ST_IN_SCRIPTING>"endforeach" {
1036 0 : return T_ENDFOREACH;
1037 : }
1038 :
1039 : <ST_IN_SCRIPTING>"declare" {
1040 7 : return T_DECLARE;
1041 : }
1042 :
1043 : <ST_IN_SCRIPTING>"enddeclare" {
1044 0 : return T_ENDDECLARE;
1045 : }
1046 :
1047 : <ST_IN_SCRIPTING>"instanceof" {
1048 22 : return T_INSTANCEOF;
1049 : }
1050 :
1051 : <ST_IN_SCRIPTING>"as" {
1052 5924 : return T_AS;
1053 : }
1054 :
1055 : <ST_IN_SCRIPTING>"switch" {
1056 388 : return T_SWITCH;
1057 : }
1058 :
1059 : <ST_IN_SCRIPTING>"endswitch" {
1060 0 : return T_ENDSWITCH;
1061 : }
1062 :
1063 : <ST_IN_SCRIPTING>"case" {
1064 1315 : return T_CASE;
1065 : }
1066 :
1067 : <ST_IN_SCRIPTING>"default" {
1068 215 : return T_DEFAULT;
1069 : }
1070 :
1071 : <ST_IN_SCRIPTING>"break" {
1072 1405 : return T_BREAK;
1073 : }
1074 :
1075 : <ST_IN_SCRIPTING>"continue" {
1076 173 : return T_CONTINUE;
1077 : }
1078 :
1079 : <ST_IN_SCRIPTING>"echo" {
1080 22507 : return T_ECHO;
1081 : }
1082 :
1083 : <ST_IN_SCRIPTING>"print" {
1084 2212 : return T_PRINT;
1085 : }
1086 :
1087 : <ST_IN_SCRIPTING>"class" {
1088 4139 : return T_CLASS;
1089 : }
1090 :
1091 : <ST_IN_SCRIPTING>"interface" {
1092 119 : return T_INTERFACE;
1093 : }
1094 :
1095 : <ST_IN_SCRIPTING>"extends" {
1096 808 : return T_EXTENDS;
1097 : }
1098 :
1099 : <ST_IN_SCRIPTING>"implements" {
1100 197 : return T_IMPLEMENTS;
1101 : }
1102 :
1103 : <ST_IN_SCRIPTING>"->" {
1104 20002 : yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
1105 20002 : return T_OBJECT_OPERATOR;
1106 : }
1107 :
1108 : <ST_LOOKING_FOR_PROPERTY>"->" {
1109 59 : return T_OBJECT_OPERATOR;
1110 : }
1111 :
1112 : <ST_LOOKING_FOR_PROPERTY>{LABEL} {
1113 19967 : yy_pop_state(TSRMLS_C);
1114 19967 : zend_copy_value(zendlval, yytext, yyleng);
1115 19967 : zendlval->type = IS_STRING;
1116 19967 : return T_STRING;
1117 : }
1118 :
1119 : <ST_LOOKING_FOR_PROPERTY>{ANY_CHAR} {
1120 94 : yyless(0);
1121 94 : yy_pop_state(TSRMLS_C);
1122 : }
1123 94 :
1124 : <ST_IN_SCRIPTING>"::" {
1125 6743 : return T_PAAMAYIM_NEKUDOTAYIM;
1126 : }
1127 :
1128 : <ST_IN_SCRIPTING>"new" {
1129 7061 : return T_NEW;
1130 : }
1131 :
1132 : <ST_IN_SCRIPTING>"clone" {
1133 45 : return T_CLONE;
1134 : }
1135 :
1136 : <ST_IN_SCRIPTING>"var" {
1137 107 : return T_VAR;
1138 : }
1139 :
1140 : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("int"|"integer"){TABS_AND_SPACES}")" {
1141 172 : return T_INT_CAST;
1142 : }
1143 :
1144 : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("real"|"double"|"float"){TABS_AND_SPACES}")" {
1145 19 : return T_DOUBLE_CAST;
1146 : }
1147 :
1148 : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"string"{TABS_AND_SPACES}")" {
1149 77 : return T_STRING_CAST;
1150 : }
1151 :
1152 : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"binary"{TABS_AND_SPACES}")" {
1153 38 : return T_STRING_CAST;
1154 : }
1155 :
1156 : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"array"{TABS_AND_SPACES}")" {
1157 5 : return T_ARRAY_CAST;
1158 : }
1159 :
1160 : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"object"{TABS_AND_SPACES}")" {
1161 144 : return T_OBJECT_CAST;
1162 : }
1163 :
1164 : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("bool"|"boolean"){TABS_AND_SPACES}")" {
1165 33 : return T_BOOL_CAST;
1166 : }
1167 :
1168 : <ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("unset"){TABS_AND_SPACES}")" {
1169 1 : return T_UNSET_CAST;
1170 : }
1171 :
1172 : <ST_IN_SCRIPTING>"eval" {
1173 1188 : return T_EVAL;
1174 : }
1175 :
1176 : <ST_IN_SCRIPTING>"include" {
1177 1577 : return T_INCLUDE;
1178 : }
1179 :
1180 : <ST_IN_SCRIPTING>"include_once" {
1181 50 : return T_INCLUDE_ONCE;
1182 : }
1183 :
1184 : <ST_IN_SCRIPTING>"require" {
1185 767 : return T_REQUIRE;
1186 : }
1187 :
1188 : <ST_IN_SCRIPTING>"require_once" {
1189 1828 : return T_REQUIRE_ONCE;
1190 : }
1191 :
1192 : <ST_IN_SCRIPTING>"use" {
1193 0 : return T_USE;
1194 : }
1195 :
1196 : <ST_IN_SCRIPTING>"global" {
1197 1028 : return T_GLOBAL;
1198 : }
1199 :
1200 : <ST_IN_SCRIPTING>"isset" {
1201 1138 : return T_ISSET;
1202 : }
1203 :
1204 : <ST_IN_SCRIPTING>"empty" {
1205 780 : return T_EMPTY;
1206 : }
1207 :
1208 : <ST_IN_SCRIPTING>"__halt_compiler" {
1209 9 : return T_HALT_COMPILER;
1210 : }
1211 :
1212 : <ST_IN_SCRIPTING>"static" {
1213 3420 : return T_STATIC;
1214 : }
1215 :
1216 : <ST_IN_SCRIPTING>"abstract" {
1217 84 : return T_ABSTRACT;
1218 : }
1219 :
1220 : <ST_IN_SCRIPTING>"final" {
1221 23 : return T_FINAL;
1222 : }
1223 :
1224 : <ST_IN_SCRIPTING>"private" {
1225 565 : return T_PRIVATE;
1226 : }
1227 :
1228 : <ST_IN_SCRIPTING>"protected" {
1229 415 : return T_PROTECTED;
1230 : }
1231 :
1232 : <ST_IN_SCRIPTING>"public" {
1233 2124 : return T_PUBLIC;
1234 : }
1235 :
1236 : <ST_IN_SCRIPTING>"unset" {
1237 1228 : return T_UNSET;
1238 : }
1239 :
1240 : <ST_IN_SCRIPTING>"=>" {
1241 24626 : return T_DOUBLE_ARROW;
1242 : }
1243 :
1244 : <ST_IN_SCRIPTING>"list" {
1245 78 : return T_LIST;
1246 : }
1247 :
1248 : <ST_IN_SCRIPTING>"array" {
1249 17769 : return T_ARRAY;
1250 : }
1251 :
1252 : <ST_IN_SCRIPTING>"++" {
1253 5402 : return T_INC;
1254 : }
1255 :
1256 : <ST_IN_SCRIPTING>"--" {
1257 58 : return T_DEC;
1258 : }
1259 :
1260 : <ST_IN_SCRIPTING>"===" {
1261 3029 : return T_IS_IDENTICAL;
1262 : }
1263 :
1264 : <ST_IN_SCRIPTING>"!==" {
1265 1182 : return T_IS_NOT_IDENTICAL;
1266 : }
1267 :
1268 : <ST_IN_SCRIPTING>"==" {
1269 8191 : return T_IS_EQUAL;
1270 : }
1271 :
1272 : <ST_IN_SCRIPTING>"!="|"<>" {
1273 1762 : return T_IS_NOT_EQUAL;
1274 : }
1275 :
1276 : <ST_IN_SCRIPTING>"<=" {
1277 1570 : return T_IS_SMALLER_OR_EQUAL;
1278 : }
1279 :
1280 : <ST_IN_SCRIPTING>">=" {
1281 221 : return T_IS_GREATER_OR_EQUAL;
1282 : }
1283 :
1284 : <ST_IN_SCRIPTING>"+=" {
1285 159 : return T_PLUS_EQUAL;
1286 : }
1287 :
1288 : <ST_IN_SCRIPTING>"-=" {
1289 132 : return T_MINUS_EQUAL;
1290 : }
1291 :
1292 : <ST_IN_SCRIPTING>"*=" {
1293 10 : return T_MUL_EQUAL;
1294 : }
1295 :
1296 : <ST_IN_SCRIPTING>"/=" {
1297 4 : return T_DIV_EQUAL;
1298 : }
1299 :
1300 : <ST_IN_SCRIPTING>".=" {
1301 816 : return T_CONCAT_EQUAL;
1302 : }
1303 :
1304 : <ST_IN_SCRIPTING>"%=" {
1305 1 : return T_MOD_EQUAL;
1306 : }
1307 :
1308 : <ST_IN_SCRIPTING>"<<=" {
1309 4 : return T_SL_EQUAL;
1310 : }
1311 :
1312 : <ST_IN_SCRIPTING>">>=" {
1313 5 : return T_SR_EQUAL;
1314 : }
1315 :
1316 : <ST_IN_SCRIPTING>"&=" {
1317 3 : return T_AND_EQUAL;
1318 : }
1319 :
1320 : <ST_IN_SCRIPTING>"|=" {
1321 2 : return T_OR_EQUAL;
1322 : }
1323 :
1324 : <ST_IN_SCRIPTING>"^=" {
1325 2 : return T_XOR_EQUAL;
1326 : }
1327 :
1328 : <ST_IN_SCRIPTING>"||" {
1329 848 : return T_BOOLEAN_OR;
1330 : }
1331 :
1332 : <ST_IN_SCRIPTING>"&&" {
1333 2387 : return T_BOOLEAN_AND;
1334 : }
1335 :
1336 : <ST_IN_SCRIPTING>"OR" {
1337 727 : return T_LOGICAL_OR;
1338 : }
1339 :
1340 : <ST_IN_SCRIPTING>"AND" {
1341 12 : return T_LOGICAL_AND;
1342 : }
1343 :
1344 : <ST_IN_SCRIPTING>"XOR" {
1345 1 : return T_LOGICAL_XOR;
1346 : }
1347 :
1348 : <ST_IN_SCRIPTING>"<<" {
1349 89 : return T_SL;
1350 : }
1351 :
1352 : <ST_IN_SCRIPTING>">>" {
1353 18 : return T_SR;
1354 : }
1355 :
1356 : <ST_IN_SCRIPTING>{TOKENS} {
1357 922490 : return yytext[0];
1358 : }
1359 :
1360 :
1361 : <ST_IN_SCRIPTING>"{" {
1362 53587 : yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
1363 53587 : return '{';
1364 : }
1365 :
1366 :
1367 : <ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"${" {
1368 77 : yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC);
1369 77 : return T_DOLLAR_OPEN_CURLY_BRACES;
1370 : }
1371 :
1372 :
1373 : <ST_IN_SCRIPTING>"}" {
1374 53844 : RESET_DOC_COMMENT();
1375 : /* This is a temporary fix which is dependant on flex and it's implementation */
1376 53844 : if (yy_start_stack_ptr) {
1377 53843 : yy_pop_state(TSRMLS_C);
1378 : }
1379 53844 : return '}';
1380 : }
1381 :
1382 :
1383 : <ST_LOOKING_FOR_VARNAME>{LABEL} {
1384 77 : zend_copy_value(zendlval, yytext, yyleng);
1385 77 : zendlval->type = IS_STRING;
1386 77 : yy_pop_state(TSRMLS_C);
1387 77 : yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
1388 77 : return T_STRING_VARNAME;
1389 : }
1390 :
1391 :
1392 : <ST_LOOKING_FOR_VARNAME>{ANY_CHAR} {
1393 0 : yyless(0);
1394 0 : yy_pop_state(TSRMLS_C);
1395 0 : yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
1396 : }
1397 0 :
1398 :
1399 : <ST_IN_SCRIPTING>{LNUM} {
1400 54220 : if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */
1401 53473 : zendlval->value.lval = strtol(yytext, NULL, 0);
1402 : } else {
1403 747 : errno = 0;
1404 747 : zendlval->value.lval = strtol(yytext, NULL, 0);
1405 747 : if (errno == ERANGE) { /* Overflow */
1406 383 : if (yytext[0] == '0') { /* octal overflow */
1407 83 : zendlval->value.dval = zend_oct_strtod(yytext, NULL);
1408 : } else {
1409 300 : zendlval->value.dval = zend_strtod(yytext, NULL);
1410 : }
1411 383 : zendlval->type = IS_DOUBLE;
1412 383 : return T_DNUMBER;
1413 : }
1414 : }
1415 :
1416 53837 : zendlval->type = IS_LONG;
1417 53837 : return T_LNUMBER;
1418 : }
1419 :
1420 : <ST_IN_SCRIPTING>{HNUM} {
1421 990 : char *hex = yytext + 2; /* Skip "0x" */
1422 990 : int len = yyleng - 2;
1423 :
1424 : /* Skip any leading 0s */
1425 2244 : while (*hex == '0') {
1426 264 : hex++;
1427 264 : len--;
1428 : }
1429 :
1430 990 : if (len < SIZEOF_LONG * 2 || (len == SIZEOF_LONG * 2 && *hex <= '7')) {
1431 897 : zendlval->value.lval = strtol(hex, NULL, 16);
1432 897 : zendlval->type = IS_LONG;
1433 897 : return T_LNUMBER;
1434 : } else {
1435 93 : zendlval->value.dval = zend_hex_strtod(hex, NULL);
1436 93 : zendlval->type = IS_DOUBLE;
1437 93 : return T_DNUMBER;
1438 : }
1439 : }
1440 :
1441 : <ST_VAR_OFFSET>0|([1-9][0-9]*) { /* Offset could be treated as a long */
1442 580 : if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) {
1443 290 : zendlval->value.lval = strtol(yytext, NULL, 10);
1444 290 : zendlval->type = IS_LONG;
1445 : } else {
1446 0 : zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
1447 0 : zendlval->value.str.len = yyleng;
1448 0 : zendlval->type = IS_STRING;
1449 : }
1450 290 : return T_NUM_STRING;
1451 : }
1452 :
1453 : <ST_VAR_OFFSET>{LNUM}|{HNUM} { /* Offset must be treated as a string */
1454 0 : zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
1455 0 : zendlval->value.str.len = yyleng;
1456 0 : zendlval->type = IS_STRING;
1457 0 : return T_NUM_STRING;
1458 : }
1459 :
1460 : <ST_IN_SCRIPTING>{DNUM}|{EXPONENT_DNUM} {
1461 6799 : zendlval->value.dval = zend_strtod(yytext, NULL);
1462 6799 : zendlval->type = IS_DOUBLE;
1463 6799 : return T_DNUMBER;
1464 : }
1465 :
1466 : <ST_IN_SCRIPTING>"__CLASS__" {
1467 42 : char *class_name = NULL;
1468 :
1469 42 : if (CG(active_class_entry)) {
1470 41 : class_name = CG(active_class_entry)->name;
1471 : }
1472 :
1473 42 : if (!class_name) {
1474 1 : class_name = "";
1475 : }
1476 42 : zendlval->value.str.len = strlen(class_name);
1477 42 : zendlval->value.str.val = estrndup(class_name, zendlval->value.str.len);
1478 42 : zendlval->type = IS_STRING;
1479 42 : return T_CLASS_C;
1480 : }
1481 :
1482 : <ST_IN_SCRIPTING>"__FUNCTION__" {
1483 64 : char *func_name = NULL;
1484 :
1485 64 : if (CG(active_op_array)) {
1486 63 : func_name = CG(active_op_array)->function_name;
1487 : }
1488 :
1489 64 : if (!func_name) {
1490 2 : func_name = "";
1491 : }
1492 64 : zendlval->value.str.len = strlen(func_name);
1493 64 : zendlval->value.str.val = estrndup(func_name, zendlval->value.str.len);
1494 64 : zendlval->type = IS_STRING;
1495 64 : return T_FUNC_C;
1496 : }
1497 :
1498 : <ST_IN_SCRIPTING>"__METHOD__" {
1499 659 : char *class_name = CG(active_class_entry) ? CG(active_class_entry)->name : NULL;
1500 659 : char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL;
1501 659 : size_t len = 0;
1502 :
1503 659 : if (class_name) {
1504 639 : len += strlen(class_name) + 2;
1505 : }
1506 659 : if (func_name) {
1507 657 : len += strlen(func_name);
1508 : }
1509 :
1510 659 : zendlval->value.str.len = zend_spprintf(&zendlval->value.str.val, 0, "%s%s%s",
1511 : class_name ? class_name : "",
1512 : class_name && func_name ? "::" : "",
1513 : func_name ? func_name : ""
1514 : );
1515 659 : zendlval->type = IS_STRING;
1516 659 : return T_METHOD_C;
1517 : }
1518 :
1519 : <ST_IN_SCRIPTING>"__LINE__" {
1520 12 : zendlval->value.lval = CG(zend_lineno);
1521 12 : zendlval->type = IS_LONG;
1522 12 : return T_LINE;
1523 : }
1524 :
1525 : <ST_IN_SCRIPTING>"__FILE__" {
1526 4339 : char *filename = zend_get_compiled_filename(TSRMLS_C);
1527 :
1528 4339 : if (!filename) {
1529 0 : filename = "";
1530 : }
1531 4339 : zendlval->value.str.len = strlen(filename);
1532 4339 : zendlval->value.str.val = estrndup(filename, zendlval->value.str.len);
1533 4339 : zendlval->type = IS_STRING;
1534 4339 : return T_FILE;
1535 : }
1536 :
1537 : <INITIAL>(([^<]|"<"[^?%s<]){1,400})|"<s"|"<" {
1538 : #ifdef ZEND_MULTIBYTE
1539 : if (SCNG(output_filter)) {
1540 : int readsize;
1541 : readsize = SCNG(output_filter)(&(zendlval->value.str.val), &(zendlval->value.str.len), yytext, yyleng TSRMLS_CC);
1542 : if (readsize < yyleng) {
1543 : yyless(readsize);
1544 : }
1545 : } else {
1546 : zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
1547 : zendlval->value.str.len = yyleng;
1548 : }
1549 : #else /* !ZEND_MULTIBYTE */
1550 2717 : zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
1551 2717 : zendlval->value.str.len = yyleng;
1552 : #endif /* ZEND_MULTIBYTE */
1553 2717 : zendlval->type = IS_STRING;
1554 2717 : HANDLE_NEWLINES(yytext, yyleng);
1555 2717 : return T_INLINE_HTML;
1556 : }
1557 :
1558 : <INITIAL>"<?"|"<script"{WHITESPACE}+"language"{WHITESPACE}*"="{WHITESPACE}*("php"|"\"php\""|"\'php\'"){WHITESPACE}*">" {
1559 7 : HANDLE_NEWLINES(yytext, yyleng);
1560 7 : if (CG(short_tags) || yyleng>2) { /* yyleng>2 means it's not <? but <script> */
1561 5 : zendlval->value.str.val = yytext; /* no copying - intentional */
1562 5 : zendlval->value.str.len = yyleng;
1563 5 : zendlval->type = IS_STRING;
1564 5 : BEGIN(ST_IN_SCRIPTING);
1565 5 : return T_OPEN_TAG;
1566 : } else {
1567 2 : zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
1568 2 : zendlval->value.str.len = yyleng;
1569 2 : zendlval->type = IS_STRING;
1570 2 : return T_INLINE_HTML;
1571 : }
1572 : }
1573 :
1574 :
1575 : <INITIAL>"<%="|"<?=" {
1576 9 : if ((yytext[1]=='%' && CG(asp_tags)) || (yytext[1]=='?' && CG(short_tags))) {
1577 5 : zendlval->value.str.val = yytext; /* no copying - intentional */
1578 5 : zendlval->value.str.len = yyleng;
1579 5 : zendlval->type = IS_STRING;
1580 5 : BEGIN(ST_IN_SCRIPTING);
1581 5 : return T_OPEN_TAG_WITH_ECHO;
1582 : } else {
1583 4 : zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
1584 4 : zendlval->value.str.len = yyleng;
1585 4 : zendlval->type = IS_STRING;
1586 4 : return T_INLINE_HTML;
1587 : }
1588 : }
1589 :
1590 :
1591 : <INITIAL>"<%" {
1592 0 : if (CG(asp_tags)) {
1593 0 : zendlval->value.str.val = yytext; /* no copying - intentional */
1594 0 : zendlval->value.str.len = yyleng;
1595 0 : zendlval->type = IS_STRING;
1596 0 : BEGIN(ST_IN_SCRIPTING);
1597 0 : return T_OPEN_TAG;
1598 : } else {
1599 0 : zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
1600 0 : zendlval->value.str.len = yyleng;
1601 0 : zendlval->type = IS_STRING;
1602 0 : return T_INLINE_HTML;
1603 : }
1604 : }
1605 :
1606 :
1607 : <INITIAL>"<?php"([ \t]|{NEWLINE}) {
1608 17682 : zendlval->value.str.val = yytext; /* no copying - intentional */
1609 17682 : zendlval->value.str.len = yyleng;
1610 17682 : zendlval->type = IS_STRING;
1611 17682 : HANDLE_NEWLINE(yytext[yyleng-1]);
1612 17682 : BEGIN(ST_IN_SCRIPTING);
1613 17682 : return T_OPEN_TAG;
1614 : }
1615 :
1616 : <ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>"$"{LABEL} {
1617 272140 : zend_copy_value(zendlval, (yytext+1), (yyleng-1));
1618 272140 : zendlval->type = IS_STRING;
1619 272140 : return T_VARIABLE;
1620 : }
1621 :
1622 : %{
1623 : /* Make sure a label character follows "->", otherwise there is no property
1624 : * and "->" will be taken literally
1625 : */ %}
1626 : <ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE>"$"{LABEL}"->"[a-zA-Z_\x7f-\xff] {
1627 59 : yyless(yyleng - 3);
1628 59 : yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC);
1629 59 : zend_copy_value(zendlval, (yytext+1), (yyleng-1));
1630 59 : zendlval->type = IS_STRING;
1631 59 : return T_VARIABLE;
1632 : }
1633 :
1634 : %{
1635 : /* A [ always designates a variable offset, regardless of what follows
1636 : */ %}
1637 : <ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE>"$"{LABEL}"[" {
1638 872 : yyless(yyleng - 1);
1639 872 : yy_push_state(ST_VAR_OFFSET TSRMLS_CC);
1640 872 : zend_copy_value(zendlval, (yytext+1), (yyleng-1));
1641 872 : zendlval->type = IS_STRING;
1642 872 : return T_VARIABLE;
1643 : }
1644 :
1645 : <ST_VAR_OFFSET>"]" {
1646 871 : yy_pop_state(TSRMLS_C);
1647 871 : return ']';
1648 : }
1649 :
1650 : <ST_VAR_OFFSET>{TOKENS}|[{}"`] {
1651 : /* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */
1652 872 : return yytext[0];
1653 : }
1654 :
1655 : <ST_VAR_OFFSET>[ \n\r\t\\'#] {
1656 : /* Invalid rule to return a more explicit parse error with proper line number */
1657 1 : yyless(0);
1658 1 : yy_pop_state(TSRMLS_C);
1659 1 : ZVAL_EMPTY_STRING(zendlval); /* Empty since it won't be used */
1660 1 : return T_ENCAPSED_AND_WHITESPACE;
1661 : }
1662 :
1663 : <ST_IN_SCRIPTING,ST_VAR_OFFSET>{LABEL} {
1664 183986 : zend_copy_value(zendlval, yytext, yyleng);
1665 183986 : zendlval->type = IS_STRING;
1666 183986 : return T_STRING;
1667 : }
1668 :
1669 :
1670 : <ST_IN_SCRIPTING>{WHITESPACE} {
1671 941245 : zendlval->value.str.val = yytext; /* no copying - intentional */
1672 941245 : zendlval->value.str.len = yyleng;
1673 941245 : zendlval->type = IS_STRING;
1674 941245 : HANDLE_NEWLINES(yytext, yyleng);
1675 941245 : return T_WHITESPACE;
1676 : }
1677 :
1678 :
1679 : <ST_IN_SCRIPTING>"#"|"//" {
1680 35592 : BEGIN(ST_ONE_LINE_COMMENT);
1681 35592 : yymore();
1682 : }
1683 35592 :
1684 : <ST_ONE_LINE_COMMENT>"?"|"%"|">" {
1685 219 : yymore();
1686 : }
1687 219 :
1688 : <ST_ONE_LINE_COMMENT>[^\n\r?%>]*{ANY_CHAR} {
1689 35804 : switch (yytext[yyleng-1]) {
1690 : case '?': case '%': case '>':
1691 214 : yyless(yyleng-1);
1692 214 : yymore();
1693 : break;
1694 : case '\n':
1695 35476 : CG(zend_lineno)++;
1696 : /* intentional fall through */
1697 : default:
1698 35590 : zendlval->value.str.val = yytext; /* no copying - intentional */
1699 35590 : zendlval->value.str.len = yyleng;
1700 35590 : zendlval->type = IS_STRING;
1701 35590 : BEGIN(ST_IN_SCRIPTING);
1702 35590 : return T_COMMENT;
1703 : }
1704 : }
1705 214 :
1706 : <ST_ONE_LINE_COMMENT>{NEWLINE} {
1707 0 : zendlval->value.str.val = yytext; /* no copying - intentional */
1708 0 : zendlval->value.str.len = yyleng;
1709 0 : zendlval->type = IS_STRING;
1710 0 : BEGIN(ST_IN_SCRIPTING);
1711 0 : CG(zend_lineno)++;
1712 0 : return T_COMMENT;
1713 : }
1714 :
1715 : <ST_ONE_LINE_COMMENT>"?>"|"%>" {
1716 2 : if (CG(asp_tags) || yytext[yyleng-2] != '%') { /* asp comment? */
1717 2 : zendlval->value.str.val = yytext; /* no copying - intentional */
1718 2 : zendlval->value.str.len = yyleng-2;
1719 2 : zendlval->type = IS_STRING;
1720 2 : yyless(yyleng-2);
1721 2 : BEGIN(ST_IN_SCRIPTING);
1722 2 : return T_COMMENT;
1723 : } else {
1724 0 : yymore();
1725 : }
1726 : }
1727 0 :
1728 : <ST_IN_SCRIPTING>"/**"{WHITESPACE} {
1729 334 : CG(comment_start_line) = CG(zend_lineno);
1730 334 : RESET_DOC_COMMENT();
1731 334 : BEGIN(ST_DOC_COMMENT);
1732 334 : yymore();
1733 : }
1734 334 :
1735 : <ST_IN_SCRIPTING>"/*" {
1736 13076 : CG(comment_start_line) = CG(zend_lineno);
1737 13076 : BEGIN(ST_COMMENT);
1738 13076 : yymore();
1739 : }
1740 13076 :
1741 :
1742 : <ST_COMMENT,ST_DOC_COMMENT>[^*]+ {
1743 24651 : yymore();
1744 : }
1745 24651 :
1746 : <ST_DOC_COMMENT>"*/" {
1747 334 : CG(doc_comment) = estrndup(yytext, yyleng);
1748 334 : CG(doc_comment_len) = yyleng;
1749 334 : HANDLE_NEWLINES(yytext, yyleng);
1750 334 : BEGIN(ST_IN_SCRIPTING);
1751 334 : return T_DOC_COMMENT;
1752 : }
1753 :
1754 : <ST_COMMENT>"*/" {
1755 13075 : HANDLE_NEWLINES(yytext, yyleng);
1756 13075 : BEGIN(ST_IN_SCRIPTING);
1757 13075 : return T_COMMENT;
1758 : }
1759 :
1760 : <ST_COMMENT,ST_DOC_COMMENT>"*" {
1761 12052 : yymore();
1762 : }
1763 12052 :
1764 : <ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*">"){NEWLINE}? {
1765 17232 : zendlval->value.str.val = yytext; /* no copying - intentional */
1766 17232 : zendlval->value.str.len = yyleng;
1767 17232 : zendlval->type = IS_STRING;
1768 17232 : BEGIN(INITIAL);
1769 17232 : return T_CLOSE_TAG; /* implicit ';' at php-end tag */
1770 : }
1771 :
1772 :
1773 : <ST_IN_SCRIPTING>"%>"{NEWLINE}? {
1774 2 : if (CG(asp_tags)) {
1775 2 : BEGIN(INITIAL);
1776 2 : zendlval->value.str.len = yyleng;
1777 2 : zendlval->type = IS_STRING;
1778 2 : zendlval->value.str.val = yytext; /* no copying - intentional */
1779 2 : return T_CLOSE_TAG; /* implicit ';' at php-end tag */
1780 : } else {
1781 0 : yyless(1);
1782 0 : return yytext[0];
1783 : }
1784 : }
1785 :
1786 :
1787 : %{
1788 : /* ("{"*|"$"*) handles { or $ at the end of a string (or the entire contents)
1789 : */ %}
1790 : <ST_IN_SCRIPTING>(b?["]{DOUBLE_QUOTES_CHARS}*("{"*|"$"*)["]) {
1791 105471 : int bprefix = (yytext[0] != '"') ? 1 : 0;
1792 :
1793 105471 : zend_scan_escape_string(zendlval, yytext+bprefix+1, yyleng-bprefix-2, '"' TSRMLS_CC);
1794 105471 : return T_CONSTANT_ENCAPSED_STRING;
1795 : }
1796 :
1797 :
1798 : <ST_IN_SCRIPTING>(b?[']([^'\\]|("\\"{ANY_CHAR}))*[']) {
1799 : register char *s, *t;
1800 : char *end;
1801 64213 : int bprefix = (yytext[0] != '\'') ? 1 : 0;
1802 :
1803 64213 : zendlval->value.str.val = estrndup(yytext+bprefix+1, yyleng-bprefix-2);
1804 64213 : zendlval->value.str.len = yyleng-bprefix-2;
1805 64213 : zendlval->type = IS_STRING;
1806 :
1807 : /* convert escape sequences */
1808 64213 : s = t = zendlval->value.str.val;
1809 64213 : end = s+zendlval->value.str.len;
1810 835266 : while (s<end) {
1811 706840 : if (*s=='\\') {
1812 3244 : s++;
1813 :
1814 3244 : switch(*s) {
1815 : case '\\':
1816 : case '\'':
1817 1023 : *t++ = *s;
1818 1023 : zendlval->value.str.len--;
1819 1023 : break;
1820 : default:
1821 2221 : *t++ = '\\';
1822 2221 : *t++ = *s;
1823 : break;
1824 : }
1825 : } else {
1826 703596 : *t++ = *s;
1827 : }
1828 :
1829 706840 : if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) {
1830 858 : CG(zend_lineno)++;
1831 : }
1832 706840 : s++;
1833 : }
1834 64213 : *t = 0;
1835 :
1836 : #ifdef ZEND_MULTIBYTE
1837 : if (SCNG(output_filter)) {
1838 : s = zendlval->value.str.val;
1839 : SCNG(output_filter)(&(zendlval->value.str.val), &(zendlval->value.str.len), s, zendlval->value.str.len TSRMLS_CC);
1840 : efree(s);
1841 : }
1842 : #endif /* ZEND_MULTIBYTE */
1843 :
1844 64213 : return T_CONSTANT_ENCAPSED_STRING;
1845 : }
1846 :
1847 :
1848 : <ST_IN_SCRIPTING>b?["] {
1849 9289 : BEGIN(ST_DOUBLE_QUOTES);
1850 9289 : return '"';
1851 : }
1852 :
1853 :
1854 : <ST_IN_SCRIPTING>b?"<<<"{TABS_AND_SPACES}{LABEL}{NEWLINE} {
1855 : char *s;
1856 1269 : int bprefix = (yytext[0] != '<') ? 1 : 0;
1857 :
1858 1269 : CG(zend_lineno)++;
1859 1269 : CG(heredoc_len) = yyleng-bprefix-3-1-(yytext[yyleng-2]=='\r'?1:0);
1860 1269 : s = yytext+bprefix+3;
1861 2556 : while ((*s == ' ') || (*s == '\t')) {
1862 18 : s++;
1863 18 : CG(heredoc_len)--;
1864 : }
1865 1269 : CG(heredoc) = estrndup(s, CG(heredoc_len));
1866 1269 : BEGIN(ST_START_HEREDOC);
1867 1269 : return T_START_HEREDOC;
1868 : }
1869 :
1870 :
1871 : <ST_IN_SCRIPTING>[`] {
1872 98 : BEGIN(ST_BACKQUOTE);
1873 98 : return '`';
1874 : }
1875 :
1876 :
1877 : <ST_START_HEREDOC>{ANY_CHAR} {
1878 1105 : yyless(0);
1879 1105 : BEGIN(ST_HEREDOC);
1880 : }
1881 1105 :
1882 : <ST_START_HEREDOC>{LABEL}";"?[\n\r] {
1883 164 : int label_len = yyleng - 1;
1884 :
1885 164 : if (yytext[label_len-1]==';') {
1886 52 : label_len--;
1887 : }
1888 :
1889 164 : yyless(label_len);
1890 :
1891 164 : if (label_len==CG(heredoc_len) && !memcmp(yytext, CG(heredoc), label_len)) {
1892 52 : zendlval->value.str.val = CG(heredoc);
1893 52 : zendlval->value.str.len = label_len;
1894 52 : CG(heredoc)=NULL;
1895 52 : CG(heredoc_len)=0;
1896 52 : BEGIN(ST_IN_SCRIPTING);
1897 52 : return T_END_HEREDOC;
1898 : } else {
1899 112 : yymore();
1900 112 : BEGIN(ST_HEREDOC);
1901 : }
1902 : }
1903 112 :
1904 : %{
1905 : /* Match everything up to and including a possible ending label, so if the label
1906 : * doesn't match, it's kept with the rest of the string
1907 : *
1908 : * {HEREDOC_NEWLINE}+ handles the case of more than one newline sequence that
1909 : * couldn't be matched with HEREDOC_CHARS, because of the following label
1910 : */ %}
1911 : <ST_HEREDOC>{HEREDOC_CHARS}*{HEREDOC_NEWLINE}+{LABEL}";"?[\n\r] {
1912 1343 : char *end = yytext + yyleng - 1;
1913 :
1914 1343 : if (end[-1] == ';') {
1915 1204 : end--;
1916 1204 : yyleng--;
1917 : }
1918 :
1919 1343 : if (yyleng > CG(heredoc_len) && !memcmp(end - CG(heredoc_len), CG(heredoc), CG(heredoc_len))) {
1920 1217 : int len = yyleng - CG(heredoc_len) - 2; /* 2 for newline before and after label */
1921 :
1922 : /* May have matched fooLABEL; make sure there's a newline before it */
1923 1217 : if (yytext[len] != '\n') {
1924 0 : if (yytext[len] != '\r') {
1925 0 : goto wrong_label;
1926 : }
1927 1217 : } else if (len > 0 && yytext[len - 1] == '\r') {
1928 0 : len--; /* Windows newline */
1929 : }
1930 :
1931 : /* Go back before last label char, to match in ST_END_HEREDOC state */
1932 1217 : yyless(yyleng - 2);
1933 :
1934 : /* Subtract the remaining label length. yyleng must include newline
1935 : * before label, for zend_highlight/strip, tokenizer, etc. */
1936 1217 : yyleng -= CG(heredoc_len) - 1;
1937 :
1938 1217 : CG(increment_lineno) = 1; /* For newline before label */
1939 1217 : BEGIN(ST_END_HEREDOC);
1940 1217 : zend_scan_escape_string(zendlval, yytext, len, 0 TSRMLS_CC);
1941 1217 : return T_ENCAPSED_AND_WHITESPACE;
1942 : } else {
1943 : /* Go back to end of label, so the next match works correctly in case of
1944 : * a variable or another label at the beginning of the next line */
1945 126 : wrong_label:
1946 126 : yyless(yyleng - 1);
1947 126 : yymore();
1948 : }
1949 : }
1950 126 :
1951 : <ST_END_HEREDOC>{ANY_CHAR} {
1952 1217 : zendlval->value.str.val = CG(heredoc);
1953 1217 : zendlval->value.str.len = CG(heredoc_len);
1954 1217 : yytext = zendlval->value.str.val;
1955 1217 : yyleng = zendlval->value.str.len;
1956 1217 : CG(heredoc) = NULL;
1957 1217 : CG(heredoc_len) = 0;
1958 1217 : BEGIN(ST_IN_SCRIPTING);
1959 1217 : return T_END_HEREDOC;
1960 : }
1961 :
1962 :
1963 : <ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"{$" {
1964 231 : zendlval->value.lval = (long) '{';
1965 231 : yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
1966 231 : yyless(1);
1967 231 : return T_CURLY_OPEN;
1968 : }
1969 :
1970 :
1971 : <ST_DOUBLE_QUOTES>{DOUBLE_QUOTES_CHARS}+ {
1972 16032 : zend_scan_escape_string(zendlval, yytext, yyleng, '"' TSRMLS_CC);
1973 16032 : return T_ENCAPSED_AND_WHITESPACE;
1974 : }
1975 :
1976 : %{
1977 : /* "{"{2,}|"$"{2,} handles { before "{$" or literal $ before a variable or "${"
1978 : * (("{"+|"$"+)["]) handles { or $ at the end of a string
1979 : *
1980 : * Same for backquotes and heredocs, except the second case doesn't apply to
1981 : * heredocs. yyless(yyleng - 1) is used to correct taking one character too many
1982 : */ %}
1983 : <ST_DOUBLE_QUOTES>{DOUBLE_QUOTES_CHARS}*("{"{2,}|"$"{2,}|(("{"+|"$"+)["])) {
1984 1 : yyless(yyleng - 1);
1985 1 : zend_scan_escape_string(zendlval, yytext, yyleng, '"' TSRMLS_CC);
1986 1 : return T_ENCAPSED_AND_WHITESPACE;
1987 : }
1988 :
1989 :
1990 : <ST_BACKQUOTE>{BACKQUOTE_CHARS}+ {
1991 151 : zend_scan_escape_string(zendlval, yytext, yyleng, '`' TSRMLS_CC);
1992 151 : return T_ENCAPSED_AND_WHITESPACE;
1993 : }
1994 :
1995 : <ST_BACKQUOTE>{BACKQUOTE_CHARS}*("{"{2,}|"$"{2,}|(("{"+|"$"+)[`])) {
1996 0 : yyless(yyleng - 1);
1997 0 : zend_scan_escape_string(zendlval, yytext, yyleng, '`' TSRMLS_CC);
1998 0 : return T_ENCAPSED_AND_WHITESPACE;
1999 : }
2000 :
2001 :
2002 : %{
2003 : /* ({HEREDOC_NEWLINE}+({LABEL}";"?)?)? handles the possible case of newline
2004 : * sequences, possibly followed by a label, that couldn't be matched with
2005 : * HEREDOC_CHARS because of a following variable or "{$"
2006 : *
2007 : * This doesn't affect real ending labels, as they are followed by a newline,
2008 : * which will result in a longer match for the correct rule if present
2009 : */ %}
2010 : <ST_HEREDOC>{HEREDOC_CHARS}*({HEREDOC_NEWLINE}+({LABEL}";"?)?)? {
2011 430 : zend_scan_escape_string(zendlval, yytext, yyleng, 0 TSRMLS_CC);
2012 430 : return T_ENCAPSED_AND_WHITESPACE;
2013 : }
2014 :
2015 : <ST_HEREDOC>{HEREDOC_CHARS}*({HEREDOC_NEWLINE}+({LABEL}";"?)?)?("{"{2,}|"$"{2,}) {
2016 0 : yyless(yyleng - 1);
2017 0 : zend_scan_escape_string(zendlval, yytext, yyleng, 0 TSRMLS_CC);
2018 0 : return T_ENCAPSED_AND_WHITESPACE;
2019 : }
2020 :
2021 :
2022 : <ST_DOUBLE_QUOTES>["] {
2023 9286 : BEGIN(ST_IN_SCRIPTING);
2024 9286 : return '"';
2025 : }
2026 :
2027 :
2028 : <ST_BACKQUOTE>[`] {
2029 98 : BEGIN(ST_IN_SCRIPTING);
2030 98 : return '`';
2031 : }
2032 :
2033 :
2034 : <ST_COMMENT,ST_DOC_COMMENT><<EOF>> {
2035 1 : zend_error(E_COMPILE_WARNING,"Unterminated comment starting line %d", CG(comment_start_line));
2036 1 : yyless(yyleng - 1);
2037 1 : BEGIN(ST_IN_SCRIPTING);
2038 1 : return T_COMMENT;
2039 : }
2040 :
2041 :
2042 :
2043 : <ST_IN_SCRIPTING,ST_VAR_OFFSET>{ANY_CHAR} {
2044 0 : zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
2045 : }
|