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