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