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