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: 673 815 82.6 %
Date: 2016-09-27 Functions: 38 38 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 27 Sep 2016 10:25:52 +0000 (4 days ago)

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