1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2017 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: Bob Weinand <bwoebi@php.net> |
16 | Dmitry Stogov <dmitry@zend.com> |
17 +----------------------------------------------------------------------+
18 */
19
20 /* $Id$ */
21
22 #include "zend_ast.h"
23 #include "zend_API.h"
24 #include "zend_operators.h"
25 #include "zend_language_parser.h"
26 #include "zend_smart_str.h"
27 #include "zend_exceptions.h"
28
29 ZEND_API zend_ast_process_t zend_ast_process = NULL;
30
zend_ast_alloc(size_t size)31 static inline void *zend_ast_alloc(size_t size) {
32 return zend_arena_alloc(&CG(ast_arena), size);
33 }
34
zend_ast_realloc(void * old,size_t old_size,size_t new_size)35 static inline void *zend_ast_realloc(void *old, size_t old_size, size_t new_size) {
36 void *new = zend_ast_alloc(new_size);
37 memcpy(new, old, old_size);
38 return new;
39 }
40
zend_ast_size(uint32_t children)41 static inline size_t zend_ast_size(uint32_t children) {
42 return sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
43 }
44
zend_ast_list_size(uint32_t children)45 static inline size_t zend_ast_list_size(uint32_t children) {
46 return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
47 }
48
zend_ast_create_znode(znode * node)49 ZEND_API zend_ast *zend_ast_create_znode(znode *node) {
50 zend_ast_znode *ast;
51
52 ast = zend_ast_alloc(sizeof(zend_ast_znode));
53 ast->kind = ZEND_AST_ZNODE;
54 ast->attr = 0;
55 ast->lineno = CG(zend_lineno);
56 ast->node = *node;
57 return (zend_ast *) ast;
58 }
59
zend_ast_create_zval_with_lineno(zval * zv,zend_ast_attr attr,uint32_t lineno)60 ZEND_API zend_ast *zend_ast_create_zval_with_lineno(zval *zv, zend_ast_attr attr, uint32_t lineno) {
61 zend_ast_zval *ast;
62
63 ast = zend_ast_alloc(sizeof(zend_ast_zval));
64 ast->kind = ZEND_AST_ZVAL;
65 ast->attr = attr;
66 ZVAL_COPY_VALUE(&ast->val, zv);
67 ast->val.u2.lineno = lineno;
68 return (zend_ast *) ast;
69 }
70
zend_ast_create_zval_ex(zval * zv,zend_ast_attr attr)71 ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) {
72 return zend_ast_create_zval_with_lineno(zv, attr, CG(zend_lineno));
73 }
74
zend_ast_create_decl(zend_ast_kind kind,uint32_t flags,uint32_t start_lineno,zend_string * doc_comment,zend_string * name,zend_ast * child0,zend_ast * child1,zend_ast * child2,zend_ast * child3)75 ZEND_API zend_ast *zend_ast_create_decl(
76 zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
77 zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3
78 ) {
79 zend_ast_decl *ast;
80
81 ast = zend_ast_alloc(sizeof(zend_ast_decl));
82 ast->kind = kind;
83 ast->attr = 0;
84 ast->start_lineno = start_lineno;
85 ast->end_lineno = CG(zend_lineno);
86 ast->flags = flags;
87 ast->lex_pos = LANG_SCNG(yy_text);
88 ast->doc_comment = doc_comment;
89 ast->name = name;
90 ast->child[0] = child0;
91 ast->child[1] = child1;
92 ast->child[2] = child2;
93 ast->child[3] = child3;
94
95 return (zend_ast *) ast;
96 }
97
zend_ast_create_from_va_list(zend_ast_kind kind,zend_ast_attr attr,va_list va)98 static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) {
99 uint32_t i, children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
100 zend_ast *ast;
101
102 ast = zend_ast_alloc(zend_ast_size(children));
103 ast->kind = kind;
104 ast->attr = attr;
105 ast->lineno = (uint32_t) -1;
106
107 for (i = 0; i < children; ++i) {
108 ast->child[i] = va_arg(va, zend_ast *);
109 if (ast->child[i] != NULL) {
110 uint32_t lineno = zend_ast_get_lineno(ast->child[i]);
111 if (lineno < ast->lineno) {
112 ast->lineno = lineno;
113 }
114 }
115 }
116
117 if (ast->lineno == UINT_MAX) {
118 ast->lineno = CG(zend_lineno);
119 }
120
121 return ast;
122 }
123
zend_ast_create_ex(zend_ast_kind kind,zend_ast_attr attr,...)124 ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...) {
125 va_list va;
126 zend_ast *ast;
127
128 va_start(va, attr);
129 ast = zend_ast_create_from_va_list(kind, attr, va);
130 va_end(va);
131
132 return ast;
133 }
134
zend_ast_create(zend_ast_kind kind,...)135 ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...) {
136 va_list va;
137 zend_ast *ast;
138
139 va_start(va, kind);
140 ast = zend_ast_create_from_va_list(kind, 0, va);
141 va_end(va);
142
143 return ast;
144 }
145
zend_ast_create_list(uint32_t init_children,zend_ast_kind kind,...)146 ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...) {
147 zend_ast *ast;
148 zend_ast_list *list;
149
150 ast = zend_ast_alloc(zend_ast_list_size(4));
151 list = (zend_ast_list *) ast;
152 list->kind = kind;
153 list->attr = 0;
154 list->lineno = CG(zend_lineno);
155 list->children = 0;
156
157 {
158 va_list va;
159 uint32_t i;
160 va_start(va, kind);
161 for (i = 0; i < init_children; ++i) {
162 zend_ast *child = va_arg(va, zend_ast *);
163 ast = zend_ast_list_add(ast, child);
164 if (child != NULL) {
165 uint32_t lineno = zend_ast_get_lineno(child);
166 if (lineno < ast->lineno) {
167 ast->lineno = lineno;
168 }
169 }
170 }
171 va_end(va);
172 }
173
174 return ast;
175 }
176
is_power_of_two(uint32_t n)177 static inline zend_bool is_power_of_two(uint32_t n) {
178 return ((n != 0) && (n == (n & (~n + 1))));
179 }
180
zend_ast_list_add(zend_ast * ast,zend_ast * op)181 ZEND_API zend_ast *zend_ast_list_add(zend_ast *ast, zend_ast *op) {
182 zend_ast_list *list = zend_ast_get_list(ast);
183 if (list->children >= 4 && is_power_of_two(list->children)) {
184 list = zend_ast_realloc(list,
185 zend_ast_list_size(list->children), zend_ast_list_size(list->children * 2));
186 }
187 list->child[list->children++] = op;
188 return (zend_ast *) list;
189 }
190
zend_ast_add_array_element(zval * result,zval * offset,zval * expr)191 static int zend_ast_add_array_element(zval *result, zval *offset, zval *expr)
192 {
193 switch (Z_TYPE_P(offset)) {
194 case IS_UNDEF:
195 if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), expr)) {
196 zend_error(E_WARNING,
197 "Cannot add element to the array as the next element is already occupied");
198 zval_ptr_dtor(expr);
199 }
200 break;
201 case IS_STRING:
202 zend_symtable_update(Z_ARRVAL_P(result), Z_STR_P(offset), expr);
203 zval_dtor(offset);
204 break;
205 case IS_NULL:
206 zend_symtable_update(Z_ARRVAL_P(result), ZSTR_EMPTY_ALLOC(), expr);
207 break;
208 case IS_LONG:
209 zend_hash_index_update(Z_ARRVAL_P(result), Z_LVAL_P(offset), expr);
210 break;
211 case IS_FALSE:
212 zend_hash_index_update(Z_ARRVAL_P(result), 0, expr);
213 break;
214 case IS_TRUE:
215 zend_hash_index_update(Z_ARRVAL_P(result), 1, expr);
216 break;
217 case IS_DOUBLE:
218 zend_hash_index_update(Z_ARRVAL_P(result), zend_dval_to_lval(Z_DVAL_P(offset)), expr);
219 break;
220 case IS_RESOURCE:
221 zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(offset), Z_RES_HANDLE_P(offset));
222 zend_hash_index_update(Z_ARRVAL_P(result), Z_RES_HANDLE_P(offset), expr);
223 break;
224 default:
225 zend_throw_error(NULL, "Illegal offset type");
226 return FAILURE;
227 }
228 return SUCCESS;
229 }
230
zend_ast_evaluate(zval * result,zend_ast * ast,zend_class_entry * scope)231 ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope)
232 {
233 zval op1, op2;
234 int ret = SUCCESS;
235
236 switch (ast->kind) {
237 case ZEND_AST_BINARY_OP:
238 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
239 ret = FAILURE;
240 } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
241 zval_dtor(&op1);
242 ret = FAILURE;
243 } else {
244 binary_op_type op = get_binary_op(ast->attr);
245 ret = op(result, &op1, &op2);
246 zval_dtor(&op1);
247 zval_dtor(&op2);
248 }
249 break;
250 case ZEND_AST_GREATER:
251 case ZEND_AST_GREATER_EQUAL:
252 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
253 ret = FAILURE;
254 } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
255 zval_dtor(&op1);
256 ret = FAILURE;
257 } else {
258 /* op1 > op2 is the same as op2 < op1 */
259 binary_op_type op = ast->kind == ZEND_AST_GREATER
260 ? is_smaller_function : is_smaller_or_equal_function;
261 ret = op(result, &op2, &op1);
262 zval_dtor(&op1);
263 zval_dtor(&op2);
264 }
265 break;
266 case ZEND_AST_UNARY_OP:
267 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
268 ret = FAILURE;
269 } else {
270 unary_op_type op = get_unary_op(ast->attr);
271 ret = op(result, &op1);
272 zval_dtor(&op1);
273 }
274 break;
275 case ZEND_AST_ZVAL:
276 {
277 zval *zv = zend_ast_get_zval(ast);
278 if (scope) {
279 /* class constants may be updated in-place */
280 if (Z_OPT_CONSTANT_P(zv)) {
281 if (UNEXPECTED(zval_update_constant_ex(zv, 1, scope) != SUCCESS)) {
282 ret = FAILURE;
283 break;
284 }
285 }
286 ZVAL_DUP(result, zv);
287 } else {
288 ZVAL_DUP(result, zv);
289 if (Z_OPT_CONSTANT_P(result)) {
290 if (UNEXPECTED(zval_update_constant_ex(result, 1, scope) != SUCCESS)) {
291 ret = FAILURE;
292 break;
293 }
294 }
295 }
296 break;
297 }
298 case ZEND_AST_AND:
299 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
300 ret = FAILURE;
301 break;
302 }
303 if (zend_is_true(&op1)) {
304 if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
305 zval_dtor(&op1);
306 ret = FAILURE;
307 break;
308 }
309 ZVAL_BOOL(result, zend_is_true(&op2));
310 zval_dtor(&op2);
311 } else {
312 ZVAL_FALSE(result);
313 }
314 zval_dtor(&op1);
315 break;
316 case ZEND_AST_OR:
317 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
318 ret = FAILURE;
319 break;
320 }
321 if (zend_is_true(&op1)) {
322 ZVAL_TRUE(result);
323 } else {
324 if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
325 zval_dtor(&op1);
326 ret = FAILURE;
327 break;
328 }
329 ZVAL_BOOL(result, zend_is_true(&op2));
330 zval_dtor(&op2);
331 }
332 zval_dtor(&op1);
333 break;
334 case ZEND_AST_CONDITIONAL:
335 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
336 ret = FAILURE;
337 break;
338 }
339 if (zend_is_true(&op1)) {
340 if (!ast->child[1]) {
341 *result = op1;
342 } else {
343 if (UNEXPECTED(zend_ast_evaluate(result, ast->child[1], scope) != SUCCESS)) {
344 zval_dtor(&op1);
345 ret = FAILURE;
346 break;
347 }
348 zval_dtor(&op1);
349 }
350 } else {
351 if (UNEXPECTED(zend_ast_evaluate(result, ast->child[2], scope) != SUCCESS)) {
352 zval_dtor(&op1);
353 ret = FAILURE;
354 break;
355 }
356 zval_dtor(&op1);
357 }
358 break;
359 case ZEND_AST_COALESCE:
360 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
361 ret = FAILURE;
362 break;
363 }
364 if (Z_TYPE(op1) > IS_NULL) {
365 *result = op1;
366 } else {
367 if (UNEXPECTED(zend_ast_evaluate(result, ast->child[1], scope) != SUCCESS)) {
368 zval_dtor(&op1);
369 ret = FAILURE;
370 break;
371 }
372 zval_dtor(&op1);
373 }
374 break;
375 case ZEND_AST_UNARY_PLUS:
376 if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) {
377 ret = FAILURE;
378 } else {
379 ZVAL_LONG(&op1, 0);
380 ret = add_function(result, &op1, &op2);
381 zval_dtor(&op2);
382 }
383 break;
384 case ZEND_AST_UNARY_MINUS:
385 if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) {
386 ret = FAILURE;
387 } else {
388 ZVAL_LONG(&op1, 0);
389 ret = sub_function(result, &op1, &op2);
390 zval_dtor(&op2);
391 }
392 break;
393 case ZEND_AST_ARRAY:
394 array_init(result);
395 {
396 uint32_t i;
397 zend_ast_list *list = zend_ast_get_list(ast);
398 for (i = 0; i < list->children; i++) {
399 zend_ast *elem = list->child[i];
400 if (elem->child[1]) {
401 if (UNEXPECTED(zend_ast_evaluate(&op1, elem->child[1], scope) != SUCCESS)) {
402 zval_dtor(result);
403 return FAILURE;
404 }
405 } else {
406 ZVAL_UNDEF(&op1);
407 }
408 if (UNEXPECTED(zend_ast_evaluate(&op2, elem->child[0], scope) != SUCCESS)) {
409 zval_dtor(&op1);
410 zval_dtor(result);
411 return FAILURE;
412 }
413 if (UNEXPECTED(zend_ast_add_array_element(result, &op1, &op2) != SUCCESS)) {
414 zval_dtor(&op1);
415 zval_dtor(&op2);
416 zval_dtor(result);
417 return FAILURE;
418 }
419 }
420 }
421 break;
422 case ZEND_AST_DIM:
423 if (ast->child[1] == NULL) {
424 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
425 }
426
427 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
428 ret = FAILURE;
429 } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
430 zval_dtor(&op1);
431 ret = FAILURE;
432 } else {
433 zval tmp;
434
435 if (ast->attr == ZEND_DIM_IS) {
436 zend_fetch_dimension_by_zval_is(&tmp, &op1, &op2, IS_CONST);
437 } else {
438 zend_fetch_dimension_by_zval(&tmp, &op1, &op2);
439 }
440
441 if (UNEXPECTED(Z_ISREF(tmp))) {
442 ZVAL_DUP(result, Z_REFVAL(tmp));
443 } else {
444 ZVAL_DUP(result, &tmp);
445 }
446 zval_ptr_dtor(&tmp);
447 zval_dtor(&op1);
448 zval_dtor(&op2);
449 }
450 break;
451 default:
452 zend_throw_error(NULL, "Unsupported constant expression");
453 ret = FAILURE;
454 }
455 return ret;
456 }
457
zend_ast_copy(zend_ast * ast)458 ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
459 {
460 if (ast == NULL) {
461 return NULL;
462 } else if (ast->kind == ZEND_AST_ZVAL) {
463 zend_ast_zval *new = emalloc(sizeof(zend_ast_zval));
464 new->kind = ZEND_AST_ZVAL;
465 new->attr = ast->attr;
466 ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
467 return (zend_ast *) new;
468 } else if (zend_ast_is_list(ast)) {
469 zend_ast_list *list = zend_ast_get_list(ast);
470 zend_ast_list *new = emalloc(zend_ast_list_size(list->children));
471 uint32_t i;
472 new->kind = list->kind;
473 new->attr = list->attr;
474 new->children = list->children;
475 for (i = 0; i < list->children; i++) {
476 new->child[i] = zend_ast_copy(list->child[i]);
477 }
478 return (zend_ast *) new;
479 } else {
480 uint32_t i, children = zend_ast_get_num_children(ast);
481 zend_ast *new = emalloc(zend_ast_size(children));
482 new->kind = ast->kind;
483 new->attr = ast->attr;
484 for (i = 0; i < children; i++) {
485 new->child[i] = zend_ast_copy(ast->child[i]);
486 }
487 return new;
488 }
489 }
490
zend_ast_destroy_ex(zend_ast * ast,zend_bool free)491 static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
492 if (!ast) {
493 return;
494 }
495
496 switch (ast->kind) {
497 case ZEND_AST_ZVAL:
498 /* Destroy value without using GC: When opcache moves arrays into SHM it will
499 * free the zend_array structure, so references to it from outside the op array
500 * become invalid. GC would cause such a reference in the root buffer. */
501 zval_ptr_dtor_nogc(zend_ast_get_zval(ast));
502 break;
503 case ZEND_AST_FUNC_DECL:
504 case ZEND_AST_CLOSURE:
505 case ZEND_AST_METHOD:
506 case ZEND_AST_CLASS:
507 {
508 zend_ast_decl *decl = (zend_ast_decl *) ast;
509 if (decl->name) {
510 zend_string_release(decl->name);
511 }
512 if (decl->doc_comment) {
513 zend_string_release(decl->doc_comment);
514 }
515 zend_ast_destroy_ex(decl->child[0], free);
516 zend_ast_destroy_ex(decl->child[1], free);
517 zend_ast_destroy_ex(decl->child[2], free);
518 zend_ast_destroy_ex(decl->child[3], free);
519 break;
520 }
521 default:
522 if (zend_ast_is_list(ast)) {
523 zend_ast_list *list = zend_ast_get_list(ast);
524 uint32_t i;
525 for (i = 0; i < list->children; i++) {
526 zend_ast_destroy_ex(list->child[i], free);
527 }
528 } else {
529 uint32_t i, children = zend_ast_get_num_children(ast);
530 for (i = 0; i < children; i++) {
531 zend_ast_destroy_ex(ast->child[i], free);
532 }
533 }
534 }
535
536 if (free) {
537 efree(ast);
538 }
539 }
540
zend_ast_destroy(zend_ast * ast)541 ZEND_API void zend_ast_destroy(zend_ast *ast) {
542 zend_ast_destroy_ex(ast, 0);
543 }
zend_ast_destroy_and_free(zend_ast * ast)544 ZEND_API void zend_ast_destroy_and_free(zend_ast *ast) {
545 zend_ast_destroy_ex(ast, 1);
546 }
547
zend_ast_apply(zend_ast * ast,zend_ast_apply_func fn)548 ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn) {
549 if (zend_ast_is_list(ast)) {
550 zend_ast_list *list = zend_ast_get_list(ast);
551 uint32_t i;
552 for (i = 0; i < list->children; ++i) {
553 fn(&list->child[i]);
554 }
555 } else {
556 uint32_t i, children = zend_ast_get_num_children(ast);
557 for (i = 0; i < children; ++i) {
558 fn(&ast->child[i]);
559 }
560 }
561 }
562
563 /*
564 * Operator Precendence
565 * ====================
566 * priority associativity operators
567 * ----------------------------------
568 * 10 left include, include_once, eval, require, require_once
569 * 20 left ,
570 * 30 left or
571 * 40 left xor
572 * 50 left and
573 * 60 right print
574 * 70 right yield
575 * 80 right =>
576 * 85 right yield from
577 * 90 right = += -= *= /= .= %= &= |= ^= <<= >>= **=
578 * 100 left ? :
579 * 110 right ??
580 * 120 left ||
581 * 130 left &&
582 * 140 left |
583 * 150 left ^
584 * 160 left &
585 * 170 non-associative == != === !==
586 * 180 non-associative < <= > >= <=>
587 * 190 left << >>
588 * 200 left + - .
589 * 210 left * / %
590 * 220 right !
591 * 230 non-associative instanceof
592 * 240 right + - ++ -- ~ (type) @
593 * 250 right **
594 * 260 left [
595 * 270 non-associative clone new
596 */
597
598 static void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent);
599
zend_ast_export_str(smart_str * str,zend_string * s)600 static void zend_ast_export_str(smart_str *str, zend_string *s)
601 {
602 size_t i;
603
604 for (i = 0; i < ZSTR_LEN(s); i++) {
605 unsigned char c = ZSTR_VAL(s)[i];
606 if (c == '\'' || c == '\\') {
607 smart_str_appendc(str, '\\');
608 smart_str_appendc(str, c);
609 } else {
610 smart_str_appendc(str, c);
611 }
612 }
613 }
614
zend_ast_export_qstr(smart_str * str,char quote,zend_string * s)615 static void zend_ast_export_qstr(smart_str *str, char quote, zend_string *s)
616 {
617 size_t i;
618
619 for (i = 0; i < ZSTR_LEN(s); i++) {
620 unsigned char c = ZSTR_VAL(s)[i];
621 if (c < ' ') {
622 switch (c) {
623 case '\n':
624 smart_str_appends(str, "\\n");
625 break;
626 case '\r':
627 smart_str_appends(str, "\\r");
628 break;
629 case '\t':
630 smart_str_appends(str, "\\t");
631 break;
632 case '\f':
633 smart_str_appends(str, "\\f");
634 break;
635 case '\v':
636 smart_str_appends(str, "\\v");
637 break;
638 #ifdef ZEND_WIN32
639 case VK_ESCAPE:
640 #else
641 case '\e':
642 #endif
643 smart_str_appends(str, "\\e");
644 break;
645 default:
646 smart_str_appends(str, "\\0");
647 smart_str_appendc(str, '0' + (c / 8));
648 smart_str_appendc(str, '0' + (c % 8));
649 break;
650 }
651 } else {
652 if (c == quote || c == '$' || c == '\\') {
653 smart_str_appendc(str, '\\');
654 }
655 smart_str_appendc(str, c);
656 }
657 }
658 }
659
zend_ast_export_indent(smart_str * str,int indent)660 static void zend_ast_export_indent(smart_str *str, int indent)
661 {
662 while (indent > 0) {
663 smart_str_appends(str, " ");
664 indent--;
665 }
666 }
667
zend_ast_export_name(smart_str * str,zend_ast * ast,int priority,int indent)668 static void zend_ast_export_name(smart_str *str, zend_ast *ast, int priority, int indent)
669 {
670 if (ast->kind == ZEND_AST_ZVAL) {
671 zval *zv = zend_ast_get_zval(ast);
672
673 if (Z_TYPE_P(zv) == IS_STRING) {
674 smart_str_append(str, Z_STR_P(zv));
675 return;
676 }
677 }
678 zend_ast_export_ex(str, ast, priority, indent);
679 }
680
zend_ast_export_ns_name(smart_str * str,zend_ast * ast,int priority,int indent)681 static void zend_ast_export_ns_name(smart_str *str, zend_ast *ast, int priority, int indent)
682 {
683 if (ast->kind == ZEND_AST_ZVAL) {
684 zval *zv = zend_ast_get_zval(ast);
685
686 if (Z_TYPE_P(zv) == IS_STRING) {
687 if (ast->attr == ZEND_NAME_FQ) {
688 smart_str_appendc(str, '\\');
689 } else if (ast->attr == ZEND_NAME_RELATIVE) {
690 smart_str_appends(str, "namespace\\");
691 }
692 smart_str_append(str, Z_STR_P(zv));
693 return;
694 }
695 }
696 zend_ast_export_ex(str, ast, priority, indent);
697 }
698
zend_ast_valid_var_char(char ch)699 static int zend_ast_valid_var_char(char ch)
700 {
701 unsigned char c = (unsigned char)ch;
702
703 if (c != '_' && c < 127 &&
704 (c < '0' || c > '9') &&
705 (c < 'A' || c > 'Z') &&
706 (c < 'a' || c > 'z')) {
707 return 0;
708 }
709 return 1;
710 }
711
zend_ast_valid_var_name(const char * s,size_t len)712 static int zend_ast_valid_var_name(const char *s, size_t len)
713 {
714 unsigned char c;
715 size_t i;
716
717 if (len == 0) {
718 return 0;
719 }
720 c = (unsigned char)s[0];
721 if (c != '_' && c < 127 &&
722 (c < 'A' || c > 'Z') &&
723 (c < 'a' || c > 'z')) {
724 return 0;
725 }
726 for (i = 1; i < len; i++) {
727 c = (unsigned char)s[i];
728 if (c != '_' && c < 127 &&
729 (c < '0' || c > '9') &&
730 (c < 'A' || c > 'Z') &&
731 (c < 'a' || c > 'z')) {
732 return 0;
733 }
734 }
735 return 1;
736 }
737
zend_ast_export_var(smart_str * str,zend_ast * ast,int priority,int indent)738 static void zend_ast_export_var(smart_str *str, zend_ast *ast, int priority, int indent)
739 {
740 if (ast->kind == ZEND_AST_ZVAL) {
741 zval *zv = zend_ast_get_zval(ast);
742 if (Z_TYPE_P(zv) == IS_STRING &&
743 zend_ast_valid_var_name(Z_STRVAL_P(zv), Z_STRLEN_P(zv))) {
744 smart_str_append(str, Z_STR_P(zv));
745 return;
746 }
747 } else if (ast->kind == ZEND_AST_VAR) {
748 zend_ast_export_ex(str, ast, 0, indent);
749 return;
750 }
751 smart_str_appendc(str, '{');
752 zend_ast_export_name(str, ast, 0, indent);
753 smart_str_appendc(str, '}');
754 }
755
zend_ast_export_list(smart_str * str,zend_ast_list * list,int separator,int priority,int indent)756 static void zend_ast_export_list(smart_str *str, zend_ast_list *list, int separator, int priority, int indent)
757 {
758 uint32_t i = 0;
759
760 while (i < list->children) {
761 if (i != 0 && separator) {
762 smart_str_appends(str, ", ");
763 }
764 zend_ast_export_ex(str, list->child[i], priority, indent);
765 i++;
766 }
767 }
768
zend_ast_export_encaps_list(smart_str * str,char quote,zend_ast_list * list,int indent)769 static void zend_ast_export_encaps_list(smart_str *str, char quote, zend_ast_list *list, int indent)
770 {
771 uint32_t i = 0;
772 zend_ast *ast;
773
774 while (i < list->children) {
775 ast = list->child[i];
776 if (ast->kind == ZEND_AST_ZVAL) {
777 zval *zv = zend_ast_get_zval(ast);
778
779 ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
780 zend_ast_export_qstr(str, quote, Z_STR_P(zv));
781 } else if (ast->kind == ZEND_AST_VAR &&
782 ast->child[0]->kind == ZEND_AST_ZVAL &&
783 (i + 1 == list->children ||
784 list->child[i + 1]->kind != ZEND_AST_ZVAL ||
785 !zend_ast_valid_var_char(
786 *Z_STRVAL_P(
787 zend_ast_get_zval(list->child[i + 1]))))) {
788 zend_ast_export_ex(str, ast, 0, indent);
789 } else {
790 smart_str_appendc(str, '{');
791 zend_ast_export_ex(str, ast, 0, indent);
792 smart_str_appendc(str, '}');
793 }
794 i++;
795 }
796 }
797
zend_ast_export_name_list(smart_str * str,zend_ast_list * list,int indent)798 static void zend_ast_export_name_list(smart_str *str, zend_ast_list *list, int indent)
799 {
800 uint32_t i = 0;
801
802 while (i < list->children) {
803 if (i != 0) {
804 smart_str_appends(str, ", ");
805 }
806 zend_ast_export_name(str, list->child[i], 0, indent);
807 i++;
808 }
809 }
810
zend_ast_export_var_list(smart_str * str,zend_ast_list * list,int indent)811 static void zend_ast_export_var_list(smart_str *str, zend_ast_list *list, int indent)
812 {
813 uint32_t i = 0;
814
815 while (i < list->children) {
816 if (i != 0) {
817 smart_str_appends(str, ", ");
818 }
819 if (list->child[i]->attr) {
820 smart_str_appendc(str, '&');
821 }
822 smart_str_appendc(str, '$');
823 zend_ast_export_name(str, list->child[i], 20, indent);
824 i++;
825 }
826 }
827
zend_ast_export_stmt(smart_str * str,zend_ast * ast,int indent)828 static void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int indent)
829 {
830 if (!ast) {
831 return;
832 }
833
834 if (ast->kind == ZEND_AST_STMT_LIST ||
835 ast->kind == ZEND_AST_TRAIT_ADAPTATIONS) {
836 zend_ast_list *list = (zend_ast_list*)ast;
837 uint32_t i = 0;
838
839 while (i < list->children) {
840 ast = list->child[i];
841 zend_ast_export_stmt(str, ast, indent);
842 i++;
843 }
844 } else {
845 zend_ast_export_indent(str, indent);
846 zend_ast_export_ex(str, ast, 0, indent);
847 switch (ast->kind) {
848 case ZEND_AST_LABEL:
849 case ZEND_AST_IF:
850 case ZEND_AST_SWITCH:
851 case ZEND_AST_WHILE:
852 case ZEND_AST_TRY:
853 case ZEND_AST_FOR:
854 case ZEND_AST_FOREACH:
855 case ZEND_AST_FUNC_DECL:
856 case ZEND_AST_METHOD:
857 case ZEND_AST_CLASS:
858 case ZEND_AST_USE_TRAIT:
859 case ZEND_AST_NAMESPACE:
860 case ZEND_AST_DECLARE:
861 break;
862 default:
863 smart_str_appendc(str, ';');
864 break;
865 }
866 smart_str_appendc(str, '\n');
867 }
868 }
869
zend_ast_export_if_stmt(smart_str * str,zend_ast_list * list,int indent)870 static void zend_ast_export_if_stmt(smart_str *str, zend_ast_list *list, int indent)
871 {
872 uint32_t i;
873 zend_ast *ast;
874
875 tail_call:
876 i = 0;
877 while (i < list->children) {
878 ast = list->child[i];
879 ZEND_ASSERT(ast->kind == ZEND_AST_IF_ELEM);
880 if (ast->child[0]) {
881 if (i == 0) {
882 smart_str_appends(str, "if (");
883 } else {
884 zend_ast_export_indent(str, indent);
885 smart_str_appends(str, "} elseif (");
886 }
887 zend_ast_export_ex(str, ast->child[0], 0, indent);
888 smart_str_appends(str, ") {\n");
889 zend_ast_export_stmt(str, ast->child[1], indent + 1);
890 } else {
891 zend_ast_export_indent(str, indent);
892 smart_str_appends(str, "} else ");
893 if (ast->child[1]->kind == ZEND_AST_IF) {
894 list = (zend_ast_list*)ast->child[1];
895 goto tail_call;
896 } else {
897 smart_str_appends(str, "{\n");
898 zend_ast_export_stmt(str, ast->child[1], indent + 1);
899 }
900 }
901 i++;
902 }
903 zend_ast_export_indent(str, indent);
904 smart_str_appendc(str, '}');
905 }
906
zend_ast_export_zval(smart_str * str,zval * zv,int priority,int indent)907 static void zend_ast_export_zval(smart_str *str, zval *zv, int priority, int indent)
908 {
909 zend_long idx;
910 zend_string *key;
911 zval *val;
912 int first;
913
914 ZVAL_DEREF(zv);
915 switch (Z_TYPE_P(zv)) {
916 case IS_NULL:
917 smart_str_appends(str, "null");
918 break;
919 case IS_FALSE:
920 smart_str_appends(str, "false");
921 break;
922 case IS_TRUE:
923 smart_str_appends(str, "true");
924 break;
925 case IS_LONG:
926 smart_str_append_long(str, Z_LVAL_P(zv));
927 break;
928 case IS_DOUBLE:
929 key = zend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(zv));
930 smart_str_appendl(str, ZSTR_VAL(key), ZSTR_LEN(key));
931 zend_string_release(key);
932 break;
933 case IS_STRING:
934 smart_str_appendc(str, '\'');
935 zend_ast_export_str(str, Z_STR_P(zv));
936 smart_str_appendc(str, '\'');
937 break;
938 case IS_ARRAY:
939 smart_str_appendc(str, '[');
940 first = 1;
941 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(zv), idx, key, val) {
942 if (first) {
943 first = 0;
944 } else {
945 smart_str_appends(str, ", ");
946 }
947 if (key) {
948 smart_str_appendc(str, '\'');
949 zend_ast_export_str(str, key);
950 smart_str_appends(str, "' => ");
951 } else {
952 smart_str_append_long(str, idx);
953 smart_str_appends(str, " => ");
954 }
955 zend_ast_export_zval(str, val, 0, indent);
956 } ZEND_HASH_FOREACH_END();
957 smart_str_appendc(str, ']');
958 break;
959 case IS_CONSTANT:
960 smart_str_appendl(str, Z_STRVAL_P(zv), Z_STRLEN_P(zv));
961 break;
962 case IS_CONSTANT_AST:
963 zend_ast_export_ex(str, Z_ASTVAL_P(zv), priority, indent);
964 break;
965 EMPTY_SWITCH_DEFAULT_CASE();
966 }
967 }
968
zend_ast_export_class_no_header(smart_str * str,zend_ast_decl * decl,int indent)969 static void zend_ast_export_class_no_header(smart_str *str, zend_ast_decl *decl, int indent) {
970 if (decl->child[0]) {
971 smart_str_appends(str, " extends ");
972 zend_ast_export_ns_name(str, decl->child[0], 0, indent);
973 }
974 if (decl->child[1]) {
975 smart_str_appends(str, " implements ");
976 zend_ast_export_ex(str, decl->child[1], 0, indent);
977 }
978 smart_str_appends(str, " {\n");
979 zend_ast_export_stmt(str, decl->child[2], indent + 1);
980 zend_ast_export_indent(str, indent);
981 smart_str_appends(str, "}");
982 }
983
984 #define BINARY_OP(_op, _p, _pl, _pr) do { \
985 op = _op; \
986 p = _p; \
987 pl = _pl; \
988 pr = _pr; \
989 goto binary_op; \
990 } while (0)
991
992 #define PREFIX_OP(_op, _p, _pl) do { \
993 op = _op; \
994 p = _p; \
995 pl = _pl; \
996 goto prefix_op; \
997 } while (0)
998
999 #define FUNC_OP(_op) do { \
1000 op = _op; \
1001 goto func_op; \
1002 } while (0)
1003
1004 #define POSTFIX_OP(_op, _p, _pl) do { \
1005 op = _op; \
1006 p = _p; \
1007 pl = _pl; \
1008 goto postfix_op; \
1009 } while (0)
1010
1011 #define APPEND_NODE_1(_op) do { \
1012 op = _op; \
1013 goto append_node_1; \
1014 } while (0)
1015
1016 #define APPEND_STR(_op) do { \
1017 op = _op; \
1018 goto append_str; \
1019 } while (0)
1020
1021 #define APPEND_DEFAULT_VALUE(n) do { \
1022 p = n; \
1023 goto append_default_value; \
1024 } while (0)
1025
zend_ast_export_ex(smart_str * str,zend_ast * ast,int priority,int indent)1026 static void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent)
1027 {
1028 zend_ast_decl *decl;
1029 int p, pl, pr;
1030 const char *op;
1031
1032 tail_call:
1033 if (!ast) {
1034 return;
1035 }
1036 switch (ast->kind) {
1037 /* special nodes */
1038 case ZEND_AST_ZVAL:
1039 zend_ast_export_zval(str, zend_ast_get_zval(ast), priority, indent);
1040 break;
1041 case ZEND_AST_ZNODE:
1042 /* This AST kind is only used for temporary nodes during compilation */
1043 ZEND_ASSERT(0);
1044 break;
1045
1046 /* declaration nodes */
1047 case ZEND_AST_FUNC_DECL:
1048 case ZEND_AST_CLOSURE:
1049 case ZEND_AST_METHOD:
1050 decl = (zend_ast_decl *) ast;
1051 if (decl->flags & ZEND_ACC_PUBLIC) {
1052 smart_str_appends(str, "public ");
1053 } else if (decl->flags & ZEND_ACC_PROTECTED) {
1054 smart_str_appends(str, "protected ");
1055 } else if (decl->flags & ZEND_ACC_PRIVATE) {
1056 smart_str_appends(str, "private ");
1057 }
1058 if (decl->flags & ZEND_ACC_STATIC) {
1059 smart_str_appends(str, "static ");
1060 }
1061 if (decl->flags & ZEND_ACC_ABSTRACT) {
1062 smart_str_appends(str, "abstract ");
1063 }
1064 if (decl->flags & ZEND_ACC_FINAL) {
1065 smart_str_appends(str, "final ");
1066 }
1067 smart_str_appends(str, "function ");
1068 if (decl->flags & ZEND_ACC_RETURN_REFERENCE) {
1069 smart_str_appendc(str, '&');
1070 }
1071 if (ast->kind != ZEND_AST_CLOSURE) {
1072 smart_str_appendl(str, ZSTR_VAL(decl->name), ZSTR_LEN(decl->name));
1073 }
1074 smart_str_appendc(str, '(');
1075 zend_ast_export_ex(str, decl->child[0], 0, indent);
1076 smart_str_appendc(str, ')');
1077 zend_ast_export_ex(str, decl->child[1], 0, indent);
1078 if (decl->child[3]) {
1079 smart_str_appends(str, ": ");
1080 zend_ast_export_ns_name(str, decl->child[3], 0, indent);
1081 }
1082 if (decl->child[2]) {
1083 smart_str_appends(str, " {\n");
1084 zend_ast_export_stmt(str, decl->child[2], indent + 1);
1085 zend_ast_export_indent(str, indent);
1086 smart_str_appendc(str, '}');
1087 if (ast->kind != ZEND_AST_CLOSURE) {
1088 smart_str_appendc(str, '\n');
1089 }
1090 } else {
1091 smart_str_appends(str, ";\n");
1092 }
1093 break;
1094 case ZEND_AST_CLASS:
1095 decl = (zend_ast_decl *) ast;
1096 if (decl->flags & ZEND_ACC_INTERFACE) {
1097 smart_str_appends(str, "interface ");
1098 } else if (decl->flags & ZEND_ACC_TRAIT) {
1099 smart_str_appends(str, "trait ");
1100 } else {
1101 if (decl->flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
1102 smart_str_appends(str, "abstract ");
1103 }
1104 if (decl->flags & ZEND_ACC_FINAL) {
1105 smart_str_appends(str, "final ");
1106 }
1107 smart_str_appends(str, "class ");
1108 }
1109 smart_str_appendl(str, ZSTR_VAL(decl->name), ZSTR_LEN(decl->name));
1110 zend_ast_export_class_no_header(str, decl, indent);
1111 smart_str_appendc(str, '\n');
1112 break;
1113
1114 /* list nodes */
1115 case ZEND_AST_ARG_LIST:
1116 case ZEND_AST_EXPR_LIST:
1117 case ZEND_AST_PARAM_LIST:
1118 simple_list:
1119 zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
1120 break;
1121 case ZEND_AST_LIST:
1122 smart_str_appends(str, "list(");
1123 zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
1124 smart_str_appendc(str, ')');
1125 break;
1126 case ZEND_AST_ARRAY:
1127 smart_str_appendc(str, '[');
1128 zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
1129 smart_str_appendc(str, ']');
1130 break;
1131 case ZEND_AST_ENCAPS_LIST:
1132 smart_str_appendc(str, '"');
1133 zend_ast_export_encaps_list(str, '"', (zend_ast_list*)ast, indent);
1134 smart_str_appendc(str, '"');
1135 break;
1136 case ZEND_AST_STMT_LIST:
1137 case ZEND_AST_TRAIT_ADAPTATIONS:
1138 zend_ast_export_stmt(str, ast, indent);
1139 break;
1140 case ZEND_AST_IF:
1141 zend_ast_export_if_stmt(str, (zend_ast_list*)ast, indent);
1142 break;
1143 case ZEND_AST_SWITCH_LIST:
1144 case ZEND_AST_CATCH_LIST:
1145 zend_ast_export_list(str, (zend_ast_list*)ast, 0, 0, indent);
1146 break;
1147 case ZEND_AST_CLOSURE_USES:
1148 smart_str_appends(str, " use(");
1149 zend_ast_export_var_list(str, (zend_ast_list*)ast, indent);
1150 smart_str_appendc(str, ')');
1151 break;
1152 case ZEND_AST_PROP_DECL:
1153 if (ast->attr & ZEND_ACC_PUBLIC) {
1154 smart_str_appends(str, "public ");
1155 } else if (ast->attr & ZEND_ACC_PROTECTED) {
1156 smart_str_appends(str, "protected ");
1157 } else if (ast->attr & ZEND_ACC_PRIVATE) {
1158 smart_str_appends(str, "private ");
1159 }
1160 if (ast->attr & ZEND_ACC_STATIC) {
1161 smart_str_appends(str, "static ");
1162 }
1163 goto simple_list;
1164 case ZEND_AST_CONST_DECL:
1165 case ZEND_AST_CLASS_CONST_DECL:
1166 smart_str_appends(str, "const ");
1167 goto simple_list;
1168 case ZEND_AST_NAME_LIST:
1169 zend_ast_export_name_list(str, (zend_ast_list*)ast, indent);
1170 break;
1171 case ZEND_AST_USE:
1172 smart_str_appends(str, "use ");
1173 if (ast->attr == T_FUNCTION) {
1174 smart_str_appends(str, "function ");
1175 } else if (ast->attr == T_CONST) {
1176 smart_str_appends(str, "const ");
1177 }
1178 goto simple_list;
1179
1180 /* 0 child nodes */
1181 case ZEND_AST_MAGIC_CONST:
1182 switch (ast->attr) {
1183 case T_LINE: APPEND_STR("__LINE__");
1184 case T_FILE: APPEND_STR("__FILE__");
1185 case T_DIR: APPEND_STR("__DIR__");
1186 case T_TRAIT_C: APPEND_STR("__TRAIT__");
1187 case T_METHOD_C: APPEND_STR("__METHOD__");
1188 case T_FUNC_C: APPEND_STR("__FUNCTION__");
1189 case T_NS_C: APPEND_STR("__NAMESPACE__");
1190 case T_CLASS_C: APPEND_STR("__CLASS__");
1191 EMPTY_SWITCH_DEFAULT_CASE();
1192 }
1193 break;
1194 case ZEND_AST_TYPE:
1195 switch (ast->attr) {
1196 case IS_ARRAY: APPEND_STR("array");
1197 case IS_CALLABLE: APPEND_STR("callable");
1198 EMPTY_SWITCH_DEFAULT_CASE();
1199 }
1200 break;
1201
1202 /* 1 child node */
1203 case ZEND_AST_VAR:
1204 smart_str_appendc(str, '$');
1205 zend_ast_export_var(str, ast->child[0], 0, indent);
1206 break;
1207 case ZEND_AST_CONST:
1208 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1209 break;
1210 case ZEND_AST_UNPACK:
1211 smart_str_appends(str, "...");
1212 ast = ast->child[0];
1213 goto tail_call;
1214 case ZEND_AST_UNARY_PLUS: PREFIX_OP("+", 240, 241);
1215 case ZEND_AST_UNARY_MINUS: PREFIX_OP("-", 240, 241);
1216 case ZEND_AST_CAST:
1217 switch (ast->attr) {
1218 case IS_NULL: PREFIX_OP("(unset)", 240, 241);
1219 case _IS_BOOL: PREFIX_OP("(bool)", 240, 241);
1220 case IS_LONG: PREFIX_OP("(int)", 240, 241);
1221 case IS_DOUBLE: PREFIX_OP("(double)", 240, 241);
1222 case IS_STRING: PREFIX_OP("(string)", 240, 241);
1223 case IS_ARRAY: PREFIX_OP("(array)", 240, 241);
1224 case IS_OBJECT: PREFIX_OP("(object)", 240, 241);
1225 EMPTY_SWITCH_DEFAULT_CASE();
1226 }
1227 break;
1228 case ZEND_AST_EMPTY:
1229 FUNC_OP("empty");
1230 case ZEND_AST_ISSET:
1231 FUNC_OP("isset");
1232 case ZEND_AST_SILENCE:
1233 PREFIX_OP("@", 240, 241);
1234 case ZEND_AST_SHELL_EXEC:
1235 smart_str_appendc(str, '`');
1236 if (ast->child[0]->kind == ZEND_AST_ENCAPS_LIST) {
1237 zend_ast_export_encaps_list(str, '`', (zend_ast_list*)ast->child[0], indent);
1238 } else {
1239 zval *zv;
1240 ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_ZVAL);
1241 zv = zend_ast_get_zval(ast->child[0]);
1242 ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
1243 zend_ast_export_qstr(str, '`', Z_STR_P(zv));
1244 }
1245 smart_str_appendc(str, '`');
1246 break;
1247 case ZEND_AST_CLONE:
1248 PREFIX_OP("clone ", 270, 271);
1249 case ZEND_AST_EXIT:
1250 if (ast->child[0]) {
1251 FUNC_OP("exit");
1252 } else {
1253 APPEND_STR("exit");
1254 }
1255 break;
1256 case ZEND_AST_PRINT:
1257 PREFIX_OP("print ", 60, 61);
1258 case ZEND_AST_INCLUDE_OR_EVAL:
1259 switch (ast->attr) {
1260 case ZEND_INCLUDE_ONCE: FUNC_OP("include_once");
1261 case ZEND_INCLUDE: FUNC_OP("include");
1262 case ZEND_REQUIRE_ONCE: FUNC_OP("require_once");
1263 case ZEND_REQUIRE: FUNC_OP("require");
1264 case ZEND_EVAL: FUNC_OP("eval");
1265 EMPTY_SWITCH_DEFAULT_CASE();
1266 }
1267 break;
1268 case ZEND_AST_UNARY_OP:
1269 switch (ast->attr) {
1270 case ZEND_BW_NOT: PREFIX_OP("~", 240, 241);
1271 case ZEND_BOOL_NOT: PREFIX_OP("!", 240, 241);
1272 EMPTY_SWITCH_DEFAULT_CASE();
1273 }
1274 break;
1275 case ZEND_AST_PRE_INC:
1276 PREFIX_OP("++", 240, 241);
1277 case ZEND_AST_PRE_DEC:
1278 PREFIX_OP("--", 240, 241);
1279 case ZEND_AST_POST_INC:
1280 POSTFIX_OP("++", 240, 241);
1281 case ZEND_AST_POST_DEC:
1282 POSTFIX_OP("--", 240, 241);
1283
1284 case ZEND_AST_GLOBAL:
1285 APPEND_NODE_1("global");
1286 case ZEND_AST_UNSET:
1287 FUNC_OP("unset");
1288 case ZEND_AST_RETURN:
1289 APPEND_NODE_1("return");
1290 case ZEND_AST_LABEL:
1291 zend_ast_export_name(str, ast->child[0], 0, indent);
1292 smart_str_appendc(str, ':');
1293 break;
1294 case ZEND_AST_REF:
1295 smart_str_appendc(str, '&');
1296 ast = ast->child[0];
1297 goto tail_call;
1298 case ZEND_AST_HALT_COMPILER:
1299 APPEND_STR("__HALT_COMPILER()");
1300 case ZEND_AST_ECHO:
1301 APPEND_NODE_1("echo");
1302 case ZEND_AST_THROW:
1303 APPEND_NODE_1("throw");
1304 case ZEND_AST_GOTO:
1305 smart_str_appends(str, "goto ");
1306 zend_ast_export_name(str, ast->child[0], 0, indent);
1307 break;
1308 case ZEND_AST_BREAK:
1309 APPEND_NODE_1("break");
1310 case ZEND_AST_CONTINUE:
1311 APPEND_NODE_1("continue");
1312
1313 /* 2 child nodes */
1314 case ZEND_AST_DIM:
1315 zend_ast_export_ex(str, ast->child[0], 260, indent);
1316 smart_str_appendc(str, '[');
1317 if (ast->child[1]) {
1318 zend_ast_export_ex(str, ast->child[1], 0, indent);
1319 }
1320 smart_str_appendc(str, ']');
1321 break;
1322 case ZEND_AST_PROP:
1323 zend_ast_export_ex(str, ast->child[0], 0, indent);
1324 smart_str_appends(str, "->");
1325 zend_ast_export_var(str, ast->child[1], 0, indent);
1326 break;
1327 case ZEND_AST_STATIC_PROP:
1328 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1329 smart_str_appends(str, "::$");
1330 zend_ast_export_var(str, ast->child[1], 0, indent);
1331 break;
1332 case ZEND_AST_CALL:
1333 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1334 smart_str_appendc(str, '(');
1335 zend_ast_export_ex(str, ast->child[1], 0, indent);
1336 smart_str_appendc(str, ')');
1337 break;
1338 case ZEND_AST_CLASS_CONST:
1339 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1340 smart_str_appends(str, "::");
1341 zend_ast_export_name(str, ast->child[1], 0, indent);
1342 break;
1343 case ZEND_AST_ASSIGN: BINARY_OP(" = ", 90, 91, 90);
1344 case ZEND_AST_ASSIGN_REF: BINARY_OP(" =& ", 90, 91, 90);
1345 case ZEND_AST_ASSIGN_OP:
1346 switch (ast->attr) {
1347 case ZEND_ASSIGN_ADD: BINARY_OP(" += ", 90, 91, 90);
1348 case ZEND_ASSIGN_SUB: BINARY_OP(" -= ", 90, 91, 90);
1349 case ZEND_ASSIGN_MUL: BINARY_OP(" *= ", 90, 91, 90);
1350 case ZEND_ASSIGN_DIV: BINARY_OP(" /= ", 90, 91, 90);
1351 case ZEND_ASSIGN_MOD: BINARY_OP(" %= ", 90, 91, 90);
1352 case ZEND_ASSIGN_SL: BINARY_OP(" <<= ", 90, 91, 90);
1353 case ZEND_ASSIGN_SR: BINARY_OP(" >>= ", 90, 91, 90);
1354 case ZEND_ASSIGN_CONCAT: BINARY_OP(" .= ", 90, 91, 90);
1355 case ZEND_ASSIGN_BW_OR: BINARY_OP(" |= ", 90, 91, 90);
1356 case ZEND_ASSIGN_BW_AND: BINARY_OP(" &= ", 90, 91, 90);
1357 case ZEND_ASSIGN_BW_XOR: BINARY_OP(" ^= ", 90, 91, 90);
1358 case ZEND_ASSIGN_POW: BINARY_OP(" **= ", 90, 91, 90);
1359 EMPTY_SWITCH_DEFAULT_CASE();
1360 }
1361 break;
1362 case ZEND_AST_BINARY_OP:
1363 switch (ast->attr) {
1364 case ZEND_ADD: BINARY_OP(" + ", 200, 200, 201);
1365 case ZEND_SUB: BINARY_OP(" - ", 200, 200, 201);
1366 case ZEND_MUL: BINARY_OP(" * ", 210, 210, 211);
1367 case ZEND_DIV: BINARY_OP(" / ", 210, 210, 211);
1368 case ZEND_MOD: BINARY_OP(" % ", 210, 210, 211);
1369 case ZEND_SL: BINARY_OP(" << ", 190, 190, 191);
1370 case ZEND_SR: BINARY_OP(" >> ", 190, 190, 191);
1371 case ZEND_CONCAT: BINARY_OP(" . ", 200, 200, 201);
1372 case ZEND_BW_OR: BINARY_OP(" | ", 140, 140, 141);
1373 case ZEND_BW_AND: BINARY_OP(" & ", 160, 160, 161);
1374 case ZEND_BW_XOR: BINARY_OP(" ^ ", 150, 150, 151);
1375 case ZEND_IS_IDENTICAL: BINARY_OP(" === ", 170, 171, 171);
1376 case ZEND_IS_NOT_IDENTICAL: BINARY_OP(" !== ", 170, 171, 171);
1377 case ZEND_IS_EQUAL: BINARY_OP(" == ", 170, 171, 171);
1378 case ZEND_IS_NOT_EQUAL: BINARY_OP(" != ", 170, 171, 171);
1379 case ZEND_IS_SMALLER: BINARY_OP(" < ", 180, 181, 181);
1380 case ZEND_IS_SMALLER_OR_EQUAL: BINARY_OP(" <= ", 180, 181, 181);
1381 case ZEND_POW: BINARY_OP(" ** ", 250, 251, 250);
1382 case ZEND_BOOL_XOR: BINARY_OP(" xor ", 40, 40, 41);
1383 case ZEND_SPACESHIP: BINARY_OP(" <=> ", 180, 181, 181);
1384 EMPTY_SWITCH_DEFAULT_CASE();
1385 }
1386 break;
1387 case ZEND_AST_GREATER: BINARY_OP(" > ", 180, 181, 181);
1388 case ZEND_AST_GREATER_EQUAL: BINARY_OP(" >= ", 180, 181, 181);
1389 case ZEND_AST_AND: BINARY_OP(" && ", 130, 130, 131);
1390 case ZEND_AST_OR: BINARY_OP(" || ", 120, 120, 121);
1391 case ZEND_AST_ARRAY_ELEM:
1392 if (ast->child[1]) {
1393 zend_ast_export_ex(str, ast->child[1], 80, indent);
1394 smart_str_appends(str, " => ");
1395 }
1396 zend_ast_export_ex(str, ast->child[0], 80, indent);
1397 break;
1398 case ZEND_AST_NEW:
1399 smart_str_appends(str, "new ");
1400 if (ast->child[0]->kind == ZEND_AST_CLASS) {
1401 smart_str_appends(str, "class");
1402 if (zend_ast_get_list(ast->child[1])->children) {
1403 smart_str_appendc(str, '(');
1404 zend_ast_export_ex(str, ast->child[1], 0, indent);
1405 smart_str_appendc(str, ')');
1406 }
1407 zend_ast_export_class_no_header(str, (zend_ast_decl *) ast->child[0], indent);
1408 } else {
1409 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1410 smart_str_appendc(str, '(');
1411 zend_ast_export_ex(str, ast->child[1], 0, indent);
1412 smart_str_appendc(str, ')');
1413 }
1414 break;
1415 case ZEND_AST_INSTANCEOF:
1416 zend_ast_export_ex(str, ast->child[0], 0, indent);
1417 smart_str_appends(str, " instanceof ");
1418 zend_ast_export_ns_name(str, ast->child[1], 0, indent);
1419 break;
1420 case ZEND_AST_YIELD:
1421 if (priority > 70) smart_str_appendc(str, '(');
1422 smart_str_appends(str, "yield ");
1423 if (ast->child[0]) {
1424 if (ast->child[1]) {
1425 zend_ast_export_ex(str, ast->child[1], 70, indent);
1426 smart_str_appends(str, " => ");
1427 }
1428 zend_ast_export_ex(str, ast->child[0], 70, indent);
1429 }
1430 if (priority > 70) smart_str_appendc(str, ')');
1431 break;
1432 case ZEND_AST_YIELD_FROM:
1433 PREFIX_OP("yield from ", 85, 86);
1434 case ZEND_AST_COALESCE: BINARY_OP(" ?? ", 110, 111, 110);
1435 case ZEND_AST_STATIC:
1436 smart_str_appends(str, "static $");
1437 zend_ast_export_name(str, ast->child[0], 0, indent);
1438 APPEND_DEFAULT_VALUE(1);
1439 case ZEND_AST_WHILE:
1440 smart_str_appends(str, "while (");
1441 zend_ast_export_ex(str, ast->child[0], 0, indent);
1442 smart_str_appends(str, ") {\n");
1443 zend_ast_export_stmt(str, ast->child[1], indent + 1);
1444 zend_ast_export_indent(str, indent);
1445 smart_str_appendc(str, '}');
1446 break;
1447 case ZEND_AST_DO_WHILE:
1448 smart_str_appends(str, "do {\n");
1449 zend_ast_export_stmt(str, ast->child[0], indent + 1);
1450 zend_ast_export_indent(str, indent);
1451 smart_str_appends(str, "} while (");
1452 zend_ast_export_ex(str, ast->child[1], 0, indent);
1453 smart_str_appendc(str, ')');
1454 break;
1455
1456 case ZEND_AST_IF_ELEM:
1457 if (ast->child[0]) {
1458 smart_str_appends(str, "if (");
1459 zend_ast_export_ex(str, ast->child[0], 0, indent);
1460 smart_str_appends(str, ") {\n");
1461 zend_ast_export_stmt(str, ast->child[1], indent + 1);
1462 } else {
1463 smart_str_appends(str, "else {\n");
1464 zend_ast_export_stmt(str, ast->child[1], indent + 1);
1465 }
1466 zend_ast_export_indent(str, indent);
1467 smart_str_appendc(str, '}');
1468 break;
1469 case ZEND_AST_SWITCH:
1470 smart_str_appends(str, "switch (");
1471 zend_ast_export_ex(str, ast->child[0], 0, indent);
1472 smart_str_appends(str, ") {\n");
1473 zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
1474 zend_ast_export_indent(str, indent);
1475 smart_str_appendc(str, '}');
1476 break;
1477 case ZEND_AST_SWITCH_CASE:
1478 zend_ast_export_indent(str, indent);
1479 if (ast->child[0]) {
1480 smart_str_appends(str, "case ");
1481 zend_ast_export_ex(str, ast->child[0], 0, indent);
1482 smart_str_appends(str, ":\n");
1483 } else {
1484 smart_str_appends(str, "default:\n");
1485 }
1486 zend_ast_export_stmt(str, ast->child[1], indent + 1);
1487 break;
1488 case ZEND_AST_DECLARE:
1489 smart_str_appends(str, "declare(");
1490 ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_CONST_DECL);
1491 zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent);
1492 smart_str_appendc(str, ')');
1493 if (ast->child[1]) {
1494 smart_str_appends(str, " {\n");
1495 zend_ast_export_stmt(str, ast->child[1], indent + 1);
1496 zend_ast_export_indent(str, indent);
1497 smart_str_appendc(str, '}');
1498 } else {
1499 smart_str_appendc(str, ';');
1500 }
1501 break;
1502 case ZEND_AST_PROP_ELEM:
1503 smart_str_appendc(str, '$');
1504 /* break missing intentionally */
1505 case ZEND_AST_CONST_ELEM:
1506 zend_ast_export_name(str, ast->child[0], 0, indent);
1507 APPEND_DEFAULT_VALUE(1);
1508 case ZEND_AST_USE_TRAIT:
1509 smart_str_appends(str, "use ");
1510 zend_ast_export_ex(str, ast->child[0], 0, indent);
1511 if (ast->child[1]) {
1512 smart_str_appends(str, " {\n");
1513 zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
1514 zend_ast_export_indent(str, indent);
1515 smart_str_appends(str, "}");
1516 } else {
1517 smart_str_appends(str, ";");
1518 }
1519 break;
1520 case ZEND_AST_TRAIT_PRECEDENCE:
1521 zend_ast_export_ex(str, ast->child[0], 0, indent);
1522 smart_str_appends(str, " insteadof ");
1523 zend_ast_export_ex(str, ast->child[1], 0, indent);
1524 break;
1525 case ZEND_AST_METHOD_REFERENCE:
1526 if (ast->child[0]) {
1527 zend_ast_export_name(str, ast->child[0], 0, indent);
1528 smart_str_appends(str, "::");
1529 }
1530 zend_ast_export_name(str, ast->child[1], 0, indent);
1531 break;
1532 case ZEND_AST_NAMESPACE:
1533 smart_str_appends(str, "namespace");
1534 if (ast->child[0]) {
1535 smart_str_appendc(str, ' ');
1536 zend_ast_export_name(str, ast->child[0], 0, indent);
1537 }
1538 if (ast->child[1]) {
1539 smart_str_appends(str, " {\n");
1540 zend_ast_export_stmt(str, ast->child[1], indent + 1);
1541 zend_ast_export_indent(str, indent);
1542 smart_str_appends(str, "}\n");
1543 } else {
1544 smart_str_appendc(str, ';');
1545 }
1546 break;
1547 case ZEND_AST_USE_ELEM:
1548 case ZEND_AST_TRAIT_ALIAS:
1549 zend_ast_export_name(str, ast->child[0], 0, indent);
1550 if (ast->attr & ZEND_ACC_PUBLIC) {
1551 smart_str_appends(str, " as public");
1552 } else if (ast->attr & ZEND_ACC_PROTECTED) {
1553 smart_str_appends(str, " as protected");
1554 } else if (ast->attr & ZEND_ACC_PRIVATE) {
1555 smart_str_appends(str, " as private");
1556 } else if (ast->child[1]) {
1557 smart_str_appends(str, " as");
1558 }
1559 if (ast->child[1]) {
1560 smart_str_appendc(str, ' ');
1561 zend_ast_export_name(str, ast->child[1], 0, indent);
1562 }
1563 break;
1564
1565 /* 3 child nodes */
1566 case ZEND_AST_METHOD_CALL:
1567 zend_ast_export_ex(str, ast->child[0], 0, indent);
1568 smart_str_appends(str, "->");
1569 zend_ast_export_var(str, ast->child[1], 0, indent);
1570 smart_str_appendc(str, '(');
1571 zend_ast_export_ex(str, ast->child[2], 0, indent);
1572 smart_str_appendc(str, ')');
1573 break;
1574 case ZEND_AST_STATIC_CALL:
1575 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1576 smart_str_appends(str, "::");
1577 zend_ast_export_var(str, ast->child[1], 0, indent);
1578 smart_str_appendc(str, '(');
1579 zend_ast_export_ex(str, ast->child[2], 0, indent);
1580 smart_str_appendc(str, ')');
1581 break;
1582 case ZEND_AST_CONDITIONAL:
1583 if (priority > 100) smart_str_appendc(str, '(');
1584 zend_ast_export_ex(str, ast->child[0], 100, indent);
1585 if (ast->child[1]) {
1586 smart_str_appends(str, " ? ");
1587 zend_ast_export_ex(str, ast->child[1], 101, indent);
1588 smart_str_appends(str, " : ");
1589 } else {
1590 smart_str_appends(str, " ?: ");
1591 }
1592 zend_ast_export_ex(str, ast->child[2], 101, indent);
1593 if (priority > 100) smart_str_appendc(str, ')');
1594 break;
1595
1596 case ZEND_AST_TRY:
1597 smart_str_appends(str, "try {\n");
1598 zend_ast_export_stmt(str, ast->child[0], indent + 1);
1599 zend_ast_export_indent(str, indent);
1600 zend_ast_export_ex(str, ast->child[1], 0, indent);
1601 if (ast->child[2]) {
1602 smart_str_appends(str, "} finally {\n");
1603 zend_ast_export_stmt(str, ast->child[2], indent + 1);
1604 zend_ast_export_indent(str, indent);
1605 }
1606 smart_str_appendc(str, '}');
1607 break;
1608 case ZEND_AST_CATCH:
1609 smart_str_appends(str, "} catch (");
1610 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1611 smart_str_appends(str, " $");
1612 zend_ast_export_var(str, ast->child[1], 0, indent);
1613 smart_str_appends(str, ") {\n");
1614 zend_ast_export_stmt(str, ast->child[2], indent + 1);
1615 zend_ast_export_indent(str, indent);
1616 break;
1617 case ZEND_AST_PARAM:
1618 if (ast->child[0]) {
1619 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1620 smart_str_appendc(str, ' ');
1621 }
1622 if (ast->attr & ZEND_PARAM_REF) {
1623 smart_str_appendc(str, '&');
1624 }
1625 if (ast->attr & ZEND_PARAM_VARIADIC) {
1626 smart_str_appends(str, "...");
1627 }
1628 smart_str_appendc(str, '$');
1629 zend_ast_export_name(str, ast->child[1], 0, indent);
1630 APPEND_DEFAULT_VALUE(2);
1631
1632 /* 4 child nodes */
1633 case ZEND_AST_FOR:
1634 smart_str_appends(str, "for (");
1635 zend_ast_export_ex(str, ast->child[0], 0, indent);
1636 smart_str_appendc(str, ';');
1637 if (ast->child[1]) {
1638 smart_str_appendc(str, ' ');
1639 zend_ast_export_ex(str, ast->child[1], 0, indent);
1640 }
1641 smart_str_appendc(str, ';');
1642 if (ast->child[2]) {
1643 smart_str_appendc(str, ' ');
1644 zend_ast_export_ex(str, ast->child[2], 0, indent);
1645 }
1646 smart_str_appends(str, ") {\n");
1647 zend_ast_export_stmt(str, ast->child[3], indent + 1);
1648 zend_ast_export_indent(str, indent);
1649 smart_str_appendc(str, '}');
1650 break;
1651 case ZEND_AST_FOREACH:
1652 smart_str_appends(str, "foreach (");
1653 zend_ast_export_ex(str, ast->child[0], 0, indent);
1654 smart_str_appends(str, " as ");
1655 if (ast->child[2]) {
1656 zend_ast_export_ex(str, ast->child[2], 0, indent);
1657 smart_str_appends(str, " => ");
1658 }
1659 zend_ast_export_ex(str, ast->child[1], 0, indent);
1660 smart_str_appends(str, ") {\n");
1661 zend_ast_export_stmt(str, ast->child[3], indent + 1);
1662 zend_ast_export_indent(str, indent);
1663 smart_str_appendc(str, '}');
1664 break;
1665 EMPTY_SWITCH_DEFAULT_CASE();
1666 }
1667 return;
1668
1669 binary_op:
1670 if (priority > p) smart_str_appendc(str, '(');
1671 zend_ast_export_ex(str, ast->child[0], pl, indent);
1672 smart_str_appends(str, op);
1673 zend_ast_export_ex(str, ast->child[1], pr, indent);
1674 if (priority > p) smart_str_appendc(str, ')');
1675 return;
1676
1677 prefix_op:
1678 if (priority > p) smart_str_appendc(str, '(');
1679 smart_str_appends(str, op);
1680 zend_ast_export_ex(str, ast->child[0], pl, indent);
1681 if (priority > p) smart_str_appendc(str, ')');
1682 return;
1683
1684 postfix_op:
1685 if (priority > p) smart_str_appendc(str, '(');
1686 zend_ast_export_ex(str, ast->child[0], pl, indent);
1687 smart_str_appends(str, op);
1688 if (priority > p) smart_str_appendc(str, ')');
1689 return;
1690
1691 func_op:
1692 smart_str_appends(str, op);
1693 smart_str_appendc(str, '(');
1694 zend_ast_export_ex(str, ast->child[0], 0, indent);
1695 smart_str_appendc(str, ')');
1696 return;
1697
1698 append_node_1:
1699 smart_str_appends(str, op);
1700 if (ast->child[0]) {
1701 smart_str_appendc(str, ' ');
1702 ast = ast->child[0];
1703 goto tail_call;
1704 }
1705 return;
1706
1707 append_str:
1708 smart_str_appends(str, op);
1709 return;
1710
1711 append_default_value:
1712 if (ast->child[p]) {
1713 smart_str_appends(str, " = ");
1714 ast = ast->child[p];
1715 goto tail_call;
1716 }
1717 return;
1718 }
1719
zend_ast_export(const char * prefix,zend_ast * ast,const char * suffix)1720 ZEND_API zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix)
1721 {
1722 smart_str str = {0};
1723
1724 smart_str_appends(&str, prefix);
1725 zend_ast_export_ex(&str, ast, 0, 0);
1726 smart_str_appends(&str, suffix);
1727 smart_str_0(&str);
1728 return str.s;
1729 }
1730