PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - Zend - zend_ast.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 654 791 82.7 %
Date: 2015-05-21 Functions: 37 37 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Thu, 21 May 2015 19:58:51 +0000 (4 days ago)

Copyright © 2005-2015 The PHP Group
All rights reserved.