cvs: ZendEngine2 / zend_exceptions.c

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

  Modified files:              
    /ZendEngine2	zend_exceptions.c 
  Log:
  - Add support for linking exceptions (implements TODO)
  # Right now backtrace is broken, for internal functions I only see the
  # first char and debugging reveals the length of the function name is seen
  # as one when building the trace. There is something out of the scope of
  # this patch broken.

-- 
Zend Engine CVS Mailing List (http://cvs.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
helly-20080712145651.txt (text/plain, 10.8 KB)
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_exceptions.c?r1=1.120&r2=1.121&diff_format=u
Index: ZendEngine2/zend_exceptions.c
diff -u ZendEngine2/zend_exceptions.c:1.120 ZendEngine2/zend_exceptions.c:1.121
--- ZendEngine2/zend_exceptions.c:1.120	Thu Apr 17 10:21:25 2008
+++ ZendEngine2/zend_exceptions.c	Sat Jul 12 14:56:51 2008
@@ -19,7 +19,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_exceptions.c,v 1.120 2008/04/17 10:21:25 dmitry Exp $ */
+/* $Id: zend_exceptions.c,v 1.121 2008/07/12 14:56:51 helly Exp $ */
 
 #include "zend.h"
 #include "zend_API.h"
@@ -33,13 +33,11 @@
 static zend_object_handlers default_exception_handlers;
 ZEND_API void (*zend_throw_exception_hook)(zval *ex TSRMLS_DC);
 
-
 void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */
 {
 	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;
 	}
@@ -122,17 +120,17 @@
 }
 /* }}} */
 
-/* {{{ proto Exception::__construct(string message, int code) U
+/* {{{ proto Exception::__construct(string message, int code [, Exception previous]) U
    Exception constructor */
 ZEND_METHOD(exception, __construct)
 {
 	void  *message = NULL;
 	long   code = 0;
-	zval  *object;
+	zval  *object, *previous = NULL;
 	int    argc = ZEND_NUM_ARGS(), message_len;
 	zend_uchar message_type;
 
-	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|tl", &message, &message_len, &message_type, &code) == FAILURE) {
+	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|tlO", &message, &message_len, &message_type, &code, &previous, default_exception_ce) == FAILURE) {
 		zend_error(E_ERROR, "Wrong parameters for Exception([string $exception [, long $code ]])");
 	}
 
@@ -149,20 +147,24 @@
 	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]]) U
+/* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Exception previous]]]) U
    ErrorException constructor */
 ZEND_METHOD(error_exception, __construct)
 {
 	void  *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;
 	zend_uchar message_type, file_type;
 
-	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|tlltl", &message, &message_len, &message_type, &code, &severity, &filename, &filename_len, &file_type, &lineno) == FAILURE) {
+	if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|tlltlO", &message, &message_len, &message_type, &code, &severity, &filename, &filename_len, &file_type, &lineno, &previous, default_exception_ce) == FAILURE) {
 		zend_error(E_ERROR, "Wrong parameters for ErrorException([string $exception [, long $code, [ long $severity, [ string $filename, [ long $lineno ]]]]])");
 	}
 
@@ -180,6 +182,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) {
@@ -302,8 +308,8 @@
 		zval copy; \
 		int use_copy; \
 		zend_make_printable_zval((zv), &copy, &use_copy); \
-		TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
-		zval_dtor(&copy); \
+		TRACE_APPEND_STRL(Z_STRVAL_P((use_copy ? &copy : (zv))), Z_STRLEN_P((use_copy ? &copy : (zv)))); \
+		if (use_copy) zval_dtor(&copy); \
 	} else { \
 		TRACE_APPEND_STRL(Z_STRVAL_P((zv)), Z_STRLEN_P((zv))); \
 	}
@@ -311,17 +317,9 @@
 #define TRACE_APPEND_STR(val)                                            \
 	TRACE_APPEND_STRL(val, sizeof(val)-1)
 
-#define TRACE_APPEND_KEY(key)                                            \
+#define TRACE_APPEND_KEY(key,dump)                                            \
 	if (zend_ascii_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \
-		if (Z_TYPE_PP(tmp) == IS_UNICODE) { \
-			zval copy; \
-			int use_copy; \
-			zend_make_printable_zval(*tmp, &copy, &use_copy); \
-	    TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \
-	    zval_dtor(&copy); \
-		} else { \
-	    TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));           \
-	  } \
+	    TRACE_APPEND_ZVAL(*tmp);           \
 	}
 /* }}} */
 
@@ -495,9 +493,9 @@
 	} else {
 		TRACE_APPEND_STR("[internal function]: ");
 	}
-	TRACE_APPEND_KEY("class");
-	TRACE_APPEND_KEY("type");
-	TRACE_APPEND_KEY("function");
+	TRACE_APPEND_KEY("class",0);
+	TRACE_APPEND_KEY("type",0);
+	TRACE_APPEND_KEY("function",1);
 	TRACE_APPEND_CHR('(');
 	if (zend_ascii_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) {
 		int last_len = *len;
@@ -532,6 +530,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;
@@ -548,46 +555,58 @@
    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_long(&line);
-
+	exception = getThis();
 	ZVAL_ASCII_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1, 1);
 
-	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);
-	zval_dtor(&fname);
-
-	if (Z_TYPE_P(trace) != IS_STRING && Z_TYPE_P(trace) != IS_UNICODE) {
-		trace = NULL;
-	}
+	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_long(&line);
+
+		fci.size = sizeof(fci);
+		fci.function_table = &Z_OBJCE_P(getThis())->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 && Z_TYPE_P(trace) != IS_UNICODE) {
+			trace = NULL;
+		}
+
+		if (Z_UNILEN(message) > 0) {
+			len = zend_spprintf(&str, 0, "exception '%v' with message '%R' in %R:%ld\nStack trace:\n%s%s%s",
+								Z_OBJCE_P(exception)->name, Z_TYPE(message), Z_UNIVAL(message), Z_TYPE(file), Z_UNIVAL(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 '%v' in %R:%ld\nStack trace:\n%s%s%s",
+								Z_OBJCE_P(exception)->name, Z_TYPE(file), Z_UNIVAL(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);
 
-	if (Z_UNILEN(message) > 0) {
-		len = zend_spprintf(&str, 0, "exception '%v' with message '%R' in %R:%ld\nStack trace:\n%s",
-							Z_OBJCE_P(getThis())->name, Z_TYPE(message), Z_UNIVAL(message), Z_TYPE(file), Z_UNIVAL(file), Z_LVAL(line),
-							(trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n");
-	} else {
-		len = zend_spprintf(&str, 0, "exception '%v' in %R:%ld\nStack trace:\n%s",
-							Z_OBJCE_P(getThis())->name, Z_TYPE(file), Z_UNIVAL(file), Z_LVAL(line),
-							(trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n");
+		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. */
@@ -597,10 +616,6 @@
 		zval_ptr_dtor(&trace);
 	}
 
-	zval_dtor(&message);
-	zval_dtor(&file);
-	zval_dtor(&line);
-
 	RETURN_STRINGL(str, len, 0);
 }
 /* }}} */
@@ -619,6 +634,7 @@
 ZEND_BEGIN_ARG_INFO_EX(arginfo_exception___construct, 0, 0, 0)
 	ZEND_ARG_INFO(0, message)
 	ZEND_ARG_INFO(0, code)
+	ZEND_ARG_INFO(0, previous)
 ZEND_END_ARG_INFO()
 
 static const zend_function_entry default_exception_functions[] = {
@@ -629,6 +645,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}
@@ -641,6 +658,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[] = {
@@ -666,6 +684,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.