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

Generated by: LCOV version 1.10

Generated at Sat, 29 Aug 2015 10:22:10 +0000 (2 days ago)

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