summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndi Gutmans <andi@php.net>2002-02-13 19:26:07 +0000
committerAndi Gutmans <andi@php.net>2002-02-13 19:26:07 +0000
commit21b04ff2a6cf1b6f8e9a50d538d7ae41a5c50214 (patch)
treef0a6d32f9f21097980ce08a626b46d3465685b4b
parentd43e8898547184c3031f74cf2e93fdad59502a18 (diff)
downloadphp-git-21b04ff2a6cf1b6f8e9a50d538d7ae41a5c50214.tar.gz
@ Allow a series of consecutive catch() statements (Andi, Zend Engine)
<?php class MyException1 { } class MyException2 { } try { throw new MyException2(); } catch (MyException1 $m) { print "Caught MyException1"; } catch (MyException2 $m) { print "Caught MyException2"; }
-rw-r--r--Zend/zend_compile.c13
-rw-r--r--Zend/zend_compile.h2
-rw-r--r--Zend/zend_language_parser.y8
3 files changed, 15 insertions, 8 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index b4010ea1a4..865cdfc1dc 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -1255,7 +1255,7 @@ static void throw_list_applier(long *opline_num, long *catch_opline)
}
}
-void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var TSRMLS_DC)
+void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, zend_bool first_catch TSRMLS_DC)
{
long catch_op_number = get_next_op_number(CG(active_op_array));
zend_op *opline;
@@ -1266,11 +1266,12 @@ void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var
SET_UNUSED(opline->op1); /* FIXME: Define IS_CLASS or something like that */
opline->op2 = *catch_var;
- zend_llist_apply_with_argument(CG(throw_list), (llist_apply_with_arg_func_t) throw_list_applier, &CG(catch_begin) TSRMLS_CC);
- zend_llist_destroy(CG(throw_list));
- efree(CG(throw_list));
- CG(throw_list) = (void *) try_token->throw_list;
-
+ if (first_catch) {
+ zend_llist_apply_with_argument(CG(throw_list), (llist_apply_with_arg_func_t) throw_list_applier, &CG(catch_begin) TSRMLS_CC);
+ zend_llist_destroy(CG(throw_list));
+ efree(CG(throw_list));
+ CG(throw_list) = (void *) try_token->throw_list;
+ }
try_token->u.opline_num = catch_op_number;
}
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 52d43d2b88..0a07932ee7 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -279,7 +279,7 @@ void zend_do_end_function_call(znode *function_name, znode *result, znode *argum
void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC);
void zend_do_try(znode *try_token TSRMLS_DC);
-void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var TSRMLS_DC);
+void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, zend_bool first_catch TSRMLS_DC);
void zend_do_end_catch(znode *try_token TSRMLS_DC);
void zend_do_throw(znode *expr TSRMLS_DC);
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 8d61e973ca..30f04d874a 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -206,11 +206,17 @@ unticked_statement:
| T_DECLARE { zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(TSRMLS_C); }
| ';' /* empty statement */
| T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}'
- T_CATCH '(' catch_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$1, &$8, &$9 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
+ catches
| T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); }
| T_DELETE cvar ';' { zend_do_end_variable_parse(BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1, ZEND_UNSET_OBJ TSRMLS_CC); }
;
+catches:
+ catches T_CATCH '(' catch_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$2, &$4, &$5, 0 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$2 TSRMLS_CC); }
+ | T_CATCH '(' catch_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$4, 1 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); }
+;
+
+
unset_variables:
unset_variable
| unset_variables ',' unset_variable