]> granicus.if.org Git - php/commitdiff
@- Added set_exception_handler() function for registering a global,
authorStig Bakken <ssb@php.net>
Fri, 16 Aug 2002 00:41:37 +0000 (00:41 +0000)
committerStig Bakken <ssb@php.net>
Fri, 16 Aug 2002 00:41:37 +0000 (00:41 +0000)
@  catch-all exception handling function (Stig)
- Added set_exception_handler() function for registering a global,
  catch-all exception handling function (Stig)

Zend/zend.c
Zend/zend_builtin_functions.c
Zend/zend_execute_API.c
Zend/zend_globals.h
tests/lang/035.phpt

index a37274a1de98cf87d013ae87967056294ba137f1..71468ae63fc8ee21567d562827f5da8a5b4e80cc 100644 (file)
@@ -45,6 +45,7 @@ BOOL WINAPI IsDebuggerPresent(VOID);
 
 /* true multithread-shared globals */
 ZEND_API zend_class_entry *zend_standard_class_def = NULL;
+ZEND_API zend_class_entry *zend_exception_class_def = NULL;
 ZEND_API int (*zend_printf)(const char *format, ...);
 ZEND_API zend_write_func_t zend_write;
 ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path);
@@ -271,6 +272,33 @@ static void register_standard_class(void)
 }
 
 
+static void register_exception_class(void)
+{
+       zend_exception_class_def = malloc(sizeof(zend_class_entry));
+       
+       zend_exception_class_def->type = ZEND_INTERNAL_CLASS;
+       zend_exception_class_def->name_length = sizeof("Exception") - 1;
+       zend_exception_class_def->name = zend_strndup("Exception", zend_exception_class_def->name_length);
+       zend_exception_class_def->parent = NULL;
+       zend_hash_init_ex(&zend_exception_class_def->default_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
+       zend_hash_init_ex(&zend_exception_class_def->private_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
+       zend_hash_init_ex(&zend_exception_class_def->protected_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
+       zend_exception_class_def->static_members = (HashTable *) malloc(sizeof(HashTable));
+       zend_hash_init_ex(zend_exception_class_def->static_members, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
+       zend_hash_init_ex(&zend_exception_class_def->constants_table, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
+       zend_hash_init_ex(&zend_exception_class_def->class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
+       zend_hash_init_ex(&zend_exception_class_def->function_table, 0, NULL, ZEND_FUNCTION_DTOR, 1, 0);
+       zend_exception_class_def->constructor = NULL;
+       zend_exception_class_def->destructor = NULL;
+       zend_exception_class_def->clone = NULL;
+       zend_exception_class_def->handle_function_call = NULL;
+       zend_exception_class_def->handle_property_get = NULL;
+       zend_exception_class_def->handle_property_set = NULL;
+       zend_exception_class_def->refcount = 1;
+       zend_hash_add(GLOBAL_CLASS_TABLE, "exception", sizeof("exception"), &zend_exception_class_def, sizeof(zend_class_entry *), NULL);
+}
+
+
 static void zend_set_default_compile_time_values(TSRMLS_D)
 {
        /* default compile-time values */
@@ -331,6 +359,7 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS
        zend_init_rsrc_plist(TSRMLS_C);
        EG(lambda_count)=0;
        EG(user_error_handler) = NULL;
+       EG(user_exception_handler) = NULL;
        EG(in_execution) = 0;
 }
 
@@ -443,9 +472,11 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i
        zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, NULL, 1, 0);
 
        register_standard_class();
+       register_exception_class();
        zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0);
        zend_init_rsrc_list_dtors();
 
+
        /* This zval can be used to initialize allocate zval's to an uninit'ed value */
        zval_used_for_init.is_ref = 0;
        zval_used_for_init.refcount = 1;
@@ -471,6 +502,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i
        zend_startup_constants();
        zend_set_default_compile_time_values(TSRMLS_C);
        EG(user_error_handler) = NULL;
+       EG(user_exception_handler) = NULL;
 #endif
        zend_register_standard_constants(TSRMLS_C);
 
@@ -828,8 +860,32 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_co
                        EG(return_value_ptr_ptr) = retval ? retval : &local_retval;
                        zend_execute(EG(active_op_array) TSRMLS_CC);
                        if (EG(exception)) {
+#if 1 /* support set_exception_handler() */
+                               if (EG(user_exception_handler)) {
+                                       zval *orig_user_exception_handler;
+                                       zval ***params, *retval2;
+                                       params = (zval ***)emalloc(sizeof(zval **));
+                                       params[0] = &EG(exception);
+                                       orig_user_exception_handler = EG(user_exception_handler);
+                                       if (call_user_function_ex(CG(function_table), NULL, orig_user_exception_handler, &retval2, 1, params, 1, NULL TSRMLS_CC) == SUCCESS) {
+                                               zval_ptr_dtor(&retval2);
+                                       }
+                                        efree(params);
+                                       zval_ptr_dtor(&EG(exception));
+                                       EG(exception) = NULL;
+                               } else {
+                                       zval_ptr_dtor(&EG(exception));
+                                       EG(exception) = NULL;
+                                       zend_error(E_ERROR, "Uncaught exception!");
+                               }
+                                if (!retval) {
+                                    zval_ptr_dtor(EG(return_value_ptr_ptr));
+                                    local_retval = NULL;
+                                }
+#else
                                zval_ptr_dtor(&EG(exception));
                                zend_error(E_ERROR, "Uncaught exception!");
+#endif
                        } else if (!retval) {
                                zval_ptr_dtor(EG(return_value_ptr_ptr));
                                local_retval = NULL;
index b826c5499194502ceab8fcc0e2c6bc6915e98f30..f58ab238767ca349d6050dbaf1c7af6aa7075a0d 100644 (file)
@@ -56,6 +56,8 @@ static ZEND_FUNCTION(get_class_methods);
 static ZEND_FUNCTION(trigger_error);
 static ZEND_FUNCTION(set_error_handler);
 static ZEND_FUNCTION(restore_error_handler);
+static ZEND_FUNCTION(set_exception_handler);
+static ZEND_FUNCTION(restore_exception_handler);
 static ZEND_FUNCTION(get_declared_classes);
 static ZEND_FUNCTION(get_defined_functions);
 static ZEND_FUNCTION(get_defined_vars);
@@ -108,6 +110,8 @@ static zend_function_entry builtin_functions[] = {
        ZEND_FALIAS(user_error,         trigger_error,          NULL)
        ZEND_FE(set_error_handler,              NULL)
        ZEND_FE(restore_error_handler,  NULL)
+       ZEND_FE(set_exception_handler,          NULL)
+       ZEND_FE(restore_exception_handler,      NULL)
        ZEND_FE(get_declared_classes, NULL)
        ZEND_FE(get_defined_functions, NULL)
        ZEND_FE(get_defined_vars,       NULL)
@@ -958,6 +962,59 @@ ZEND_FUNCTION(restore_error_handler)
 /* }}} */
 
 
+/* {{{ proto string set_exception_handler(string exception_handler)
+   Sets a user-defined exception handler function.  Returns the previously defined exception handler, or false on error */
+ZEND_FUNCTION(set_exception_handler)
+{
+       zval **exception_handler;
+       zend_bool had_orig_exception_handler=0;
+
+       if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &exception_handler)==FAILURE) {
+               ZEND_WRONG_PARAM_COUNT();
+       }
+
+       convert_to_string_ex(exception_handler);
+       if (EG(user_exception_handler)) {
+               had_orig_exception_handler = 1;
+               *return_value = *EG(user_exception_handler);
+               zval_copy_ctor(return_value);
+               zend_ptr_stack_push(&EG(user_exception_handlers), EG(user_exception_handler));
+       }
+       ALLOC_ZVAL(EG(user_exception_handler));
+
+       if (Z_STRLEN_PP(exception_handler)==0) { /* unset user-defined handler */
+               FREE_ZVAL(EG(user_exception_handler));
+               EG(user_exception_handler) = NULL;
+               RETURN_TRUE;
+       }
+
+       *EG(user_exception_handler) = **exception_handler;
+       zval_copy_ctor(EG(user_exception_handler));
+
+       if (!had_orig_exception_handler) {
+               RETURN_NULL();
+       }
+}
+/* }}} */
+
+
+/* {{{ proto void restore_exception_handler(void)
+   Restores the previously defined exception handler function */
+ZEND_FUNCTION(restore_exception_handler)
+{
+       if (EG(user_exception_handler)) {
+               zval_ptr_dtor(&EG(user_exception_handler));
+       }
+       if (zend_ptr_stack_num_elements(&EG(user_exception_handlers))==0) {
+               EG(user_exception_handler) = NULL;
+       } else {
+               EG(user_exception_handler) = zend_ptr_stack_pop(&EG(user_exception_handlers));
+       }
+       RETURN_TRUE;
+}
+/* }}} */
+
+
 static int copy_class_name(zend_class_entry **pce, int num_args, va_list args, zend_hash_key *hash_key)
 {
        zval *array = va_arg(args, zval *);
@@ -1199,7 +1256,6 @@ ZEND_FUNCTION(debug_backtrace)
        char *function_name;
        char *filename;
        char *class_name;
-       zend_uint class_name_length;
        zval *stack_frame;
 
        ptr = EG(current_execute_data);
@@ -1217,7 +1273,6 @@ ZEND_FUNCTION(debug_backtrace)
 
                if (ptr->object) {
                        class_name = Z_OBJCE(*ptr->object)->name;
-                       class_name_length = Z_OBJCE(*ptr->object)->name_length;
                }
                if (ptr->function_state.function->common.scope) {
                        class_name = ptr->function_state.function->common.scope->name;
@@ -1294,3 +1349,11 @@ ZEND_FUNCTION(get_extension_funcs)
        }
 }
 /* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
index bb14adf93d322b1ae7c2098cd76185e8fc134c80..7f7d8bce89c667e35e22d0a3dec773b17ff3dc95 100644 (file)
@@ -158,6 +158,7 @@ void init_executor(TSRMLS_D)
        EG(user_error_handler) = NULL;
 
        zend_ptr_stack_init(&EG(user_error_handlers));
+       zend_ptr_stack_init(&EG(user_exception_handlers));
 
        EG(orig_error_reporting) = EG(error_reporting);
        zend_objects_store_init(&EG(objects_store), 1024);
@@ -232,9 +233,17 @@ void shutdown_executor(TSRMLS_D)
                        FREE_ZVAL(EG(user_error_handler));
                }
 
+               if (EG(user_exception_handler)) {
+                       zval_dtor(EG(user_exception_handler));
+                       FREE_ZVAL(EG(user_exception_handler));
+               }
+
                zend_ptr_stack_clean(&EG(user_error_handlers), ZVAL_DESTRUCTOR, 1);
                zend_ptr_stack_destroy(&EG(user_error_handlers));
 
+               zend_ptr_stack_clean(&EG(user_exception_handlers), ZVAL_DESTRUCTOR, 1);
+               zend_ptr_stack_destroy(&EG(user_exception_handlers));
+
                EG(error_reporting) = EG(orig_error_reporting);
                zend_objects_store_destroy(&EG(objects_store));
        } zend_end_try();
index 6de7392e1822782f6a6a4df5f113a9d793fa8749..711c2520bcb0831d58961e62918ee79051428446 100644 (file)
@@ -193,7 +193,9 @@ struct _zend_executor_globals {
        int garbage_ptr;
 
        zval *user_error_handler;
+       zval *user_exception_handler;
        zend_ptr_stack user_error_handlers;
+       zend_ptr_stack user_exception_handlers;
 
        /* timeout support */
        int timeout_seconds;
index e02c243b39435cce9d1000256cdfedf3fa2b5eaf..5f22d52cae38012e9e2f8d3cf3b1d7898c8cbde7 100644 (file)
@@ -1,7 +1,21 @@
+--TEST--
+ZE2: set_exception_handler()
+--SKIPIF--
+<?php if (version_compare(zend_version(), "2", "<")) print "skip"; ?>
+--FILE--
+<?php
 
----- EXPECTED OUTPUT
-test_i
-test
----- ACTUAL OUTPUT
-test_itest
----- FAILED
+set_exception_handler("my_handler");
+try {
+    throw new exception();
+} catch (stdClass $e) {
+    print "BAR\n";
+}
+
+function my_handler($exception) {
+    print "FOO\n";
+}
+
+?>
+--EXPECT--
+FOO