REDUCE

12.2 The Basic Error Functions

(error NUMBER: integer MESSAGE:any): None Returned expr
Under the initial (and usual) values of a couple of switches, the error message is printed and an interactive break loop (see below) is entered. If the user ”quits” out of the interactive break loop, control returns to the innermost error handler.

The user may supply an error handler. The interactive break loop and the top level loop also supply error handlers, so if the user makes no special preparation, control will return to an existing break loop or to the top level of PSL.

Whenever a call on error results in return to an error handler, the error number of the error becomes the value returned by the error handler. Fluid variables and local bindings are unbound to return to the environment of the error handler. Global variables are not affected by the process. The error message is printed with 5 leading asterisks on both the standard output device and the currently selected output device unless the standard output device is not open. If the message is a list it is displayed without top level parentheses. The message from the error call is available for later examination in the global variable emsg⋆.

Note: the exact format of error messages generated by PSL functions described in this document may not be exactly as given and should not be relied upon to be in any particular form. Likewise, error numbers generated by PSL functions are not fixed. Currently, a number of different calls on error result in the same error message and number.

(continuableerror NUMBER:integer MESSAGE:any
FORM: form): any expr
 
Similar to error. If an interactive break is entered due to a call on continuableerror, the user has options of ”continuing” or ”retrying” (see information on the break loop, below). In either of these cases the call on continuableerror returns. The value returned is as described in the documentation of the interactive break loop.

The FORM argument is used for ”retrying” after a continuable error. The FORM is generally made to look like a call on the function that signalled the error (actual argument values filled in), and the function signalling the error generally returns with the value returned by the call on continuableerror. For example the call on conterror, in the example below is equivalent to the following call on continuableerror:

(continuableerror 99 "Attempt to divide by 0 in DIVIDE"  
          (list 'divide (mkquote u) (mkquote v)))

The FORM argument may be nil. In this case it is expected that the break will be left via ”continue” rather than ”retry”.

As in the example above, setting up the errorform* can get a bit tricky, often involving mkquoteing of already evaluated arguments. The following macro may be useful.

(conterror [ARGS:any]): any macro
The format of ARGS is
(errornumber formatstring {arguments to printf} reevalform).
The FORMATSTRING is used with the following arguments in a call on bldmsg to build an error message. If the only argument to printf is a string, the FORMATSTRING may be omitted, and no call to bldmsg is made. REEVALFORM is something like (foo x y) which becomes (list 'foo (mkquote x) (mkquote y)) to be passed to the function continuableerror.
(de divide (u v)  
  (cond ((zerop v)  
          (conterror 99  
                "Attempt to divide by 0 in DIVIDE"  
                (divide u v)))  
         (t (cons (quotient u v) (remainder u v)))  
 ))

(fatalerror S:any): None Returned expr
This function allows neither continuation nor even a return to any error handler.
    (de fatalerror (s)  
      (errorprintf "⋆⋆⋆⋆⋆ Fatal error: %S" s)  
      (while t (quit))  
      nil)