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: 656 792 82.8 %
Date: 2015-06-27 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     4423000 : static inline void *zend_ast_alloc(size_t size) {
      32     4423000 :         return zend_arena_alloc(&CG(ast_arena), size);
      33             : }
      34             : 
      35       67058 : static inline void *zend_ast_realloc(void *old, size_t old_size, size_t new_size) {
      36       67058 :         void *new = zend_ast_alloc(new_size);
      37       67058 :         memcpy(new, old, old_size);
      38       67058 :         return new;
      39             : }
      40             : 
      41     1896423 : static inline size_t zend_ast_size(uint32_t children) {
      42     1896423 :         return sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
      43             : }
      44             : 
      45      789446 : static inline size_t zend_ast_list_size(uint32_t children) {
      46      789446 :         return sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * children;
      47             : }
      48             : 
      49        7157 : ZEND_API zend_ast *zend_ast_create_znode(znode *node) {
      50             :         zend_ast_znode *ast;
      51             : 
      52        7157 :         ast = zend_ast_alloc(sizeof(zend_ast_znode));
      53        7157 :         ast->kind = ZEND_AST_ZNODE;
      54        7157 :         ast->attr = 0;
      55        7157 :         ast->lineno = CG(zend_lineno);
      56        7157 :         ast->node = *node;
      57        7157 :         return (zend_ast *) ast;
      58             : }
      59             : 
      60     1753667 : ZEND_API zend_ast *zend_ast_create_zval_ex(zval *zv, zend_ast_attr attr) {
      61             :         zend_ast_zval *ast;
      62             : 
      63     1753667 :         ast = zend_ast_alloc(sizeof(zend_ast_zval));
      64     1753667 :         ast->kind = ZEND_AST_ZVAL;
      65     1753667 :         ast->attr = attr;
      66     1753667 :         ZVAL_COPY_VALUE(&ast->val, zv);
      67     1753667 :         ast->val.u2.lineno = CG(zend_lineno);
      68     1753667 :         return (zend_ast *) ast;
      69             : }
      70             : 
      71       43568 : 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       43568 :         ast = zend_ast_alloc(sizeof(zend_ast_decl));
      78       43568 :         ast->kind = kind;
      79       43568 :         ast->attr = 0;
      80       43568 :         ast->start_lineno = start_lineno;
      81       43568 :         ast->end_lineno = CG(zend_lineno);
      82       43568 :         ast->flags = flags;
      83       43568 :         ast->lex_pos = LANG_SCNG(yy_text);
      84       43568 :         ast->doc_comment = doc_comment;
      85       43568 :         ast->name = name;
      86       43568 :         ast->child[0] = child0;
      87       43568 :         ast->child[1] = child1;
      88       43568 :         ast->child[2] = child2;
      89       43568 :         ast->child[3] = child3;
      90             : 
      91       43568 :         return (zend_ast *) ast;
      92             : }
      93             : 
      94     1896293 : static zend_ast *zend_ast_create_from_va_list(zend_ast_kind kind, zend_ast_attr attr, va_list va) {
      95     1896293 :         uint32_t i, children = kind >> ZEND_AST_NUM_CHILDREN_SHIFT;
      96             :         zend_ast *ast;
      97             : 
      98     1896293 :         ast = zend_ast_alloc(zend_ast_size(children));
      99     1896293 :         ast->kind = kind;
     100     1896293 :         ast->attr = attr;
     101     1896293 :         ast->lineno = (uint32_t) -1;
     102             : 
     103     4974574 :         for (i = 0; i < children; ++i) {
     104     3078281 :                 ast->child[i] = va_arg(va, zend_ast *);
     105     3078281 :                 if (ast->child[i] != NULL) {
     106     5654326 :                         uint32_t lineno = zend_ast_get_lineno(ast->child[i]);
     107     2827163 :                         if (lineno < ast->lineno) {
     108     1884630 :                                 ast->lineno = lineno;
     109             :                         }
     110             :                 }
     111             :         }
     112             : 
     113     1896293 :         if (ast->lineno == UINT_MAX) {
     114       12311 :                 ast->lineno = CG(zend_lineno);
     115             :         }
     116             : 
     117     1896293 :         return ast;
     118             : }
     119             : 
     120      220167 : 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      220167 :         va_start(va, attr);
     125      220167 :         ast = zend_ast_create_from_va_list(kind, attr, va);
     126      220167 :         va_end(va);
     127             : 
     128      220167 :         return ast;
     129             : }
     130             : 
     131     1676126 : ZEND_API zend_ast *zend_ast_create(zend_ast_kind kind, ...) {
     132             :         va_list va;
     133             :         zend_ast *ast;
     134             : 
     135     1676126 :         va_start(va, kind);
     136     1676126 :         ast = zend_ast_create_from_va_list(kind, 0, va);
     137     1676126 :         va_end(va);
     138             : 
     139     1676126 :         return ast;
     140             : }
     141             : 
     142      655257 : 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      655257 :         ast = zend_ast_alloc(zend_ast_list_size(4));
     147      655257 :         list = (zend_ast_list *) ast;
     148      655257 :         list->kind = kind;
     149      655257 :         list->attr = 0;
     150      655257 :         list->lineno = CG(zend_lineno);
     151      655257 :         list->children = 0;
     152             : 
     153             :         {
     154             :                 va_list va;
     155             :                 uint32_t i;
     156      655257 :                 va_start(va, kind);
     157     1115953 :                 for (i = 0; i < init_children; ++i) {
     158      460696 :                         ast = zend_ast_list_add(ast, va_arg(va, zend_ast *));
     159             :                 }
     160      655257 :                 va_end(va);
     161             :         }
     162             : 
     163      655257 :         return ast;
     164             : }
     165             : 
     166      354314 : static inline zend_bool is_power_of_two(uint32_t n) {
     167      354314 :         return ((n != 0) && (n == (n & (~n + 1))));
     168             : }
     169             : 
     170     1371890 : ZEND_API zend_ast *zend_ast_list_add(zend_ast *ast, zend_ast *op) {
     171     1371890 :         zend_ast_list *list = zend_ast_get_list(ast);
     172     1371890 :         if (list->children >= 4 && is_power_of_two(list->children)) {
     173       67058 :                         list = zend_ast_realloc(list,
     174             :                         zend_ast_list_size(list->children), zend_ast_list_size(list->children * 2));
     175             :         }
     176     1371890 :         list->child[list->children++] = op;
     177     1371890 :         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), STR_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_error(E_EXCEPTION | E_ERROR, "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_error(E_EXCEPTION | E_ERROR, "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     4660629 : static void zend_ast_destroy_ex(zend_ast *ast, zend_bool free) {
     448     4660629 :         if (!ast) {
     449      369207 :                 return;
     450             :         }
     451             : 
     452     4291422 :         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     1690930 :                         break;
     459             :                 case ZEND_AST_FUNC_DECL:
     460             :                 case ZEND_AST_CLOSURE:
     461             :                 case ZEND_AST_METHOD:
     462             :                 case ZEND_AST_CLASS:
     463             :                 {
     464       43086 :                         zend_ast_decl *decl = (zend_ast_decl *) ast;
     465       43086 :                         if (decl->name) {
     466       43072 :                             zend_string_release(decl->name);
     467             :                         }
     468       43086 :                         if (decl->doc_comment) {
     469        2463 :                                 zend_string_release(decl->doc_comment);
     470             :                         }
     471       43086 :                         zend_ast_destroy_ex(decl->child[0], free);
     472       43086 :                         zend_ast_destroy_ex(decl->child[1], free);
     473       43086 :                         zend_ast_destroy_ex(decl->child[2], free);
     474       43086 :                         zend_ast_destroy_ex(decl->child[3], free);
     475       43086 :                         break;
     476             :                 }
     477             :                 default:
     478     2557406 :                         if (zend_ast_is_list(ast)) {
     479      653594 :                                 zend_ast_list *list = zend_ast_get_list(ast);
     480             :                                 uint32_t i;
     481     2023656 :                                 for (i = 0; i < list->children; i++) {
     482     1370062 :                                         zend_ast_destroy_ex(list->child[i], free);
     483             :                                 }
     484             :                         } else {
     485     1903812 :                                 uint32_t i, children = zend_ast_get_num_children(ast);
     486     4963527 :                                 for (i = 0; i < children; i++) {
     487     3059715 :                                         zend_ast_destroy_ex(ast->child[i], free);
     488             :                                 }
     489             :                         }
     490             :         }
     491             : 
     492     4291422 :         if (free) {
     493         439 :                 efree(ast);
     494             :         }
     495             : }
     496             : 
     497       58402 : ZEND_API void zend_ast_destroy(zend_ast *ast) {
     498       58402 :         zend_ast_destroy_ex(ast, 0);
     499       58402 : }
     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 < s->len; i++) {
     561          97 :                 unsigned char c = s->val[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 < s->len; i++) {
     576          18 :                 unsigned char c = s->val[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 PHP_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         132 : static void zend_ast_export_indent(smart_str *str, int indent)
     617             : {
     618         591 :         while (indent > 0) {
     619             :                 smart_str_appends(str, "    ");
     620         327 :                 indent--;
     621             :         }
     622         132 : }
     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         159 : static void zend_ast_export_ns_name(smart_str *str, zend_ast *ast, int priority, int indent)
     638             : {
     639         159 :         if (ast->kind == ZEND_AST_ZVAL) {
     640         151 :                 zval *zv = zend_ast_get_zval(ast);
     641             : 
     642         151 :                 if (Z_TYPE_P(zv) == IS_STRING) {
     643         151 :                     if (ast->attr == ZEND_NAME_FQ) {
     644             :                                 smart_str_appendc(str, '\\');
     645         148 :                     } else if (ast->attr == ZEND_NAME_RELATIVE) {
     646             :                                 smart_str_appends(str, "namespace\\");
     647             :                     }
     648         151 :                         smart_str_append(str, Z_STR_P(zv));
     649         151 :                         return;
     650             :                 }
     651             :         }
     652           8 :         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         127 : static void zend_ast_export_list(smart_str *str, zend_ast_list *list, int separator, int priority, int indent)
     713             : {
     714         127 :         uint32_t i = 0;
     715             : 
     716         371 :         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         127 : }
     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         138 : static void zend_ast_export_stmt(smart_str *str, zend_ast *ast, int indent)
     785             : {
     786         277 :         if (ast->kind == ZEND_AST_STMT_LIST ||
     787          96 :             ast->kind == ZEND_AST_TRAIT_ADAPTATIONS) {
     788          43 :                 zend_ast_list *list = (zend_ast_list*)ast;
     789          43 :                 uint32_t i = 0;
     790             : 
     791         188 :                 while (i < list->children) {
     792         102 :                         ast = list->child[i];
     793         102 :                         zend_ast_export_stmt(str, ast, indent);
     794         102 :                         i++;
     795             :                 }
     796             :         } else {
     797          95 :                 zend_ast_export_indent(str, indent);
     798          95 :                 zend_ast_export_ex(str, ast, 0, indent);
     799          95 :                 switch (ast->kind) {
     800             :                         case ZEND_AST_LABEL:
     801             :                         case ZEND_AST_IF:
     802             :                         case ZEND_AST_SWITCH:
     803             :                         case ZEND_AST_WHILE:
     804             :                         case ZEND_AST_TRY:
     805             :                         case ZEND_AST_FOR:
     806             :                         case ZEND_AST_FOREACH:
     807             :                         case ZEND_AST_FUNC_DECL:
     808             :                         case ZEND_AST_METHOD:
     809             :                         case ZEND_AST_CLASS:
     810             :                         case ZEND_AST_USE_TRAIT:
     811             :                         case ZEND_AST_NAMESPACE:
     812             :                         case ZEND_AST_DECLARE:
     813          20 :                                 break;
     814             :                         default:
     815             :                                 smart_str_appendc(str, ';');
     816             :                                 break;
     817             :                 }
     818             :                 smart_str_appendc(str, '\n');
     819             :         }
     820         138 : }
     821             : 
     822           6 : static void zend_ast_export_if_stmt(smart_str *str, zend_ast_list *list, int indent)
     823             : {
     824             :         uint32_t i;
     825             :         zend_ast *ast;
     826             : 
     827             : tail_call:
     828           6 :         i = 0;
     829          20 :         while (i < list->children) {
     830          10 :                 ast = list->child[i];
     831             :                 ZEND_ASSERT(ast->kind == ZEND_AST_IF_ELEM);
     832          10 :                 if (ast->child[0]) {
     833           7 :                         if (i == 0) {
     834             :                                 smart_str_appends(str, "if (");
     835             :                         } else {
     836           1 :                                 zend_ast_export_indent(str, indent);
     837             :                                 smart_str_appends(str, "} elseif (");
     838             :                         }
     839           7 :                         zend_ast_export_ex(str, ast->child[0], 0, indent);
     840             :                         smart_str_appends(str, ") {\n");
     841           7 :                         zend_ast_export_stmt(str, ast->child[1], indent + 1);
     842             :                 } else {
     843           3 :                         zend_ast_export_indent(str, indent);
     844             :                         smart_str_appends(str, "} else ");
     845           3 :                         if (ast->child[1]->kind == ZEND_AST_IF) {
     846           2 :                                 list = (zend_ast_list*)ast->child[1];
     847           2 :                                 goto tail_call;
     848             :                         } else {
     849             :                                 smart_str_appends(str, "{\n");
     850           1 :                                 zend_ast_export_stmt(str, ast->child[1], indent + 1);
     851             :                         }
     852             :                 }
     853           8 :                 i++;
     854             :         }
     855           4 :         zend_ast_export_indent(str, indent);
     856             :         smart_str_appendc(str, '}');
     857           4 : }
     858             : 
     859          96 : static void zend_ast_export_zval(smart_str *str, zval *zv, int priority, int indent)
     860             : {
     861             :         zend_long idx;
     862             :         zend_string *key;
     863             :         zval *val;
     864             :         int first;
     865             : 
     866          96 :         ZVAL_DEREF(zv);
     867          96 :         switch (Z_TYPE_P(zv)) {
     868             :                 case IS_NULL:
     869             :                         smart_str_appends(str, "null");
     870           0 :                         break;
     871             :                 case IS_FALSE:
     872             :                         smart_str_appends(str, "false");
     873           0 :                         break;
     874             :                 case IS_TRUE:
     875             :                         smart_str_appends(str, "true");
     876           0 :                         break;
     877             :                 case IS_LONG:
     878          65 :                         smart_str_append_long(str, Z_LVAL_P(zv));
     879          65 :                         break;
     880             :                 case IS_DOUBLE:
     881           0 :                         key = zend_strpprintf(0, "%.*G", (int) EG(precision), Z_DVAL_P(zv));
     882           0 :                         smart_str_appendl(str, key->val, key->len);
     883             :                         zend_string_release(key);
     884           0 :                         break;
     885             :                 case IS_STRING:
     886             :                         smart_str_appendc(str, '\'');
     887          31 :                         zend_ast_export_str(str, Z_STR_P(zv));
     888             :                         smart_str_appendc(str, '\'');
     889          31 :                         break;
     890             :                 case IS_ARRAY:
     891             :                         smart_str_appendc(str, '[');
     892           0 :                         first = 1;
     893           0 :                         ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(zv), idx, key, val) {
     894           0 :                                 if (first) {
     895           0 :                                         first = 0;
     896             :                                 } else {
     897             :                                         smart_str_appends(str, ", ");
     898             :                                 }
     899           0 :                                 if (key) {
     900             :                                         smart_str_appendc(str, '\'');
     901           0 :                                         zend_ast_export_str(str, key);
     902             :                                         smart_str_appends(str, "' => ");
     903             :                                 } else {
     904             :                                         smart_str_append_long(str, idx);
     905             :                                         smart_str_appends(str, " => ");
     906             :                                 }
     907           0 :                                 zend_ast_export_zval(str, val, 0, indent);
     908             :                         } ZEND_HASH_FOREACH_END();
     909             :                         smart_str_appendc(str, ']');
     910           0 :                         break;
     911             :                 case IS_CONSTANT:
     912           0 :                         smart_str_appendl(str, Z_STRVAL_P(zv), Z_STRLEN_P(zv));
     913           0 :                         break;
     914             :                 case IS_CONSTANT_AST:
     915           0 :                         zend_ast_export_ex(str, Z_ASTVAL_P(zv), priority, indent);
     916             :                         break;
     917             :                 EMPTY_SWITCH_DEFAULT_CASE();
     918             :         }
     919          96 : }
     920             : 
     921             : #define BINARY_OP(_op, _p, _pl, _pr) do { \
     922             :                 op = _op; \
     923             :                 p = _p; \
     924             :                 pl = _pl; \
     925             :                 pr = _pr; \
     926             :                 goto binary_op; \
     927             :         } while (0)
     928             : 
     929             : #define PREFIX_OP(_op, _p, _pl) do { \
     930             :                 op = _op; \
     931             :                 p = _p; \
     932             :                 pl = _pl; \
     933             :                 goto prefix_op; \
     934             :         } while (0)
     935             : 
     936             : #define FUNC_OP(_op) do { \
     937             :                 op = _op; \
     938             :                 goto func_op; \
     939             :         } while (0)
     940             : 
     941             : #define POSTFIX_OP(_op, _p, _pl) do { \
     942             :                 op = _op; \
     943             :                 p = _p; \
     944             :                 pl = _pl; \
     945             :                 goto postfix_op; \
     946             :         } while (0)
     947             : 
     948             : #define APPEND_NODE_1(_op) do { \
     949             :                 op = _op; \
     950             :                 goto append_node_1; \
     951             :         } while (0)
     952             : 
     953             : #define APPEND_STR(_op) do { \
     954             :                 op = _op; \
     955             :                 goto append_str; \
     956             :         } while (0)
     957             : 
     958             : #define APPEND_DEFAULT_VALUE(n) do { \
     959             :                 p = n; \
     960             :                 goto append_default_value; \
     961             :         } while (0)
     962             : 
     963        1078 : static void zend_ast_export_ex(smart_str *str, zend_ast *ast, int priority, int indent)
     964             : {
     965             :         zend_ast_decl *decl;
     966             :         int p, pl, pr;
     967             :         const char *op;
     968             : 
     969             : tail_call:
     970        1078 :         if (!ast) {
     971           6 :                 return;
     972             :         }
     973        1072 :         switch (ast->kind) {
     974             :                 /* special nodes */
     975             :                 case ZEND_AST_ZVAL:
     976          96 :                         zend_ast_export_zval(str, zend_ast_get_zval(ast), priority, indent);
     977          96 :                         break;
     978             :                 case ZEND_AST_ZNODE:
     979             :                         /* This AST kind is only used for temporary nodes during compilation */
     980             :                         ZEND_ASSERT(0);
     981           0 :                         break;
     982             : 
     983             :                 /* declaration nodes */
     984             :                 case ZEND_AST_FUNC_DECL:
     985             :                 case ZEND_AST_CLOSURE:
     986             :                 case ZEND_AST_METHOD:
     987           9 :                         decl = (zend_ast_decl *) ast;
     988           9 :                         if (decl->flags & ZEND_ACC_PUBLIC) {
     989             :                                 smart_str_appends(str, "public ");
     990           8 :                         } else if (decl->flags & ZEND_ACC_PROTECTED) {
     991             :                                 smart_str_appends(str, "protected ");
     992           7 :                         } else if (decl->flags & ZEND_ACC_PRIVATE) {
     993             :                                 smart_str_appends(str, "private ");
     994             :                         }
     995           9 :                         if (decl->flags & ZEND_ACC_STATIC) {
     996             :                                 smart_str_appends(str, "static ");
     997             :                         }
     998           9 :                         if (decl->flags & ZEND_ACC_ABSTRACT) {
     999             :                                 smart_str_appends(str, "abstract ");
    1000             :                         }
    1001           9 :                         if (decl->flags & ZEND_ACC_FINAL) {
    1002             :                                 smart_str_appends(str, "final ");
    1003             :                         }
    1004             :                         smart_str_appends(str, "function ");
    1005           9 :                         if (decl->flags & ZEND_ACC_RETURN_REFERENCE) {
    1006             :                                 smart_str_appendc(str, '&');
    1007             :                         }
    1008           9 :                         if (ast->kind != ZEND_AST_CLOSURE) {
    1009           3 :                                 smart_str_appendl(str, decl->name->val, decl->name->len);
    1010             :                         }
    1011             :                         smart_str_appendc(str, '(');
    1012           9 :                         zend_ast_export_ex(str, decl->child[0], 0, indent);
    1013             :                         smart_str_appendc(str, ')');
    1014           9 :                         zend_ast_export_ex(str, decl->child[1], 0, indent);
    1015           9 :                         if (decl->child[3]) {
    1016             :                                 smart_str_appends(str, ": ");
    1017           3 :                                 zend_ast_export_ns_name(str, decl->child[3], 0, indent);
    1018             :                         }
    1019           9 :                         if (decl->child[2]) {
    1020             :                                 smart_str_appends(str, " {\n");
    1021           8 :                                 zend_ast_export_stmt(str, decl->child[2], indent + 1);
    1022           8 :                                 zend_ast_export_indent(str, indent);
    1023             :                                 smart_str_appendc(str, '}');
    1024           8 :                                 if (ast->kind != ZEND_AST_CLOSURE) {
    1025             :                                         smart_str_appendc(str, '\n');
    1026             :                                 }
    1027             :                         } else {
    1028             :                                 smart_str_appends(str, ";\n");
    1029             :                         }
    1030           9 :                         break;
    1031             :                 case ZEND_AST_CLASS:
    1032           3 :                         decl = (zend_ast_decl *) ast;
    1033           3 :                         if (decl->flags & ZEND_ACC_INTERFACE) {
    1034             :                                 smart_str_appends(str, "interface ");
    1035           3 :                         } else if (decl->flags & ZEND_ACC_TRAIT) {
    1036             :                                 smart_str_appends(str, "trait ");
    1037             :                         } else {
    1038           3 :                                 if (decl->flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
    1039             :                                         smart_str_appends(str, "abstract ");
    1040             :                                 }
    1041           3 :                                 if (decl->flags & ZEND_ACC_FINAL) {
    1042             :                                         smart_str_appends(str, "final ");
    1043             :                                 }
    1044             :                                 smart_str_appends(str, "class ");
    1045             :                         }
    1046           3 :                         smart_str_appendl(str, decl->name->val, decl->name->len);
    1047           3 :                         if (decl->child[0]) {
    1048             :                                 smart_str_appends(str, " extends ");
    1049           1 :                                 zend_ast_export_ns_name(str, decl->child[0], 0, indent);
    1050             :                         }
    1051           3 :                         if (decl->child[1]) {
    1052             :                                 smart_str_appends(str, " implements ");
    1053           1 :                                 zend_ast_export_ex(str, decl->child[1], 0, indent);
    1054             :                         }
    1055             :                         smart_str_appends(str, " {\n");
    1056           3 :                         zend_ast_export_stmt(str, decl->child[2], indent + 1);
    1057           3 :                         zend_ast_export_indent(str, indent);
    1058             :                         smart_str_appends(str, "}\n");
    1059           3 :                         break;
    1060             : 
    1061             :                 /* list nodes */
    1062             :                 case ZEND_AST_ARG_LIST:
    1063             :                 case ZEND_AST_EXPR_LIST:
    1064             :                 case ZEND_AST_PARAM_LIST:
    1065             : simple_list:
    1066         118 :                         zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
    1067         118 :                         break;
    1068             :                 case ZEND_AST_LIST:
    1069             :                         smart_str_appends(str, "list(");
    1070           1 :                         zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
    1071             :                         smart_str_appendc(str, ')');
    1072           1 :                         break;
    1073             :                 case ZEND_AST_ARRAY:
    1074             :                         smart_str_appendc(str, '[');
    1075           4 :                         zend_ast_export_list(str, (zend_ast_list*)ast, 1, 20, indent);
    1076             :                         smart_str_appendc(str, ']');
    1077           4 :                         break;
    1078             :                 case ZEND_AST_ENCAPS_LIST:
    1079             :                         smart_str_appendc(str, '"');
    1080           6 :                         zend_ast_export_encaps_list(str, '"', (zend_ast_list*)ast, indent);
    1081             :                         smart_str_appendc(str, '"');
    1082           6 :                         break;
    1083             :                 case ZEND_AST_STMT_LIST:
    1084             :                 case ZEND_AST_TRAIT_ADAPTATIONS:
    1085           1 :                         zend_ast_export_stmt(str, ast, indent);
    1086           1 :                         break;
    1087             :                 case ZEND_AST_IF:
    1088           4 :                         zend_ast_export_if_stmt(str, (zend_ast_list*)ast, indent);
    1089           4 :                         break;
    1090             :                 case ZEND_AST_SWITCH_LIST:
    1091             :                 case ZEND_AST_CATCH_LIST:
    1092           2 :                         zend_ast_export_list(str, (zend_ast_list*)ast, 0, 0, indent);
    1093           2 :                         break;
    1094             :                 case ZEND_AST_CLOSURE_USES:
    1095             :                         smart_str_appends(str, " use(");
    1096           3 :                         zend_ast_export_var_list(str, (zend_ast_list*)ast, indent);
    1097             :                         smart_str_appendc(str, ')');
    1098           3 :                         break;
    1099             :                 case ZEND_AST_PROP_DECL:
    1100           3 :                         if (ast->attr & ZEND_ACC_PUBLIC) {
    1101             :                                 smart_str_appends(str, "public ");
    1102           2 :                         } else if (ast->attr & ZEND_ACC_PROTECTED) {
    1103             :                                 smart_str_appends(str, "protected ");
    1104           1 :                         } else if (ast->attr & ZEND_ACC_PRIVATE) {
    1105             :                                 smart_str_appends(str, "private ");
    1106             :                         }
    1107           3 :                         if (ast->attr & ZEND_ACC_STATIC) {
    1108             :                                 smart_str_appends(str, "static ");
    1109             :                         }
    1110           3 :                         goto simple_list;
    1111             :                 case ZEND_AST_CONST_DECL:
    1112             :                 case ZEND_AST_CLASS_CONST_DECL:
    1113             :                         smart_str_appends(str, "const ");
    1114           2 :                         goto simple_list;
    1115             :                 case ZEND_AST_NAME_LIST:
    1116           4 :                         zend_ast_export_name_list(str, (zend_ast_list*)ast, indent);
    1117           4 :                         break;
    1118             :                 case ZEND_AST_USE:
    1119             :                         smart_str_appends(str, "use ");
    1120           0 :                         if (ast->attr == T_FUNCTION) {
    1121             :                                 smart_str_appends(str, "function ");
    1122           0 :                         } else if (ast->attr == T_CONST) {
    1123             :                                 smart_str_appends(str, "const ");
    1124             :                         }
    1125           0 :                         goto simple_list;
    1126             : 
    1127             :                 /* 0 child nodes */
    1128             :                 case ZEND_AST_MAGIC_CONST:
    1129           0 :                         switch (ast->attr) {
    1130           0 :                                 case T_LINE:     APPEND_STR("__LINE__");
    1131           0 :                                 case T_FILE:     APPEND_STR("__FILE__");
    1132           0 :                                 case T_DIR:      APPEND_STR("__DIR__");
    1133           0 :                                 case T_TRAIT_C:  APPEND_STR("__TRAIT__");
    1134           0 :                                 case T_METHOD_C: APPEND_STR("__METHOD__");
    1135           0 :                                 case T_FUNC_C:   APPEND_STR("__FUNCTION__");
    1136           0 :                                 case T_NS_C:     APPEND_STR("__NAMESPACE__");
    1137           0 :                                 case T_CLASS_C:  APPEND_STR("__CLASS__");
    1138             :                                 EMPTY_SWITCH_DEFAULT_CASE();
    1139             :                         }
    1140           0 :                         break;
    1141             :                 case ZEND_AST_TYPE:
    1142           4 :                         switch (ast->attr) {
    1143           4 :                                 case IS_ARRAY:    APPEND_STR("array");
    1144           0 :                                 case IS_CALLABLE: APPEND_STR("callable");
    1145             :                                 EMPTY_SWITCH_DEFAULT_CASE();
    1146             :                         }
    1147           0 :                         break;
    1148             : 
    1149             :                 /* 1 child node */
    1150             :                 case ZEND_AST_VAR:
    1151             :                         smart_str_appendc(str, '$');
    1152         285 :                         zend_ast_export_var(str, ast->child[0], 0, indent);
    1153         285 :                         break;
    1154             :                 case ZEND_AST_CONST:
    1155          50 :                         zend_ast_export_ns_name(str, ast->child[0], 0, indent);
    1156          50 :                         break;
    1157             :                 case ZEND_AST_UNPACK:
    1158             :                         smart_str_appends(str, "...");
    1159           1 :                         ast = ast->child[0];
    1160           1 :                         goto tail_call;
    1161           0 :                 case ZEND_AST_UNARY_PLUS:  PREFIX_OP("+", 240, 241);
    1162           0 :                 case ZEND_AST_UNARY_MINUS: PREFIX_OP("-", 240, 241);
    1163             :                 case ZEND_AST_CAST:
    1164           0 :                         switch (ast->attr) {
    1165           0 :                                 case IS_NULL:      PREFIX_OP("(unset)",  240, 241);
    1166           0 :                                 case _IS_BOOL:     PREFIX_OP("(bool)",   240, 241);
    1167           0 :                                 case IS_LONG:      PREFIX_OP("(int)",    240, 241);
    1168           0 :                                 case IS_DOUBLE:    PREFIX_OP("(double)", 240, 241);
    1169           0 :                                 case IS_STRING:    PREFIX_OP("(string)", 240, 241);
    1170           0 :                                 case IS_ARRAY:     PREFIX_OP("(array)",  240, 241);
    1171           0 :                                 case IS_OBJECT:    PREFIX_OP("(object)", 240, 241);
    1172             :                                 EMPTY_SWITCH_DEFAULT_CASE();
    1173             :                         }
    1174           0 :                         break;
    1175             :                 case ZEND_AST_EMPTY:
    1176           1 :                         FUNC_OP("empty");
    1177             :                 case ZEND_AST_ISSET:
    1178           1 :                         FUNC_OP("isset");
    1179             :                 case ZEND_AST_SILENCE:
    1180          37 :                         PREFIX_OP("@", 240, 241);
    1181             :                 case ZEND_AST_SHELL_EXEC:
    1182             :                         smart_str_appendc(str, '`');
    1183           1 :                         if (ast->child[0]->kind == ZEND_AST_ENCAPS_LIST) {
    1184           1 :                                 zend_ast_export_encaps_list(str, '`', (zend_ast_list*)ast->child[0], indent);
    1185             :                         } else {
    1186           0 :                                 zend_ast_export_ex(str, ast->child[0], 0, indent);
    1187             :                         }
    1188             :                         smart_str_appendc(str, '`');
    1189           1 :                         break;
    1190             :                 case ZEND_AST_CLONE:
    1191           1 :                         PREFIX_OP("clone ", 270, 271);
    1192             :                 case ZEND_AST_EXIT:
    1193           0 :                         if (ast->child[0]) {
    1194           0 :                                 FUNC_OP("exit");
    1195             :                         } else {
    1196           0 :                                 APPEND_STR("exit");
    1197             :                         }
    1198             :                         break;
    1199             :                 case ZEND_AST_PRINT:
    1200           1 :                         PREFIX_OP("print ", 60, 61);
    1201             :                 case ZEND_AST_INCLUDE_OR_EVAL:
    1202           1 :                         switch (ast->attr) {
    1203           0 :                                 case ZEND_INCLUDE_ONCE: FUNC_OP("include_once");
    1204           0 :                                 case ZEND_INCLUDE:      FUNC_OP("include");
    1205           0 :                                 case ZEND_REQUIRE_ONCE: FUNC_OP("require_once");
    1206           0 :                                 case ZEND_REQUIRE:      FUNC_OP("require");
    1207           1 :                                 case ZEND_EVAL:         FUNC_OP("eval");
    1208             :                                 EMPTY_SWITCH_DEFAULT_CASE();
    1209             :                         }
    1210           0 :                         break;
    1211             :                 case ZEND_AST_UNARY_OP:
    1212           2 :                         switch (ast->attr) {
    1213           0 :                                 case ZEND_BW_NOT:   PREFIX_OP("~", 240, 241);
    1214           2 :                                 case ZEND_BOOL_NOT: PREFIX_OP("!", 240, 241);
    1215             :                                 EMPTY_SWITCH_DEFAULT_CASE();
    1216             :                         }
    1217           0 :                         break;
    1218             :                 case ZEND_AST_PRE_INC:
    1219           0 :                         PREFIX_OP("++", 240, 241);
    1220             :                 case ZEND_AST_PRE_DEC:
    1221           1 :                         PREFIX_OP("--", 240, 241);
    1222             :                 case ZEND_AST_POST_INC:
    1223           3 :                         POSTFIX_OP("++", 240, 241);
    1224             :                 case ZEND_AST_POST_DEC:
    1225           1 :                         POSTFIX_OP("--", 240, 241);
    1226             : 
    1227             :                 case ZEND_AST_GLOBAL:
    1228           2 :                         APPEND_NODE_1("global");
    1229             :                 case ZEND_AST_UNSET:
    1230           1 :                         FUNC_OP("unset");
    1231             :                 case ZEND_AST_RETURN:
    1232           6 :                         APPEND_NODE_1("return");
    1233             :                 case ZEND_AST_LABEL:
    1234           1 :                         zend_ast_export_name(str, ast->child[0], 0, indent);
    1235             :                         smart_str_appendc(str, ':');
    1236           1 :                         break;
    1237             :                 case ZEND_AST_REF:
    1238             :                         smart_str_appendc(str, '&');
    1239           1 :                         ast = ast->child[0];
    1240           1 :                         goto tail_call;
    1241             :                 case ZEND_AST_HALT_COMPILER:
    1242           0 :                         APPEND_STR("__HALT_COMPILER()");
    1243             :                 case ZEND_AST_ECHO:
    1244           4 :                         APPEND_NODE_1("echo");
    1245             :                 case ZEND_AST_THROW:
    1246           0 :                         APPEND_NODE_1("throw");
    1247             :                 case ZEND_AST_GOTO:
    1248             :                         smart_str_appends(str, "goto ");
    1249           1 :                         zend_ast_export_name(str, ast->child[0], 0, indent);
    1250           1 :                         break;
    1251             :                 case ZEND_AST_BREAK:
    1252           2 :                         APPEND_NODE_1("break");
    1253             :                 case ZEND_AST_CONTINUE:
    1254           2 :                         APPEND_NODE_1("continue");
    1255             : 
    1256             :                 /* 2 child nodes */
    1257             :                 case ZEND_AST_DIM:
    1258           5 :                         zend_ast_export_ex(str, ast->child[0], 260, indent);
    1259             :                         smart_str_appendc(str, '[');
    1260           5 :                         if (ast->child[1]) {
    1261           5 :                                 zend_ast_export_ex(str, ast->child[1], 0, indent);
    1262             :                         }
    1263             :                         smart_str_appendc(str, ']');
    1264           5 :                         break;
    1265             :                 case ZEND_AST_PROP:
    1266          67 :                         zend_ast_export_ex(str, ast->child[0], 0, indent);
    1267             :                         smart_str_appends(str, "->");
    1268          67 :                         zend_ast_export_var(str, ast->child[1], 0, indent);
    1269          67 :                         break;
    1270             :                 case ZEND_AST_STATIC_PROP:
    1271           3 :                         zend_ast_export_ns_name(str, ast->child[0], 0, indent);
    1272             :                         smart_str_appends(str, "::$");
    1273           3 :                         zend_ast_export_var(str, ast->child[1], 0, indent);
    1274           3 :                         break;
    1275             :                 case ZEND_AST_CALL:
    1276          83 :                         zend_ast_export_ns_name(str, ast->child[0], 0, indent);
    1277             :                         smart_str_appendc(str, '(');
    1278          83 :                         zend_ast_export_ex(str, ast->child[1], 0, indent);
    1279             :                         smart_str_appendc(str, ')');
    1280          83 :                         break;
    1281             :                 case ZEND_AST_CLASS_CONST:
    1282           4 :                         zend_ast_export_ns_name(str, ast->child[0], 0, indent);
    1283             :                         smart_str_appends(str, "::");
    1284           4 :                         zend_ast_export_name(str, ast->child[1], 0, indent);
    1285           4 :                         break;
    1286          47 :                 case ZEND_AST_ASSIGN:            BINARY_OP(" = ",   90, 91, 90);
    1287           0 :                 case ZEND_AST_ASSIGN_REF:        BINARY_OP(" =& ",  90, 91, 90);
    1288             :                 case ZEND_AST_ASSIGN_OP:
    1289           0 :                         switch (ast->attr) {
    1290           0 :                                 case ZEND_ASSIGN_ADD:    BINARY_OP(" += ",  90, 91, 90);
    1291           0 :                                 case ZEND_ASSIGN_SUB:    BINARY_OP(" -= ",  90, 91, 90);
    1292           0 :                                 case ZEND_ASSIGN_MUL:    BINARY_OP(" *= ",  90, 91, 90);
    1293           0 :                                 case ZEND_ASSIGN_DIV:    BINARY_OP(" /= ",  90, 91, 90);
    1294           0 :                                 case ZEND_ASSIGN_MOD:    BINARY_OP(" %= ",  90, 91, 90);
    1295           0 :                                 case ZEND_ASSIGN_SL:     BINARY_OP(" <<= ", 90, 91, 90);
    1296           0 :                                 case ZEND_ASSIGN_SR:     BINARY_OP(" >>= ", 90, 91, 90);
    1297           0 :                                 case ZEND_ASSIGN_CONCAT: BINARY_OP(" .= ",  90, 91, 90);
    1298           0 :                                 case ZEND_ASSIGN_BW_OR:  BINARY_OP(" |= ",  90, 91, 90);
    1299           0 :                                 case ZEND_ASSIGN_BW_AND: BINARY_OP(" &= ",  90, 91, 90);
    1300           0 :                                 case ZEND_ASSIGN_BW_XOR: BINARY_OP(" ^= ",  90, 91, 90);
    1301           0 :                                 case ZEND_POW:           BINARY_OP(" **= ", 90, 91, 90);
    1302             :                                 EMPTY_SWITCH_DEFAULT_CASE();
    1303             :                         }
    1304           0 :                         break;
    1305             :                 case ZEND_AST_BINARY_OP:
    1306         101 :                         switch (ast->attr) {
    1307           1 :                                 case ZEND_ADD:                 BINARY_OP(" + ",   200, 200, 201);
    1308           0 :                                 case ZEND_SUB:                 BINARY_OP(" - ",   200, 200, 201);
    1309           0 :                                 case ZEND_MUL:                 BINARY_OP(" * ",   210, 210, 211);
    1310           0 :                                 case ZEND_DIV:                 BINARY_OP(" / ",   210, 210, 211);
    1311           0 :                                 case ZEND_MOD:                 BINARY_OP(" % ",   210, 210, 211);
    1312           0 :                                 case ZEND_SL:                  BINARY_OP(" << ",  190, 190, 191);
    1313           0 :                                 case ZEND_SR:                  BINARY_OP(" >> ",  190, 190, 191);
    1314          14 :                                 case ZEND_CONCAT:              BINARY_OP(" . ",   200, 200, 201);
    1315           0 :                                 case ZEND_BW_OR:               BINARY_OP(" | ",   140, 140, 141);
    1316           0 :                                 case ZEND_BW_AND:              BINARY_OP(" & ",   160, 160, 161);
    1317           0 :                                 case ZEND_BW_XOR:              BINARY_OP(" ^ ",   150, 150, 151);
    1318          59 :                                 case ZEND_IS_IDENTICAL:        BINARY_OP(" === ", 170, 171, 171);
    1319           0 :                                 case ZEND_IS_NOT_IDENTICAL:    BINARY_OP(" !== ", 170, 171, 171);
    1320          21 :                                 case ZEND_IS_EQUAL:            BINARY_OP(" == ",  170, 171, 171);
    1321           2 :                                 case ZEND_IS_NOT_EQUAL:        BINARY_OP(" != ",  170, 171, 171);
    1322           2 :                                 case ZEND_IS_SMALLER:          BINARY_OP(" < ",   180, 181, 181);
    1323           2 :                                 case ZEND_IS_SMALLER_OR_EQUAL: BINARY_OP(" <= ",  180, 181, 181);
    1324           0 :                                 case ZEND_POW:                 BINARY_OP(" ** ",  250, 251, 250);
    1325           0 :                                 case ZEND_BOOL_XOR:            BINARY_OP(" xor ",  40,  40,  41);
    1326           0 :                                 case ZEND_SPACESHIP:           BINARY_OP(" <=> ", 180, 181, 181);
    1327             :                                 EMPTY_SWITCH_DEFAULT_CASE();
    1328             :                         }
    1329           0 :                         break;
    1330           6 :                 case ZEND_AST_GREATER:                 BINARY_OP(" > ",   180, 181, 181);
    1331           0 :                 case ZEND_AST_GREATER_EQUAL:           BINARY_OP(" >= ",  180, 181, 181);
    1332           7 :                 case ZEND_AST_AND:                     BINARY_OP(" && ",  130, 130, 131);
    1333           6 :                 case ZEND_AST_OR:                      BINARY_OP(" || ",  120, 120, 121);
    1334             :                 case ZEND_AST_ARRAY_ELEM:
    1335          13 :                         if (ast->child[1]) {
    1336           2 :                                 zend_ast_export_ex(str, ast->child[1], 80, indent);
    1337             :                                 smart_str_appends(str, " => ");
    1338             :                         }
    1339          13 :                         zend_ast_export_ex(str, ast->child[0], 80, indent);
    1340          13 :                         break;
    1341             :                 case ZEND_AST_NEW:
    1342             :                         smart_str_appends(str, "new ");
    1343           3 :                         zend_ast_export_ns_name(str, ast->child[0], 0, indent);
    1344             :                         smart_str_appendc(str, '(');
    1345           3 :                         zend_ast_export_ex(str, ast->child[1], 0, indent);
    1346             :                         smart_str_appendc(str, ')');
    1347           3 :                         break;
    1348           0 :                 case ZEND_AST_INSTANCEOF: BINARY_OP(" instanceof ", 230, 231, 231);
    1349             :                 case ZEND_AST_YIELD:
    1350           1 :                         if (priority > 70) smart_str_appendc(str, '(');
    1351             :                         smart_str_appends(str, "yield ");
    1352           1 :                         if (ast->child[0]) {
    1353           1 :                                 if (ast->child[1]) {
    1354           1 :                                         zend_ast_export_ex(str, ast->child[1], 70, indent);
    1355             :                                         smart_str_appends(str, " => ");
    1356             :                                 }
    1357           1 :                                 zend_ast_export_ex(str, ast->child[0], 70, indent);
    1358             :                         }
    1359           1 :                         if (priority > 70) smart_str_appendc(str, ')');
    1360           1 :                         break;
    1361             :                 case ZEND_AST_YIELD_FROM:
    1362           1 :                         PREFIX_OP("yield from ", 85, 86);
    1363           1 :                 case ZEND_AST_COALESCE: BINARY_OP(" ?? ", 110, 111, 110);
    1364             :                 case ZEND_AST_STATIC:
    1365             :                         smart_str_appends(str, "static $");
    1366           2 :                         zend_ast_export_name(str, ast->child[0], 0, indent);
    1367           2 :                         APPEND_DEFAULT_VALUE(1);
    1368             :                 case ZEND_AST_WHILE:
    1369             :                         smart_str_appends(str, "while (");
    1370           1 :                         zend_ast_export_ex(str, ast->child[0], 0, indent);
    1371             :                         smart_str_appends(str, ") {\n");
    1372           1 :                         zend_ast_export_stmt(str, ast->child[1], indent + 1);
    1373           1 :                         zend_ast_export_indent(str, indent);
    1374             :                         smart_str_appendc(str, '}');
    1375           1 :                         break;
    1376             :                 case ZEND_AST_DO_WHILE:
    1377             :                         smart_str_appends(str, "do {\n");
    1378           2 :                         zend_ast_export_stmt(str, ast->child[0], indent + 1);
    1379           2 :                         zend_ast_export_indent(str, indent);
    1380             :                         smart_str_appends(str, "} while (");
    1381           2 :                         zend_ast_export_ex(str, ast->child[1], 0, indent);
    1382             :                         smart_str_appendc(str, ')');
    1383           2 :                         break;
    1384             : 
    1385             :                 case ZEND_AST_IF_ELEM:
    1386           0 :                         if (ast->child[0]) {
    1387             :                                 smart_str_appends(str, "if (");
    1388           0 :                                 zend_ast_export_ex(str, ast->child[0], 0, indent);
    1389             :                                 smart_str_appends(str, ") {\n");
    1390           0 :                                 zend_ast_export_stmt(str, ast->child[1], indent + 1);
    1391             :                         } else {
    1392             :                                 smart_str_appends(str, "else {\n");
    1393           0 :                                 zend_ast_export_stmt(str, ast->child[1], indent + 1);
    1394             :                         }
    1395           0 :                         zend_ast_export_indent(str, indent);
    1396             :                         smart_str_appendc(str, '}');
    1397           0 :                         break;
    1398             :                 case ZEND_AST_SWITCH:
    1399             :                         smart_str_appends(str, "switch (");
    1400           1 :                         zend_ast_export_ex(str, ast->child[0], 0, indent);
    1401             :                         smart_str_appends(str, ") {\n");
    1402           1 :                         zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
    1403           1 :                         zend_ast_export_indent(str, indent);
    1404             :                         smart_str_appendc(str, '}');
    1405           1 :                         break;
    1406             :                 case ZEND_AST_SWITCH_CASE:
    1407           6 :                         zend_ast_export_indent(str, indent);
    1408           6 :                         if (ast->child[0]) {
    1409             :                                 smart_str_appends(str, "case ");
    1410           5 :                                 zend_ast_export_ex(str, ast->child[0], 0, indent);
    1411             :                                 smart_str_appends(str, ":\n");
    1412             :                         } else {
    1413             :                                 smart_str_appends(str, "default:\n");
    1414             :                         }
    1415           6 :                         zend_ast_export_stmt(str, ast->child[1], indent + 1);
    1416           6 :                         break;
    1417             :                 case ZEND_AST_DECLARE:
    1418             :                         smart_str_appends(str, "declare(");
    1419             :                         ZEND_ASSERT(ast->child[0]->kind == ZEND_AST_CONST_DECL);
    1420           2 :                         zend_ast_export_list(str, (zend_ast_list*)ast->child[0], 1, 0, indent);
    1421             :                         smart_str_appendc(str, ')');
    1422           2 :                         if (ast->child[1]) {
    1423             :                                 smart_str_appends(str, " {\n");
    1424           1 :                                 zend_ast_export_stmt(str, ast->child[1], indent + 1);
    1425           1 :                                 zend_ast_export_indent(str, indent);
    1426             :                                 smart_str_appendc(str, '}');
    1427             :                         } else {
    1428             :                                 smart_str_appendc(str, ';');
    1429             :                         }
    1430           2 :                         break;
    1431             :                 case ZEND_AST_PROP_ELEM:
    1432             :                         smart_str_appendc(str, '$');
    1433             :                         /* break missing intentionally */
    1434             :                 case ZEND_AST_CONST_ELEM:
    1435          10 :                         zend_ast_export_name(str, ast->child[0], 0, indent);
    1436          10 :                         APPEND_DEFAULT_VALUE(1);
    1437             :                 case ZEND_AST_USE_TRAIT:
    1438             :                         smart_str_appends(str, "use ");
    1439           2 :                         zend_ast_export_ex(str, ast->child[0], 0, indent);
    1440           2 :                         if (ast->child[1]) {
    1441             :                                 smart_str_appends(str, " {\n");
    1442           1 :                                 zend_ast_export_ex(str, ast->child[1], 0, indent + 1);
    1443           1 :                                 zend_ast_export_indent(str, indent);
    1444             :                                 smart_str_appends(str, "}");
    1445             :                         } else {
    1446             :                                 smart_str_appends(str, ";");
    1447             :                         }
    1448           2 :                         break;
    1449             :                 case ZEND_AST_TRAIT_PRECEDENCE:
    1450           1 :                         zend_ast_export_ex(str, ast->child[0], 0, indent);
    1451             :                         smart_str_appends(str, " insteadof ");
    1452           1 :                         zend_ast_export_ex(str, ast->child[1], 0, indent);
    1453           1 :                         break;
    1454             :                 case ZEND_AST_METHOD_REFERENCE:
    1455           4 :                         if (ast->child[0]) {
    1456           2 :                                 zend_ast_export_name(str, ast->child[0], 0, indent);
    1457             :                                 smart_str_appends(str, "::");
    1458             :                         }
    1459           4 :                         zend_ast_export_name(str, ast->child[1], 0, indent);
    1460           4 :                         break;
    1461             :                 case ZEND_AST_NAMESPACE:
    1462             :                         smart_str_appends(str, "namespace");
    1463           0 :                         if (ast->child[0]) {
    1464             :                                 smart_str_appendc(str, ' ');
    1465           0 :                                 zend_ast_export_name(str, ast->child[0], 0, indent);
    1466             :                         }
    1467           0 :                         if (ast->child[1]) {
    1468             :                                 smart_str_appends(str, " {\n");
    1469           0 :                                 zend_ast_export_stmt(str, ast->child[1], indent + 1);
    1470           0 :                                 zend_ast_export_indent(str, indent);
    1471             :                                 smart_str_appends(str, "}\n");
    1472             :                         } else {
    1473             :                                 smart_str_appendc(str, ';');
    1474             :                         }
    1475           0 :                         break;
    1476             :                 case ZEND_AST_USE_ELEM:
    1477             :                 case ZEND_AST_TRAIT_ALIAS:
    1478           3 :                         zend_ast_export_name(str, ast->child[0], 0, indent);
    1479           3 :                         if (ast->attr & ZEND_ACC_PUBLIC) {
    1480             :                                 smart_str_appends(str, " as public");
    1481           2 :                         } else if (ast->attr & ZEND_ACC_PROTECTED) {
    1482             :                                 smart_str_appends(str, " as protected");
    1483           1 :                         } else if (ast->attr & ZEND_ACC_PRIVATE) {
    1484             :                                 smart_str_appends(str, " as private");
    1485           1 :                         } else if (ast->child[1]) {
    1486             :                                 smart_str_appends(str, " as");
    1487             :                         }
    1488           3 :                         if (ast->child[1]) {
    1489             :                                 smart_str_appendc(str, ' ');
    1490           2 :                                 zend_ast_export_name(str, ast->child[1], 0, indent);
    1491             :                         }
    1492           3 :                         break;
    1493             : 
    1494             :                 /* 3 child nodes */
    1495             :                 case ZEND_AST_METHOD_CALL:
    1496          12 :                         zend_ast_export_ex(str, ast->child[0], 0, indent);
    1497             :                         smart_str_appends(str, "->");
    1498          12 :                         zend_ast_export_var(str, ast->child[1], 0, indent);
    1499             :                         smart_str_appendc(str, '(');
    1500          12 :                         zend_ast_export_ex(str, ast->child[2], 0, indent);
    1501             :                         smart_str_appendc(str, ')');
    1502          12 :                         break;
    1503             :                 case ZEND_AST_STATIC_CALL:
    1504           3 :                         zend_ast_export_ns_name(str, ast->child[0], 0, indent);
    1505             :                         smart_str_appends(str, "::");
    1506           3 :                         zend_ast_export_var(str, ast->child[1], 0, indent);
    1507             :                         smart_str_appendc(str, '(');
    1508           3 :                         zend_ast_export_ex(str, ast->child[2], 0, indent);
    1509             :                         smart_str_appendc(str, ')');
    1510           3 :                         break;
    1511             :                 case ZEND_AST_CONDITIONAL:
    1512           2 :                         if (priority > 100) smart_str_appendc(str, '(');
    1513           2 :                         zend_ast_export_ex(str, ast->child[0], 100, indent);
    1514           2 :                         if (ast->child[1]) {
    1515             :                                 smart_str_appends(str, " ? ");
    1516           1 :                                 zend_ast_export_ex(str, ast->child[1], 101, indent);
    1517             :                                 smart_str_appends(str, " : ");
    1518             :                         } else {
    1519             :                                 smart_str_appends(str, " ?: ");
    1520             :                         }
    1521           2 :                         zend_ast_export_ex(str, ast->child[2], 101, indent);
    1522           2 :                         if (priority > 100) smart_str_appendc(str, ')');
    1523           2 :                         break;
    1524             : 
    1525             :                 case ZEND_AST_TRY:
    1526             :                         smart_str_appends(str, "try {\n");
    1527           1 :                         zend_ast_export_stmt(str, ast->child[0], indent + 1);
    1528           1 :                         zend_ast_export_indent(str, indent);
    1529           1 :                         zend_ast_export_ex(str, ast->child[1], 0, indent);
    1530           1 :                         if (ast->child[2]) {
    1531             :                                 smart_str_appends(str, "} finally {\n");
    1532           1 :                                 zend_ast_export_stmt(str, ast->child[2], indent + 1);
    1533           1 :                                 zend_ast_export_indent(str, indent);
    1534             :                         }
    1535             :                         smart_str_appendc(str, '}');
    1536           1 :                         break;
    1537             :                 case ZEND_AST_CATCH:
    1538             :                         smart_str_appends(str, "} catch (");
    1539           2 :                         zend_ast_export_ns_name(str, ast->child[0], 0, indent);
    1540             :                         smart_str_appends(str, " $");
    1541           2 :                         zend_ast_export_var(str, ast->child[1], 0, indent);
    1542             :                         smart_str_appends(str, ") {\n");
    1543           2 :                         zend_ast_export_stmt(str, ast->child[2], indent + 1);
    1544           2 :                         zend_ast_export_indent(str, indent);
    1545           2 :                         break;
    1546             :                 case ZEND_AST_PARAM:
    1547           7 :                         if (ast->child[0]) {
    1548           7 :                                 zend_ast_export_ns_name(str, ast->child[0], 0, indent);
    1549             :                                 smart_str_appendc(str, ' ');
    1550             :                         }
    1551           7 :                         if (ast->attr & ZEND_PARAM_REF) {
    1552             :                                 smart_str_appendc(str, '&');
    1553             :                         }
    1554           7 :                         if (ast->attr & ZEND_PARAM_VARIADIC) {
    1555             :                                 smart_str_appends(str, "...");
    1556             :                         }
    1557             :                         smart_str_appendc(str, '$');
    1558           7 :                         zend_ast_export_name(str, ast->child[1], 0, indent);
    1559           7 :                         APPEND_DEFAULT_VALUE(2);
    1560             : 
    1561             :                 /* 4 child nodes */
    1562             :                 case ZEND_AST_FOR:
    1563             :                         smart_str_appends(str, "for (");
    1564           1 :                         zend_ast_export_ex(str, ast->child[0], 0, indent);
    1565             :                         smart_str_appendc(str, ';');
    1566           1 :                         if (ast->child[1]) {
    1567             :                                 smart_str_appendc(str, ' ');
    1568           1 :                                 zend_ast_export_ex(str, ast->child[1], 0, indent);
    1569             :                         }
    1570             :                         smart_str_appendc(str, ';');
    1571           1 :                         if (ast->child[2]) {
    1572             :                                 smart_str_appendc(str, ' ');
    1573           1 :                                 zend_ast_export_ex(str, ast->child[2], 0, indent);
    1574             :                         }
    1575             :                         smart_str_appends(str, ") {\n");
    1576           1 :                         zend_ast_export_stmt(str, ast->child[3], indent + 1);
    1577           1 :                         zend_ast_export_indent(str, indent);
    1578             :                         smart_str_appendc(str, '}');
    1579           1 :                         break;
    1580             :                 case ZEND_AST_FOREACH:
    1581             :                         smart_str_appends(str, "foreach (");
    1582           1 :                         zend_ast_export_ex(str, ast->child[0], 0, indent);
    1583             :                         smart_str_appends(str, " as ");
    1584           1 :                         if (ast->child[2]) {
    1585           1 :                                 zend_ast_export_ex(str, ast->child[2], 0, indent);
    1586             :                                 smart_str_appends(str, " => ");
    1587             :                         }
    1588           1 :                         zend_ast_export_ex(str, ast->child[1], 0, indent);
    1589             :                         smart_str_appends(str, ") {\n");
    1590           1 :                         zend_ast_export_stmt(str, ast->child[3], indent + 1);
    1591           1 :                         zend_ast_export_indent(str, indent);
    1592             :                         smart_str_appendc(str, '}');
    1593             :                         break;
    1594             :                 EMPTY_SWITCH_DEFAULT_CASE();
    1595             :         }
    1596         812 :         return;
    1597             : 
    1598             : binary_op:
    1599         168 :         if (priority > p) smart_str_appendc(str, '(');
    1600         168 :         zend_ast_export_ex(str, ast->child[0], pl, indent);
    1601         168 :         smart_str_appends(str, op);
    1602         168 :         zend_ast_export_ex(str, ast->child[1], pr, indent);
    1603         168 :         if (priority > p) smart_str_appendc(str, ')');
    1604         168 :         return;
    1605             : 
    1606             : prefix_op:
    1607          43 :         if (priority > p) smart_str_appendc(str, '(');
    1608          43 :         smart_str_appends(str, op);
    1609          43 :         zend_ast_export_ex(str, ast->child[0], pl, indent);
    1610          43 :         if (priority > p) smart_str_appendc(str, ')');
    1611          43 :         return;
    1612             : 
    1613             : postfix_op:
    1614           4 :         if (priority > p) smart_str_appendc(str, '(');
    1615           4 :         zend_ast_export_ex(str, ast->child[0], pl, indent);
    1616           4 :         smart_str_appends(str, op);
    1617           4 :         if (priority > p) smart_str_appendc(str, ')');
    1618           4 :         return;
    1619             : 
    1620             : func_op:
    1621           4 :         smart_str_appends(str, op);
    1622             :         smart_str_appendc(str, '(');
    1623           4 :         zend_ast_export_ex(str, ast->child[0], 0, indent);
    1624             :         smart_str_appendc(str, ')');
    1625           4 :         return;
    1626             : 
    1627             : append_node_1:
    1628          16 :         smart_str_appends(str, op);
    1629          16 :         if (ast->child[0]) {
    1630             :                 smart_str_appendc(str, ' ');
    1631          13 :                 ast = ast->child[0];
    1632          13 :                 goto tail_call;
    1633             :         }
    1634           3 :         return;
    1635             : 
    1636             : append_str:
    1637           4 :         smart_str_appends(str, op);
    1638           4 :         return;
    1639             : 
    1640             : append_default_value:
    1641          19 :         if (ast->child[p]) {
    1642             :                 smart_str_appends(str, " = ");
    1643          12 :                 ast = ast->child[p];
    1644          12 :                 goto tail_call;
    1645             :         }
    1646           7 :         return;
    1647             : }
    1648             : 
    1649         159 : ZEND_API zend_string *zend_ast_export(const char *prefix, zend_ast *ast, const char *suffix)
    1650             : {
    1651         159 :         smart_str str = {0};
    1652             : 
    1653         159 :         smart_str_appends(&str, prefix);
    1654         159 :         zend_ast_export_ex(&str, ast, 0, 0);
    1655         159 :         smart_str_appends(&str, suffix);
    1656             :         smart_str_0(&str);
    1657         159 :         return str.s;
    1658             : }

Generated by: LCOV version 1.10

Generated at Sat, 27 Jun 2015 09:41:05 +0000 (2 days ago)

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