cvs: ZendEngine2(PHP_5_3) / zend_exceptions.c

"Marcus Boerger" <[email protected]>
Newsgroups gmane.comp.php.cvs.zend
Message-ID <cvshelly1215874634@cvsserver>
helly		Sat Jul 12 14:57:14 2008 UTC

  Modified files:              (Branch: PHP_5_3)
    /ZendEngine2	zend_exceptions.c 
  Log:
  - MFH Add support for linking exceptions (implements TODO)

-- 
Zend Engine CVS Mailing List (http://cvs.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
helly-20080712145714.txt (text/plain, 8.7 KB)
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_exceptions.c?r1=1.79.2.6.2.9.2.6&r2=1.79.2.6.2.9.2.7&diff_format=u
Index: ZendEngine2/zend_exceptions.c
diff -u ZendEngine2/zend_exceptions.c:1.79.2.6.2.9.2.6 ZendEngine2/zend_exceptions.c:1.79.2.6.2.9.2.7
--- ZendEngine2/zend_exceptions.c:1.79.2.6.2.9.2.6	Thu Apr 17 10:21:38 2008
+++ ZendEngine2/zend_exceptions.c	Sat Jul 12 14:57:14 2008
@@ -19,7 +19,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_exceptions.c,v 1.79.2.6.2.9.2.6 2008/04/17 10:21:38 dmitry Exp $ */
+/* $Id: zend_exceptions.c,v 1.79.2.6.2.9.2.7 2008/07/12 14:57:14 helly Exp $ */
 
 #include "zend.h"
 #include "zend_API.h"
@@ -37,8 +37,7 @@
 {
 	if (exception != NULL) {
 		if (EG(exception)) {
-			/* FIXME:  bail out? */
-			return;
+			zend_update_property(default_exception_ce, exception, "previous", sizeof("previous")-1, EG(exception) TSRMLS_CC);
 		}
 		EG(exception) = exception;
 	}
@@ -121,16 +120,16 @@
 }
 /* }}} */
 
-/* {{{ proto Exception::__construct(string message, int code)
+/* {{{ proto Exception::__construct(string message, int code [, Exception previous])
    Exception constructor */
 ZEND_METHOD(exception, __construct)
 {
 	char  *message = NULL;
 	long   code = 0;
-	zval  *object;
+	zval  *object, *previous = NULL;
 	int    argc = ZEND_NUM_ARGS(), message_len;
 
-	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|sl", &message, &message_len, &code) == FAILURE) {
+	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|slO", &message, &message_len, &code, &previous, default_exception_ce) == FAILURE) {
 		zend_error(E_ERROR, "Wrong parameters for Exception([string $exception [, long $code ]])");
 	}
 
@@ -143,19 +142,23 @@
 	if (code) {
 		zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code TSRMLS_CC);
 	}
+
+	if (previous) {
+		zend_update_property(default_exception_ce, object, "previous", sizeof("previous")-1, previous TSRMLS_CC);
+	}
 }
 /* }}} */
 
-/* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno]])
+/* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Exception previous]]])
    ErrorException constructor */
 ZEND_METHOD(error_exception, __construct)
 {
 	char  *message = NULL, *filename = NULL;
 	long   code = 0, severity = E_ERROR, lineno;
-	zval  *object;
+	zval  *object, *previous = NULL;
 	int    argc = ZEND_NUM_ARGS(), message_len, filename_len;
 
-	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|sllsl", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno) == FAILURE) {
+	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|sllslO", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno, &previous, default_exception_ce) == FAILURE) {
 		zend_error(E_ERROR, "Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno ]]]]])");
 	}
 
@@ -169,6 +172,10 @@
 		zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code TSRMLS_CC);
 	}
 
+	if (previous) {
+		zend_update_property(default_exception_ce, object, "previous", sizeof("previous")-1, previous TSRMLS_CC);
+	}
+
 	zend_update_property_long(default_exception_ce, object, "severity", sizeof("severity")-1, severity TSRMLS_CC);
 
 	if (argc >= 4) {
@@ -445,6 +452,15 @@
 }
 /* }}} */
 
+/* {{{ proto string Exception::getPrevious()
+   Return previous Exception or NULL. */
+ZEND_METHOD(exception, getPrevious)
+{
+	zval *previous;
+	previous = zend_read_property(default_exception_ce, getThis(), "previous", sizeof("previous")-1, 1 TSRMLS_CC);
+	RETURN_ZVAL(previous, 1, 0);
+}
+
 int zend_spprintf(char **message, int max_len, char *format, ...) /* {{{ */
 {
 	va_list arg;
@@ -461,47 +477,60 @@
    Obtain the string representation of the Exception object */
 ZEND_METHOD(exception, __toString)
 {
-	zval message, file, line, *trace;
-	char *str;
-	int len;
+	zval message, file, line, *trace, *exception;
+	char *str = estrndup("", 0), *prev_str;
+	int len = 0;
 	zend_fcall_info fci;
 	zval fname;
 
-	_default_exception_get_entry(getThis(), "message", sizeof("message")-1, &message TSRMLS_CC);
-	_default_exception_get_entry(getThis(), "file", sizeof("file")-1, &file TSRMLS_CC);
-	_default_exception_get_entry(getThis(), "line", sizeof("line")-1, &line TSRMLS_CC);
-
-	convert_to_string(&message);
-	convert_to_string(&file);
-	convert_to_long(&line);
-
+	exception = getThis();
 	ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1, 0);
 
-	fci.size = sizeof(fci);
-	fci.function_table = &Z_OBJCE_P(getThis())->function_table;
-	fci.function_name = &fname;
-	fci.symbol_table = NULL;
-	fci.object_pp = &getThis();
-	fci.retval_ptr_ptr = &trace;
-	fci.param_count = 0;
-	fci.params = NULL;
-	fci.no_separation = 1;
-
-	zend_call_function(&fci, NULL TSRMLS_CC);
-
-	if (Z_TYPE_P(trace) != IS_STRING) {
-		trace = NULL;
-	}
-
-	if (Z_STRLEN(message) > 0) {
-		len = zend_spprintf(&str, 0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s", 
-							Z_OBJCE_P(getThis())->name, Z_STRVAL(message), Z_STRVAL(file), Z_LVAL(line), 
-							(trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n");
-	} else {
-		len = zend_spprintf(&str, 0, "exception '%s' in %s:%ld\nStack trace:\n%s", 
-							Z_OBJCE_P(getThis())->name, Z_STRVAL(file), Z_LVAL(line), 
-							(trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n");
+	while (exception && Z_TYPE_P(exception) == IS_OBJECT) {
+		prev_str = str;
+		_default_exception_get_entry(exception, "message", sizeof("message")-1, &message TSRMLS_CC);
+		_default_exception_get_entry(exception, "file", sizeof("file")-1, &file TSRMLS_CC);
+		_default_exception_get_entry(exception, "line", sizeof("line")-1, &line TSRMLS_CC);
+
+		convert_to_string(&message);
+		convert_to_string(&file);
+		convert_to_long(&line);
+
+		fci.size = sizeof(fci);
+		fci.function_table = &Z_OBJCE_P(exception)->function_table;
+		fci.function_name = &fname;
+		fci.symbol_table = NULL;
+		fci.object_pp = &exception;
+		fci.retval_ptr_ptr = &trace;
+		fci.param_count = 0;
+		fci.params = NULL;
+		fci.no_separation = 1;
+
+		zend_call_function(&fci, NULL TSRMLS_CC);
+
+		if (Z_TYPE_P(trace) != IS_STRING) {
+			trace = NULL;
+		}
+
+		if (Z_STRLEN(message) > 0) {
+			len = zend_spprintf(&str, 0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s%s%s",
+								Z_OBJCE_P(exception)->name, Z_STRVAL(message), Z_STRVAL(file), Z_LVAL(line),
+								(trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n",
+								len ? "\n\nNext " : "", prev_str);
+		} else {
+			len = zend_spprintf(&str, 0, "exception '%s' in %s:%ld\nStack trace:\n%s%s%s",
+								Z_OBJCE_P(exception)->name, Z_STRVAL(file), Z_LVAL(line),
+								(trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n",
+								len ? "\n\nNext " : "", prev_str);
+		}
+		efree(prev_str);
+		zval_dtor(&message);
+		zval_dtor(&file);
+		zval_dtor(&line);
+
+		exception = zend_read_property(default_exception_ce, exception, "previous", sizeof("previous")-1, 0 TSRMLS_CC);
 	}
+	zval_dtor(&fname);
 
 	/* We store the result in the private property string so we can access
 	 * the result in uncaught exception handlers without memleaks. */
@@ -511,10 +540,6 @@
 		zval_ptr_dtor(&trace);
 	}
 
-	zval_dtor(&message);
-	zval_dtor(&file);
-	zval_dtor(&line);
-
 	RETURN_STRINGL(str, len, 0);
 }
 /* }}} */
@@ -543,6 +568,7 @@
 	ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
 	ZEND_ME(exception, getLine, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
 	ZEND_ME(exception, getTrace, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
+	ZEND_ME(exception, getPrevious, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
 	ZEND_ME(exception, getTraceAsString, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
 	ZEND_ME(exception, __toString, NULL, 0)
 	{NULL, NULL, NULL}
@@ -555,6 +581,7 @@
 	ZEND_ARG_INFO(0, severity)
 	ZEND_ARG_INFO(0, filename)
 	ZEND_ARG_INFO(0, lineno)
+	ZEND_ARG_INFO(0, previous)
 ZEND_END_ARG_INFO()
 
 static const zend_function_entry error_exception_functions[] = {
@@ -580,6 +607,7 @@
 	zend_declare_property_null(default_exception_ce, "file", sizeof("file")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
 	zend_declare_property_null(default_exception_ce, "line", sizeof("line")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
 	zend_declare_property_null(default_exception_ce, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
+	zend_declare_property_null(default_exception_ce, "previous", sizeof("previous")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
 
 	INIT_CLASS_ENTRY(ce, "ErrorException", error_exception_functions);
 	error_exception_ce = zend_register_internal_class_ex(&ce, default_exception_ce, NULL TSRMLS_CC);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.