diff options
author | Andi Gutmans <andi@php.net> | 2002-01-13 20:21:55 +0000 |
---|---|---|
committer | Andi Gutmans <andi@php.net> | 2002-01-13 20:21:55 +0000 |
commit | f1e8815c26cae7cdc6ce7975688866e8dba1dbc6 (patch) | |
tree | 2b83bff02dce11f6d02c77531953c24d55b4d379 /Zend | |
parent | 4cfbd67b0815dbe4fb1a7e1d4e877d725ea1063d (diff) | |
download | php-git-f1e8815c26cae7cdc6ce7975688866e8dba1dbc6.tar.gz |
- Change exception handling to use the Java-like catch(MyException $exception)
- semantics. Example:
<?php
class MyException {
function __construct($exception)
{
$this->exception = $exception;
}
function Display()
{
print "MyException: $this->exception\n";
}
}
class MyExceptionFoo extends MyException {
function __construct($exception)
{
$this->exception = $exception;
}
function Display()
{
print "MyException: $this->exception\n";
}
}
try {
throw new MyExceptionFoo("Hello");
} catch (MyException $exception) {
$exception->Display();
}
?>
Diffstat (limited to 'Zend')
-rw-r--r-- | Zend/zend_compile.c | 18 | ||||
-rw-r--r-- | Zend/zend_compile.h | 2 | ||||
-rw-r--r-- | Zend/zend_execute.c | 35 | ||||
-rw-r--r-- | Zend/zend_globals.h | 1 | ||||
-rw-r--r-- | Zend/zend_language_parser.y | 6 |
5 files changed, 43 insertions, 19 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 472c85daf9..55a3e5e756 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -958,13 +958,18 @@ void zend_do_begin_dynamic_function_call(znode *function_name TSRMLS_DC) void do_fetch_class(znode *result, znode *class_entry, znode *class_name TSRMLS_DC) { - zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + long fetch_class_op_number; + zend_op *opline; + + fetch_class_op_number = get_next_op_number(CG(active_op_array)); + opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_FETCH_CLASS; if (class_entry) { opline->op1 = *class_entry; } else { SET_UNUSED(opline->op1); + CG(catch_begin) = fetch_class_op_number; } zend_str_tolower(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len); if ((class_name->u.constant.value.str.len == (sizeof("self") - 1)) && @@ -1261,17 +1266,18 @@ static void throw_list_applier(long *opline_num, long *catch_opline) } } -void zend_do_begin_catch(znode *try_token, znode *catch_var TSRMLS_DC) +void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var TSRMLS_DC) { long catch_op_number = get_next_op_number(CG(active_op_array)); zend_op *opline; opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_CATCH; - opline->op1 = *catch_var; - SET_UNUSED(opline->op2); + opline->op1 = *catch_class; + 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, &catch_op_number TSRMLS_CC); + 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; @@ -1281,7 +1287,7 @@ void zend_do_begin_catch(znode *try_token, znode *catch_var TSRMLS_DC) void zend_do_end_catch(znode *try_token TSRMLS_DC) { - CG(active_op_array)->opcodes[try_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); + CG(active_op_array)->opcodes[try_token->u.opline_num].extended_value = get_next_op_number(CG(active_op_array)); } void zend_do_throw(znode *expr TSRMLS_DC) diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index d95cdb849f..621bd8b5f8 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -281,7 +281,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_var TSRMLS_DC); +void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var 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_execute.c b/Zend/zend_execute.c index f304028c24..e89038f31e 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1937,7 +1937,10 @@ do_fcall_common: zval *exception; value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - + + if (value->type != IS_OBJECT) { + zend_error(E_ERROR, "Can only throw objects"); + } /* Not sure if a complete copy is what we want here */ MAKE_STD_ZVAL(exception); *exception = *value; @@ -1956,15 +1959,31 @@ do_fcall_common: } NEXT_OPCODE(); case ZEND_CATCH: - /* Check if this is really an exception, if not, jump over code */ - if (EG(exception) == NULL) { - EX(opline) = &op_array->opcodes[EX(opline)->op2.u.opline_num]; + { + zend_class_entry *ce; + + /* Check if this is really an exception, if not, jump over code */ + if (EG(exception) == NULL) { + EX(opline) = &op_array->opcodes[EX(opline)->extended_value]; continue; + } + ce = Z_OBJCE_P(EG(exception)); + if (ce != EX(Ts)[EX(opline)->op1.u.var].EA.class_entry) { + while (ce->parent) { + if (ce->parent == EX(Ts)[EX(opline)->op1.u.var].EA.class_entry) { + goto exception_should_be_taken; + } + ce = ce->parent; + } + EX(opline) = &op_array->opcodes[EX(opline)->extended_value]; + continue; + } +exception_should_be_taken: + zend_hash_update(EG(active_symbol_table), EX(opline)->op2.u.constant.value.str.val, + EX(opline)->op2.u.constant.value.str.len+1, &EG(exception), sizeof(zval *), (void **) NULL); + EG(exception) = NULL; + NEXT_OPCODE(); } - zend_hash_update(EG(active_symbol_table), EX(opline)->op1.u.constant.value.str.val, - EX(opline)->op1.u.constant.value.str.len+1, &EG(exception), sizeof(zval *), (void **) NULL); - EG(exception) = NULL; - NEXT_OPCODE(); case ZEND_NAMESPACE: { #if 0 diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index fa7de6d92a..2ac149e47b 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -111,6 +111,7 @@ struct _zend_compiler_globals { zend_llist open_files; zend_llist *throw_list; + long catch_begin; struct _zend_ini_parser_param *ini_parser_param; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index fac50ff644..38805c68e8 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -206,11 +206,9 @@ 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 '(' T_VARIABLE ')' { zend_do_begin_catch(&$1, &$8 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } + 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); } | 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); } - | T_NAMESPACE namespace_class_entry ';' { do_namespace(&$2 TSRMLS_CC); } - | T_NAMESPACE ';' { do_namespace(NULL TSRMLS_CC); } ; unset_variables: @@ -531,7 +529,7 @@ parse_class_name_entry: | T_STRING T_PAAMAYIM_NEKUDOTAYIM { $$ = $1; zend_str_tolower($$.u.constant.value.str.val, $$.u.constant.value.str.len); } ; -namespace_class_entry: +catch_class_entry: parse_class_entry T_STRING { do_fetch_class(&$$, &$1, &$2 TSRMLS_CC); } | T_STRING { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); } ; |