Index: lang.base.php =================================================================== --- lang.base.php (revision 6237) +++ lang.base.php (working copy) @@ -51,19 +51,11 @@ function errorAt($file, $line= -1) { $errors= &xp::registry('errors'); - // If no line is requested, this is O(n) + // If no line is requested, we check for an error in the file if ($line < 0) return !empty($errors[$file]); - // Else, we'll have to search... - if (isset($errors[$file])) for ( - $i= 0, $s= sizeof($errors[$file]); - $i < $s; - $i++ - ) { - if ($line == $errors[$file][$i][2]) return TRUE; - } - - return FALSE; + // Else, we also take the line number into account + return !empty($errors[$file][$line]); } // }}} @@ -149,7 +141,7 @@ if (0 == error_reporting() || is_null($file)) return; $errors= &xp::registry('errors'); - $errors[$file][]= array($code, $msg, $line); + @$errors[$file][$line][$msg]++; xp::registry('errors', $errors); } // }}} Index: lang/Throwable.class.php =================================================================== --- lang/Throwable.class.php (revision 6237) +++ lang/Throwable.class.php (working copy) @@ -26,25 +26,27 @@ */ function __construct($message) { static $except= array( - 'call_user_func_array', 'call_user_func', 'object', '__call', '__set', '__get' + 'call_user_func_array' => 1, + 'call_user_func' => 1, + 'object' => 1 ); $this->message= $message; $errors= xp::registry('errors'); - foreach (debug_backtrace() as $trace) { - if (!isset($trace['function']) || in_array($trace['function'], $except)) continue; + foreach (debug_backtrace() as $no => $trace) { + if (!isset($trace['function']) || isset($except[$trace['function']])) continue; // Pop error messages off the copied error stack if (isset($trace['file']) && isset($errors[$trace['file']])) { $messages= $errors[$trace['file']]; unset($errors[$trace['file']]); } else { - $messages= array(); + $messages= array(array('' => 1)); } // Not all of these are always set: debug_backtrace() should // initialize these - at least - to NULL, IMO => Workaround. - $this->trace[]= &new StackTraceElement( + $this->addStackTraceFor( isset($trace['file']) ? $trace['file'] : NULL, isset($trace['class']) ? $trace['class'] : NULL, isset($trace['function']) ? $trace['function'] : NULL, @@ -60,18 +62,46 @@ ? strtolower(substr(basename($key), 0, -10)) : '
' ); - for ($i= 0, $s= sizeof($errors[$key]); $i < $s; $i++) { - $this->trace[]= &new StackTraceElement( - $key, + + foreach ($errors as $file => $list) { + $this->addStackTraceFor( + $file, $class, NULL, - $errors[$key][$i][2], + NULL, array(), - array($errors[$key][$i]) + $list ); } } } + + /** + * Adds new stacktrace elements to the internal list of stacktrace + * elements, each for one error. + * + * @access protected + * @param string file + * @param string class + * @param string function + * @param int originalline + * @param mixed[] args + * @param mixed[] errors + */ + function addStackTraceFor($file, $class, $function, $originalline, $args, $errors) { + foreach ($errors as $line => $errormsg) { + foreach ($errormsg as $message => $amount) { + $this->trace[]= &new StackTraceElement( + $file, + $class, + $function, + $originalline ? $originalline : $line, + $args, + $message.($amount > 1 ? ' (... '.($amount - 1).' more)' : '') + ); + } + } + } /** * Get Message @@ -128,7 +158,7 @@ $this->message ); for ($i= 0, $t= sizeof($this->trace); $i < $t; $i++) { - $s.= $this->trace[$i]->toString(); + $s.= $this->trace[$i]->toString(); } return $s; } Index: lang/StackTraceElement.class.php =================================================================== --- lang/StackTraceElement.class.php (revision 6237) +++ lang/StackTraceElement.class.php (working copy) @@ -18,7 +18,7 @@ $method = '', $line = 0, $args = array(), - $messages = array(); + $message = ''; /** * Constructor @@ -29,15 +29,15 @@ * @param string method * @param int line * @param array args - * @param array messages + * @param string message */ - function __construct($file, $class, $method, $line, $args, $messages) { + function __construct($file, $class, $method, $line, $args, $message) { $this->file = $file; $this->class = $class; $this->method = $method; $this->line = $line; $this->args = $args; - $this->messages = $messages; + $this->message = $message; } /** @@ -71,29 +71,15 @@ } } } - $fmt= sprintf( - " at %s::%s(%s) [line %%3\$d of %s] %%2\$s\n", + return sprintf( + " at %s::%s(%s) [line %d of %s] %s\n", isset($this->class) ? xp::nameOf($this->class) : '
', isset($this->method) ? $this->method : '
', implode(', ', $args), - basename(isset($this->file) ? $this->file : __FILE__) + $this->line, + basename(isset($this->file) ? $this->file : __FILE__), + $this->message ); - - if (!$this->messages) { - return sprintf( - $fmt, - E_USER_NOTICE, - '', - isset($this->line) ? $this->line : __LINE__ - ); - } - - $str= ''; - for ($i= 0, $s= sizeof($this->messages); $i < $s; $i++) { - $str.= rtrim(vsprintf($fmt, $this->messages[$i]))."\n"; - } - return $str; } - } ?>