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