1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 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@php.net> |
17 +----------------------------------------------------------------------+
18 */
19
20 #include "zend_ast.h"
21 #include "zend_API.h"
22 #include "zend_operators.h"
23 #include "zend_language_parser.h"
24 #include "zend_smart_str.h"
25 #include "zend_exceptions.h"
26 #include "zend_constants.h"
27 #include "zend_enum.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_list_size(uint32_t children)41 static inline size_t zend_ast_list_size(uint32_t children) {
42 return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
43 }
44
zend_ast_create_znode(znode * node)45 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_znode(znode *node) {
46 zend_ast_znode *ast;
47
48 ast = zend_ast_alloc(sizeof(zend_ast_znode));
49 ast->kind = ZEND_AST_ZNODE;
50 ast->attr = 0;
51 ast->lineno = CG(zend_lineno);
52 ast->node = *node;
53 return (zend_ast *) ast;
54 }
55
zend_ast_create_zval_int(zval * zv,uint32_t attr,uint32_t lineno)56 static zend_always_inline zend_ast * zend_ast_create_zval_int(zval *zv, uint32_t attr, uint32_t lineno) {
57 zend_ast_zval *ast;
58
59 ast = zend_ast_alloc(sizeof(zend_ast_zval));
60 ast->kind = ZEND_AST_ZVAL;
61 ast->attr = attr;
62 ZVAL_COPY_VALUE(&ast->val, zv);
63 Z_LINENO(ast->val) = lineno;
64 return (zend_ast *) ast;
65 }
66
zend_ast_create_zval_with_lineno(zval * zv,uint32_t lineno)67 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_with_lineno(zval *zv, uint32_t lineno) {
68 return zend_ast_create_zval_int(zv, 0, lineno);
69 }
70
zend_ast_create_zval_ex(zval * zv,zend_ast_attr attr)71 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) {
72 return zend_ast_create_zval_int(zv, attr, CG(zend_lineno));
73 }
74
zend_ast_create_zval(zval * zv)75 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval(zval *zv) {
76 return zend_ast_create_zval_int(zv, 0, CG(zend_lineno));
77 }
78
zend_ast_create_zval_from_str(zend_string * str)79 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_str(zend_string *str) {
80 zval zv;
81 ZVAL_STR(&zv, str);
82 return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
83 }
84
zend_ast_create_zval_from_long(zend_long lval)85 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_zval_from_long(zend_long lval) {
86 zval zv;
87 ZVAL_LONG(&zv, lval);
88 return zend_ast_create_zval_int(&zv, 0, CG(zend_lineno));
89 }
90
zend_ast_create_constant(zend_string * name,zend_ast_attr attr)91 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_constant(zend_string *name, zend_ast_attr attr) {
92 zend_ast_zval *ast;
93
94 ast = zend_ast_alloc(sizeof(zend_ast_zval));
95 ast->kind = ZEND_AST_CONSTANT;
96 ast->attr = attr;
97 ZVAL_STR(&ast->val, name);
98 Z_LINENO(ast->val) = CG(zend_lineno);
99 return (zend_ast *) ast;
100 }
101
zend_ast_create_class_const_or_name(zend_ast * class_name,zend_ast * name)102 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_class_const_or_name(zend_ast *class_name, zend_ast *name) {
103 zend_string *name_str = zend_ast_get_str(name);
104 if (zend_string_equals_literal_ci(name_str, "class")) {
105 zend_string_release(name_str);
106 return zend_ast_create(ZEND_AST_CLASS_NAME, class_name);
107 } else {
108 return zend_ast_create(ZEND_AST_CLASS_CONST, class_name, name);
109 }
110 }
111
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,zend_ast * child4)112 ZEND_API zend_ast *zend_ast_create_decl(
113 zend_ast_kind kind, uint32_t flags, uint32_t start_lineno, zend_string *doc_comment,
114 zend_string *name, zend_ast *child0, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4
115 ) {
116 zend_ast_decl *ast;
117
118 ast = zend_ast_alloc(sizeof(zend_ast_decl));
119 ast->kind = kind;
120 ast->attr = 0;
121 ast->start_lineno = start_lineno;
122 ast->end_lineno = CG(zend_lineno);
123 ast->flags = flags;
124 ast->lex_pos = LANG_SCNG(yy_text);
125 ast->doc_comment = doc_comment;
126 ast->name = name;
127 ast->child[0] = child0;
128 ast->child[1] = child1;
129 ast->child[2] = child2;
130 ast->child[3] = child3;
131 ast->child[4] = child4;
132
133 return (zend_ast *) ast;
134 }
135
136 #if ZEND_AST_SPEC
zend_ast_create_0(zend_ast_kind kind)137 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_0(zend_ast_kind kind) {
138 zend_ast *ast;
139
140 ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 0);
141 ast = zend_ast_alloc(zend_ast_size(0));
142 ast->kind = kind;
143 ast->attr = 0;
144 ast->lineno = CG(zend_lineno);
145
146 return ast;
147 }
148
zend_ast_create_1(zend_ast_kind kind,zend_ast * child)149 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_1(zend_ast_kind kind, zend_ast *child) {
150 zend_ast *ast;
151 uint32_t lineno;
152
153 ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 1);
154 ast = zend_ast_alloc(zend_ast_size(1));
155 ast->kind = kind;
156 ast->attr = 0;
157 ast->child[0] = child;
158 if (child) {
159 lineno = zend_ast_get_lineno(child);
160 } else {
161 lineno = CG(zend_lineno);
162 }
163 ast->lineno = lineno;
164
165 return ast;
166 }
167
zend_ast_create_2(zend_ast_kind kind,zend_ast * child1,zend_ast * child2)168 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
169 zend_ast *ast;
170 uint32_t lineno;
171
172 ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 2);
173 ast = zend_ast_alloc(zend_ast_size(2));
174 ast->kind = kind;
175 ast->attr = 0;
176 ast->child[0] = child1;
177 ast->child[1] = child2;
178 if (child1) {
179 lineno = zend_ast_get_lineno(child1);
180 } else if (child2) {
181 lineno = zend_ast_get_lineno(child2);
182 } else {
183 lineno = CG(zend_lineno);
184 }
185 ast->lineno = lineno;
186
187 return ast;
188 }
189
zend_ast_create_3(zend_ast_kind kind,zend_ast * child1,zend_ast * child2,zend_ast * child3)190 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_3(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3) {
191 zend_ast *ast;
192 uint32_t lineno;
193
194 ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 3);
195 ast = zend_ast_alloc(zend_ast_size(3));
196 ast->kind = kind;
197 ast->attr = 0;
198 ast->child[0] = child1;
199 ast->child[1] = child2;
200 ast->child[2] = child3;
201 if (child1) {
202 lineno = zend_ast_get_lineno(child1);
203 } else if (child2) {
204 lineno = zend_ast_get_lineno(child2);
205 } else if (child3) {
206 lineno = zend_ast_get_lineno(child3);
207 } else {
208 lineno = CG(zend_lineno);
209 }
210 ast->lineno = lineno;
211
212 return ast;
213 }
214
zend_ast_create_4(zend_ast_kind kind,zend_ast * child1,zend_ast * child2,zend_ast * child3,zend_ast * child4)215 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_4(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4) {
216 zend_ast *ast;
217 uint32_t lineno;
218
219 ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 4);
220 ast = zend_ast_alloc(zend_ast_size(4));
221 ast->kind = kind;
222 ast->attr = 0;
223 ast->child[0] = child1;
224 ast->child[1] = child2;
225 ast->child[2] = child3;
226 ast->child[3] = child4;
227 if (child1) {
228 lineno = zend_ast_get_lineno(child1);
229 } else if (child2) {
230 lineno = zend_ast_get_lineno(child2);
231 } else if (child3) {
232 lineno = zend_ast_get_lineno(child3);
233 } else if (child4) {
234 lineno = zend_ast_get_lineno(child4);
235 } else {
236 lineno = CG(zend_lineno);
237 }
238 ast->lineno = lineno;
239
240 return ast;
241 }
242
zend_ast_create_5(zend_ast_kind kind,zend_ast * child1,zend_ast * child2,zend_ast * child3,zend_ast * child4,zend_ast * child5)243 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_5(zend_ast_kind kind, zend_ast *child1, zend_ast *child2, zend_ast *child3, zend_ast *child4, zend_ast *child5) {
244 zend_ast *ast;
245 uint32_t lineno;
246
247 ZEND_ASSERT(kind >> ZEND_AST_NUM_CHILDREN_SHIFT == 5);
248 ast = zend_ast_alloc(zend_ast_size(5));
249 ast->kind = kind;
250 ast->attr = 0;
251 ast->child[0] = child1;
252 ast->child[1] = child2;
253 ast->child[2] = child3;
254 ast->child[3] = child4;
255 ast->child[4] = child5;
256 if (child1) {
257 lineno = zend_ast_get_lineno(child1);
258 } else if (child2) {
259 lineno = zend_ast_get_lineno(child2);
260 } else if (child3) {
261 lineno = zend_ast_get_lineno(child3);
262 } else if (child4) {
263 lineno = zend_ast_get_lineno(child4);
264 } else if (child5) {
265 lineno = zend_ast_get_lineno(child5);
266 } else {
267 lineno = CG(zend_lineno);
268 }
269 ast->lineno = lineno;
270
271 return ast;
272 }
273
zend_ast_create_list_0(zend_ast_kind kind)274 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_0(zend_ast_kind kind) {
275 zend_ast *ast;
276 zend_ast_list *list;
277
278 ast = zend_ast_alloc(zend_ast_list_size(4));
279 list = (zend_ast_list *) ast;
280 list->kind = kind;
281 list->attr = 0;
282 list->lineno = CG(zend_lineno);
283 list->children = 0;
284
285 return ast;
286 }
287
zend_ast_create_list_1(zend_ast_kind kind,zend_ast * child)288 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_1(zend_ast_kind kind, zend_ast *child) {
289 zend_ast *ast;
290 zend_ast_list *list;
291 uint32_t lineno;
292
293 ast = zend_ast_alloc(zend_ast_list_size(4));
294 list = (zend_ast_list *) ast;
295 list->kind = kind;
296 list->attr = 0;
297 list->children = 1;
298 list->child[0] = child;
299 if (child) {
300 lineno = zend_ast_get_lineno(child);
301 if (lineno > CG(zend_lineno)) {
302 lineno = CG(zend_lineno);
303 }
304 } else {
305 lineno = CG(zend_lineno);
306 }
307 list->lineno = lineno;
308
309 return ast;
310 }
311
zend_ast_create_list_2(zend_ast_kind kind,zend_ast * child1,zend_ast * child2)312 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_create_list_2(zend_ast_kind kind, zend_ast *child1, zend_ast *child2) {
313 zend_ast *ast;
314 zend_ast_list *list;
315 uint32_t lineno;
316
317 ast = zend_ast_alloc(zend_ast_list_size(4));
318 list = (zend_ast_list *) ast;
319 list->kind = kind;
320 list->attr = 0;
321 list->children = 2;
322 list->child[0] = child1;
323 list->child[1] = child2;
324 if (child1) {
325 lineno = zend_ast_get_lineno(child1);
326 if (lineno > CG(zend_lineno)) {
327 lineno = CG(zend_lineno);
328 }
329 } else if (child2) {
330 lineno = zend_ast_get_lineno(child2);
331 if (lineno > CG(zend_lineno)) {
332 lineno = CG(zend_lineno);
333 }
334 } else {
335 list->children = 0;
336 lineno = CG(zend_lineno);
337 }
338 list->lineno = lineno;
339
340 return ast;
341 }
342 #else
zend_ast_create_from_va_list(zend_ast_kind kind,zend_ast_attr attr,va_list va)343 static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) {
344 uint32_t i, children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
345 zend_ast *ast;
346
347 ast = zend_ast_alloc(zend_ast_size(children));
348 ast->kind = kind;
349 ast->attr = attr;
350 ast->lineno = (uint32_t) -1;
351
352 for (i = 0; i < children; ++i) {
353 ast->child[i] = va_arg(va, zend_ast *);
354 if (ast->child[i] != NULL) {
355 uint32_t lineno = zend_ast_get_lineno(ast->child[i]);
356 if (lineno < ast->lineno) {
357 ast->lineno = lineno;
358 }
359 }
360 }
361
362 if (ast->lineno == UINT_MAX) {
363 ast->lineno = CG(zend_lineno);
364 }
365
366 return ast;
367 }
368
zend_ast_create_ex(zend_ast_kind kind,zend_ast_attr attr,...)369 ZEND_API zend_ast *zend_ast_create_ex(zend_ast_kind kind, zend_ast_attr attr, ...) {
370 va_list va;
371 zend_ast *ast;
372
373 va_start(va, attr);
374 ast = zend_ast_create_from_va_list(kind, attr, va);
375 va_end(va);
376
377 return ast;
378 }
379
zend_ast_create(zend_ast_kind kind,...)380 ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...) {
381 va_list va;
382 zend_ast *ast;
383
384 va_start(va, kind);
385 ast = zend_ast_create_from_va_list(kind, 0, va);
386 va_end(va);
387
388 return ast;
389 }
390
zend_ast_create_list(uint32_t init_children,zend_ast_kind kind,...)391 ZEND_API zend_ast *zend_ast_create_list(uint32_t init_children, zend_ast_kind kind, ...) {
392 zend_ast *ast;
393 zend_ast_list *list;
394
395 ast = zend_ast_alloc(zend_ast_list_size(4));
396 list = (zend_ast_list *) ast;
397 list->kind = kind;
398 list->attr = 0;
399 list->lineno = CG(zend_lineno);
400 list->children = 0;
401
402 {
403 va_list va;
404 uint32_t i;
405 va_start(va, kind);
406 for (i = 0; i < init_children; ++i) {
407 zend_ast *child = va_arg(va, zend_ast *);
408 ast = zend_ast_list_add(ast, child);
409 if (child != NULL) {
410 uint32_t lineno = zend_ast_get_lineno(child);
411 if (lineno < ast->lineno) {
412 ast->lineno = lineno;
413 }
414 }
415 }
416 va_end(va);
417 }
418
419 return ast;
420 }
421 #endif
422
is_power_of_two(uint32_t n)423 static inline bool is_power_of_two(uint32_t n) {
424 return ((n != 0) && (n == (n & (~n + 1))));
425 }
426
zend_ast_list_add(zend_ast * ast,zend_ast * op)427 ZEND_API zend_ast * ZEND_FASTCALL zend_ast_list_add(zend_ast *ast, zend_ast *op) {
428 zend_ast_list *list = zend_ast_get_list(ast);
429 if (list->children >= 4 && is_power_of_two(list->children)) {
430 list = zend_ast_realloc(list,
431 zend_ast_list_size(list->children), zend_ast_list_size(list->children * 2));
432 }
433 list->child[list->children++] = op;
434 return (zend_ast *) list;
435 }
436
zend_ast_add_array_element(zval * result,zval * offset,zval * expr)437 static zend_result zend_ast_add_array_element(zval *result, zval *offset, zval *expr)
438 {
439 if (Z_TYPE_P(offset) == IS_UNDEF) {
440 if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), expr)) {
441 zend_throw_error(NULL,
442 "Cannot add element to the array as the next element is already occupied");
443 return FAILURE;
444 }
445 return SUCCESS;
446 }
447
448 if (array_set_zval_key(Z_ARRVAL_P(result), offset, expr) == FAILURE) {
449 return FAILURE;
450 }
451
452 zval_ptr_dtor_nogc(offset);
453 zval_ptr_dtor_nogc(expr);
454 return SUCCESS;
455 }
456
zend_ast_add_unpacked_element(zval * result,zval * expr)457 static zend_result zend_ast_add_unpacked_element(zval *result, zval *expr) {
458 if (EXPECTED(Z_TYPE_P(expr) == IS_ARRAY)) {
459 HashTable *ht = Z_ARRVAL_P(expr);
460 zval *val;
461 zend_string *key;
462
463 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
464 if (key) {
465 zend_hash_update(Z_ARRVAL_P(result), key, val);
466 } else {
467 if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), val)) {
468 zend_throw_error(NULL,
469 "Cannot add element to the array as the next element is already occupied");
470 return FAILURE;
471 }
472 }
473 Z_TRY_ADDREF_P(val);
474 } ZEND_HASH_FOREACH_END();
475 return SUCCESS;
476 }
477
478 /* Objects or references cannot occur in a constant expression. */
479 zend_throw_error(NULL, "Only arrays and Traversables can be unpacked");
480 return FAILURE;
481 }
482
zend_ast_fetch_class(zend_ast * ast,zend_class_entry * scope)483 zend_class_entry *zend_ast_fetch_class(zend_ast *ast, zend_class_entry *scope)
484 {
485 return zend_fetch_class_with_scope(zend_ast_get_str(ast), ast->attr | ZEND_FETCH_CLASS_EXCEPTION, scope);
486 }
487
zend_ast_evaluate(zval * result,zend_ast * ast,zend_class_entry * scope)488 ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *scope)
489 {
490 zval op1, op2;
491 zend_result ret = SUCCESS;
492
493 switch (ast->kind) {
494 case ZEND_AST_BINARY_OP:
495 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
496 ret = FAILURE;
497 } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
498 zval_ptr_dtor_nogc(&op1);
499 ret = FAILURE;
500 } else {
501 binary_op_type op = get_binary_op(ast->attr);
502 ret = op(result, &op1, &op2);
503 zval_ptr_dtor_nogc(&op1);
504 zval_ptr_dtor_nogc(&op2);
505 }
506 break;
507 case ZEND_AST_GREATER:
508 case ZEND_AST_GREATER_EQUAL:
509 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
510 ret = FAILURE;
511 } else if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
512 zval_ptr_dtor_nogc(&op1);
513 ret = FAILURE;
514 } else {
515 /* op1 > op2 is the same as op2 < op1 */
516 binary_op_type op = ast->kind == ZEND_AST_GREATER
517 ? is_smaller_function : is_smaller_or_equal_function;
518 ret = op(result, &op2, &op1);
519 zval_ptr_dtor_nogc(&op1);
520 zval_ptr_dtor_nogc(&op2);
521 }
522 break;
523 case ZEND_AST_UNARY_OP:
524 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
525 ret = FAILURE;
526 } else {
527 unary_op_type op = get_unary_op(ast->attr);
528 ret = op(result, &op1);
529 zval_ptr_dtor_nogc(&op1);
530 }
531 break;
532 case ZEND_AST_ZVAL:
533 {
534 zval *zv = zend_ast_get_zval(ast);
535
536 ZVAL_COPY(result, zv);
537 break;
538 }
539 case ZEND_AST_CONSTANT:
540 {
541 zend_string *name = zend_ast_get_constant_name(ast);
542 zval *zv = zend_get_constant_ex(name, scope, ast->attr);
543
544 if (UNEXPECTED(zv == NULL)) {
545 ZVAL_UNDEF(result);
546 return FAILURE;
547 }
548 ZVAL_COPY_OR_DUP(result, zv);
549 break;
550 }
551 case ZEND_AST_CONSTANT_CLASS:
552 if (scope) {
553 ZVAL_STR_COPY(result, scope->name);
554 } else {
555 ZVAL_EMPTY_STRING(result);
556 }
557 break;
558 case ZEND_AST_CLASS_NAME:
559 if (!scope) {
560 zend_throw_error(NULL, "Cannot use \"self\" when no class scope is active");
561 return FAILURE;
562 }
563 if (ast->attr == ZEND_FETCH_CLASS_SELF) {
564 ZVAL_STR_COPY(result, scope->name);
565 } else if (ast->attr == ZEND_FETCH_CLASS_PARENT) {
566 if (!scope->parent) {
567 zend_throw_error(NULL,
568 "Cannot use \"parent\" when current class scope has no parent");
569 return FAILURE;
570 }
571 ZVAL_STR_COPY(result, scope->parent->name);
572 } else {
573 ZEND_ASSERT(0 && "Should have errored during compilation");
574 }
575 break;
576 case ZEND_AST_AND:
577 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
578 ret = FAILURE;
579 break;
580 }
581 if (zend_is_true(&op1)) {
582 if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
583 zval_ptr_dtor_nogc(&op1);
584 ret = FAILURE;
585 break;
586 }
587 ZVAL_BOOL(result, zend_is_true(&op2));
588 zval_ptr_dtor_nogc(&op2);
589 } else {
590 ZVAL_FALSE(result);
591 }
592 zval_ptr_dtor_nogc(&op1);
593 break;
594 case ZEND_AST_OR:
595 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
596 ret = FAILURE;
597 break;
598 }
599 if (zend_is_true(&op1)) {
600 ZVAL_TRUE(result);
601 } else {
602 if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
603 zval_ptr_dtor_nogc(&op1);
604 ret = FAILURE;
605 break;
606 }
607 ZVAL_BOOL(result, zend_is_true(&op2));
608 zval_ptr_dtor_nogc(&op2);
609 }
610 zval_ptr_dtor_nogc(&op1);
611 break;
612 case ZEND_AST_CONDITIONAL:
613 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
614 ret = FAILURE;
615 break;
616 }
617 if (zend_is_true(&op1)) {
618 if (!ast->child[1]) {
619 *result = op1;
620 } else {
621 if (UNEXPECTED(zend_ast_evaluate(result, ast->child[1], scope) != SUCCESS)) {
622 zval_ptr_dtor_nogc(&op1);
623 ret = FAILURE;
624 break;
625 }
626 zval_ptr_dtor_nogc(&op1);
627 }
628 } else {
629 if (UNEXPECTED(zend_ast_evaluate(result, ast->child[2], scope) != SUCCESS)) {
630 zval_ptr_dtor_nogc(&op1);
631 ret = FAILURE;
632 break;
633 }
634 zval_ptr_dtor_nogc(&op1);
635 }
636 break;
637 case ZEND_AST_COALESCE:
638 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
639 ret = FAILURE;
640 break;
641 }
642 if (Z_TYPE(op1) > IS_NULL) {
643 *result = op1;
644 } else {
645 if (UNEXPECTED(zend_ast_evaluate(result, ast->child[1], scope) != SUCCESS)) {
646 zval_ptr_dtor_nogc(&op1);
647 ret = FAILURE;
648 break;
649 }
650 zval_ptr_dtor_nogc(&op1);
651 }
652 break;
653 case ZEND_AST_UNARY_PLUS:
654 if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) {
655 ret = FAILURE;
656 } else {
657 ZVAL_LONG(&op1, 0);
658 ret = add_function(result, &op1, &op2);
659 zval_ptr_dtor_nogc(&op2);
660 }
661 break;
662 case ZEND_AST_UNARY_MINUS:
663 if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[0], scope) != SUCCESS)) {
664 ret = FAILURE;
665 } else {
666 ZVAL_LONG(&op1, 0);
667 ret = sub_function(result, &op1, &op2);
668 zval_ptr_dtor_nogc(&op2);
669 }
670 break;
671 case ZEND_AST_ARRAY:
672 {
673 uint32_t i;
674 zend_ast_list *list = zend_ast_get_list(ast);
675
676 if (!list->children) {
677 ZVAL_EMPTY_ARRAY(result);
678 break;
679 }
680 array_init(result);
681 for (i = 0; i < list->children; i++) {
682 zend_ast *elem = list->child[i];
683 if (elem->kind == ZEND_AST_UNPACK) {
684 if (UNEXPECTED(zend_ast_evaluate(&op1, elem->child[0], scope) != SUCCESS)) {
685 zval_ptr_dtor_nogc(result);
686 return FAILURE;
687 }
688 if (UNEXPECTED(zend_ast_add_unpacked_element(result, &op1) != SUCCESS)) {
689 zval_ptr_dtor_nogc(&op1);
690 zval_ptr_dtor_nogc(result);
691 return FAILURE;
692 }
693 zval_ptr_dtor_nogc(&op1);
694 continue;
695 }
696 if (elem->child[1]) {
697 if (UNEXPECTED(zend_ast_evaluate(&op1, elem->child[1], scope) != SUCCESS)) {
698 zval_ptr_dtor_nogc(result);
699 return FAILURE;
700 }
701 } else {
702 ZVAL_UNDEF(&op1);
703 }
704 if (UNEXPECTED(zend_ast_evaluate(&op2, elem->child[0], scope) != SUCCESS)) {
705 zval_ptr_dtor_nogc(&op1);
706 zval_ptr_dtor_nogc(result);
707 return FAILURE;
708 }
709 if (UNEXPECTED(zend_ast_add_array_element(result, &op1, &op2) != SUCCESS)) {
710 zval_ptr_dtor_nogc(&op1);
711 zval_ptr_dtor_nogc(&op2);
712 zval_ptr_dtor_nogc(result);
713 return FAILURE;
714 }
715 }
716 }
717 break;
718 case ZEND_AST_DIM:
719 if (ast->child[1] == NULL) {
720 zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading");
721 }
722
723 if (UNEXPECTED(zend_ast_evaluate(&op1, ast->child[0], scope) != SUCCESS)) {
724 ret = FAILURE;
725 break;
726 }
727
728 // DIM on objects is disallowed because it allows executing arbitrary expressions
729 if (Z_TYPE(op1) == IS_OBJECT) {
730 zval_ptr_dtor_nogc(&op1);
731 zend_throw_error(NULL, "Cannot use [] on objects in constant expression");
732 ret = FAILURE;
733 break;
734 }
735
736 if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) {
737 zval_ptr_dtor_nogc(&op1);
738 ret = FAILURE;
739 break;
740 }
741
742 zend_fetch_dimension_const(result, &op1, &op2, (ast->attr & ZEND_DIM_IS) ? BP_VAR_IS : BP_VAR_R);
743
744 zval_ptr_dtor_nogc(&op1);
745 zval_ptr_dtor_nogc(&op2);
746 if (UNEXPECTED(EG(exception))) {
747 return FAILURE;
748 }
749
750 break;
751 case ZEND_AST_CONST_ENUM_INIT:
752 {
753 zend_ast *class_name_ast = ast->child[0];
754 zend_string *class_name = zend_ast_get_str(class_name_ast);
755
756 zend_ast *case_name_ast = ast->child[1];
757 zend_string *case_name = zend_ast_get_str(case_name_ast);
758
759 zend_ast *case_value_ast = ast->child[2];
760 zval *case_value_zv = case_value_ast != NULL
761 ? zend_ast_get_zval(case_value_ast)
762 : NULL;
763
764 zend_class_entry *ce = zend_lookup_class(class_name);
765 if (!ce) {
766 /* Class may not be available when resolving constants on a dynamically
767 * declared enum during preloading. */
768 ZEND_ASSERT(CG(compiler_options) & ZEND_COMPILE_PRELOAD);
769 return FAILURE;
770 }
771
772 zend_enum_new(result, ce, case_name, case_value_zv);
773 break;
774 }
775 case ZEND_AST_CLASS_CONST:
776 {
777 zend_string *class_name = zend_ast_get_str(ast->child[0]);
778 zend_string *const_name = zend_ast_get_str(ast->child[1]);
779 zval *zv = zend_get_class_constant_ex(class_name, const_name, scope, ast->attr);
780
781 if (UNEXPECTED(zv == NULL)) {
782 ZVAL_UNDEF(result);
783 return FAILURE;
784 }
785 ZVAL_COPY_OR_DUP(result, zv);
786 break;
787 }
788 case ZEND_AST_NEW:
789 {
790 zend_class_entry *ce = zend_ast_fetch_class(ast->child[0], scope);
791 if (!ce) {
792 return FAILURE;
793 }
794
795 if (object_init_ex(result, ce) != SUCCESS) {
796 return FAILURE;
797 }
798
799 zend_ast_list *args_ast = zend_ast_get_list(ast->child[1]);
800 if (args_ast->attr) {
801 /* Has named arguments. */
802 HashTable *args = zend_new_array(args_ast->children);
803 for (uint32_t i = 0; i < args_ast->children; i++) {
804 zend_ast *arg_ast = args_ast->child[i];
805 zend_string *name = NULL;
806 zval arg;
807 if (arg_ast->kind == ZEND_AST_NAMED_ARG) {
808 name = zend_ast_get_str(arg_ast->child[0]);
809 arg_ast = arg_ast->child[1];
810 }
811 if (zend_ast_evaluate(&arg, arg_ast, scope) == FAILURE) {
812 zend_array_destroy(args);
813 zval_ptr_dtor(result);
814 return FAILURE;
815 }
816 if (name) {
817 if (!zend_hash_add(args, name, &arg)) {
818 zend_throw_error(NULL,
819 "Named parameter $%s overwrites previous argument",
820 ZSTR_VAL(name));
821 zend_array_destroy(args);
822 zval_ptr_dtor(result);
823 return FAILURE;
824 }
825 } else {
826 zend_hash_next_index_insert(args, &arg);
827 }
828 }
829
830 zend_function *ctor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
831 if (ctor) {
832 zend_call_known_function(
833 ctor, Z_OBJ_P(result), Z_OBJCE_P(result), NULL, 0, NULL, args);
834 }
835
836 zend_array_destroy(args);
837 } else {
838 ALLOCA_FLAG(use_heap)
839 zval *args = do_alloca(sizeof(zval) * args_ast->children, use_heap);
840 for (uint32_t i = 0; i < args_ast->children; i++) {
841 if (zend_ast_evaluate(&args[i], args_ast->child[i], scope) == FAILURE) {
842 for (uint32_t j = 0; j < i; j++) {
843 zval_ptr_dtor(&args[j]);
844 }
845 free_alloca(args, use_heap);
846 zval_ptr_dtor(result);
847 return FAILURE;
848 }
849 }
850
851 zend_function *ctor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
852 if (ctor) {
853 zend_call_known_instance_method(
854 ctor, Z_OBJ_P(result), NULL, args_ast->children, args);
855 }
856
857 for (uint32_t i = 0; i < args_ast->children; i++) {
858 zval_ptr_dtor(&args[i]);
859 }
860 free_alloca(args, use_heap);
861 }
862
863 if (EG(exception)) {
864 zend_object_store_ctor_failed(Z_OBJ_P(result));
865 zval_ptr_dtor(result);
866 return FAILURE;
867 }
868 return SUCCESS;
869 }
870 default:
871 zend_throw_error(NULL, "Unsupported constant expression");
872 ret = FAILURE;
873 }
874 return ret;
875 }
876
zend_ast_tree_size(zend_ast * ast)877 static size_t ZEND_FASTCALL zend_ast_tree_size(zend_ast *ast)
878 {
879 size_t size;
880
881 if (ast->kind == ZEND_AST_ZVAL || ast->kind == ZEND_AST_CONSTANT) {
882 size = sizeof(zend_ast_zval);
883 } else if (zend_ast_is_list(ast)) {
884 uint32_t i;
885 zend_ast_list *list = zend_ast_get_list(ast);
886
887 size = zend_ast_list_size(list->children);
888 for (i = 0; i < list->children; i++) {
889 if (list->child[i]) {
890 size += zend_ast_tree_size(list->child[i]);
891 }
892 }
893 } else {
894 uint32_t i, children = zend_ast_get_num_children(ast);
895
896 size = zend_ast_size(children);
897 for (i = 0; i < children; i++) {
898 if (ast->child[i]) {
899 size += zend_ast_tree_size(ast->child[i]);
900 }
901 }
902 }
903 return size;
904 }
905
zend_ast_tree_copy(zend_ast * ast,void * buf)906 static void* ZEND_FASTCALL zend_ast_tree_copy(zend_ast *ast, void *buf)
907 {
908 if (ast->kind == ZEND_AST_ZVAL) {
909 zend_ast_zval *new = (zend_ast_zval*)buf;
910 new->kind = ZEND_AST_ZVAL;
911 new->attr = ast->attr;
912 ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
913 buf = (void*)((char*)buf + sizeof(zend_ast_zval));
914 } else if (ast->kind == ZEND_AST_CONSTANT) {
915 zend_ast_zval *new = (zend_ast_zval*)buf;
916 new->kind = ZEND_AST_CONSTANT;
917 new->attr = ast->attr;
918 ZVAL_STR_COPY(&new->val, zend_ast_get_constant_name(ast));
919 buf = (void*)((char*)buf + sizeof(zend_ast_zval));
920 } else if (zend_ast_is_list(ast)) {
921 zend_ast_list *list = zend_ast_get_list(ast);
922 zend_ast_list *new = (zend_ast_list*)buf;
923 uint32_t i;
924 new->kind = list->kind;
925 new->attr = list->attr;
926 new->children = list->children;
927 buf = (void*)((char*)buf + zend_ast_list_size(list->children));
928 for (i = 0; i < list->children; i++) {
929 if (list->child[i]) {
930 new->child[i] = (zend_ast*)buf;
931 buf = zend_ast_tree_copy(list->child[i], buf);
932 } else {
933 new->child[i] = NULL;
934 }
935 }
936 } else {
937 uint32_t i, children = zend_ast_get_num_children(ast);
938 zend_ast *new = (zend_ast*)buf;
939 new->kind = ast->kind;
940 new->attr = ast->attr;
941 buf = (void*)((char*)buf + zend_ast_size(children));
942 for (i = 0; i < children; i++) {
943 if (ast->child[i]) {
944 new->child[i] = (zend_ast*)buf;
945 buf = zend_ast_tree_copy(ast->child[i], buf);
946 } else {
947 new->child[i] = NULL;
948 }
949 }
950 }
951 return buf;
952 }
953
zend_ast_copy(zend_ast * ast)954 ZEND_API zend_ast_ref * ZEND_FASTCALL zend_ast_copy(zend_ast *ast)
955 {
956 size_t tree_size;
957 zend_ast_ref *ref;
958
959 ZEND_ASSERT(ast != NULL);
960 tree_size = zend_ast_tree_size(ast) + sizeof(zend_ast_ref);
961 ref = emalloc(tree_size);
962 zend_ast_tree_copy(ast, GC_AST(ref));
963 GC_SET_REFCOUNT(ref, 1);
964 GC_TYPE_INFO(ref) = GC_CONSTANT_AST;
965 return ref;
966 }
967
zend_ast_destroy(zend_ast * ast)968 ZEND_API void ZEND_FASTCALL zend_ast_destroy(zend_ast *ast)
969 {
970 tail_call:
971 if (!ast) {
972 return;
973 }
974
975 if (EXPECTED(ast->kind >= ZEND_AST_VAR)) {
976 uint32_t i, children = zend_ast_get_num_children(ast);
977
978 for (i = 1; i < children; i++) {
979 zend_ast_destroy(ast->child[i]);
980 }
981 ast = ast->child[0];
982 goto tail_call;
983 } else if (EXPECTED(ast->kind == ZEND_AST_ZVAL)) {
984 zval_ptr_dtor_nogc(zend_ast_get_zval(ast));
985 } else if (EXPECTED(zend_ast_is_list(ast))) {
986 zend_ast_list *list = zend_ast_get_list(ast);
987 if (list->children) {
988 uint32_t i;
989
990 for (i = 1; i < list->children; i++) {
991 zend_ast_destroy(list->child[i]);
992 }
993 ast = list->child[0];
994 goto tail_call;
995 }
996 } else if (EXPECTED(ast->kind == ZEND_AST_CONSTANT)) {
997 zend_string_release_ex(zend_ast_get_constant_name(ast), 0);
998 } else if (EXPECTED(ast->kind >= ZEND_AST_FUNC_DECL)) {
999 zend_ast_decl *decl = (zend_ast_decl *) ast;
1000
1001 if (decl->name) {
1002 zend_string_release_ex(decl->name, 0);
1003 }
1004 if (decl->doc_comment) {
1005 zend_string_release_ex(decl->doc_comment, 0);
1006 }
1007 zend_ast_destroy(decl->child[0]);
1008 zend_ast_destroy(decl->child[1]);
1009 zend_ast_destroy(decl->child[2]);
1010 zend_ast_destroy(decl->child[3]);
1011 ast = decl->child[4];
1012 goto tail_call;
1013 }
1014 }
1015
zend_ast_ref_destroy(zend_ast_ref * ast)1016 ZEND_API void ZEND_FASTCALL zend_ast_ref_destroy(zend_ast_ref *ast)
1017 {
1018 zend_ast_destroy(GC_AST(ast));
1019 efree(ast);
1020 }
1021
zend_ast_apply(zend_ast * ast,zend_ast_apply_func fn,void * context)1022 ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn, void *context) {
1023 if (zend_ast_is_list(ast)) {
1024 zend_ast_list *list = zend_ast_get_list(ast);
1025 uint32_t i;
1026 for (i = 0; i < list->children; ++i) {
1027 fn(&list->child[i], context);
1028 }
1029 } else {
1030 uint32_t i, children = zend_ast_get_num_children(ast);
1031 for (i = 0; i < children; ++i) {
1032 fn(&ast->child[i], context);
1033 }
1034 }
1035 }
1036
1037 /*
1038 * Operator Precedence
1039 * ====================
1040 * priority associativity operators
1041 * ----------------------------------
1042 * 10 left include, include_once, eval, require, require_once
1043 * 20 left ,
1044 * 30 left or
1045 * 40 left xor
1046 * 50 left and
1047 * 60 right print
1048 * 70 right yield
1049 * 80 right =>
1050 * 85 right yield from
1051 * 90 right = += -= *= /= .= %= &= |= ^= <<= >>= **=
1052 * 100 left ? :
1053 * 110 right ??
1054 * 120 left ||
1055 * 130 left &&
1056 * 140 left |
1057 * 150 left ^
1058 * 160 left &
1059 * 170 non-associative == != === !==
1060 * 180 non-associative < <= > >= <=>
1061 * 185 left .
1062 * 190 left << >>
1063 * 200 left + -
1064 * 210 left * / %
1065 * 220 right !
1066 * 230 non-associative instanceof
1067 * 240 right + - ++ -- ~ (type) @
1068 * 250 right **
1069 * 260 left [
1070 * 270 non-associative clone new
1071 */
1072
1073 static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent);
1074
zend_ast_export_str(smart_str * str,zend_string * s)1075 static ZEND_COLD void zend_ast_export_str(smart_str *str, zend_string *s)
1076 {
1077 size_t i;
1078
1079 for (i = 0; i < ZSTR_LEN(s); i++) {
1080 unsigned char c = ZSTR_VAL(s)[i];
1081 if (c == '\'' || c == '\\') {
1082 smart_str_appendc(str, '\\');
1083 smart_str_appendc(str, c);
1084 } else {
1085 smart_str_appendc(str, c);
1086 }
1087 }
1088 }
1089
zend_ast_export_qstr(smart_str * str,char quote,zend_string * s)1090 static ZEND_COLD void zend_ast_export_qstr(smart_str *str, char quote, zend_string *s)
1091 {
1092 size_t i;
1093
1094 for (i = 0; i < ZSTR_LEN(s); i++) {
1095 unsigned char c = ZSTR_VAL(s)[i];
1096 if (c < ' ') {
1097 switch (c) {
1098 case '\n':
1099 smart_str_appends(str, "\\n");
1100 break;
1101 case '\r':
1102 smart_str_appends(str, "\\r");
1103 break;
1104 case '\t':
1105 smart_str_appends(str, "\\t");
1106 break;
1107 case '\f':
1108 smart_str_appends(str, "\\f");
1109 break;
1110 case '\v':
1111 smart_str_appends(str, "\\v");
1112 break;
1113 #ifdef ZEND_WIN32
1114 case VK_ESCAPE:
1115 #else
1116 case '\e':
1117 #endif
1118 smart_str_appends(str, "\\e");
1119 break;
1120 default:
1121 smart_str_appends(str, "\\0");
1122 smart_str_appendc(str, '0' + (c / 8));
1123 smart_str_appendc(str, '0' + (c % 8));
1124 break;
1125 }
1126 } else {
1127 if (c == quote || c == '$' || c == '\\') {
1128 smart_str_appendc(str, '\\');
1129 }
1130 smart_str_appendc(str, c);
1131 }
1132 }
1133 }
1134
zend_ast_export_indent(smart_str * str,int indent)1135 static ZEND_COLD void zend_ast_export_indent(smart_str *str, int indent)
1136 {
1137 while (indent > 0) {
1138 smart_str_appends(str, " ");
1139 indent--;
1140 }
1141 }
1142
zend_ast_export_name(smart_str * str,zend_ast * ast,int priority,int indent)1143 static ZEND_COLD void zend_ast_export_name(smart_str *str, zend_ast *ast, int priority, int indent)
1144 {
1145 if (ast->kind == ZEND_AST_ZVAL) {
1146 zval *zv = zend_ast_get_zval(ast);
1147
1148 if (Z_TYPE_P(zv) == IS_STRING) {
1149 smart_str_append(str, Z_STR_P(zv));
1150 return;
1151 }
1152 }
1153 zend_ast_export_ex(str, ast, priority, indent);
1154 }
1155
zend_ast_export_ns_name(smart_str * str,zend_ast * ast,int priority,int indent)1156 static ZEND_COLD void zend_ast_export_ns_name(smart_str *str, zend_ast *ast, int priority, int indent)
1157 {
1158 if (ast->kind == ZEND_AST_ZVAL) {
1159 zval *zv = zend_ast_get_zval(ast);
1160
1161 if (Z_TYPE_P(zv) == IS_STRING) {
1162 if (ast->attr == ZEND_NAME_FQ) {
1163 smart_str_appendc(str, '\\');
1164 } else if (ast->attr == ZEND_NAME_RELATIVE) {
1165 smart_str_appends(str, "namespace\\");
1166 }
1167 smart_str_append(str, Z_STR_P(zv));
1168 return;
1169 }
1170 }
1171 zend_ast_export_ex(str, ast, priority, indent);
1172 }
1173
zend_ast_valid_var_char(char ch)1174 static ZEND_COLD bool zend_ast_valid_var_char(char ch)
1175 {
1176 unsigned char c = (unsigned char)ch;
1177
1178 if (c != '_' && c < 127 &&
1179 (c < '0' || c > '9') &&
1180 (c < 'A' || c > 'Z') &&
1181 (c < 'a' || c > 'z')) {
1182 return 0;
1183 }
1184 return 1;
1185 }
1186
zend_ast_valid_var_name(const char * s,size_t len)1187 static ZEND_COLD bool zend_ast_valid_var_name(const char *s, size_t len)
1188 {
1189 unsigned char c;
1190 size_t i;
1191
1192 if (len == 0) {
1193 return 0;
1194 }
1195 c = (unsigned char)s[0];
1196 if (c != '_' && c < 127 &&
1197 (c < 'A' || c > 'Z') &&
1198 (c < 'a' || c > 'z')) {
1199 return 0;
1200 }
1201 for (i = 1; i < len; i++) {
1202 c = (unsigned char)s[i];
1203 if (c != '_' && c < 127 &&
1204 (c < '0' || c > '9') &&
1205 (c < 'A' || c > 'Z') &&
1206 (c < 'a' || c > 'z')) {
1207 return 0;
1208 }
1209 }
1210 return 1;
1211 }
1212
zend_ast_var_needs_braces(char ch)1213 static ZEND_COLD bool zend_ast_var_needs_braces(char ch)
1214 {
1215 return ch == '[' || zend_ast_valid_var_char(ch);
1216 }
1217
zend_ast_export_var(smart_str * str,zend_ast * ast,int priority,int indent)1218 static ZEND_COLD void zend_ast_export_var(smart_str *str, zend_ast *ast, int priority, int indent)
1219 {
1220 if (ast->kind == ZEND_AST_ZVAL) {
1221 zval *zv = zend_ast_get_zval(ast);
1222 if (Z_TYPE_P(zv) == IS_STRING &&
1223 zend_ast_valid_var_name(Z_STRVAL_P(zv), Z_STRLEN_P(zv))) {
1224 smart_str_append(str, Z_STR_P(zv));
1225 return;
1226 }
1227 } else if (ast->kind == ZEND_AST_VAR) {
1228 zend_ast_export_ex(str, ast, 0, indent);
1229 return;
1230 }
1231 smart_str_appendc(str, '{');
1232 zend_ast_export_name(str, ast, 0, indent);
1233 smart_str_appendc(str, '}');
1234 }
1235
zend_ast_export_list(smart_str * str,zend_ast_list * list,bool separator,int priority,int indent)1236 static ZEND_COLD void zend_ast_export_list(smart_str *str, zend_ast_list *list, bool separator, int priority, int indent)
1237 {
1238 uint32_t i = 0;
1239
1240 while (i < list->children) {
1241 if (i != 0 && separator) {
1242 smart_str_appends(str, ", ");
1243 }
1244 zend_ast_export_ex(str, list->child[i], priority, indent);
1245 i++;
1246 }
1247 }
1248
zend_ast_export_encaps_list(smart_str * str,char quote,zend_ast_list * list,int indent)1249 static ZEND_COLD void zend_ast_export_encaps_list(smart_str *str, char quote, zend_ast_list *list, int indent)
1250 {
1251 uint32_t i = 0;
1252 zend_ast *ast;
1253
1254 while (i < list->children) {
1255 ast = list->child[i];
1256 if (ast->kind == ZEND_AST_ZVAL) {
1257 zval *zv = zend_ast_get_zval(ast);
1258
1259 ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
1260 zend_ast_export_qstr(str, quote, Z_STR_P(zv));
1261 } else if (ast->kind == ZEND_AST_VAR &&
1262 ast->child[0]->kind == ZEND_AST_ZVAL &&
1263 (i + 1 == list->children ||
1264 list->child[i + 1]->kind != ZEND_AST_ZVAL ||
1265 !zend_ast_var_needs_braces(
1266 *Z_STRVAL_P(
1267 zend_ast_get_zval(list->child[i + 1]))))) {
1268 zend_ast_export_ex(str, ast, 0, indent);
1269 } else {
1270 smart_str_appendc(str, '{');
1271 zend_ast_export_ex(str, ast, 0, indent);
1272 smart_str_appendc(str, '}');
1273 }
1274 i++;
1275 }
1276 }
1277
zend_ast_export_name_list_ex(smart_str * str,zend_ast_list * list,int indent,const char * separator)1278 static ZEND_COLD void zend_ast_export_name_list_ex(smart_str *str, zend_ast_list *list, int indent, const char *separator)
1279 {
1280 uint32_t i = 0;
1281
1282 while (i < list->children) {
1283 if (i != 0) {
1284 smart_str_appends(str, separator);
1285 }
1286 zend_ast_export_name(str, list->child[i], 0, indent);
1287 i++;
1288 }
1289 }
1290
1291 #define zend_ast_export_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, ", ")
1292 #define zend_ast_export_catch_name_list(s, l, i) zend_ast_export_name_list_ex(s, l, i, "|")
1293
zend_ast_export_var_list(smart_str * str,zend_ast_list * list,int indent)1294 static ZEND_COLD void zend_ast_export_var_list(smart_str *str, zend_ast_list *list, int indent)
1295 {
1296 uint32_t i = 0;
1297
1298 while (i < list->children) {
1299 if (i != 0) {
1300 smart_str_appends(str, ", ");
1301 }
1302 if (list->child[i]->attr & ZEND_BIND_REF) {
1303 smart_str_appendc(str, '&');
1304 }
1305 smart_str_appendc(str, '$');
1306 zend_ast_export_name(str, list->child[i], 20, indent);
1307 i++;
1308 }
1309 }
1310
zend_ast_export_stmt(smart_str * str,zend_ast * ast,int indent)1311 static ZEND_COLD void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int indent)
1312 {
1313 if (!ast) {
1314 return;
1315 }
1316
1317 if (ast->kind == ZEND_AST_STMT_LIST ||
1318 ast->kind == ZEND_AST_TRAIT_ADAPTATIONS) {
1319 zend_ast_list *list = (zend_ast_list*)ast;
1320 uint32_t i = 0;
1321
1322 while (i < list->children) {
1323 ast = list->child[i];
1324 zend_ast_export_stmt(str, ast, indent);
1325 i++;
1326 }
1327 } else {
1328 zend_ast_export_indent(str, indent);
1329 zend_ast_export_ex(str, ast, 0, indent);
1330 switch (ast->kind) {
1331 case ZEND_AST_LABEL:
1332 case ZEND_AST_IF:
1333 case ZEND_AST_SWITCH:
1334 case ZEND_AST_WHILE:
1335 case ZEND_AST_TRY:
1336 case ZEND_AST_FOR:
1337 case ZEND_AST_FOREACH:
1338 case ZEND_AST_FUNC_DECL:
1339 case ZEND_AST_METHOD:
1340 case ZEND_AST_CLASS:
1341 case ZEND_AST_USE_TRAIT:
1342 case ZEND_AST_NAMESPACE:
1343 case ZEND_AST_DECLARE:
1344 break;
1345 default:
1346 smart_str_appendc(str, ';');
1347 break;
1348 }
1349 smart_str_appendc(str, '\n');
1350 }
1351 }
1352
zend_ast_export_if_stmt(smart_str * str,zend_ast_list * list,int indent)1353 static ZEND_COLD void zend_ast_export_if_stmt(smart_str *str, zend_ast_list *list, int indent)
1354 {
1355 uint32_t i;
1356 zend_ast *ast;
1357
1358 tail_call:
1359 i = 0;
1360 while (i < list->children) {
1361 ast = list->child[i];
1362 ZEND_ASSERT(ast->kind == ZEND_AST_IF_ELEM);
1363 if (ast->child[0]) {
1364 if (i == 0) {
1365 smart_str_appends(str, "if (");
1366 } else {
1367 zend_ast_export_indent(str, indent);
1368 smart_str_appends(str, "} elseif (");
1369 }
1370 zend_ast_export_ex(str, ast->child[0], 0, indent);
1371 smart_str_appends(str, ") {\n");
1372 zend_ast_export_stmt(str, ast->child[1], indent + 1);
1373 } else {
1374 zend_ast_export_indent(str, indent);
1375 smart_str_appends(str, "} else ");
1376 if (ast->child[1] && ast->child[1]->kind == ZEND_AST_IF) {
1377 list = (zend_ast_list*)ast->child[1];
1378 goto tail_call;
1379 } else {
1380 smart_str_appends(str, "{\n");
1381 zend_ast_export_stmt(str, ast->child[1], indent + 1);
1382 }
1383 }
1384 i++;
1385 }
1386 zend_ast_export_indent(str, indent);
1387 smart_str_appendc(str, '}');
1388 }
1389
zend_ast_export_zval(smart_str * str,zval * zv,int priority,int indent)1390 static ZEND_COLD void zend_ast_export_zval(smart_str *str, zval *zv, int priority, int indent)
1391 {
1392 ZVAL_DEREF(zv);
1393 switch (Z_TYPE_P(zv)) {
1394 case IS_NULL:
1395 smart_str_appends(str, "null");
1396 break;
1397 case IS_FALSE:
1398 smart_str_appends(str, "false");
1399 break;
1400 case IS_TRUE:
1401 smart_str_appends(str, "true");
1402 break;
1403 case IS_LONG:
1404 smart_str_append_long(str, Z_LVAL_P(zv));
1405 break;
1406 case IS_DOUBLE:
1407 smart_str_append_double(
1408 str, Z_DVAL_P(zv), (int) EG(precision), /* zero_fraction */ false);
1409 break;
1410 case IS_STRING:
1411 smart_str_appendc(str, '\'');
1412 zend_ast_export_str(str, Z_STR_P(zv));
1413 smart_str_appendc(str, '\'');
1414 break;
1415 case IS_ARRAY: {
1416 zend_long idx;
1417 zend_string *key;
1418 zval *val;
1419 bool first = true;
1420 smart_str_appendc(str, '[');
1421 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(zv), idx, key, val) {
1422 if (first) {
1423 first = false;
1424 } else {
1425 smart_str_appends(str, ", ");
1426 }
1427 if (key) {
1428 smart_str_appendc(str, '\'');
1429 zend_ast_export_str(str, key);
1430 smart_str_appends(str, "' => ");
1431 } else {
1432 smart_str_append_long(str, idx);
1433 smart_str_appends(str, " => ");
1434 }
1435 zend_ast_export_zval(str, val, 0, indent);
1436 } ZEND_HASH_FOREACH_END();
1437 smart_str_appendc(str, ']');
1438 break;
1439 }
1440 case IS_CONSTANT_AST:
1441 zend_ast_export_ex(str, Z_ASTVAL_P(zv), priority, indent);
1442 break;
1443 EMPTY_SWITCH_DEFAULT_CASE();
1444 }
1445 }
1446
zend_ast_export_class_no_header(smart_str * str,zend_ast_decl * decl,int indent)1447 static ZEND_COLD void zend_ast_export_class_no_header(smart_str *str, zend_ast_decl *decl, int indent) {
1448 if (decl->child[0]) {
1449 smart_str_appends(str, " extends ");
1450 zend_ast_export_ns_name(str, decl->child[0], 0, indent);
1451 }
1452 if (decl->child[1]) {
1453 smart_str_appends(str, " implements ");
1454 zend_ast_export_ex(str, decl->child[1], 0, indent);
1455 }
1456 smart_str_appends(str, " {\n");
1457 zend_ast_export_stmt(str, decl->child[2], indent + 1);
1458 zend_ast_export_indent(str, indent);
1459 smart_str_appends(str, "}");
1460 }
1461
zend_ast_export_attribute_group(smart_str * str,zend_ast * ast,int indent)1462 static ZEND_COLD void zend_ast_export_attribute_group(smart_str *str, zend_ast *ast, int indent) {
1463 zend_ast_list *list = zend_ast_get_list(ast);
1464 for (uint32_t i = 0; i < list->children; i++) {
1465 zend_ast *attr = list->child[i];
1466
1467 if (i) {
1468 smart_str_appends(str, ", ");
1469 }
1470 zend_ast_export_ns_name(str, attr->child[0], 0, indent);
1471
1472 if (attr->child[1]) {
1473 smart_str_appendc(str, '(');
1474 zend_ast_export_ex(str, attr->child[1], 0, indent);
1475 smart_str_appendc(str, ')');
1476 }
1477 }
1478 }
1479
zend_ast_export_attributes(smart_str * str,zend_ast * ast,int indent,bool newlines)1480 static ZEND_COLD void zend_ast_export_attributes(smart_str *str, zend_ast *ast, int indent, bool newlines) {
1481 zend_ast_list *list = zend_ast_get_list(ast);
1482 uint32_t i;
1483
1484 for (i = 0; i < list->children; i++) {
1485 smart_str_appends(str, "#[");
1486 zend_ast_export_attribute_group(str, list->child[i], indent);
1487 smart_str_appends(str, "]");
1488
1489 if (newlines) {
1490 smart_str_appendc(str, '\n');
1491 zend_ast_export_indent(str, indent);
1492 } else {
1493 smart_str_appendc(str, ' ');
1494 }
1495 }
1496 }
1497
zend_ast_export_visibility(smart_str * str,uint32_t flags)1498 static ZEND_COLD void zend_ast_export_visibility(smart_str *str, uint32_t flags) {
1499 if (flags & ZEND_ACC_PUBLIC) {
1500 smart_str_appends(str, "public ");
1501 } else if (flags & ZEND_ACC_PROTECTED) {
1502 smart_str_appends(str, "protected ");
1503 } else if (flags & ZEND_ACC_PRIVATE) {
1504 smart_str_appends(str, "private ");
1505 }
1506 }
1507
zend_ast_export_type(smart_str * str,zend_ast * ast,int indent)1508 static ZEND_COLD void zend_ast_export_type(smart_str *str, zend_ast *ast, int indent) {
1509 if (ast->kind == ZEND_AST_TYPE_UNION) {
1510 zend_ast_list *list = zend_ast_get_list(ast);
1511 for (uint32_t i = 0; i < list->children; i++) {
1512 if (i != 0) {
1513 smart_str_appendc(str, '|');
1514 }
1515 zend_ast_export_type(str, list->child[i], indent);
1516 }
1517 return;
1518 }
1519 if (ast->kind == ZEND_AST_TYPE_INTERSECTION) {
1520 zend_ast_list *list = zend_ast_get_list(ast);
1521 for (uint32_t i = 0; i < list->children; i++) {
1522 if (i != 0) {
1523 smart_str_appendc(str, '&');
1524 }
1525 zend_ast_export_type(str, list->child[i], indent);
1526 }
1527 return;
1528 }
1529 if (ast->attr & ZEND_TYPE_NULLABLE) {
1530 smart_str_appendc(str, '?');
1531 }
1532 zend_ast_export_ns_name(str, ast, 0, indent);
1533 }
1534
1535 #define BINARY_OP(_op, _p, _pl, _pr) do { \
1536 op = _op; \
1537 p = _p; \
1538 pl = _pl; \
1539 pr = _pr; \
1540 goto binary_op; \
1541 } while (0)
1542
1543 #define PREFIX_OP(_op, _p, _pl) do { \
1544 op = _op; \
1545 p = _p; \
1546 pl = _pl; \
1547 goto prefix_op; \
1548 } while (0)
1549
1550 #define FUNC_OP(_op) do { \
1551 op = _op; \
1552 goto func_op; \
1553 } while (0)
1554
1555 #define POSTFIX_OP(_op, _p, _pl) do { \
1556 op = _op; \
1557 p = _p; \
1558 pl = _pl; \
1559 goto postfix_op; \
1560 } while (0)
1561
1562 #define APPEND_NODE_1(_op) do { \
1563 op = _op; \
1564 goto append_node_1; \
1565 } while (0)
1566
1567 #define APPEND_STR(_op) do { \
1568 op = _op; \
1569 goto append_str; \
1570 } while (0)
1571
1572 #define APPEND_DEFAULT_VALUE(n) do { \
1573 p = n; \
1574 goto append_default_value; \
1575 } while (0)
1576
zend_ast_export_ex(smart_str * str,zend_ast * ast,int priority,int indent)1577 static ZEND_COLD void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent)
1578 {
1579 zend_ast_decl *decl;
1580 int p, pl, pr;
1581 const char *op;
1582
1583 tail_call:
1584 if (!ast) {
1585 return;
1586 }
1587 switch (ast->kind) {
1588 /* special nodes */
1589 case ZEND_AST_ZVAL:
1590 zend_ast_export_zval(str, zend_ast_get_zval(ast), priority, indent);
1591 break;
1592 case ZEND_AST_CONSTANT: {
1593 zend_string *name = zend_ast_get_constant_name(ast);
1594 smart_str_appendl(str, ZSTR_VAL(name), ZSTR_LEN(name));
1595 break;
1596 }
1597 case ZEND_AST_CONSTANT_CLASS:
1598 smart_str_appendl(str, "__CLASS__", sizeof("__CLASS__")-1);
1599 break;
1600 case ZEND_AST_ZNODE:
1601 /* This AST kind is only used for temporary nodes during compilation */
1602 ZEND_UNREACHABLE();
1603 break;
1604
1605 /* declaration nodes */
1606 case ZEND_AST_FUNC_DECL:
1607 case ZEND_AST_CLOSURE:
1608 case ZEND_AST_ARROW_FUNC:
1609 case ZEND_AST_METHOD:
1610 decl = (zend_ast_decl *) ast;
1611 if (decl->child[4]) {
1612 bool newlines = !(ast->kind == ZEND_AST_CLOSURE || ast->kind == ZEND_AST_ARROW_FUNC);
1613 zend_ast_export_attributes(str, decl->child[4], indent, newlines);
1614 }
1615
1616 zend_ast_export_visibility(str, decl->flags);
1617
1618 if (decl->flags & ZEND_ACC_STATIC) {
1619 smart_str_appends(str, "static ");
1620 }
1621 if (decl->flags & ZEND_ACC_ABSTRACT) {
1622 smart_str_appends(str, "abstract ");
1623 }
1624 if (decl->flags & ZEND_ACC_FINAL) {
1625 smart_str_appends(str, "final ");
1626 }
1627 if (decl->kind == ZEND_AST_ARROW_FUNC) {
1628 smart_str_appends(str, "fn");
1629 } else {
1630 smart_str_appends(str, "function ");
1631 }
1632 if (decl->flags & ZEND_ACC_RETURN_REFERENCE) {
1633 smart_str_appendc(str, '&');
1634 }
1635 if (ast->kind != ZEND_AST_CLOSURE && ast->kind != ZEND_AST_ARROW_FUNC) {
1636 smart_str_appendl(str, ZSTR_VAL(decl->name), ZSTR_LEN(decl->name));
1637 }
1638 smart_str_appendc(str, '(');
1639 zend_ast_export_ex(str, decl->child[0], 0, indent);
1640 smart_str_appendc(str, ')');
1641 zend_ast_export_ex(str, decl->child[1], 0, indent);
1642 if (decl->child[3]) {
1643 smart_str_appends(str, ": ");
1644 zend_ast_export_type(str, decl->child[3], indent);
1645 }
1646 if (decl->child[2]) {
1647 if (decl->kind == ZEND_AST_ARROW_FUNC) {
1648 ZEND_ASSERT(decl->child[2]->kind == ZEND_AST_RETURN);
1649 smart_str_appends(str, " => ");
1650 zend_ast_export_ex(str, decl->child[2]->child[0], 0, indent);
1651 break;
1652 }
1653
1654 smart_str_appends(str, " {\n");
1655 zend_ast_export_stmt(str, decl->child[2], indent + 1);
1656 zend_ast_export_indent(str, indent);
1657 smart_str_appendc(str, '}');
1658 if (ast->kind != ZEND_AST_CLOSURE) {
1659 smart_str_appendc(str, '\n');
1660 }
1661 } else {
1662 smart_str_appends(str, ";\n");
1663 }
1664 break;
1665 case ZEND_AST_CLASS:
1666 decl = (zend_ast_decl *) ast;
1667 if (decl->child[3]) {
1668 zend_ast_export_attributes(str, decl->child[3], indent, 1);
1669 }
1670 if (decl->flags & ZEND_ACC_INTERFACE) {
1671 smart_str_appends(str, "interface ");
1672 } else if (decl->flags & ZEND_ACC_TRAIT) {
1673 smart_str_appends(str, "trait ");
1674 } else if (decl->flags & ZEND_ACC_ENUM) {
1675 smart_str_appends(str, "enum ");
1676 } else {
1677 if (decl->flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
1678 smart_str_appends(str, "abstract ");
1679 }
1680 if (decl->flags & ZEND_ACC_FINAL) {
1681 smart_str_appends(str, "final ");
1682 }
1683 smart_str_appends(str, "class ");
1684 }
1685 smart_str_appendl(str, ZSTR_VAL(decl->name), ZSTR_LEN(decl->name));
1686 if (decl->flags & ZEND_ACC_ENUM && decl->child[4]) {
1687 smart_str_appends(str, ": ");
1688 zend_ast_export_type(str, decl->child[4], indent);
1689 }
1690 zend_ast_export_class_no_header(str, decl, indent);
1691 smart_str_appendc(str, '\n');
1692 break;
1693
1694 /* list nodes */
1695 case ZEND_AST_ARG_LIST:
1696 case ZEND_AST_EXPR_LIST:
1697 case ZEND_AST_PARAM_LIST:
1698 simple_list:
1699 zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
1700 break;
1701 case ZEND_AST_ARRAY:
1702 smart_str_appendc(str, '[');
1703 zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
1704 smart_str_appendc(str, ']');
1705 break;
1706 case ZEND_AST_ENCAPS_LIST:
1707 smart_str_appendc(str, '"');
1708 zend_ast_export_encaps_list(str, '"', (zend_ast_list*)ast, indent);
1709 smart_str_appendc(str, '"');
1710 break;
1711 case ZEND_AST_STMT_LIST:
1712 case ZEND_AST_TRAIT_ADAPTATIONS:
1713 zend_ast_export_stmt(str, ast, indent);
1714 break;
1715 case ZEND_AST_IF:
1716 zend_ast_export_if_stmt(str, (zend_ast_list*)ast, indent);
1717 break;
1718 case ZEND_AST_SWITCH_LIST:
1719 case ZEND_AST_CATCH_LIST:
1720 case ZEND_AST_MATCH_ARM_LIST:
1721 zend_ast_export_list(str, (zend_ast_list*)ast, 0, 0, indent);
1722 break;
1723 case ZEND_AST_CLOSURE_USES:
1724 smart_str_appends(str, " use(");
1725 zend_ast_export_var_list(str, (zend_ast_list*)ast, indent);
1726 smart_str_appendc(str, ')');
1727 break;
1728 case ZEND_AST_PROP_GROUP: {
1729 zend_ast *type_ast = ast->child[0];
1730 zend_ast *prop_ast = ast->child[1];
1731
1732 if (ast->child[2]) {
1733 zend_ast_export_attributes(str, ast->child[2], indent, 1);
1734 }
1735
1736 zend_ast_export_visibility(str, ast->attr);
1737
1738 if (ast->attr & ZEND_ACC_STATIC) {
1739 smart_str_appends(str, "static ");
1740 }
1741 if (ast->attr & ZEND_ACC_READONLY) {
1742 smart_str_appends(str, "readonly ");
1743 }
1744
1745 if (type_ast) {
1746 zend_ast_export_type(str, type_ast, indent);
1747 smart_str_appendc(str, ' ');
1748 }
1749
1750 ast = prop_ast;
1751 goto simple_list;
1752 }
1753
1754 case ZEND_AST_CONST_DECL:
1755 smart_str_appends(str, "const ");
1756 goto simple_list;
1757 case ZEND_AST_CLASS_CONST_GROUP:
1758 if (ast->child[1]) {
1759 zend_ast_export_attributes(str, ast->child[1], indent, 1);
1760 }
1761
1762 zend_ast_export_visibility(str, ast->attr);
1763 smart_str_appends(str, "const ");
1764
1765 ast = ast->child[0];
1766
1767 goto simple_list;
1768 case ZEND_AST_NAME_LIST:
1769 zend_ast_export_name_list(str, (zend_ast_list*)ast, indent);
1770 break;
1771 case ZEND_AST_USE:
1772 smart_str_appends(str, "use ");
1773 if (ast->attr == T_FUNCTION) {
1774 smart_str_appends(str, "function ");
1775 } else if (ast->attr == T_CONST) {
1776 smart_str_appends(str, "const ");
1777 }
1778 goto simple_list;
1779
1780 /* 0 child nodes */
1781 case ZEND_AST_MAGIC_CONST:
1782 switch (ast->attr) {
1783 case T_LINE: APPEND_STR("__LINE__");
1784 case T_FILE: APPEND_STR("__FILE__");
1785 case T_DIR: APPEND_STR("__DIR__");
1786 case T_TRAIT_C: APPEND_STR("__TRAIT__");
1787 case T_METHOD_C: APPEND_STR("__METHOD__");
1788 case T_FUNC_C: APPEND_STR("__FUNCTION__");
1789 case T_NS_C: APPEND_STR("__NAMESPACE__");
1790 case T_CLASS_C: APPEND_STR("__CLASS__");
1791 EMPTY_SWITCH_DEFAULT_CASE();
1792 }
1793 break;
1794 case ZEND_AST_TYPE:
1795 switch (ast->attr & ~ZEND_TYPE_NULLABLE) {
1796 case IS_ARRAY: APPEND_STR("array");
1797 case IS_CALLABLE: APPEND_STR("callable");
1798 case IS_STATIC: APPEND_STR("static");
1799 case IS_MIXED: APPEND_STR("mixed");
1800 EMPTY_SWITCH_DEFAULT_CASE();
1801 }
1802 break;
1803
1804 /* 1 child node */
1805 case ZEND_AST_VAR:
1806 smart_str_appendc(str, '$');
1807 zend_ast_export_var(str, ast->child[0], 0, indent);
1808 break;
1809 case ZEND_AST_CONST:
1810 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1811 break;
1812 case ZEND_AST_UNPACK:
1813 smart_str_appends(str, "...");
1814 ast = ast->child[0];
1815 goto tail_call;
1816 case ZEND_AST_UNARY_PLUS: PREFIX_OP("+", 240, 241);
1817 case ZEND_AST_UNARY_MINUS: PREFIX_OP("-", 240, 241);
1818 case ZEND_AST_CAST:
1819 switch (ast->attr) {
1820 case IS_NULL: PREFIX_OP("(unset)", 240, 241);
1821 case _IS_BOOL: PREFIX_OP("(bool)", 240, 241);
1822 case IS_LONG: PREFIX_OP("(int)", 240, 241);
1823 case IS_DOUBLE: PREFIX_OP("(double)", 240, 241);
1824 case IS_STRING: PREFIX_OP("(string)", 240, 241);
1825 case IS_ARRAY: PREFIX_OP("(array)", 240, 241);
1826 case IS_OBJECT: PREFIX_OP("(object)", 240, 241);
1827 EMPTY_SWITCH_DEFAULT_CASE();
1828 }
1829 break;
1830 case ZEND_AST_EMPTY:
1831 FUNC_OP("empty");
1832 case ZEND_AST_ISSET:
1833 FUNC_OP("isset");
1834 case ZEND_AST_SILENCE:
1835 PREFIX_OP("@", 240, 241);
1836 case ZEND_AST_SHELL_EXEC:
1837 smart_str_appendc(str, '`');
1838 if (ast->child[0]->kind == ZEND_AST_ENCAPS_LIST) {
1839 zend_ast_export_encaps_list(str, '`', (zend_ast_list*)ast->child[0], indent);
1840 } else {
1841 zval *zv;
1842 ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_ZVAL);
1843 zv = zend_ast_get_zval(ast->child[0]);
1844 ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
1845 zend_ast_export_qstr(str, '`', Z_STR_P(zv));
1846 }
1847 smart_str_appendc(str, '`');
1848 break;
1849 case ZEND_AST_CLONE:
1850 PREFIX_OP("clone ", 270, 271);
1851 case ZEND_AST_EXIT:
1852 if (ast->child[0]) {
1853 FUNC_OP("exit");
1854 } else {
1855 APPEND_STR("exit");
1856 }
1857 break;
1858 case ZEND_AST_PRINT:
1859 PREFIX_OP("print ", 60, 61);
1860 case ZEND_AST_INCLUDE_OR_EVAL:
1861 switch (ast->attr) {
1862 case ZEND_INCLUDE_ONCE: FUNC_OP("include_once");
1863 case ZEND_INCLUDE: FUNC_OP("include");
1864 case ZEND_REQUIRE_ONCE: FUNC_OP("require_once");
1865 case ZEND_REQUIRE: FUNC_OP("require");
1866 case ZEND_EVAL: FUNC_OP("eval");
1867 EMPTY_SWITCH_DEFAULT_CASE();
1868 }
1869 break;
1870 case ZEND_AST_UNARY_OP:
1871 switch (ast->attr) {
1872 case ZEND_BW_NOT: PREFIX_OP("~", 240, 241);
1873 case ZEND_BOOL_NOT: PREFIX_OP("!", 240, 241);
1874 EMPTY_SWITCH_DEFAULT_CASE();
1875 }
1876 break;
1877 case ZEND_AST_PRE_INC:
1878 PREFIX_OP("++", 240, 241);
1879 case ZEND_AST_PRE_DEC:
1880 PREFIX_OP("--", 240, 241);
1881 case ZEND_AST_POST_INC:
1882 POSTFIX_OP("++", 240, 241);
1883 case ZEND_AST_POST_DEC:
1884 POSTFIX_OP("--", 240, 241);
1885
1886 case ZEND_AST_GLOBAL:
1887 APPEND_NODE_1("global");
1888 case ZEND_AST_UNSET:
1889 FUNC_OP("unset");
1890 case ZEND_AST_RETURN:
1891 APPEND_NODE_1("return");
1892 case ZEND_AST_LABEL:
1893 zend_ast_export_name(str, ast->child[0], 0, indent);
1894 smart_str_appendc(str, ':');
1895 break;
1896 case ZEND_AST_REF:
1897 smart_str_appendc(str, '&');
1898 ast = ast->child[0];
1899 goto tail_call;
1900 case ZEND_AST_HALT_COMPILER:
1901 APPEND_STR("__HALT_COMPILER()");
1902 case ZEND_AST_ECHO:
1903 APPEND_NODE_1("echo");
1904 case ZEND_AST_THROW:
1905 APPEND_NODE_1("throw");
1906 case ZEND_AST_GOTO:
1907 smart_str_appends(str, "goto ");
1908 zend_ast_export_name(str, ast->child[0], 0, indent);
1909 break;
1910 case ZEND_AST_BREAK:
1911 APPEND_NODE_1("break");
1912 case ZEND_AST_CONTINUE:
1913 APPEND_NODE_1("continue");
1914
1915 /* 2 child nodes */
1916 case ZEND_AST_DIM:
1917 zend_ast_export_ex(str, ast->child[0], 260, indent);
1918 smart_str_appendc(str, '[');
1919 if (ast->child[1]) {
1920 zend_ast_export_ex(str, ast->child[1], 0, indent);
1921 }
1922 smart_str_appendc(str, ']');
1923 break;
1924 case ZEND_AST_PROP:
1925 case ZEND_AST_NULLSAFE_PROP:
1926 zend_ast_export_ex(str, ast->child[0], 0, indent);
1927 smart_str_appends(str, ast->kind == ZEND_AST_NULLSAFE_PROP ? "?->" : "->");
1928 zend_ast_export_var(str, ast->child[1], 0, indent);
1929 break;
1930 case ZEND_AST_STATIC_PROP:
1931 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1932 smart_str_appends(str, "::$");
1933 zend_ast_export_var(str, ast->child[1], 0, indent);
1934 break;
1935 case ZEND_AST_CALL:
1936 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1937 smart_str_appendc(str, '(');
1938 zend_ast_export_ex(str, ast->child[1], 0, indent);
1939 smart_str_appendc(str, ')');
1940 break;
1941 case ZEND_AST_CALLABLE_CONVERT:
1942 smart_str_appends(str, "...");
1943 break;
1944 case ZEND_AST_CLASS_CONST:
1945 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1946 smart_str_appends(str, "::");
1947 zend_ast_export_name(str, ast->child[1], 0, indent);
1948 break;
1949 case ZEND_AST_CLASS_NAME:
1950 if (ast->child[0] == NULL) {
1951 /* The const expr representation stores the fetch type instead. */
1952 switch (ast->attr) {
1953 case ZEND_FETCH_CLASS_SELF:
1954 smart_str_appends(str, "self");
1955 break;
1956 case ZEND_FETCH_CLASS_PARENT:
1957 smart_str_appends(str, "parent");
1958 break;
1959 EMPTY_SWITCH_DEFAULT_CASE()
1960 }
1961 } else {
1962 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1963 }
1964 smart_str_appends(str, "::class");
1965 break;
1966 case ZEND_AST_ASSIGN: BINARY_OP(" = ", 90, 91, 90);
1967 case ZEND_AST_ASSIGN_REF: BINARY_OP(" =& ", 90, 91, 90);
1968 case ZEND_AST_ASSIGN_OP:
1969 switch (ast->attr) {
1970 case ZEND_ADD: BINARY_OP(" += ", 90, 91, 90);
1971 case ZEND_SUB: BINARY_OP(" -= ", 90, 91, 90);
1972 case ZEND_MUL: BINARY_OP(" *= ", 90, 91, 90);
1973 case ZEND_DIV: BINARY_OP(" /= ", 90, 91, 90);
1974 case ZEND_MOD: BINARY_OP(" %= ", 90, 91, 90);
1975 case ZEND_SL: BINARY_OP(" <<= ", 90, 91, 90);
1976 case ZEND_SR: BINARY_OP(" >>= ", 90, 91, 90);
1977 case ZEND_CONCAT: BINARY_OP(" .= ", 90, 91, 90);
1978 case ZEND_BW_OR: BINARY_OP(" |= ", 90, 91, 90);
1979 case ZEND_BW_AND: BINARY_OP(" &= ", 90, 91, 90);
1980 case ZEND_BW_XOR: BINARY_OP(" ^= ", 90, 91, 90);
1981 case ZEND_POW: BINARY_OP(" **= ", 90, 91, 90);
1982 EMPTY_SWITCH_DEFAULT_CASE();
1983 }
1984 break;
1985 case ZEND_AST_ASSIGN_COALESCE: BINARY_OP(" \?\?= ", 90, 91, 90);
1986 case ZEND_AST_BINARY_OP:
1987 switch (ast->attr) {
1988 case ZEND_ADD: BINARY_OP(" + ", 200, 200, 201);
1989 case ZEND_SUB: BINARY_OP(" - ", 200, 200, 201);
1990 case ZEND_MUL: BINARY_OP(" * ", 210, 210, 211);
1991 case ZEND_DIV: BINARY_OP(" / ", 210, 210, 211);
1992 case ZEND_MOD: BINARY_OP(" % ", 210, 210, 211);
1993 case ZEND_SL: BINARY_OP(" << ", 190, 190, 191);
1994 case ZEND_SR: BINARY_OP(" >> ", 190, 190, 191);
1995 case ZEND_CONCAT: BINARY_OP(" . ", 185, 185, 186);
1996 case ZEND_BW_OR: BINARY_OP(" | ", 140, 140, 141);
1997 case ZEND_BW_AND: BINARY_OP(" & ", 160, 160, 161);
1998 case ZEND_BW_XOR: BINARY_OP(" ^ ", 150, 150, 151);
1999 case ZEND_IS_IDENTICAL: BINARY_OP(" === ", 170, 171, 171);
2000 case ZEND_IS_NOT_IDENTICAL: BINARY_OP(" !== ", 170, 171, 171);
2001 case ZEND_IS_EQUAL: BINARY_OP(" == ", 170, 171, 171);
2002 case ZEND_IS_NOT_EQUAL: BINARY_OP(" != ", 170, 171, 171);
2003 case ZEND_IS_SMALLER: BINARY_OP(" < ", 180, 181, 181);
2004 case ZEND_IS_SMALLER_OR_EQUAL: BINARY_OP(" <= ", 180, 181, 181);
2005 case ZEND_POW: BINARY_OP(" ** ", 250, 251, 250);
2006 case ZEND_BOOL_XOR: BINARY_OP(" xor ", 40, 40, 41);
2007 case ZEND_SPACESHIP: BINARY_OP(" <=> ", 180, 181, 181);
2008 EMPTY_SWITCH_DEFAULT_CASE();
2009 }
2010 break;
2011 case ZEND_AST_GREATER: BINARY_OP(" > ", 180, 181, 181);
2012 case ZEND_AST_GREATER_EQUAL: BINARY_OP(" >= ", 180, 181, 181);
2013 case ZEND_AST_AND: BINARY_OP(" && ", 130, 130, 131);
2014 case ZEND_AST_OR: BINARY_OP(" || ", 120, 120, 121);
2015 case ZEND_AST_ARRAY_ELEM:
2016 if (ast->child[1]) {
2017 zend_ast_export_ex(str, ast->child[1], 80, indent);
2018 smart_str_appends(str, " => ");
2019 }
2020 if (ast->attr)
2021 smart_str_appendc(str, '&');
2022 zend_ast_export_ex(str, ast->child[0], 80, indent);
2023 break;
2024 case ZEND_AST_NEW:
2025 smart_str_appends(str, "new ");
2026 if (ast->child[0]->kind == ZEND_AST_CLASS) {
2027 zend_ast_decl *decl = (zend_ast_decl *) ast->child[0];
2028 if (decl->child[3]) {
2029 zend_ast_export_attributes(str, decl->child[3], indent, 0);
2030 }
2031 smart_str_appends(str, "class");
2032 if (!zend_ast_is_list(ast->child[1])
2033 || zend_ast_get_list(ast->child[1])->children) {
2034 smart_str_appendc(str, '(');
2035 zend_ast_export_ex(str, ast->child[1], 0, indent);
2036 smart_str_appendc(str, ')');
2037 }
2038 zend_ast_export_class_no_header(str, decl, indent);
2039 } else {
2040 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2041 smart_str_appendc(str, '(');
2042 zend_ast_export_ex(str, ast->child[1], 0, indent);
2043 smart_str_appendc(str, ')');
2044 }
2045 break;
2046 case ZEND_AST_INSTANCEOF:
2047 zend_ast_export_ex(str, ast->child[0], 0, indent);
2048 smart_str_appends(str, " instanceof ");
2049 zend_ast_export_ns_name(str, ast->child[1], 0, indent);
2050 break;
2051 case ZEND_AST_YIELD:
2052 if (priority > 70) smart_str_appendc(str, '(');
2053 smart_str_appends(str, "yield ");
2054 if (ast->child[0]) {
2055 if (ast->child[1]) {
2056 zend_ast_export_ex(str, ast->child[1], 70, indent);
2057 smart_str_appends(str, " => ");
2058 }
2059 zend_ast_export_ex(str, ast->child[0], 70, indent);
2060 }
2061 if (priority > 70) smart_str_appendc(str, ')');
2062 break;
2063 case ZEND_AST_YIELD_FROM:
2064 PREFIX_OP("yield from ", 85, 86);
2065 case ZEND_AST_COALESCE: BINARY_OP(" ?? ", 110, 111, 110);
2066 case ZEND_AST_STATIC:
2067 smart_str_appends(str, "static $");
2068 zend_ast_export_name(str, ast->child[0], 0, indent);
2069 APPEND_DEFAULT_VALUE(1);
2070 case ZEND_AST_WHILE:
2071 smart_str_appends(str, "while (");
2072 zend_ast_export_ex(str, ast->child[0], 0, indent);
2073 smart_str_appends(str, ") {\n");
2074 zend_ast_export_stmt(str, ast->child[1], indent + 1);
2075 zend_ast_export_indent(str, indent);
2076 smart_str_appendc(str, '}');
2077 break;
2078 case ZEND_AST_DO_WHILE:
2079 smart_str_appends(str, "do {\n");
2080 zend_ast_export_stmt(str, ast->child[0], indent + 1);
2081 zend_ast_export_indent(str, indent);
2082 smart_str_appends(str, "} while (");
2083 zend_ast_export_ex(str, ast->child[1], 0, indent);
2084 smart_str_appendc(str, ')');
2085 break;
2086
2087 case ZEND_AST_IF_ELEM:
2088 if (ast->child[0]) {
2089 smart_str_appends(str, "if (");
2090 zend_ast_export_ex(str, ast->child[0], 0, indent);
2091 smart_str_appends(str, ") {\n");
2092 zend_ast_export_stmt(str, ast->child[1], indent + 1);
2093 } else {
2094 smart_str_appends(str, "else {\n");
2095 zend_ast_export_stmt(str, ast->child[1], indent + 1);
2096 }
2097 zend_ast_export_indent(str, indent);
2098 smart_str_appendc(str, '}');
2099 break;
2100 case ZEND_AST_SWITCH:
2101 smart_str_appends(str, "switch (");
2102 zend_ast_export_ex(str, ast->child[0], 0, indent);
2103 smart_str_appends(str, ") {\n");
2104 zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2105 zend_ast_export_indent(str, indent);
2106 smart_str_appendc(str, '}');
2107 break;
2108 case ZEND_AST_SWITCH_CASE:
2109 zend_ast_export_indent(str, indent);
2110 if (ast->child[0]) {
2111 smart_str_appends(str, "case ");
2112 zend_ast_export_ex(str, ast->child[0], 0, indent);
2113 smart_str_appends(str, ":\n");
2114 } else {
2115 smart_str_appends(str, "default:\n");
2116 }
2117 zend_ast_export_stmt(str, ast->child[1], indent + 1);
2118 break;
2119 case ZEND_AST_MATCH:
2120 smart_str_appends(str, "match (");
2121 zend_ast_export_ex(str, ast->child[0], 0, indent);
2122 smart_str_appends(str, ") {\n");
2123 zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2124 zend_ast_export_indent(str, indent);
2125 smart_str_appendc(str, '}');
2126 break;
2127 case ZEND_AST_MATCH_ARM:
2128 zend_ast_export_indent(str, indent);
2129 if (ast->child[0]) {
2130 zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent);
2131 smart_str_appends(str, " => ");
2132 } else {
2133 smart_str_appends(str, "default => ");
2134 }
2135 zend_ast_export_ex(str, ast->child[1], 0, 0);
2136 smart_str_appends(str, ",\n");
2137 break;
2138 case ZEND_AST_DECLARE:
2139 smart_str_appends(str, "declare(");
2140 ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_CONST_DECL);
2141 zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent);
2142 smart_str_appendc(str, ')');
2143 if (ast->child[1]) {
2144 smart_str_appends(str, " {\n");
2145 zend_ast_export_stmt(str, ast->child[1], indent + 1);
2146 zend_ast_export_indent(str, indent);
2147 smart_str_appendc(str, '}');
2148 } else {
2149 smart_str_appendc(str, ';');
2150 }
2151 break;
2152 case ZEND_AST_PROP_ELEM:
2153 smart_str_appendc(str, '$');
2154 ZEND_FALLTHROUGH;
2155 case ZEND_AST_CONST_ELEM:
2156 zend_ast_export_name(str, ast->child[0], 0, indent);
2157 APPEND_DEFAULT_VALUE(1);
2158 case ZEND_AST_USE_TRAIT:
2159 smart_str_appends(str, "use ");
2160 zend_ast_export_ex(str, ast->child[0], 0, indent);
2161 if (ast->child[1]) {
2162 smart_str_appends(str, " {\n");
2163 zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
2164 zend_ast_export_indent(str, indent);
2165 smart_str_appends(str, "}");
2166 } else {
2167 smart_str_appends(str, ";");
2168 }
2169 break;
2170 case ZEND_AST_TRAIT_PRECEDENCE:
2171 zend_ast_export_ex(str, ast->child[0], 0, indent);
2172 smart_str_appends(str, " insteadof ");
2173 zend_ast_export_ex(str, ast->child[1], 0, indent);
2174 break;
2175 case ZEND_AST_METHOD_REFERENCE:
2176 if (ast->child[0]) {
2177 zend_ast_export_name(str, ast->child[0], 0, indent);
2178 smart_str_appends(str, "::");
2179 }
2180 zend_ast_export_name(str, ast->child[1], 0, indent);
2181 break;
2182 case ZEND_AST_NAMESPACE:
2183 smart_str_appends(str, "namespace");
2184 if (ast->child[0]) {
2185 smart_str_appendc(str, ' ');
2186 zend_ast_export_name(str, ast->child[0], 0, indent);
2187 }
2188 if (ast->child[1]) {
2189 smart_str_appends(str, " {\n");
2190 zend_ast_export_stmt(str, ast->child[1], indent + 1);
2191 zend_ast_export_indent(str, indent);
2192 smart_str_appends(str, "}\n");
2193 } else {
2194 smart_str_appendc(str, ';');
2195 }
2196 break;
2197 case ZEND_AST_USE_ELEM:
2198 case ZEND_AST_TRAIT_ALIAS:
2199 zend_ast_export_name(str, ast->child[0], 0, indent);
2200 if (ast->attr & ZEND_ACC_PUBLIC) {
2201 smart_str_appends(str, " as public");
2202 } else if (ast->attr & ZEND_ACC_PROTECTED) {
2203 smart_str_appends(str, " as protected");
2204 } else if (ast->attr & ZEND_ACC_PRIVATE) {
2205 smart_str_appends(str, " as private");
2206 } else if (ast->child[1]) {
2207 smart_str_appends(str, " as");
2208 }
2209 if (ast->child[1]) {
2210 smart_str_appendc(str, ' ');
2211 zend_ast_export_name(str, ast->child[1], 0, indent);
2212 }
2213 break;
2214 case ZEND_AST_NAMED_ARG:
2215 smart_str_append(str, zend_ast_get_str(ast->child[0]));
2216 smart_str_appends(str, ": ");
2217 ast = ast->child[1];
2218 goto tail_call;
2219
2220 /* 3 child nodes */
2221 case ZEND_AST_METHOD_CALL:
2222 case ZEND_AST_NULLSAFE_METHOD_CALL:
2223 zend_ast_export_ex(str, ast->child[0], 0, indent);
2224 smart_str_appends(str, ast->kind == ZEND_AST_NULLSAFE_METHOD_CALL ? "?->" : "->");
2225 zend_ast_export_var(str, ast->child[1], 0, indent);
2226 smart_str_appendc(str, '(');
2227 zend_ast_export_ex(str, ast->child[2], 0, indent);
2228 smart_str_appendc(str, ')');
2229 break;
2230 case ZEND_AST_STATIC_CALL:
2231 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
2232 smart_str_appends(str, "::");
2233 zend_ast_export_var(str, ast->child[1], 0, indent);
2234 smart_str_appendc(str, '(');
2235 zend_ast_export_ex(str, ast->child[2], 0, indent);
2236 smart_str_appendc(str, ')');
2237 break;
2238 case ZEND_AST_CONDITIONAL:
2239 if (priority > 100) smart_str_appendc(str, '(');
2240 zend_ast_export_ex(str, ast->child[0], 100, indent);
2241 if (ast->child[1]) {
2242 smart_str_appends(str, " ? ");
2243 zend_ast_export_ex(str, ast->child[1], 101, indent);
2244 smart_str_appends(str, " : ");
2245 } else {
2246 smart_str_appends(str, " ?: ");
2247 }
2248 zend_ast_export_ex(str, ast->child[2], 101, indent);
2249 if (priority > 100) smart_str_appendc(str, ')');
2250 break;
2251
2252 case ZEND_AST_TRY:
2253 smart_str_appends(str, "try {\n");
2254 zend_ast_export_stmt(str, ast->child[0], indent + 1);
2255 zend_ast_export_indent(str, indent);
2256 zend_ast_export_ex(str, ast->child[1], 0, indent);
2257 if (ast->child[2]) {
2258 smart_str_appends(str, "} finally {\n");
2259 zend_ast_export_stmt(str, ast->child[2], indent + 1);
2260 zend_ast_export_indent(str, indent);
2261 }
2262 smart_str_appendc(str, '}');
2263 break;
2264 case ZEND_AST_CATCH:
2265 smart_str_appends(str, "} catch (");
2266 zend_ast_export_catch_name_list(str, zend_ast_get_list(ast->child[0]), indent);
2267 if (ast->child[1]) {
2268 smart_str_appends(str, " $");
2269 zend_ast_export_var(str, ast->child[1], 0, indent);
2270 }
2271 smart_str_appends(str, ") {\n");
2272 zend_ast_export_stmt(str, ast->child[2], indent + 1);
2273 zend_ast_export_indent(str, indent);
2274 break;
2275 case ZEND_AST_PARAM:
2276 if (ast->child[3]) {
2277 zend_ast_export_attributes(str, ast->child[3], indent, 0);
2278 }
2279 if (ast->child[0]) {
2280 zend_ast_export_type(str, ast->child[0], indent);
2281 smart_str_appendc(str, ' ');
2282 }
2283 if (ast->attr & ZEND_PARAM_REF) {
2284 smart_str_appendc(str, '&');
2285 }
2286 if (ast->attr & ZEND_PARAM_VARIADIC) {
2287 smart_str_appends(str, "...");
2288 }
2289 smart_str_appendc(str, '$');
2290 zend_ast_export_name(str, ast->child[1], 0, indent);
2291 APPEND_DEFAULT_VALUE(2);
2292 case ZEND_AST_ENUM_CASE:
2293 if (ast->child[3]) {
2294 zend_ast_export_attributes(str, ast->child[3], indent, 1);
2295 }
2296 smart_str_appends(str, "case ");
2297 zend_ast_export_name(str, ast->child[0], 0, indent);
2298 if (ast->child[1]) {
2299 smart_str_appends(str, " = ");
2300 zend_ast_export_ex(str, ast->child[1], 0, indent);
2301 }
2302 break;
2303
2304 /* 4 child nodes */
2305 case ZEND_AST_FOR:
2306 smart_str_appends(str, "for (");
2307 zend_ast_export_ex(str, ast->child[0], 0, indent);
2308 smart_str_appendc(str, ';');
2309 if (ast->child[1]) {
2310 smart_str_appendc(str, ' ');
2311 zend_ast_export_ex(str, ast->child[1], 0, indent);
2312 }
2313 smart_str_appendc(str, ';');
2314 if (ast->child[2]) {
2315 smart_str_appendc(str, ' ');
2316 zend_ast_export_ex(str, ast->child[2], 0, indent);
2317 }
2318 smart_str_appends(str, ") {\n");
2319 zend_ast_export_stmt(str, ast->child[3], indent + 1);
2320 zend_ast_export_indent(str, indent);
2321 smart_str_appendc(str, '}');
2322 break;
2323 case ZEND_AST_FOREACH:
2324 smart_str_appends(str, "foreach (");
2325 zend_ast_export_ex(str, ast->child[0], 0, indent);
2326 smart_str_appends(str, " as ");
2327 if (ast->child[2]) {
2328 zend_ast_export_ex(str, ast->child[2], 0, indent);
2329 smart_str_appends(str, " => ");
2330 }
2331 zend_ast_export_ex(str, ast->child[1], 0, indent);
2332 smart_str_appends(str, ") {\n");
2333 zend_ast_export_stmt(str, ast->child[3], indent + 1);
2334 zend_ast_export_indent(str, indent);
2335 smart_str_appendc(str, '}');
2336 break;
2337 EMPTY_SWITCH_DEFAULT_CASE();
2338 }
2339 return;
2340
2341 binary_op:
2342 if (priority > p) smart_str_appendc(str, '(');
2343 zend_ast_export_ex(str, ast->child[0], pl, indent);
2344 smart_str_appends(str, op);
2345 zend_ast_export_ex(str, ast->child[1], pr, indent);
2346 if (priority > p) smart_str_appendc(str, ')');
2347 return;
2348
2349 prefix_op:
2350 if (priority > p) smart_str_appendc(str, '(');
2351 smart_str_appends(str, op);
2352 zend_ast_export_ex(str, ast->child[0], pl, indent);
2353 if (priority > p) smart_str_appendc(str, ')');
2354 return;
2355
2356 postfix_op:
2357 if (priority > p) smart_str_appendc(str, '(');
2358 zend_ast_export_ex(str, ast->child[0], pl, indent);
2359 smart_str_appends(str, op);
2360 if (priority > p) smart_str_appendc(str, ')');
2361 return;
2362
2363 func_op:
2364 smart_str_appends(str, op);
2365 smart_str_appendc(str, '(');
2366 zend_ast_export_ex(str, ast->child[0], 0, indent);
2367 smart_str_appendc(str, ')');
2368 return;
2369
2370 append_node_1:
2371 smart_str_appends(str, op);
2372 if (ast->child[0]) {
2373 smart_str_appendc(str, ' ');
2374 ast = ast->child[0];
2375 goto tail_call;
2376 }
2377 return;
2378
2379 append_str:
2380 smart_str_appends(str, op);
2381 return;
2382
2383 append_default_value:
2384 if (ast->child[p]) {
2385 smart_str_appends(str, " = ");
2386 ast = ast->child[p];
2387 goto tail_call;
2388 }
2389 return;
2390 }
2391
zend_ast_export(const char * prefix,zend_ast * ast,const char * suffix)2392 ZEND_API ZEND_COLD zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix)
2393 {
2394 smart_str str = {0};
2395
2396 smart_str_appends(&str, prefix);
2397 zend_ast_export_ex(&str, ast, 0, 0);
2398 smart_str_appends(&str, suffix);
2399 smart_str_0(&str);
2400 return str.s;
2401 }
2402
zend_ast_with_attributes(zend_ast * ast,zend_ast * attr)2403 zend_ast * ZEND_FASTCALL zend_ast_with_attributes(zend_ast *ast, zend_ast *attr)
2404 {
2405 ZEND_ASSERT(attr->kind == ZEND_AST_ATTRIBUTE_LIST);
2406
2407 switch (ast->kind) {
2408 case ZEND_AST_FUNC_DECL:
2409 case ZEND_AST_CLOSURE:
2410 case ZEND_AST_METHOD:
2411 case ZEND_AST_ARROW_FUNC:
2412 ((zend_ast_decl *) ast)->child[4] = attr;
2413 break;
2414 case ZEND_AST_CLASS:
2415 ((zend_ast_decl *) ast)->child[3] = attr;
2416 break;
2417 case ZEND_AST_PROP_GROUP:
2418 ast->child[2] = attr;
2419 break;
2420 case ZEND_AST_PARAM:
2421 case ZEND_AST_ENUM_CASE:
2422 ast->child[3] = attr;
2423 break;
2424 case ZEND_AST_CLASS_CONST_GROUP:
2425 ast->child[1] = attr;
2426 break;
2427 EMPTY_SWITCH_DEFAULT_CASE()
2428 }
2429
2430 return ast;
2431 }
2432