src/PEAR/ErrorStack.php
function push($code, $level = 'error', $params = array(), $msg = false,
                  $repackage = false, $backtrace = false)
    {
        $context = false;
        // grab error context
        if ($this->_contextCallback) {
            if (!$backtrace) {
                $backtrace = debug_backtrace();
            }
            $context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
        }
        
        // save error
        $time = explode(' ', microtime());
        $time = $time[1] + $time[0];
        $err = array(
                'code' => $code,
                'params' => $params,
                'package' => $this->_package,
                'level' => $level,
                'time' => $time,
                'context' => $context,
                'message' => $msg,
               );

        if ($repackage) {
            $err['repackage'] = $repackage;
        }

        // set up the error message, if necessary
        if ($this->_msgCallback) {
            $msg = call_user_func_array($this->_msgCallback,
                                        array(&$this, $err));
            $err['message'] = $msg;
        }        
        $push = $log = true;
        $die = false;
        // try the overriding callback first
        $callback = $this->staticPopCallback();
        if ($callback) {
            $this->staticPushCallback($callback);
        }
        if (!is_callable($callback)) {
            // try the local callback next
            $callback = $this->popCallback();
            if (is_callable($callback)) {
                $this->pushCallback($callback);
            } else {
                // try the default callback
                $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ?
                    $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] :
                    $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*'];
            }
        }
        if (is_callable($callback)) {
            switch(call_user_func($callback, $err)){
            	case PEAR_ERRORSTACK_IGNORE: 
            		return $err;
        		break;
            	case PEAR_ERRORSTACK_PUSH: 
            		$log = false;
        		break;
            	case PEAR_ERRORSTACK_LOG: 
            		$push = false;
        		break;
            	case PEAR_ERRORSTACK_DIE: 
            		$die = true;
        		break;
                // anything else returned has the same effect as pushandlog
            }
        }
        if ($push) {
            array_unshift($this->_errors, $err);
            if (!isset($this->_errorsByLevel[$err['level']])) {
                $this->_errorsByLevel[$err['level']] = array();
            }
            $this->_errorsByLevel[$err['level']][] = &$this->_errors[0];
        }
        if ($log) {
            if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) {
                $this->_log($err);
            }
        }
        if ($die) {
            die();
        }
        if ($this->_compat && $push) {
            return $this->raiseError($msg, $code, null, null, $err);
        }
        return $err;
    }
function push($code, $level = 'error', $params = array(), $msg = false,
                  $repackage = false, $backtrace = false)
    {
        $context = false;
        // grab error context
        if ($this->_contextCallback) {
            if (!$backtrace) {
                $backtrace = debug_backtrace();
            }
            $context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
        }
        
        // save error
        $time = explode(' ', microtime());
        $time = $time[1] + $time[0];
        $err = array(
                'code' => $code,
                'params' => $params,
                'package' => $this->_package,
                'level' => $level,
                'time' => $time,
                'context' => $context,
                'message' => $msg,
               );

        if ($repackage) {
            $err['repackage'] = $repackage;
        }

        // set up the error message, if necessary
        if ($this->_msgCallback) {
            $msg = call_user_func_array($this->_msgCallback,
                                        array(&$this, $err));
            $err['message'] = $msg;
        }        
        $push = $log = true;
        $die = false;
        // try the overriding callback first
        $callback = $this->staticPopCallback();
        if ($callback) {
            $this->staticPushCallback($callback);
        }
        if (!is_callable($callback)) {
            // try the local callback next
            $callback = $this->popCallback();
            if (is_callable($callback)) {
                $this->pushCallback($callback);
            } else {
                // try the default callback
                $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ?
                    $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] :
                    $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*'];
            }
        }
        if (is_callable($callback)) {
            switch(call_user_func($callback, $err)){
            	case PEAR_ERRORSTACK_IGNORE: 
            		return $err;
        		break;
            	case PEAR_ERRORSTACK_PUSH: 
            		$log = false;
        		break;
            	case PEAR_ERRORSTACK_LOG: 
            		$push = false;
        		break;
            	case PEAR_ERRORSTACK_DIE: 
            		$die = true;
        		break;
                // anything else returned has the same effect as pushandlog
            }
        }
        if ($push) {
            array_unshift($this->_errors, $err);
            if (!isset($this->_errorsByLevel[$err['level']])) {
                $this->_errorsByLevel[$err['level']] = array();
            }
            $this->_errorsByLevel[$err['level']][] = &$this->_errors[0];
        }
        if ($log) {
            if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) {
                $this->_log($err);
            }
        }
        if ($die) {
            die();
        }
        if ($this->_compat && $push) {
            return $this->raiseError($msg, $code, null, null, $err);
        }
        return $err;
    }
Add an error to the stack

If the message generator exists, it is called with 2 parameters.
- the current Error Stack object
- an array that is in the same format as an error.  Available indices
are 'code', 'package', 'time', 'params', 'level', and 'context'

Next, if the error should contain context information, this is
handled by the context grabbing method.
Finally, the error is pushed onto the proper error stack
@param int    $code      Package-specific error code
@param string $level     Error level.  This is NOT spell-checked
@param array  $params    associative array of error parameters
@param string $msg       Error message, or a portion of it if the message
is to be generated
@param array  $repackage If this error re-packages an error pushed by
another package, place the array returned from
{@link pop()} in this parameter
@param array  $backtrace Protected parameter: use this to pass in the
{@link debug_backtrace()} that should be used
to find error context
@return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
thrown.  If a PEAR_Error is returned, the userinfo
property is set to the following array:

<code>
array(
'code' => $code,
'params' => $params,
'package' => $this->_package,
'level' => $level,
'time' => time(),
'context' => $context,
'message' => $msg,
//['repackage' => $err] repackaged error array/Exception class
);
</code>

Normally, the previous array is returned.