raise errors and warnings

SYNOPSIS

#include   "matrix.h"
int   error(int err_num, char *func_name)
int   ev_err(char *file, int err_num, int line_num,
             char *fn_name, int list_num)
int   set_err_flag(int new_flag)
int   err_list_attach(int list_num, int list_len,
                    char **err_ptr, int warn)
int   err_list_free(int list_num)
int   err_is_list_attached(int list_num)
int   warning(int warn_num, char *func_name)

DESCRIPTION

This is where errors are flagged in the system. The call \newlineerror(err_num,func_name) is in fact a macro which expands to

ev_err(__FILE__,err_num,__LINE__,func_name,0)
This call does not return. Warnings are raised by warning(warn_num,func_name) which are expands to
ev_err(__FILE__,warn_num,__LINE__,func_name,1)
This call returns zero. The call to ev_err() prints out a message to stderr indicating that an error has occurred, and where in which function it occurred, and the list of error messages to use (0 is the default). For example, it could look like:
"test1.c", line 79: sizes of objects don't match in
               function f()
which indicates that an error was flagged in file ``test1.c'' at line~79, function ``f'' where the sizes of two objects (vectors in this case) were incompatible. Once this information is printed out, control is passed to the the address saved in the buffer called restart by the last associated call to setjmp. The most convenient way of setting up restart is to use a ...catch...() macro or by an ERREXIT() or ERRABORT() macro. If restart has not been set then the program exits. If you wish to do something particular if a certain error occurs, then you could include a code fragment into main() such as the following:
if ( (code=setjmp(restart)) != 0 )
{
    if ( code = E_MEM ) /* memory error, say */
        /* something particular */
        { .... }
    else
        exit(0);
}
else
    /* make sure that error handler does jump */
    set_err_flag(EF_JUMP);
The list of standard error numbers is given below:
E_UNKNOWN       0 /* unknown error (unused) */
E_SIZES         1 /* incompatible sizes */
E_BOUNDS        2 /* index out of bounds */
E_MEM           3 /* memory (de)allocation error */
E_SING          4 /* singular matrix */
E_POSDEF        5 /* matrix not positive definite */
E_FORMAT        6 /* incorrect format input */
E_INPUT         7 /* bad input file/device */
E_NULL          8 /* NULL object passed */
E_SQUARE        9 /* matrix not square */
E_RANGE        10 /* object out of range */
E_INSITU2      11 /* only in-situ for square matrices */
E_INSITU       12 /* can't do operation in-situ */
E_ITER         13 /* too many iterations */
E_CONV         14 /* convergence criterion failed */
E_START        15 /* bad starting value */
E_SIGNAL       16 /* floating exception */
E_INTERN       17 /* some internal error */
E_EOF          18 /* unexpected end-of-file */
E_SHARED_VECS  19 /* cannot release shared vectors */
E_NEG          20 /* negative argument */
E_OVERWRITE    21 /* cannot overwrite object */
The set_err_flag() routine sets a flag which controls the behaviour of the error handling routine. The old value of this flag is returned, so that it can be restored if necessary. The list of values of this flag are given below:
EF_EXIT   0  /* exit on error  -- default */
EF_ABORT  1  /* abort on error -- dump core */
EF_JUMP   2  /* do longjmp()   -- see above code */
EF_SILENT 3  /* do not report error, but do longjmp() */
If there is a just a warning, then the default behaviour is to print out a message to stdout, and possibly stderr; the only value of the flag which has any effect is EF_SILENT. This suppresses the printing. The set of error messages, and the set of errors, can be expanded on demand by the user by means of err_list_attach(list_num, list_len, err_ptr, warn). The list number list_num should be greater than one (as numbers zero and one are taken by the standard system). The parameter list_len is the number of errors and error messages. The parameter err_ptr is an array of list_len strings. The parameter warn is TRUE or FALSE depending on whether this class of ``errors'' should be regarded as being just warnings, or whether they are (potentially) fatal. Then when an ``error'' should be raised, call
ev_err(__FILE__,err_num,__LINE__,func_name,list_num);
It may well be worthwhile to write a macro such as:
#define my_error(my_err_num,func_name) \
     ev_err(__FILE__,err_num,__LINE__,func_name,list_num)
If when originally set, the warn parameter was TRUE, then these calls behave similarly to warning(), and if it was FALSE, then these calls behave similarly to error(). These errors and exceptions are controlled using catch(), catchall() and tracecatch() (if warn was FALSE), just as for error() calls. The call err_list_free(list_num) unattaches the error list numbered\hfill\break list_num, and allows it to be re-used. The call err_is_list_attached(list_num) returns TRUE if error list\hfill\break list_num is attached, and FALSE otherwise. This can be used to find the next available free list.

EXAMPLE

Use of error() and warning():

if ( ! A )                error(E_NULL,  "my_function");
if ( A->m != A->n )       error(E_SQUARE,"my_function");
if ( i < 0 || i >= A->m ) error(E_BOUNDS,"my_function");
/* this should never happen */
if ( panic && something_really_bad )
    error(E_INTERN,"my_function");
/* issue a warning -- can still continue */
warning(WARN_UNKNOWN,"my_function");
Use of err_list_attach():
char *my_list[] = { "short circuit", "open circuit" };
int   my_list_num = 0;

main()
{
    for ( my_list_num = 0; ; my_list_num++ )
        if ( ! err_is_list_attached(my_list_num) )
            break;
    err_list_attach(my_list_num,2,my_list,FALSE);
      ......
    tracecatch(circuit_simulator(....),"main");
      ......
    err_list_free(my_list_num);
}

void circuit_simulator(....)
{
      ......
    /* open circuit error */
    ev_err(__FILE__,1,__LINE__,
           "circuit_simulator",my_list_num);
      .....
}

SEE ALSO: ERREXIT(), ERRABORT(), setjmp() and longjmp().

BUGS

Not many routines use tracecatch(), so that the trace is far from complete. Debuggers are needed in this case, if only to obtain a backtrace.

SOURCE FILE: err.c