Index: main/main.c =================================================================== RCS file: /repository/php-src/main/main.c,v retrieving revision 1.640.2.23.2.9 diff -u -p -d -r1.640.2.23.2.9 main.c --- main/main.c 16 Jun 2006 14:09:00 -0000 1.640.2.23.2.9 +++ main/main.c 11 Jul 2006 15:00:07 -0000 @@ -649,6 +649,24 @@ PHPAPI void php_set_error_handling(error } /* }}} */ +/* {{{ php_error_stack_push */ +static void php_errorstack_push(int type, const char *message, uint message_len, const char *file, uint line TSRMLS_DC) +{ + zval *error; + + if (BG(errorstack)) { + MAKE_STD_ZVAL(error); + array_init(error); + add_assoc_long_ex(error, "type", sizeof("type"), type); + add_assoc_stringl_ex(error, "message", sizeof("message"), (char *) message, message_len, 1); + add_assoc_string_ex(error, "file", sizeof("file"), (char *) file, 1); + add_assoc_long_ex(error, "line", sizeof("line"), line); + + zend_stack_push(BG(errorstack), (void *) &error, sizeof(zval *)); + } +} +/* }}} */ + /* {{{ php_error_cb extended error handling function */ static void php_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) @@ -686,6 +704,11 @@ static void php_error_cb(int type, const PG(last_error_message) = strdup(buffer); PG(last_error_file) = strdup(error_filename); PG(last_error_lineno) = error_lineno; + + /* push into errorstack */ + if (PG(track_errors)) { + php_errorstack_push(type, buffer, buffer_len, error_filename, error_lineno TSRMLS_CC); + } } /* according to error handling mode, suppress error, throw exception or show it */ Index: ext/standard/basic_functions.c =================================================================== RCS file: /repository/php-src/ext/standard/basic_functions.c,v retrieving revision 1.725.2.31.2.15 diff -u -p -d -r1.725.2.31.2.15 basic_functions.c --- ext/standard/basic_functions.c 2 Jul 2006 00:11:05 -0000 1.725.2.31.2.15 +++ ext/standard/basic_functions.c 11 Jul 2006 15:00:08 -0000 @@ -768,6 +768,20 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_error_log ZEND_END_ARG_INFO() static +ZEND_BEGIN_ARG_INFO_EX(arginfo_error_get_last, 0, 0, 0) + ZEND_ARG_INFO(0, pop) +ZEND_END_ARG_INFO() + +static +ZEND_BEGIN_ARG_INFO_EX(arginfo_error_get_all, 0, 0, 0) + ZEND_ARG_INFO(0, clean) +ZEND_END_ARG_INFO() + +static +ZEND_BEGIN_ARG_INFO_EX(arginfo_error_clear_all, 0, 0, 0) +ZEND_END_ARG_INFO() + +static ZEND_BEGIN_ARG_INFO_EX(arginfo_call_user_func, 0, 0, 1) ZEND_ARG_INFO(0, function_name) ZEND_ARG_INFO(0, parmeter) @@ -3351,6 +3365,9 @@ zend_function_entry basic_functions[] = PHP_FE(import_request_variables, arginfo_import_request_variables) PHP_FE(error_log, arginfo_error_log) + PHP_FE(error_get_last, arginfo_error_get_last) + PHP_FE(error_get_all, arginfo_error_get_all) + PHP_FE(error_clear_all, arginfo_error_clear_all) PHP_FE(call_user_func, arginfo_call_user_func) PHP_FE(call_user_func_array, arginfo_call_user_func_array) PHP_DEP_FE(call_user_method, arginfo_call_user_method) @@ -3852,6 +3869,7 @@ static void basic_globals_ctor(php_basic BG(user_compare_fci_cache) = empty_fcall_info_cache; zend_hash_init(&BG(sm_protected_env_vars), 5, NULL, NULL, 1); BG(sm_allowed_env_vars) = NULL; + BG(errorstack) = NULL; memset(&BG(url_adapt_state), 0, sizeof(BG(url_adapt_state))); memset(&BG(url_adapt_state_ex), 0, sizeof(BG(url_adapt_state_ex))); @@ -4074,6 +4092,10 @@ PHP_RINIT_FUNCTION(basic) BG(page_gid) = -1; BG(page_inode) = -1; BG(page_mtime) = -1; + + BG(errorstack) = emalloc(sizeof(zend_stack)); + zend_stack_init(BG(errorstack)); + #ifdef HAVE_PUTENV if (zend_hash_init(&BG(putenv_ht), 1, NULL, (void (*)(void *)) php_putenv_destructor, 0) == FAILURE) { return FAILURE; @@ -4105,6 +4127,7 @@ PHP_RINIT_FUNCTION(basic) return SUCCESS; } +inline void _php_errorstack_clear(zval *ar TSRMLS_DC); PHP_RSHUTDOWN_FUNCTION(basic) { @@ -4152,7 +4175,11 @@ PHP_RSHUTDOWN_FUNCTION(basic) } PHP_RSHUTDOWN(user_filters)(SHUTDOWN_FUNC_ARGS_PASSTHRU); - + + _php_errorstack_clear(NULL TSRMLS_CC); + zend_stack_destroy(BG(errorstack)); + efree(BG(errorstack)); + return SUCCESS; } @@ -4950,6 +4977,79 @@ PHPAPI int _php_error_log(int opt_err, c return SUCCESS; } +/* {{{ proto array error_get_last([bool pop = false]) + Get the last occured error and optionally pop it off the error stack */ +PHP_FUNCTION(error_get_last) +{ + zval **error = NULL; + zend_bool pop = 0; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &pop)) { + WRONG_PARAM_COUNT; + } + if (SUCCESS != zend_stack_top(BG(errorstack), (void *) &error)) { + RETURN_NULL(); + } + RETVAL_ZVAL(*error, 1, pop); + if (pop) { + zend_stack_del_top(BG(errorstack)); + } +} +/* }}} */ + +static int _php_errorstack_get_all(void *el, void *ar) +{ + zval *error = *(zval **) el; + zval *array = (zval *) ar; + + ZVAL_ADDREF(error); + add_next_index_zval(array, error); + return 0; +} + +inline void _php_errorstack_clear(zval *ar TSRMLS_DC) +{ + zval **error = NULL; + + while (SUCCESS == zend_stack_top(BG(errorstack), (void *) &error)) { + if (ar) { + ZVAL_ADDREF(*error); + add_next_index_zval(ar, *error); + } + zval_ptr_dtor(error); + zend_stack_del_top(BG(errorstack)); + } +} + +/* {{{ proto array error_get_all([bool clear = false]) + Get all accurred errors and optionally clear the error stack */ +PHP_FUNCTION(error_get_all) +{ + zend_bool clear = 0; + + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &clear)) { + WRONG_PARAM_COUNT; + } + + array_init(return_value); + if (clear) { + _php_errorstack_clear(return_value TSRMLS_CC); + } else { + zend_stack_apply_with_argument(BG(errorstack), ZEND_STACK_APPLY_TOPDOWN, _php_errorstack_get_all, return_value); + } +} + +/* {{{ proto void error_clear_all() + Clears the error stack */ +PHP_FUNCTION(error_clear_all) +{ + if (ZEND_NUM_ARGS()) { + WRONG_PARAM_COUNT; + } + _php_errorstack_clear(NULL TSRMLS_CC); +} +/* }}} */ + /* {{{ proto mixed call_user_func(string function_name [, mixed parmeter] [, mixed ...]) Call a user function which is the first parameter */ PHP_FUNCTION(call_user_func) Index: ext/standard/basic_functions.h =================================================================== RCS file: /repository/php-src/ext/standard/basic_functions.h,v retrieving revision 1.139.2.4.2.1 diff -u -p -d -r1.139.2.4.2.1 basic_functions.h --- ext/standard/basic_functions.h 14 May 2006 16:06:48 -0000 1.139.2.4.2.1 +++ ext/standard/basic_functions.h 11 Jul 2006 15:00:08 -0000 @@ -79,6 +79,9 @@ PHP_FUNCTION(get_magic_quotes_gpc); PHP_FUNCTION(import_request_variables); PHP_FUNCTION(error_log); +PHP_FUNCTION(error_get_last); +PHP_FUNCTION(error_get_all); +PHP_FUNCTION(error_clear_all); PHP_FUNCTION(call_user_func); PHP_FUNCTION(call_user_func_array); @@ -217,6 +220,8 @@ typedef struct _php_basic_globals { #endif int umask; + + zend_stack *errorstack; } php_basic_globals; #ifdef ZTS