xref: /PHP-7.0/Zend/zend_ast.c (revision f5951cc8)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2017 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 			if (scope) {
279 				/* class constants may be updated in-place */
280 				if (Z_OPT_CONSTANT_P(zv)) {
281 					if (UNEXPECTED(zval_update_constant_ex(zv, 1, scope) != SUCCESS)) {
282 						ret = FAILURE;
283 						break;
284 					}
285 				}
286 				ZVAL_DUP(result, zv);
287 			} else {
288 				ZVAL_DUP(result, zv);
289 				if (Z_OPT_CONSTANT_P(result)) {
290 					if (UNEXPECTED(zval_update_constant_ex(result, 1, scope) != SUCCESS)) {
291 						ret = FAILURE;
292 						break;
293 					}
294 				}
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 				if (ast->attr == ZEND_DIM_IS) {
436 					zend_fetch_dimension_by_zval_is(&tmp, &op1, &op2, IS_CONST);
437 				} else {
438 					zend_fetch_dimension_by_zval(&tmp, &op1, &op2);
439 				}
440 
441 				if (UNEXPECTED(Z_ISREF(tmp))) {
442 					ZVAL_DUP(result, Z_REFVAL(tmp));
443 				} else {
444 					ZVAL_DUP(result, &tmp);
445 				}
446 				zval_ptr_dtor(&tmp);
447 				zval_dtor(&op1);
448 				zval_dtor(&op2);
449 			}
450 			break;
451 		default:
452 			zend_throw_error(NULL, "Unsupported constant expression");
453 			ret = FAILURE;
454 	}
455 	return ret;
456 }
457 
zend_ast_copy(zend_ast * ast)458 ZEND_API zend_ast *zend_ast_copy(zend_ast *ast)
459 {
460 	if (ast == NULL) {
461 		return NULL;
462 	} else if (ast->kind == ZEND_AST_ZVAL) {
463 		zend_ast_zval *new = emalloc(sizeof(zend_ast_zval));
464 		new->kind = ZEND_AST_ZVAL;
465 		new->attr = ast->attr;
466 		ZVAL_COPY(&new->val, zend_ast_get_zval(ast));
467 		return (zend_ast *) new;
468 	} else if (zend_ast_is_list(ast)) {
469 		zend_ast_list *list = zend_ast_get_list(ast);
470 		zend_ast_list *new = emalloc(zend_ast_list_size(list->children));
471 		uint32_t i;
472 		new->kind = list->kind;
473 		new->attr = list->attr;
474 		new->children = list->children;
475 		for (i = 0; i < list->children; i++) {
476 			new->child[i] = zend_ast_copy(list->child[i]);
477 		}
478 		return (zend_ast *) new;
479 	} else {
480 		uint32_t i, children = zend_ast_get_num_children(ast);
481 		zend_ast *new = emalloc(zend_ast_size(children));
482 		new->kind = ast->kind;
483 		new->attr = ast->attr;
484 		for (i = 0; i < children; i++) {
485 			new->child[i] = zend_ast_copy(ast->child[i]);
486 		}
487 		return new;
488 	}
489 }
490 
zend_ast_destroy_ex(zend_ast * ast,zend_bool free)491 static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
492 	if (!ast) {
493 		return;
494 	}
495 
496 	switch (ast->kind) {
497 		case ZEND_AST_ZVAL:
498 			/* Destroy value without using GC: When opcache moves arrays into SHM it will
499 			 * free the zend_array structure, so references to it from outside the op array
500 			 * become invalid. GC would cause such a reference in the root buffer. */
501 			zval_ptr_dtor_nogc(zend_ast_get_zval(ast));
502 			break;
503 		case ZEND_AST_FUNC_DECL:
504 		case ZEND_AST_CLOSURE:
505 		case ZEND_AST_METHOD:
506 		case ZEND_AST_CLASS:
507 		{
508 			zend_ast_decl *decl = (zend_ast_decl *) ast;
509 			if (decl->name) {
510 			    zend_string_release(decl->name);
511 			}
512 			if (decl->doc_comment) {
513 				zend_string_release(decl->doc_comment);
514 			}
515 			zend_ast_destroy_ex(decl->child[0], free);
516 			zend_ast_destroy_ex(decl->child[1], free);
517 			zend_ast_destroy_ex(decl->child[2], free);
518 			zend_ast_destroy_ex(decl->child[3], free);
519 			break;
520 		}
521 		default:
522 			if (zend_ast_is_list(ast)) {
523 				zend_ast_list *list = zend_ast_get_list(ast);
524 				uint32_t i;
525 				for (i = 0; i < list->children; i++) {
526 					zend_ast_destroy_ex(list->child[i], free);
527 				}
528 			} else {
529 				uint32_t i, children = zend_ast_get_num_children(ast);
530 				for (i = 0; i < children; i++) {
531 					zend_ast_destroy_ex(ast->child[i], free);
532 				}
533 			}
534 	}
535 
536 	if (free) {
537 		efree(ast);
538 	}
539 }
540 
zend_ast_destroy(zend_ast * ast)541 ZEND_API void zend_ast_destroy(zend_ast *ast) {
542 	zend_ast_destroy_ex(ast, 0);
543 }
zend_ast_destroy_and_free(zend_ast * ast)544 ZEND_API void zend_ast_destroy_and_free(zend_ast *ast) {
545 	zend_ast_destroy_ex(ast, 1);
546 }
547 
zend_ast_apply(zend_ast * ast,zend_ast_apply_func fn)548 ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn) {
549 	if (zend_ast_is_list(ast)) {
550 		zend_ast_list *list = zend_ast_get_list(ast);
551 		uint32_t i;
552 		for (i = 0; i < list->children; ++i) {
553 			fn(&list->child[i]);
554 		}
555 	} else {
556 		uint32_t i, children = zend_ast_get_num_children(ast);
557 		for (i = 0; i < children; ++i) {
558 			fn(&ast->child[i]);
559 		}
560 	}
561 }
562 
563 /*
564  * Operator Precendence
565  * ====================
566  * priority  associativity  operators
567  * ----------------------------------
568  *   10     left            include, include_once, eval, require, require_once
569  *   20     left            ,
570  *   30     left            or
571  *   40     left            xor
572  *   50     left            and
573  *   60     right           print
574  *   70     right           yield
575  *   80     right           =>
576  *   85     right           yield from
577  *   90     right           = += -= *= /= .= %= &= |= ^= <<= >>= **=
578  *  100     left            ? :
579  *  110     right           ??
580  *  120     left            ||
581  *  130     left            &&
582  *  140     left            |
583  *  150     left            ^
584  *  160     left            &
585  *  170     non-associative == != === !==
586  *  180     non-associative < <= > >= <=>
587  *  190     left            << >>
588  *  200     left            + - .
589  *  210     left            * / %
590  *  220     right           !
591  *  230     non-associative instanceof
592  *  240     right           + - ++ -- ~ (type) @
593  *  250     right           **
594  *  260     left            [
595  *  270     non-associative clone new
596  */
597 
598 static void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent);
599 
zend_ast_export_str(smart_str * str,zend_string * s)600 static void zend_ast_export_str(smart_str *str, zend_string *s)
601 {
602 	size_t i;
603 
604 	for (i = 0; i < ZSTR_LEN(s); i++) {
605 		unsigned char c = ZSTR_VAL(s)[i];
606 		if (c == '\'' || c == '\\') {
607 			smart_str_appendc(str, '\\');
608 			smart_str_appendc(str, c);
609 		} else {
610 			smart_str_appendc(str, c);
611 		}
612 	}
613 }
614 
zend_ast_export_qstr(smart_str * str,char quote,zend_string * s)615 static void zend_ast_export_qstr(smart_str *str, char quote, zend_string *s)
616 {
617 	size_t i;
618 
619 	for (i = 0; i < ZSTR_LEN(s); i++) {
620 		unsigned char c = ZSTR_VAL(s)[i];
621 		if (c < ' ') {
622 			switch (c) {
623 				case '\n':
624 					smart_str_appends(str, "\\n");
625 					break;
626 				case '\r':
627 					smart_str_appends(str, "\\r");
628 					break;
629 				case '\t':
630 					smart_str_appends(str, "\\t");
631 					break;
632 				case '\f':
633 					smart_str_appends(str, "\\f");
634 					break;
635 				case '\v':
636 					smart_str_appends(str, "\\v");
637 					break;
638 #ifdef ZEND_WIN32
639 				case VK_ESCAPE:
640 #else
641 				case '\e':
642 #endif
643 					smart_str_appends(str, "\\e");
644 					break;
645 				default:
646 					smart_str_appends(str, "\\0");
647 					smart_str_appendc(str, '0' + (c / 8));
648 					smart_str_appendc(str, '0' + (c % 8));
649 					break;
650 			}
651 		} else {
652 			if (c == quote || c == '$' || c == '\\') {
653 				smart_str_appendc(str, '\\');
654 			}
655 			smart_str_appendc(str, c);
656 		}
657 	}
658 }
659 
zend_ast_export_indent(smart_str * str,int indent)660 static void zend_ast_export_indent(smart_str *str, int indent)
661 {
662 	while (indent > 0) {
663 		smart_str_appends(str, "    ");
664 		indent--;
665 	}
666 }
667 
zend_ast_export_name(smart_str * str,zend_ast * ast,int priority,int indent)668 static void zend_ast_export_name(smart_str *str, zend_ast *ast, int priority, int indent)
669 {
670 	if (ast->kind == ZEND_AST_ZVAL) {
671 		zval *zv = zend_ast_get_zval(ast);
672 
673 		if (Z_TYPE_P(zv) == IS_STRING) {
674 			smart_str_append(str, Z_STR_P(zv));
675 			return;
676 		}
677 	}
678 	zend_ast_export_ex(str, ast, priority, indent);
679 }
680 
zend_ast_export_ns_name(smart_str * str,zend_ast * ast,int priority,int indent)681 static void zend_ast_export_ns_name(smart_str *str, zend_ast *ast, int priority, int indent)
682 {
683 	if (ast->kind == ZEND_AST_ZVAL) {
684 		zval *zv = zend_ast_get_zval(ast);
685 
686 		if (Z_TYPE_P(zv) == IS_STRING) {
687 		    if (ast->attr == ZEND_NAME_FQ) {
688 				smart_str_appendc(str, '\\');
689 		    } else if (ast->attr == ZEND_NAME_RELATIVE) {
690 				smart_str_appends(str, "namespace\\");
691 		    }
692 			smart_str_append(str, Z_STR_P(zv));
693 			return;
694 		}
695 	}
696 	zend_ast_export_ex(str, ast, priority, indent);
697 }
698 
zend_ast_valid_var_char(char ch)699 static int zend_ast_valid_var_char(char ch)
700 {
701 	unsigned char c = (unsigned char)ch;
702 
703 	if (c != '_' && c < 127 &&
704 	    (c < '0' || c > '9') &&
705 	    (c < 'A' || c > 'Z') &&
706 	    (c < 'a' || c > 'z')) {
707 		return 0;
708 	}
709 	return 1;
710 }
711 
zend_ast_valid_var_name(const char * s,size_t len)712 static int zend_ast_valid_var_name(const char *s, size_t len)
713 {
714 	unsigned char c;
715 	size_t i;
716 
717 	if (len == 0) {
718 		return 0;
719 	}
720 	c = (unsigned char)s[0];
721 	if (c != '_' && c < 127 &&
722 	    (c < 'A' || c > 'Z') &&
723 	    (c < 'a' || c > 'z')) {
724 		return 0;
725 	}
726 	for (i = 1; i < len; i++) {
727 		c = (unsigned char)s[i];
728 		if (c != '_' && c < 127 &&
729 		    (c < '0' || c > '9') &&
730 		    (c < 'A' || c > 'Z') &&
731 		    (c < 'a' || c > 'z')) {
732 			return 0;
733 		}
734 	}
735 	return 1;
736 }
737 
zend_ast_export_var(smart_str * str,zend_ast * ast,int priority,int indent)738 static void zend_ast_export_var(smart_str *str, zend_ast *ast, int priority, int indent)
739 {
740 	if (ast->kind == ZEND_AST_ZVAL) {
741 		zval *zv = zend_ast_get_zval(ast);
742 		if (Z_TYPE_P(zv) == IS_STRING &&
743 		    zend_ast_valid_var_name(Z_STRVAL_P(zv), Z_STRLEN_P(zv))) {
744 			smart_str_append(str, Z_STR_P(zv));
745 			return;
746 		}
747 	} else if (ast->kind == ZEND_AST_VAR) {
748 		zend_ast_export_ex(str, ast, 0, indent);
749 		return;
750 	}
751 	smart_str_appendc(str, '{');
752 	zend_ast_export_name(str, ast, 0, indent);
753 	smart_str_appendc(str, '}');
754 }
755 
zend_ast_export_list(smart_str * str,zend_ast_list * list,int separator,int priority,int indent)756 static void zend_ast_export_list(smart_str *str, zend_ast_list *list, int separator, int priority, int indent)
757 {
758 	uint32_t i = 0;
759 
760 	while (i < list->children) {
761 		if (i != 0 && separator) {
762 			smart_str_appends(str, ", ");
763 		}
764 		zend_ast_export_ex(str, list->child[i], priority, indent);
765 		i++;
766 	}
767 }
768 
zend_ast_export_encaps_list(smart_str * str,char quote,zend_ast_list * list,int indent)769 static void zend_ast_export_encaps_list(smart_str *str, char quote, zend_ast_list *list, int indent)
770 {
771 	uint32_t i = 0;
772 	zend_ast *ast;
773 
774 	while (i < list->children) {
775 		ast = list->child[i];
776 		if (ast->kind == ZEND_AST_ZVAL) {
777 			zval *zv = zend_ast_get_zval(ast);
778 
779 			ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
780 			zend_ast_export_qstr(str, quote, Z_STR_P(zv));
781 		} else if (ast->kind == ZEND_AST_VAR &&
782 		           ast->child[0]->kind == ZEND_AST_ZVAL &&
783 		           (i + 1 == list->children ||
784 		            list->child[i + 1]->kind != ZEND_AST_ZVAL ||
785 		            !zend_ast_valid_var_char(
786 		                *Z_STRVAL_P(
787 		                    zend_ast_get_zval(list->child[i + 1]))))) {
788 			zend_ast_export_ex(str, ast, 0, indent);
789 		} else {
790 			smart_str_appendc(str, '{');
791 			zend_ast_export_ex(str, ast, 0, indent);
792 			smart_str_appendc(str, '}');
793 		}
794 		i++;
795 	}
796 }
797 
zend_ast_export_name_list(smart_str * str,zend_ast_list * list,int indent)798 static void zend_ast_export_name_list(smart_str *str, zend_ast_list *list, int indent)
799 {
800 	uint32_t i = 0;
801 
802 	while (i < list->children) {
803 		if (i != 0) {
804 			smart_str_appends(str, ", ");
805 		}
806 		zend_ast_export_name(str, list->child[i], 0, indent);
807 		i++;
808 	}
809 }
810 
zend_ast_export_var_list(smart_str * str,zend_ast_list * list,int indent)811 static void zend_ast_export_var_list(smart_str *str, zend_ast_list *list, int indent)
812 {
813 	uint32_t i = 0;
814 
815 	while (i < list->children) {
816 		if (i != 0) {
817 			smart_str_appends(str, ", ");
818 		}
819 		if (list->child[i]->attr) {
820 			smart_str_appendc(str, '&');
821 		}
822 		smart_str_appendc(str, '$');
823 		zend_ast_export_name(str, list->child[i], 20, indent);
824 		i++;
825 	}
826 }
827 
zend_ast_export_stmt(smart_str * str,zend_ast * ast,int indent)828 static void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int indent)
829 {
830 	if (!ast) {
831 		return;
832 	}
833 
834 	if (ast->kind == ZEND_AST_STMT_LIST ||
835 	    ast->kind == ZEND_AST_TRAIT_ADAPTATIONS) {
836 		zend_ast_list *list = (zend_ast_list*)ast;
837 		uint32_t i = 0;
838 
839 		while (i < list->children) {
840 			ast = list->child[i];
841 			zend_ast_export_stmt(str, ast, indent);
842 			i++;
843 		}
844 	} else {
845 		zend_ast_export_indent(str, indent);
846 		zend_ast_export_ex(str, ast, 0, indent);
847 		switch (ast->kind) {
848 			case ZEND_AST_LABEL:
849 			case ZEND_AST_IF:
850 			case ZEND_AST_SWITCH:
851 			case ZEND_AST_WHILE:
852 			case ZEND_AST_TRY:
853 			case ZEND_AST_FOR:
854 			case ZEND_AST_FOREACH:
855 			case ZEND_AST_FUNC_DECL:
856 			case ZEND_AST_METHOD:
857 			case ZEND_AST_CLASS:
858 			case ZEND_AST_USE_TRAIT:
859 			case ZEND_AST_NAMESPACE:
860 			case ZEND_AST_DECLARE:
861 				break;
862 			default:
863 				smart_str_appendc(str, ';');
864 				break;
865 		}
866 		smart_str_appendc(str, '\n');
867 	}
868 }
869 
zend_ast_export_if_stmt(smart_str * str,zend_ast_list * list,int indent)870 static void zend_ast_export_if_stmt(smart_str *str, zend_ast_list *list, int indent)
871 {
872 	uint32_t i;
873 	zend_ast *ast;
874 
875 tail_call:
876 	i = 0;
877 	while (i < list->children) {
878 		ast = list->child[i];
879 		ZEND_ASSERT(ast->kind == ZEND_AST_IF_ELEM);
880 		if (ast->child[0]) {
881 			if (i == 0) {
882 				smart_str_appends(str, "if (");
883 			} else {
884 				zend_ast_export_indent(str, indent);
885 				smart_str_appends(str, "} elseif (");
886 			}
887 			zend_ast_export_ex(str, ast->child[0], 0, indent);
888 			smart_str_appends(str, ") {\n");
889 			zend_ast_export_stmt(str, ast->child[1], indent + 1);
890 		} else {
891 			zend_ast_export_indent(str, indent);
892 			smart_str_appends(str, "} else ");
893 			if (ast->child[1]->kind == ZEND_AST_IF) {
894 				list = (zend_ast_list*)ast->child[1];
895 				goto tail_call;
896 			} else {
897 				smart_str_appends(str, "{\n");
898 				zend_ast_export_stmt(str, ast->child[1], indent + 1);
899 			}
900 		}
901 		i++;
902 	}
903 	zend_ast_export_indent(str, indent);
904 	smart_str_appendc(str, '}');
905 }
906 
zend_ast_export_zval(smart_str * str,zval * zv,int priority,int indent)907 static void zend_ast_export_zval(smart_str *str, zval *zv, int priority, int indent)
908 {
909 	zend_long idx;
910 	zend_string *key;
911 	zval *val;
912 	int first;
913 
914 	ZVAL_DEREF(zv);
915 	switch (Z_TYPE_P(zv)) {
916 		case IS_NULL:
917 			smart_str_appends(str, "null");
918 			break;
919 		case IS_FALSE:
920 			smart_str_appends(str, "false");
921 			break;
922 		case IS_TRUE:
923 			smart_str_appends(str, "true");
924 			break;
925 		case IS_LONG:
926 			smart_str_append_long(str, Z_LVAL_P(zv));
927 			break;
928 		case IS_DOUBLE:
929 			key = zend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(zv));
930 			smart_str_appendl(str, ZSTR_VAL(key), ZSTR_LEN(key));
931 			zend_string_release(key);
932 			break;
933 		case IS_STRING:
934 			smart_str_appendc(str, '\'');
935 			zend_ast_export_str(str, Z_STR_P(zv));
936 			smart_str_appendc(str, '\'');
937 			break;
938 		case IS_ARRAY:
939 			smart_str_appendc(str, '[');
940 			first = 1;
941 			ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(zv), idx, key, val) {
942 				if (first) {
943 					first = 0;
944 				} else {
945 					smart_str_appends(str, ", ");
946 				}
947 				if (key) {
948 					smart_str_appendc(str, '\'');
949 					zend_ast_export_str(str, key);
950 					smart_str_appends(str, "' => ");
951 				} else {
952 					smart_str_append_long(str, idx);
953 					smart_str_appends(str, " => ");
954 				}
955 				zend_ast_export_zval(str, val, 0, indent);
956 			} ZEND_HASH_FOREACH_END();
957 			smart_str_appendc(str, ']');
958 			break;
959 		case IS_CONSTANT:
960 			smart_str_appendl(str, Z_STRVAL_P(zv), Z_STRLEN_P(zv));
961 			break;
962 		case IS_CONSTANT_AST:
963 			zend_ast_export_ex(str, Z_ASTVAL_P(zv), priority, indent);
964 			break;
965 		EMPTY_SWITCH_DEFAULT_CASE();
966 	}
967 }
968 
zend_ast_export_class_no_header(smart_str * str,zend_ast_decl * decl,int indent)969 static void zend_ast_export_class_no_header(smart_str *str, zend_ast_decl *decl, int indent) {
970 	if (decl->child[0]) {
971 		smart_str_appends(str, " extends ");
972 		zend_ast_export_ns_name(str, decl->child[0], 0, indent);
973 	}
974 	if (decl->child[1]) {
975 		smart_str_appends(str, " implements ");
976 		zend_ast_export_ex(str, decl->child[1], 0, indent);
977 	}
978 	smart_str_appends(str, " {\n");
979 	zend_ast_export_stmt(str, decl->child[2], indent + 1);
980 	zend_ast_export_indent(str, indent);
981 	smart_str_appends(str, "}");
982 }
983 
984 #define BINARY_OP(_op, _p, _pl, _pr) do { \
985 		op = _op; \
986 		p = _p; \
987 		pl = _pl; \
988 		pr = _pr; \
989 		goto binary_op; \
990 	} while (0)
991 
992 #define PREFIX_OP(_op, _p, _pl) do { \
993 		op = _op; \
994 		p = _p; \
995 		pl = _pl; \
996 		goto prefix_op; \
997 	} while (0)
998 
999 #define FUNC_OP(_op) do { \
1000 		op = _op; \
1001 		goto func_op; \
1002 	} while (0)
1003 
1004 #define POSTFIX_OP(_op, _p, _pl) do { \
1005 		op = _op; \
1006 		p = _p; \
1007 		pl = _pl; \
1008 		goto postfix_op; \
1009 	} while (0)
1010 
1011 #define APPEND_NODE_1(_op) do { \
1012 		op = _op; \
1013 		goto append_node_1; \
1014 	} while (0)
1015 
1016 #define APPEND_STR(_op) do { \
1017 		op = _op; \
1018 		goto append_str; \
1019 	} while (0)
1020 
1021 #define APPEND_DEFAULT_VALUE(n) do { \
1022 		p = n; \
1023 		goto append_default_value; \
1024 	} while (0)
1025 
zend_ast_export_ex(smart_str * str,zend_ast * ast,int priority,int indent)1026 static void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent)
1027 {
1028 	zend_ast_decl *decl;
1029 	int p, pl, pr;
1030 	const char *op;
1031 
1032 tail_call:
1033 	if (!ast) {
1034 		return;
1035 	}
1036 	switch (ast->kind) {
1037 		/* special nodes */
1038 		case ZEND_AST_ZVAL:
1039 			zend_ast_export_zval(str, zend_ast_get_zval(ast), priority, indent);
1040 			break;
1041 		case ZEND_AST_ZNODE:
1042 			/* This AST kind is only used for temporary nodes during compilation */
1043 			ZEND_ASSERT(0);
1044 			break;
1045 
1046 		/* declaration nodes */
1047 		case ZEND_AST_FUNC_DECL:
1048 		case ZEND_AST_CLOSURE:
1049 		case ZEND_AST_METHOD:
1050 			decl = (zend_ast_decl *) ast;
1051 			if (decl->flags & ZEND_ACC_PUBLIC) {
1052 				smart_str_appends(str, "public ");
1053 			} else if (decl->flags & ZEND_ACC_PROTECTED) {
1054 				smart_str_appends(str, "protected ");
1055 			} else if (decl->flags & ZEND_ACC_PRIVATE) {
1056 				smart_str_appends(str, "private ");
1057 			}
1058 			if (decl->flags & ZEND_ACC_STATIC) {
1059 				smart_str_appends(str, "static ");
1060 			}
1061 			if (decl->flags & ZEND_ACC_ABSTRACT) {
1062 				smart_str_appends(str, "abstract ");
1063 			}
1064 			if (decl->flags & ZEND_ACC_FINAL) {
1065 				smart_str_appends(str, "final ");
1066 			}
1067 			smart_str_appends(str, "function ");
1068 			if (decl->flags & ZEND_ACC_RETURN_REFERENCE) {
1069 				smart_str_appendc(str, '&');
1070 			}
1071 			if (ast->kind != ZEND_AST_CLOSURE) {
1072 				smart_str_appendl(str, ZSTR_VAL(decl->name), ZSTR_LEN(decl->name));
1073 			}
1074 			smart_str_appendc(str, '(');
1075 			zend_ast_export_ex(str, decl->child[0], 0, indent);
1076 			smart_str_appendc(str, ')');
1077 			zend_ast_export_ex(str, decl->child[1], 0, indent);
1078 			if (decl->child[3]) {
1079 				smart_str_appends(str, ": ");
1080 				zend_ast_export_ns_name(str, decl->child[3], 0, indent);
1081 			}
1082 			if (decl->child[2]) {
1083 				smart_str_appends(str, " {\n");
1084 				zend_ast_export_stmt(str, decl->child[2], indent + 1);
1085 				zend_ast_export_indent(str, indent);
1086 				smart_str_appendc(str, '}');
1087 				if (ast->kind != ZEND_AST_CLOSURE) {
1088 					smart_str_appendc(str, '\n');
1089 				}
1090 			} else {
1091 				smart_str_appends(str, ";\n");
1092 			}
1093 			break;
1094 		case ZEND_AST_CLASS:
1095 			decl = (zend_ast_decl *) ast;
1096 			if (decl->flags & ZEND_ACC_INTERFACE) {
1097 				smart_str_appends(str, "interface ");
1098 			} else if (decl->flags & ZEND_ACC_TRAIT) {
1099 				smart_str_appends(str, "trait ");
1100 			} else {
1101 				if (decl->flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
1102 					smart_str_appends(str, "abstract ");
1103 				}
1104 				if (decl->flags & ZEND_ACC_FINAL) {
1105 					smart_str_appends(str, "final ");
1106 				}
1107 				smart_str_appends(str, "class ");
1108 			}
1109 			smart_str_appendl(str, ZSTR_VAL(decl->name), ZSTR_LEN(decl->name));
1110 			zend_ast_export_class_no_header(str, decl, indent);
1111 			smart_str_appendc(str, '\n');
1112 			break;
1113 
1114 		/* list nodes */
1115 		case ZEND_AST_ARG_LIST:
1116 		case ZEND_AST_EXPR_LIST:
1117 		case ZEND_AST_PARAM_LIST:
1118 simple_list:
1119 			zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
1120 			break;
1121 		case ZEND_AST_LIST:
1122 			smart_str_appends(str, "list(");
1123 			zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
1124 			smart_str_appendc(str, ')');
1125 			break;
1126 		case ZEND_AST_ARRAY:
1127 			smart_str_appendc(str, '[');
1128 			zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
1129 			smart_str_appendc(str, ']');
1130 			break;
1131 		case ZEND_AST_ENCAPS_LIST:
1132 			smart_str_appendc(str, '"');
1133 			zend_ast_export_encaps_list(str, '"', (zend_ast_list*)ast, indent);
1134 			smart_str_appendc(str, '"');
1135 			break;
1136 		case ZEND_AST_STMT_LIST:
1137 		case ZEND_AST_TRAIT_ADAPTATIONS:
1138 			zend_ast_export_stmt(str, ast, indent);
1139 			break;
1140 		case ZEND_AST_IF:
1141 			zend_ast_export_if_stmt(str, (zend_ast_list*)ast, indent);
1142 			break;
1143 		case ZEND_AST_SWITCH_LIST:
1144 		case ZEND_AST_CATCH_LIST:
1145 			zend_ast_export_list(str, (zend_ast_list*)ast, 0, 0, indent);
1146 			break;
1147 		case ZEND_AST_CLOSURE_USES:
1148 			smart_str_appends(str, " use(");
1149 			zend_ast_export_var_list(str, (zend_ast_list*)ast, indent);
1150 			smart_str_appendc(str, ')');
1151 			break;
1152 		case ZEND_AST_PROP_DECL:
1153 			if (ast->attr & ZEND_ACC_PUBLIC) {
1154 				smart_str_appends(str, "public ");
1155 			} else if (ast->attr & ZEND_ACC_PROTECTED) {
1156 				smart_str_appends(str, "protected ");
1157 			} else if (ast->attr & ZEND_ACC_PRIVATE) {
1158 				smart_str_appends(str, "private ");
1159 			}
1160 			if (ast->attr & ZEND_ACC_STATIC) {
1161 				smart_str_appends(str, "static ");
1162 			}
1163 			goto simple_list;
1164 		case ZEND_AST_CONST_DECL:
1165 		case ZEND_AST_CLASS_CONST_DECL:
1166 			smart_str_appends(str, "const ");
1167 			goto simple_list;
1168 		case ZEND_AST_NAME_LIST:
1169 			zend_ast_export_name_list(str, (zend_ast_list*)ast, indent);
1170 			break;
1171 		case ZEND_AST_USE:
1172 			smart_str_appends(str, "use ");
1173 			if (ast->attr == T_FUNCTION) {
1174 				smart_str_appends(str, "function ");
1175 			} else if (ast->attr == T_CONST) {
1176 				smart_str_appends(str, "const ");
1177 			}
1178 			goto simple_list;
1179 
1180 		/* 0 child nodes */
1181 		case ZEND_AST_MAGIC_CONST:
1182 			switch (ast->attr) {
1183 				case T_LINE:     APPEND_STR("__LINE__");
1184 				case T_FILE:     APPEND_STR("__FILE__");
1185 				case T_DIR:      APPEND_STR("__DIR__");
1186 				case T_TRAIT_C:  APPEND_STR("__TRAIT__");
1187 				case T_METHOD_C: APPEND_STR("__METHOD__");
1188 				case T_FUNC_C:   APPEND_STR("__FUNCTION__");
1189 				case T_NS_C:     APPEND_STR("__NAMESPACE__");
1190 				case T_CLASS_C:  APPEND_STR("__CLASS__");
1191 				EMPTY_SWITCH_DEFAULT_CASE();
1192 			}
1193 			break;
1194 		case ZEND_AST_TYPE:
1195 			switch (ast->attr) {
1196 				case IS_ARRAY:    APPEND_STR("array");
1197 				case IS_CALLABLE: APPEND_STR("callable");
1198 				EMPTY_SWITCH_DEFAULT_CASE();
1199 			}
1200 			break;
1201 
1202 		/* 1 child node */
1203 		case ZEND_AST_VAR:
1204 			smart_str_appendc(str, '$');
1205 			zend_ast_export_var(str, ast->child[0], 0, indent);
1206 			break;
1207 		case ZEND_AST_CONST:
1208 			zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1209 			break;
1210 		case ZEND_AST_UNPACK:
1211 			smart_str_appends(str, "...");
1212 			ast = ast->child[0];
1213 			goto tail_call;
1214 		case ZEND_AST_UNARY_PLUS:  PREFIX_OP("+", 240, 241);
1215 		case ZEND_AST_UNARY_MINUS: PREFIX_OP("-", 240, 241);
1216 		case ZEND_AST_CAST:
1217 			switch (ast->attr) {
1218 				case IS_NULL:      PREFIX_OP("(unset)",  240, 241);
1219 				case _IS_BOOL:     PREFIX_OP("(bool)",   240, 241);
1220 				case IS_LONG:      PREFIX_OP("(int)",    240, 241);
1221 				case IS_DOUBLE:    PREFIX_OP("(double)", 240, 241);
1222 				case IS_STRING:    PREFIX_OP("(string)", 240, 241);
1223 				case IS_ARRAY:     PREFIX_OP("(array)",  240, 241);
1224 				case IS_OBJECT:    PREFIX_OP("(object)", 240, 241);
1225 				EMPTY_SWITCH_DEFAULT_CASE();
1226 			}
1227 			break;
1228 		case ZEND_AST_EMPTY:
1229 			FUNC_OP("empty");
1230 		case ZEND_AST_ISSET:
1231 			FUNC_OP("isset");
1232 		case ZEND_AST_SILENCE:
1233 			PREFIX_OP("@", 240, 241);
1234 		case ZEND_AST_SHELL_EXEC:
1235 			smart_str_appendc(str, '`');
1236 			if (ast->child[0]->kind == ZEND_AST_ENCAPS_LIST) {
1237 				zend_ast_export_encaps_list(str, '`', (zend_ast_list*)ast->child[0], indent);
1238 			} else {
1239 				zval *zv;
1240 				ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_ZVAL);
1241 				zv = zend_ast_get_zval(ast->child[0]);
1242 				ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
1243 				zend_ast_export_qstr(str, '`', Z_STR_P(zv));
1244 			}
1245 			smart_str_appendc(str, '`');
1246 			break;
1247 		case ZEND_AST_CLONE:
1248 			PREFIX_OP("clone ", 270, 271);
1249 		case ZEND_AST_EXIT:
1250 			if (ast->child[0]) {
1251 				FUNC_OP("exit");
1252 			} else {
1253 				APPEND_STR("exit");
1254 			}
1255 			break;
1256 		case ZEND_AST_PRINT:
1257 			PREFIX_OP("print ", 60, 61);
1258 		case ZEND_AST_INCLUDE_OR_EVAL:
1259 			switch (ast->attr) {
1260 				case ZEND_INCLUDE_ONCE: FUNC_OP("include_once");
1261 				case ZEND_INCLUDE:      FUNC_OP("include");
1262 				case ZEND_REQUIRE_ONCE: FUNC_OP("require_once");
1263 				case ZEND_REQUIRE:      FUNC_OP("require");
1264 				case ZEND_EVAL:         FUNC_OP("eval");
1265 				EMPTY_SWITCH_DEFAULT_CASE();
1266 			}
1267 			break;
1268 		case ZEND_AST_UNARY_OP:
1269 			switch (ast->attr) {
1270 				case ZEND_BW_NOT:   PREFIX_OP("~", 240, 241);
1271 				case ZEND_BOOL_NOT: PREFIX_OP("!", 240, 241);
1272 				EMPTY_SWITCH_DEFAULT_CASE();
1273 			}
1274 			break;
1275 		case ZEND_AST_PRE_INC:
1276 			PREFIX_OP("++", 240, 241);
1277 		case ZEND_AST_PRE_DEC:
1278 			PREFIX_OP("--", 240, 241);
1279 		case ZEND_AST_POST_INC:
1280 			POSTFIX_OP("++", 240, 241);
1281 		case ZEND_AST_POST_DEC:
1282 			POSTFIX_OP("--", 240, 241);
1283 
1284 		case ZEND_AST_GLOBAL:
1285 			APPEND_NODE_1("global");
1286 		case ZEND_AST_UNSET:
1287 			FUNC_OP("unset");
1288 		case ZEND_AST_RETURN:
1289 			APPEND_NODE_1("return");
1290 		case ZEND_AST_LABEL:
1291 			zend_ast_export_name(str, ast->child[0], 0, indent);
1292 			smart_str_appendc(str, ':');
1293 			break;
1294 		case ZEND_AST_REF:
1295 			smart_str_appendc(str, '&');
1296 			ast = ast->child[0];
1297 			goto tail_call;
1298 		case ZEND_AST_HALT_COMPILER:
1299 			APPEND_STR("__HALT_COMPILER()");
1300 		case ZEND_AST_ECHO:
1301 			APPEND_NODE_1("echo");
1302 		case ZEND_AST_THROW:
1303 			APPEND_NODE_1("throw");
1304 		case ZEND_AST_GOTO:
1305 			smart_str_appends(str, "goto ");
1306 			zend_ast_export_name(str, ast->child[0], 0, indent);
1307 			break;
1308 		case ZEND_AST_BREAK:
1309 			APPEND_NODE_1("break");
1310 		case ZEND_AST_CONTINUE:
1311 			APPEND_NODE_1("continue");
1312 
1313 		/* 2 child nodes */
1314 		case ZEND_AST_DIM:
1315 			zend_ast_export_ex(str, ast->child[0], 260, indent);
1316 			smart_str_appendc(str, '[');
1317 			if (ast->child[1]) {
1318 				zend_ast_export_ex(str, ast->child[1], 0, indent);
1319 			}
1320 			smart_str_appendc(str, ']');
1321 			break;
1322 		case ZEND_AST_PROP:
1323 			zend_ast_export_ex(str, ast->child[0], 0, indent);
1324 			smart_str_appends(str, "->");
1325 			zend_ast_export_var(str, ast->child[1], 0, indent);
1326 			break;
1327 		case ZEND_AST_STATIC_PROP:
1328 			zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1329 			smart_str_appends(str, "::$");
1330 			zend_ast_export_var(str, ast->child[1], 0, indent);
1331 			break;
1332 		case ZEND_AST_CALL:
1333 			zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1334 			smart_str_appendc(str, '(');
1335 			zend_ast_export_ex(str, ast->child[1], 0, indent);
1336 			smart_str_appendc(str, ')');
1337 			break;
1338 		case ZEND_AST_CLASS_CONST:
1339 			zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1340 			smart_str_appends(str, "::");
1341 			zend_ast_export_name(str, ast->child[1], 0, indent);
1342 			break;
1343 		case ZEND_AST_ASSIGN:            BINARY_OP(" = ",   90, 91, 90);
1344 		case ZEND_AST_ASSIGN_REF:        BINARY_OP(" =& ",  90, 91, 90);
1345 		case ZEND_AST_ASSIGN_OP:
1346 			switch (ast->attr) {
1347 				case ZEND_ASSIGN_ADD:    BINARY_OP(" += ",  90, 91, 90);
1348 				case ZEND_ASSIGN_SUB:    BINARY_OP(" -= ",  90, 91, 90);
1349 				case ZEND_ASSIGN_MUL:    BINARY_OP(" *= ",  90, 91, 90);
1350 				case ZEND_ASSIGN_DIV:    BINARY_OP(" /= ",  90, 91, 90);
1351 				case ZEND_ASSIGN_MOD:    BINARY_OP(" %= ",  90, 91, 90);
1352 				case ZEND_ASSIGN_SL:     BINARY_OP(" <<= ", 90, 91, 90);
1353 				case ZEND_ASSIGN_SR:     BINARY_OP(" >>= ", 90, 91, 90);
1354 				case ZEND_ASSIGN_CONCAT: BINARY_OP(" .= ",  90, 91, 90);
1355 				case ZEND_ASSIGN_BW_OR:  BINARY_OP(" |= ",  90, 91, 90);
1356 				case ZEND_ASSIGN_BW_AND: BINARY_OP(" &= ",  90, 91, 90);
1357 				case ZEND_ASSIGN_BW_XOR: BINARY_OP(" ^= ",  90, 91, 90);
1358 				case ZEND_ASSIGN_POW:    BINARY_OP(" **= ", 90, 91, 90);
1359 				EMPTY_SWITCH_DEFAULT_CASE();
1360 			}
1361 			break;
1362 		case ZEND_AST_BINARY_OP:
1363 			switch (ast->attr) {
1364 				case ZEND_ADD:                 BINARY_OP(" + ",   200, 200, 201);
1365 				case ZEND_SUB:                 BINARY_OP(" - ",   200, 200, 201);
1366 				case ZEND_MUL:                 BINARY_OP(" * ",   210, 210, 211);
1367 				case ZEND_DIV:                 BINARY_OP(" / ",   210, 210, 211);
1368 				case ZEND_MOD:                 BINARY_OP(" % ",   210, 210, 211);
1369 				case ZEND_SL:                  BINARY_OP(" << ",  190, 190, 191);
1370 				case ZEND_SR:                  BINARY_OP(" >> ",  190, 190, 191);
1371 				case ZEND_CONCAT:              BINARY_OP(" . ",   200, 200, 201);
1372 				case ZEND_BW_OR:               BINARY_OP(" | ",   140, 140, 141);
1373 				case ZEND_BW_AND:              BINARY_OP(" & ",   160, 160, 161);
1374 				case ZEND_BW_XOR:              BINARY_OP(" ^ ",   150, 150, 151);
1375 				case ZEND_IS_IDENTICAL:        BINARY_OP(" === ", 170, 171, 171);
1376 				case ZEND_IS_NOT_IDENTICAL:    BINARY_OP(" !== ", 170, 171, 171);
1377 				case ZEND_IS_EQUAL:            BINARY_OP(" == ",  170, 171, 171);
1378 				case ZEND_IS_NOT_EQUAL:        BINARY_OP(" != ",  170, 171, 171);
1379 				case ZEND_IS_SMALLER:          BINARY_OP(" < ",   180, 181, 181);
1380 				case ZEND_IS_SMALLER_OR_EQUAL: BINARY_OP(" <= ",  180, 181, 181);
1381 				case ZEND_POW:                 BINARY_OP(" ** ",  250, 251, 250);
1382 				case ZEND_BOOL_XOR:            BINARY_OP(" xor ",  40,  40,  41);
1383 				case ZEND_SPACESHIP:           BINARY_OP(" <=> ", 180, 181, 181);
1384 				EMPTY_SWITCH_DEFAULT_CASE();
1385 			}
1386 			break;
1387 		case ZEND_AST_GREATER:                 BINARY_OP(" > ",   180, 181, 181);
1388 		case ZEND_AST_GREATER_EQUAL:           BINARY_OP(" >= ",  180, 181, 181);
1389 		case ZEND_AST_AND:                     BINARY_OP(" && ",  130, 130, 131);
1390 		case ZEND_AST_OR:                      BINARY_OP(" || ",  120, 120, 121);
1391 		case ZEND_AST_ARRAY_ELEM:
1392 			if (ast->child[1]) {
1393 				zend_ast_export_ex(str, ast->child[1], 80, indent);
1394 				smart_str_appends(str, " => ");
1395 			}
1396 			zend_ast_export_ex(str, ast->child[0], 80, indent);
1397 			break;
1398 		case ZEND_AST_NEW:
1399 			smart_str_appends(str, "new ");
1400 			if (ast->child[0]->kind == ZEND_AST_CLASS) {
1401 				smart_str_appends(str, "class");
1402 				if (zend_ast_get_list(ast->child[1])->children) {
1403 					smart_str_appendc(str, '(');
1404 					zend_ast_export_ex(str, ast->child[1], 0, indent);
1405 					smart_str_appendc(str, ')');
1406 				}
1407 				zend_ast_export_class_no_header(str, (zend_ast_decl *) ast->child[0], indent);
1408 			} else {
1409 				zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1410 				smart_str_appendc(str, '(');
1411 				zend_ast_export_ex(str, ast->child[1], 0, indent);
1412 				smart_str_appendc(str, ')');
1413 			}
1414 			break;
1415 		case ZEND_AST_INSTANCEOF:
1416 			zend_ast_export_ex(str, ast->child[0], 0, indent);
1417 			smart_str_appends(str, " instanceof ");
1418 			zend_ast_export_ns_name(str, ast->child[1], 0, indent);
1419 			break;
1420 		case ZEND_AST_YIELD:
1421 			if (priority > 70) smart_str_appendc(str, '(');
1422 			smart_str_appends(str, "yield ");
1423 			if (ast->child[0]) {
1424 				if (ast->child[1]) {
1425 					zend_ast_export_ex(str, ast->child[1], 70, indent);
1426 					smart_str_appends(str, " => ");
1427 				}
1428 				zend_ast_export_ex(str, ast->child[0], 70, indent);
1429 			}
1430 			if (priority > 70) smart_str_appendc(str, ')');
1431 			break;
1432 		case ZEND_AST_YIELD_FROM:
1433 			PREFIX_OP("yield from ", 85, 86);
1434 		case ZEND_AST_COALESCE: BINARY_OP(" ?? ", 110, 111, 110);
1435 		case ZEND_AST_STATIC:
1436 			smart_str_appends(str, "static $");
1437 			zend_ast_export_name(str, ast->child[0], 0, indent);
1438 			APPEND_DEFAULT_VALUE(1);
1439 		case ZEND_AST_WHILE:
1440 			smart_str_appends(str, "while (");
1441 			zend_ast_export_ex(str, ast->child[0], 0, indent);
1442 			smart_str_appends(str, ") {\n");
1443 			zend_ast_export_stmt(str, ast->child[1], indent + 1);
1444 			zend_ast_export_indent(str, indent);
1445 			smart_str_appendc(str, '}');
1446 			break;
1447 		case ZEND_AST_DO_WHILE:
1448 			smart_str_appends(str, "do {\n");
1449 			zend_ast_export_stmt(str, ast->child[0], indent + 1);
1450 			zend_ast_export_indent(str, indent);
1451 			smart_str_appends(str, "} while (");
1452 			zend_ast_export_ex(str, ast->child[1], 0, indent);
1453 			smart_str_appendc(str, ')');
1454 			break;
1455 
1456 		case ZEND_AST_IF_ELEM:
1457 			if (ast->child[0]) {
1458 				smart_str_appends(str, "if (");
1459 				zend_ast_export_ex(str, ast->child[0], 0, indent);
1460 				smart_str_appends(str, ") {\n");
1461 				zend_ast_export_stmt(str, ast->child[1], indent + 1);
1462 			} else {
1463 				smart_str_appends(str, "else {\n");
1464 				zend_ast_export_stmt(str, ast->child[1], indent + 1);
1465 			}
1466 			zend_ast_export_indent(str, indent);
1467 			smart_str_appendc(str, '}');
1468 			break;
1469 		case ZEND_AST_SWITCH:
1470 			smart_str_appends(str, "switch (");
1471 			zend_ast_export_ex(str, ast->child[0], 0, indent);
1472 			smart_str_appends(str, ") {\n");
1473 			zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
1474 			zend_ast_export_indent(str, indent);
1475 			smart_str_appendc(str, '}');
1476 			break;
1477 		case ZEND_AST_SWITCH_CASE:
1478 			zend_ast_export_indent(str, indent);
1479 			if (ast->child[0]) {
1480 				smart_str_appends(str, "case ");
1481 				zend_ast_export_ex(str, ast->child[0], 0, indent);
1482 				smart_str_appends(str, ":\n");
1483 			} else {
1484 				smart_str_appends(str, "default:\n");
1485 			}
1486 			zend_ast_export_stmt(str, ast->child[1], indent + 1);
1487 			break;
1488 		case ZEND_AST_DECLARE:
1489 			smart_str_appends(str, "declare(");
1490 			ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_CONST_DECL);
1491 			zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent);
1492 			smart_str_appendc(str, ')');
1493 			if (ast->child[1]) {
1494 				smart_str_appends(str, " {\n");
1495 				zend_ast_export_stmt(str, ast->child[1], indent + 1);
1496 				zend_ast_export_indent(str, indent);
1497 				smart_str_appendc(str, '}');
1498 			} else {
1499 				smart_str_appendc(str, ';');
1500 			}
1501 			break;
1502 		case ZEND_AST_PROP_ELEM:
1503 			smart_str_appendc(str, '$');
1504 			/* break missing intentionally */
1505 		case ZEND_AST_CONST_ELEM:
1506 			zend_ast_export_name(str, ast->child[0], 0, indent);
1507 			APPEND_DEFAULT_VALUE(1);
1508 		case ZEND_AST_USE_TRAIT:
1509 			smart_str_appends(str, "use ");
1510 			zend_ast_export_ex(str, ast->child[0], 0, indent);
1511 			if (ast->child[1]) {
1512 				smart_str_appends(str, " {\n");
1513 				zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
1514 				zend_ast_export_indent(str, indent);
1515 				smart_str_appends(str, "}");
1516 			} else {
1517 				smart_str_appends(str, ";");
1518 			}
1519 			break;
1520 		case ZEND_AST_TRAIT_PRECEDENCE:
1521 			zend_ast_export_ex(str, ast->child[0], 0, indent);
1522 			smart_str_appends(str, " insteadof ");
1523 			zend_ast_export_ex(str, ast->child[1], 0, indent);
1524 			break;
1525 		case ZEND_AST_METHOD_REFERENCE:
1526 			if (ast->child[0]) {
1527 				zend_ast_export_name(str, ast->child[0], 0, indent);
1528 				smart_str_appends(str, "::");
1529 			}
1530 			zend_ast_export_name(str, ast->child[1], 0, indent);
1531 			break;
1532 		case ZEND_AST_NAMESPACE:
1533 			smart_str_appends(str, "namespace");
1534 			if (ast->child[0]) {
1535 				smart_str_appendc(str, ' ');
1536 				zend_ast_export_name(str, ast->child[0], 0, indent);
1537 			}
1538 			if (ast->child[1]) {
1539 				smart_str_appends(str, " {\n");
1540 				zend_ast_export_stmt(str, ast->child[1], indent + 1);
1541 				zend_ast_export_indent(str, indent);
1542 				smart_str_appends(str, "}\n");
1543 			} else {
1544 				smart_str_appendc(str, ';');
1545 			}
1546 			break;
1547 		case ZEND_AST_USE_ELEM:
1548 		case ZEND_AST_TRAIT_ALIAS:
1549 			zend_ast_export_name(str, ast->child[0], 0, indent);
1550 			if (ast->attr & ZEND_ACC_PUBLIC) {
1551 				smart_str_appends(str, " as public");
1552 			} else if (ast->attr & ZEND_ACC_PROTECTED) {
1553 				smart_str_appends(str, " as protected");
1554 			} else if (ast->attr & ZEND_ACC_PRIVATE) {
1555 				smart_str_appends(str, " as private");
1556 			} else if (ast->child[1]) {
1557 				smart_str_appends(str, " as");
1558 			}
1559 			if (ast->child[1]) {
1560 				smart_str_appendc(str, ' ');
1561 				zend_ast_export_name(str, ast->child[1], 0, indent);
1562 			}
1563 			break;
1564 
1565 		/* 3 child nodes */
1566 		case ZEND_AST_METHOD_CALL:
1567 			zend_ast_export_ex(str, ast->child[0], 0, indent);
1568 			smart_str_appends(str, "->");
1569 			zend_ast_export_var(str, ast->child[1], 0, indent);
1570 			smart_str_appendc(str, '(');
1571 			zend_ast_export_ex(str, ast->child[2], 0, indent);
1572 			smart_str_appendc(str, ')');
1573 			break;
1574 		case ZEND_AST_STATIC_CALL:
1575 			zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1576 			smart_str_appends(str, "::");
1577 			zend_ast_export_var(str, ast->child[1], 0, indent);
1578 			smart_str_appendc(str, '(');
1579 			zend_ast_export_ex(str, ast->child[2], 0, indent);
1580 			smart_str_appendc(str, ')');
1581 			break;
1582 		case ZEND_AST_CONDITIONAL:
1583 			if (priority > 100) smart_str_appendc(str, '(');
1584 			zend_ast_export_ex(str, ast->child[0], 100, indent);
1585 			if (ast->child[1]) {
1586 				smart_str_appends(str, " ? ");
1587 				zend_ast_export_ex(str, ast->child[1], 101, indent);
1588 				smart_str_appends(str, " : ");
1589 			} else {
1590 				smart_str_appends(str, " ?: ");
1591 			}
1592 			zend_ast_export_ex(str, ast->child[2], 101, indent);
1593 			if (priority > 100) smart_str_appendc(str, ')');
1594 			break;
1595 
1596 		case ZEND_AST_TRY:
1597 			smart_str_appends(str, "try {\n");
1598 			zend_ast_export_stmt(str, ast->child[0], indent + 1);
1599 			zend_ast_export_indent(str, indent);
1600 			zend_ast_export_ex(str, ast->child[1], 0, indent);
1601 			if (ast->child[2]) {
1602 				smart_str_appends(str, "} finally {\n");
1603 				zend_ast_export_stmt(str, ast->child[2], indent + 1);
1604 				zend_ast_export_indent(str, indent);
1605 			}
1606 			smart_str_appendc(str, '}');
1607 			break;
1608 		case ZEND_AST_CATCH:
1609 			smart_str_appends(str, "} catch (");
1610 			zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1611 			smart_str_appends(str, " $");
1612 			zend_ast_export_var(str, ast->child[1], 0, indent);
1613 			smart_str_appends(str, ") {\n");
1614 			zend_ast_export_stmt(str, ast->child[2], indent + 1);
1615 			zend_ast_export_indent(str, indent);
1616 			break;
1617 		case ZEND_AST_PARAM:
1618 			if (ast->child[0]) {
1619 				zend_ast_export_ns_name(str, ast->child[0], 0, indent);
1620 				smart_str_appendc(str, ' ');
1621 			}
1622 			if (ast->attr & ZEND_PARAM_REF) {
1623 				smart_str_appendc(str, '&');
1624 			}
1625 			if (ast->attr & ZEND_PARAM_VARIADIC) {
1626 				smart_str_appends(str, "...");
1627 			}
1628 			smart_str_appendc(str, '$');
1629 			zend_ast_export_name(str, ast->child[1], 0, indent);
1630 			APPEND_DEFAULT_VALUE(2);
1631 
1632 		/* 4 child nodes */
1633 		case ZEND_AST_FOR:
1634 			smart_str_appends(str, "for (");
1635 			zend_ast_export_ex(str, ast->child[0], 0, indent);
1636 			smart_str_appendc(str, ';');
1637 			if (ast->child[1]) {
1638 				smart_str_appendc(str, ' ');
1639 				zend_ast_export_ex(str, ast->child[1], 0, indent);
1640 			}
1641 			smart_str_appendc(str, ';');
1642 			if (ast->child[2]) {
1643 				smart_str_appendc(str, ' ');
1644 				zend_ast_export_ex(str, ast->child[2], 0, indent);
1645 			}
1646 			smart_str_appends(str, ") {\n");
1647 			zend_ast_export_stmt(str, ast->child[3], indent + 1);
1648 			zend_ast_export_indent(str, indent);
1649 			smart_str_appendc(str, '}');
1650 			break;
1651 		case ZEND_AST_FOREACH:
1652 			smart_str_appends(str, "foreach (");
1653 			zend_ast_export_ex(str, ast->child[0], 0, indent);
1654 			smart_str_appends(str, " as ");
1655 			if (ast->child[2]) {
1656 				zend_ast_export_ex(str, ast->child[2], 0, indent);
1657 				smart_str_appends(str, " => ");
1658 			}
1659 			zend_ast_export_ex(str, ast->child[1], 0, indent);
1660 			smart_str_appends(str, ") {\n");
1661 			zend_ast_export_stmt(str, ast->child[3], indent + 1);
1662 			zend_ast_export_indent(str, indent);
1663 			smart_str_appendc(str, '}');
1664 			break;
1665 		EMPTY_SWITCH_DEFAULT_CASE();
1666 	}
1667 	return;
1668 
1669 binary_op:
1670 	if (priority > p) smart_str_appendc(str, '(');
1671 	zend_ast_export_ex(str, ast->child[0], pl, indent);
1672 	smart_str_appends(str, op);
1673 	zend_ast_export_ex(str, ast->child[1], pr, indent);
1674 	if (priority > p) smart_str_appendc(str, ')');
1675 	return;
1676 
1677 prefix_op:
1678 	if (priority > p) smart_str_appendc(str, '(');
1679 	smart_str_appends(str, op);
1680 	zend_ast_export_ex(str, ast->child[0], pl, indent);
1681 	if (priority > p) smart_str_appendc(str, ')');
1682 	return;
1683 
1684 postfix_op:
1685 	if (priority > p) smart_str_appendc(str, '(');
1686 	zend_ast_export_ex(str, ast->child[0], pl, indent);
1687 	smart_str_appends(str, op);
1688 	if (priority > p) smart_str_appendc(str, ')');
1689 	return;
1690 
1691 func_op:
1692 	smart_str_appends(str, op);
1693 	smart_str_appendc(str, '(');
1694 	zend_ast_export_ex(str, ast->child[0], 0, indent);
1695 	smart_str_appendc(str, ')');
1696 	return;
1697 
1698 append_node_1:
1699 	smart_str_appends(str, op);
1700 	if (ast->child[0]) {
1701 		smart_str_appendc(str, ' ');
1702 		ast = ast->child[0];
1703 		goto tail_call;
1704 	}
1705 	return;
1706 
1707 append_str:
1708 	smart_str_appends(str, op);
1709 	return;
1710 
1711 append_default_value:
1712 	if (ast->child[p]) {
1713 		smart_str_appends(str, " = ");
1714 		ast = ast->child[p];
1715 		goto tail_call;
1716 	}
1717 	return;
1718 }
1719 
zend_ast_export(const char * prefix,zend_ast * ast,const char * suffix)1720 ZEND_API zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix)
1721 {
1722 	smart_str str = {0};
1723 
1724 	smart_str_appends(&str, prefix);
1725 	zend_ast_export_ex(&str, ast, 0, 0);
1726 	smart_str_appends(&str, suffix);
1727 	smart_str_0(&str);
1728 	return str.s;
1729 }
1730