static void zend_persist_ast_calc(zend_ast *ast) { uint32_t i; if (ast->kind == ZEND_AST_ZVAL) { ADD_SIZE(sizeof(zend_ast_zval)); zend_persist_zval_calc(zend_ast_get_zval(ast)); } else if (zend_ast_is_list(ast)) { zend_ast_list *list = zend_ast_get_list(ast); ADD_SIZE(sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children); for (i = 0; i < list->children; i++) { if (list->child[i]) { zend_persist_ast_calc(list->child[i]); } } } else { uint32_t children = zend_ast_get_num_children(ast); ADD_SIZE(sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children); for (i = 0; i < children; i++) { if (ast->child[i]) { zend_persist_ast_calc(ast->child[i]); } } } }
static inline zend_bool ast_is_name(zend_ast *ast, zend_ast *parent, uint32_t i) { if (!ast || ast->kind != ZEND_AST_ZVAL || Z_TYPE_P(zend_ast_get_zval(ast)) != IS_STRING) { return 0; } if (parent->kind == ZEND_AST_NAME_LIST) { return 1; } if (i == 0) { return parent->kind == ZEND_AST_CATCH || parent->kind == ZEND_AST_CLASS || parent->kind == ZEND_AST_PARAM || parent->kind == ZEND_AST_METHOD_REFERENCE || parent->kind == ZEND_AST_CALL || parent->kind == ZEND_AST_CONST || parent->kind == ZEND_AST_NEW || parent->kind == ZEND_AST_STATIC_CALL || parent->kind == ZEND_AST_CLASS_CONST || parent->kind == ZEND_AST_STATIC_PROP ; } if (i == 1) { return parent->kind == ZEND_AST_INSTANCEOF; } if (i == 3) { return parent->kind == ZEND_AST_FUNC_DECL || parent->kind == ZEND_AST_CLOSURE || parent->kind == ZEND_AST_METHOD; } return 0; }
static void ast_create_virtual_node( zval *zv, zend_ast_kind kind, zend_ast *ast, zend_long version) { zval tmp_zv, tmp_zv2; object_init_ex(zv, ast_node_ce); ZVAL_LONG(&tmp_zv, kind); ast_update_property(zv, AST_STR(kind), &tmp_zv, AST_CACHE_SLOT_KIND); ZVAL_LONG(&tmp_zv, ast->attr); ast_update_property(zv, AST_STR(flags), &tmp_zv, AST_CACHE_SLOT_FLAGS); ZVAL_LONG(&tmp_zv, zend_ast_get_lineno(ast)); ast_update_property(zv, AST_STR(lineno), &tmp_zv, AST_CACHE_SLOT_LINENO); array_init(&tmp_zv); ast_update_property(zv, AST_STR(children), &tmp_zv, AST_CACHE_SLOT_CHILDREN); ZVAL_COPY(&tmp_zv2, zend_ast_get_zval(ast)); if (version >= 30) { zend_hash_add_new(Z_ARRVAL(tmp_zv), ast_kind_child_name(kind, 0), &tmp_zv2); } else { zend_hash_next_index_insert(Z_ARRVAL(tmp_zv), &tmp_zv2); } }
static void ast_create_virtual_node(zval *zv, zend_ast_kind kind, zend_ast *ast) { zval tmp_zv, tmp_zv2; object_init_ex(zv, ast_node_ce); ZVAL_LONG(&tmp_zv, kind); ast_update_property(zv, AST_G(str_kind), &tmp_zv, AST_CACHE_SLOT_KIND); ZVAL_LONG(&tmp_zv, ast->attr); ast_update_property(zv, AST_G(str_flags), &tmp_zv, AST_CACHE_SLOT_FLAGS); ZVAL_LONG(&tmp_zv, zend_ast_get_lineno(ast)); ast_update_property(zv, AST_G(str_lineno), &tmp_zv, AST_CACHE_SLOT_LINENO); array_init(&tmp_zv); ast_update_property(zv, AST_G(str_children), &tmp_zv, AST_CACHE_SLOT_CHILDREN); ZVAL_COPY(&tmp_zv2, zend_ast_get_zval(ast)); zend_hash_next_index_insert(Z_ARRVAL(tmp_zv), &tmp_zv2); }
static zend_ast *zend_ast_clone(zend_ast *ast) { uint32_t i; if (ast->kind == ZEND_AST_ZVAL) { zend_ast_zval *copy = emalloc(sizeof(zend_ast_zval)); copy->kind = ZEND_AST_ZVAL; copy->attr = ast->attr; ZVAL_COPY_VALUE(©->val, zend_ast_get_zval(ast)); zend_clone_zval(©->val, 0); return (zend_ast *) copy; } else if (zend_ast_is_list(ast)) { zend_ast_list *list = zend_ast_get_list(ast); zend_ast_list *copy = emalloc( sizeof(zend_ast_list) - sizeof(zend_ast *) + sizeof(zend_ast *) * list->children); copy->kind = list->kind; copy->attr = list->attr; copy->children = list->children; for (i = 0; i < list->children; i++) { if (list->child[i]) { copy->child[i] = zend_ast_clone(list->child[i]); } else { copy->child[i] = NULL; } } return (zend_ast *) copy; } else { uint32_t children = zend_ast_get_num_children(ast); zend_ast *copy = emalloc(sizeof(zend_ast) - sizeof(zend_ast *) + sizeof(zend_ast *) * children); copy->kind = ast->kind; copy->attr = ast->attr; for (i = 0; i < children; i++) { if (ast->child[i]) { copy->child[i] = zend_ast_clone(ast->child[i]); } else { copy->child[i] = NULL; } } return copy; } }
static void ast_to_zval(zval *zv, zend_ast *ast) { zval tmp_zv; zend_bool is_decl; if (ast == NULL) { ZVAL_NULL(zv); return; } if (ast->kind == ZEND_AST_ZVAL) { ZVAL_COPY(zv, zend_ast_get_zval(ast)); return; } is_decl = ast_kind_is_decl(ast->kind); object_init_ex(zv, is_decl ? ast_decl_ce : ast_node_ce); ZVAL_LONG(&tmp_zv, ast->kind); ast_update_property(zv, AST_G(str_kind), &tmp_zv, AST_CACHE_SLOT_KIND); ZVAL_LONG(&tmp_zv, zend_ast_get_lineno(ast)); ast_update_property(zv, AST_G(str_lineno), &tmp_zv, AST_CACHE_SLOT_LINENO); if (is_decl) { zend_ast_decl *decl = (zend_ast_decl *) ast; ZVAL_LONG(&tmp_zv, decl->flags); ast_update_property(zv, AST_G(str_flags), &tmp_zv, NULL); ZVAL_LONG(&tmp_zv, decl->end_lineno); ast_update_property(zv, AST_G(str_endLineno), &tmp_zv, NULL); if (decl->name) { ZVAL_STR_COPY(&tmp_zv, decl->name); } else { ZVAL_NULL(&tmp_zv); } ast_update_property(zv, AST_G(str_name), &tmp_zv, NULL); if (decl->doc_comment) { ZVAL_STR_COPY(&tmp_zv, decl->doc_comment); } else { ZVAL_NULL(&tmp_zv); } ast_update_property(zv, AST_G(str_docComment), &tmp_zv, NULL); } else { ZVAL_LONG(&tmp_zv, ast->attr); ast_update_property(zv, AST_G(str_flags), &tmp_zv, AST_CACHE_SLOT_FLAGS); } if (ast->kind == ZEND_AST_PROP_DECL) { zend_ast_list *props = zend_ast_get_list(ast); zend_ast *last_prop = props->child[props->children - 1]; /* PROP_DECL stores the doc comment as last property */ if (last_prop->kind == ZEND_AST_ZVAL) { props->children -= 1; ZVAL_STR(&tmp_zv, zend_ast_get_str(last_prop)); ast_update_property(zv, AST_G(str_docComment), &tmp_zv, NULL); } } array_init(&tmp_zv); ast_update_property(zv, AST_G(str_children), &tmp_zv, AST_CACHE_SLOT_CHILDREN); { uint32_t i, count; zend_ast **children = ast_get_children(ast, &count); for (i = 0; i < count; ++i) { zend_ast *child = children[i]; zval child_zv; if (ast_is_name(child, ast, i)) { ast_create_virtual_node(&child_zv, AST_NAME, child); } else if (ast->kind == ZEND_AST_CLOSURE_USES) { ast_create_virtual_node(&child_zv, AST_CLOSURE_VAR, child); } else { ast_to_zval(&child_zv, child); } zend_hash_next_index_insert(Z_ARRVAL(tmp_zv), &child_zv); } } }
static void ast_to_zval(zval *zv, zend_ast *ast, zend_long version) { zval tmp_zv; zend_bool is_decl; if (ast == NULL) { ZVAL_NULL(zv); return; } if (ast->kind == ZEND_AST_ZVAL) { ZVAL_COPY(zv, zend_ast_get_zval(ast)); return; } if (version >= 20) { switch (ast->kind) { case ZEND_AST_ASSIGN_OP: ast->attr = ast_assign_op_to_binary_op(ast->attr); break; case ZEND_AST_GREATER: ast->kind = ZEND_AST_BINARY_OP; ast->attr = AST_BINARY_IS_GREATER; break; case ZEND_AST_GREATER_EQUAL: ast->kind = ZEND_AST_BINARY_OP; ast->attr = AST_BINARY_IS_GREATER_OR_EQUAL; break; case ZEND_AST_OR: ast->kind = ZEND_AST_BINARY_OP; ast->attr = AST_BINARY_BOOL_OR; break; case ZEND_AST_AND: ast->kind = ZEND_AST_BINARY_OP; ast->attr = AST_BINARY_BOOL_AND; break; case ZEND_AST_SILENCE: ast->kind = ZEND_AST_UNARY_OP; ast->attr = AST_SILENCE; break; case ZEND_AST_UNARY_PLUS: ast->kind = ZEND_AST_UNARY_OP; ast->attr = AST_PLUS; break; case ZEND_AST_UNARY_MINUS: ast->kind = ZEND_AST_UNARY_OP; ast->attr = AST_MINUS; break; } } is_decl = ast_kind_is_decl(ast->kind); object_init_ex(zv, is_decl ? ast_decl_ce : ast_node_ce); ZVAL_LONG(&tmp_zv, ast->kind); ast_update_property(zv, AST_STR(kind), &tmp_zv, AST_CACHE_SLOT_KIND); ZVAL_LONG(&tmp_zv, zend_ast_get_lineno(ast)); ast_update_property(zv, AST_STR(lineno), &tmp_zv, AST_CACHE_SLOT_LINENO); if (is_decl) { zend_ast_decl *decl = (zend_ast_decl *) ast; ZVAL_LONG(&tmp_zv, decl->flags); ast_update_property(zv, AST_STR(flags), &tmp_zv, NULL); ZVAL_LONG(&tmp_zv, decl->end_lineno); ast_update_property(zv, AST_STR(endLineno), &tmp_zv, NULL); if (decl->name) { ZVAL_STR_COPY(&tmp_zv, decl->name); } else { ZVAL_NULL(&tmp_zv); } ast_update_property(zv, AST_STR(name), &tmp_zv, NULL); if (decl->doc_comment) { ZVAL_STR_COPY(&tmp_zv, decl->doc_comment); } else { ZVAL_NULL(&tmp_zv); } ast_update_property(zv, AST_STR(docComment), &tmp_zv, NULL); } else { ZVAL_LONG(&tmp_zv, ast->attr); ast_update_property(zv, AST_STR(flags), &tmp_zv, AST_CACHE_SLOT_FLAGS); } if (version < 15 && ast->kind == ZEND_AST_PROP_DECL) { /* Before version 15 the first docComment was stored on the PROP_DECL */ zend_ast_list *props = zend_ast_get_list(ast); uint32_t i; for (i = 0; i < props->children; ++i) { zend_ast *prop = props->child[i]; if (prop->child[2]) { ZVAL_STR_COPY(&tmp_zv, zend_ast_get_str(prop->child[2])); ast_update_property(zv, AST_STR(docComment), &tmp_zv, NULL); break; } } } if (version >= 15 && ast->kind == ZEND_AST_PROP_ELEM && ast->child[2]) { ZVAL_STR_COPY(&tmp_zv, zend_ast_get_str(ast->child[2])); ast_update_property(zv, AST_STR(docComment), &tmp_zv, NULL); } array_init(&tmp_zv); ast_update_property(zv, AST_STR(children), &tmp_zv, AST_CACHE_SLOT_CHILDREN); ast_fill_children_ht(Z_ARRVAL(tmp_zv), ast, version); }