From 117714d12210ed702a4caaa9879c29b3190114d4 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 9 Jul 2014 23:46:22 +0200 Subject: [PATCH] Port goto label --- Zend/zend_ast.h | 1 + Zend/zend_compile.c | 22 ++++++++++++++++++++++ Zend/zend_language_parser.y | 2 +- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 12d51dc137..cb731a39da 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -74,6 +74,7 @@ enum _zend_ast_kind { ZEND_AST_GLOBAL, ZEND_AST_UNSET, ZEND_AST_RETURN, + ZEND_AST_LABEL, }; typedef unsigned short zend_ast_kind; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 664883657a..83caf8f07f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -7036,6 +7036,25 @@ void zend_compile_goto(zend_ast *ast TSRMLS_DC) { zend_resolve_goto_label(CG(active_op_array), opline, 0 TSRMLS_CC); } +void zend_compile_label(zend_ast *ast TSRMLS_DC) { + zval *label = zend_ast_get_zval(ast->child[0]); + zend_label dest; + + ZEND_ASSERT(Z_TYPE_P(label) == IS_STRING); + + if (!CG(context).labels) { + ALLOC_HASHTABLE(CG(context).labels); + zend_hash_init(CG(context).labels, 8, NULL, ptr_dtor, 0); + } + + dest.brk_cont = CG(context).current_brk_cont; + dest.opline_num = get_next_op_number(CG(active_op_array)); + + if (!zend_hash_add_mem(CG(context).labels, Z_STR_P(label), &dest, sizeof(zend_label))) { + zend_error_noreturn(E_COMPILE_ERROR, "Label '%s' already defined", Z_STRVAL_P(label)); + } +} + void zend_compile_stmt_list(zend_ast *ast TSRMLS_DC) { zend_uint i; for (i = 0; i < ast->children; ++i) { @@ -7818,6 +7837,9 @@ void zend_compile_stmt(zend_ast *ast TSRMLS_DC) { case ZEND_GOTO: zend_compile_goto(ast TSRMLS_CC); return; + case ZEND_AST_LABEL: + zend_compile_label(ast TSRMLS_CC); + return; EMPTY_SWITCH_DEFAULT_CASE() } } diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 2743288676..e3cd937824 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -318,7 +318,7 @@ inner_statement: statement: unticked_statement { AS($$); DO_TICKS(); } - | T_STRING ':' { zend_do_label(&$1 TSRMLS_CC); } + | T_STRING ':' { $$.u.ast = zend_ast_create_unary(ZEND_AST_LABEL, AST_ZVAL(&$1)); AS($$); } ; unticked_statement: -- 2.50.1