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