]> granicus.if.org Git - php/commitdiff
- Change exception handling to use the Java-like catch(MyException $exception)
authorAndi Gutmans <andi@php.net>
Sun, 13 Jan 2002 20:21:55 +0000 (20:21 +0000)
committerAndi Gutmans <andi@php.net>
Sun, 13 Jan 2002 20:21:55 +0000 (20:21 +0000)
- 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();
}
?>

Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_globals.h
Zend/zend_language_parser.y

index 472c85daf9b5116aabf92d3eead02f1b8115743e..55a3e5e756b3ab18d8afb051fe66d7477ff4d97e 100644 (file)
@@ -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)
index d95cdb849f813f434899cfb8494bff7d40241a50..621bd8b5f8c03e3782d9a7bcaca16e3b4367c462 100644 (file)
@@ -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);
 
index f304028c24a64ce69ca6e9a2927e60f9c72fa428..e89038f31e38142bcf154eadba6a6c399c777cab 100644 (file)
@@ -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
index fa7de6d92a584c943cfe9d248ee9aea3d2cc062b..2ac149e47bf67d2e0ce23b3bcbd51ed3dc3322fe 100644 (file)
@@ -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;
 
index fac50ff64480c878658d47f76d053a9244ce7344..38805c68e8bdadee541685646adea7272271d7b0 100644 (file)
@@ -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); }
 ;