home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / mesch12a.zip / err.c < prev    next >
C/C++ Source or Header  |  1994-01-13  |  10KB  |  339 lines

  1.  
  2. /**************************************************************************
  3. **
  4. ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
  5. **
  6. **                 Meschach Library
  7. ** 
  8. ** This Meschach Library is provided "as is" without any express 
  9. ** or implied warranty of any kind with respect to this software. 
  10. ** In particular the authors shall not be liable for any direct, 
  11. ** indirect, special, incidental or consequential damages arising 
  12. ** in any way from use of the software.
  13. ** 
  14. ** Everyone is granted permission to copy, modify and redistribute this
  15. ** Meschach Library, provided:
  16. **  1.  All copies contain this copyright notice.
  17. **  2.  All modified copies shall carry a notice stating who
  18. **      made the last modification and the date of such modification.
  19. **  3.  No charge is made for this software or works derived from it.  
  20. **      This clause shall not be construed as constraining other software
  21. **      distributed on the same medium as this software, nor is a
  22. **      distribution fee considered a charge.
  23. **
  24. ***************************************************************************/
  25.  
  26.  
  27. /*
  28.   File with basic error-handling operations
  29.   Based on previous version on Zilog
  30.   System 8000 setret() etc.
  31.   Ported to Pyramid 9810 late 1987
  32.   */
  33.  
  34. static    char    rcsid[] = "$Id: err.c,v 1.5 1994/01/13 05:37:35 des Exp $";
  35.  
  36. #include    <stdio.h>
  37. #include    <setjmp.h>
  38. #include    <ctype.h>
  39. #include        "err.h"
  40.  
  41.  
  42. #ifdef SYSV
  43. /* AT&T System V */
  44. #include    <sys/signal.h>
  45. #else
  46. /* something else -- assume BSD or ANSI C */
  47. #include    <signal.h>
  48. #endif
  49.  
  50.  
  51.  
  52. #define        FALSE    0
  53. #define        TRUE    1
  54.  
  55. #define    EF_EXIT        0
  56. #define    EF_ABORT    1
  57. #define    EF_JUMP        2
  58. #define    EF_SILENT    3
  59.  
  60. /* The only error caught in this file! */
  61. #define    E_SIGNAL    16
  62.  
  63. static    char    *err_mesg[] =
  64. {      "unknown error",            /* 0 */
  65.       "sizes of objects don't match",    /* 1 */
  66.       "index out of bounds",        /* 2 */
  67.       "can't allocate memory",        /* 3 */
  68.       "singular matrix",            /* 4 */
  69.       "matrix not positive definite",    /* 5 */
  70.       "incorrect format input",        /* 6 */
  71.       "bad input file/device",        /* 7 */
  72.       "NULL objects passed",        /* 8 */
  73.       "matrix not square",            /* 9 */
  74.       "object out of range",        /* 10 */
  75.       "can't do operation in situ for non-square matrix",   /* 11 */
  76.       "can't do operation in situ",        /* 12 */
  77.       "excessive number of iterations",    /* 13 */
  78.       "convergence criterion failed",    /* 14 */
  79.       "bad starting value",            /* 15 */
  80.       "floating exception",            /* 16 */
  81.       "internal inconsistency (data structure)",/* 17 */
  82.       "unexpected end-of-file",        /* 18 */
  83.       "shared vectors (cannot release them)",  /* 19 */  
  84.       "negative argument",            /* 20 */
  85.       "cannot overwrite object"             /* 21 */
  86.      };
  87.  
  88. #define    MAXERR    (sizeof(err_mesg)/sizeof(char *))
  89.  
  90. static char *warn_mesg[] = {
  91.    "unknown warning",                /* 0 */
  92.    "wrong type number (use macro TYPE_*)",    /* 1 */
  93.    "no corresponding mem_stat_mark",        /* 2 */
  94.    "computed norm of a residual is less than 0",  /* 3 */
  95.    "resizing a shared vector"            /* 4 */
  96. };
  97.  
  98. #define MAXWARN  (sizeof(warn_mesg)/sizeof(char *))
  99.  
  100.  
  101.  
  102. #define    MAX_ERRS    100
  103.  
  104. jmp_buf    restart;
  105.  
  106.  
  107. /* array of pointers to lists of errors */
  108.  
  109. typedef struct {
  110.    char **listp;    /* pointer to a list of errors */
  111.    unsigned len;    /* length of the list */
  112.    unsigned warn;   /* =FALSE - errors, =TRUE - warnings */
  113. }  Err_list;
  114.  
  115. static Err_list     err_list[ERR_LIST_MAX_LEN] = {
  116.  {err_mesg,MAXERR,FALSE},    /* basic errors list */
  117.  {warn_mesg,MAXWARN,TRUE}    /* basic warnings list */
  118. };
  119.  
  120.  
  121. static int err_list_end = 2;   /* number of elements in err_list */
  122.  
  123. /* attach a new list of errors pointed by err_ptr
  124.    or change a previous one;
  125.    list_len is the number of elements in the list;
  126.    list_num is the list number;
  127.    warn == FALSE - errors (stop the program),
  128.    warn == TRUE - warnings (continue the program);
  129.    Note: lists numbered 0 and 1 are attached automatically,
  130.    you do not need to do it
  131.    */
  132. int err_list_attach(list_num, list_len,err_ptr,warn)
  133. int list_num, list_len, warn;
  134. char **err_ptr;
  135. {
  136.    if (list_num < 0 || list_len <= 0 ||
  137.        err_ptr == (char **)NULL) 
  138.      return -1;
  139.    
  140.    if (list_num >= ERR_LIST_MAX_LEN) {
  141.     fprintf(stderr,"\n file \"%s\": %s %s\n",
  142.         "err.c","increase the value of ERR_LIST_MAX_LEN",
  143.         "in matrix.h and zmatdef.h");
  144.     if ( ! isatty(fileno(stdout)) )
  145.       fprintf(stderr,"\n file \"%s\": %s %s\n",
  146.           "err.c","increase the value of ERR_LIST_MAX_LEN",
  147.           "in matrix.h and zmatdef.h");
  148.     printf("Exiting program\n");
  149.     exit(0);
  150.      }
  151.  
  152.    if (err_list[list_num].listp != (char **)NULL &&
  153.        err_list[list_num].listp != err_ptr)
  154.      free((char *)err_list[list_num].listp);
  155.    err_list[list_num].listp = err_ptr;
  156.    err_list[list_num].len = list_len;
  157.    err_list[list_num].warn = warn;
  158.    err_list_end = list_num+1;
  159.    
  160.    return list_num;
  161. }
  162.  
  163.  
  164. /* release the error list numbered list_num */
  165. int err_list_free(list_num)
  166. int list_num;
  167. {
  168.    if (list_num < 0 || list_num >= err_list_end) return -1;
  169.    if (err_list[list_num].listp != (char **)NULL) {
  170.       err_list[list_num].listp = (char **)NULL;
  171.       err_list[list_num].len = 0;
  172.       err_list[list_num].warn = 0;
  173.    }
  174.    return 0;
  175. }
  176.  
  177.  
  178. /* check if list_num is attached;
  179.    return FALSE if not;
  180.    return TRUE if yes
  181.    */
  182. int err_is_list_attached(list_num)
  183. int list_num;
  184. {
  185.    if (list_num < 0 || list_num >= err_list_end)
  186.      return FALSE;
  187.    
  188.    if (err_list[list_num].listp != (char **)NULL)
  189.      return TRUE;
  190.    
  191.    return FALSE;
  192. }
  193.  
  194. /* other local variables */
  195.  
  196. static    int    err_flag = EF_EXIT, num_errs = 0, cnt_errs = 1;
  197.  
  198. /* set_err_flag -- sets err_flag -- returns old err_flag */
  199. int    set_err_flag(flag)
  200. int    flag;
  201. {
  202.    int    tmp;
  203.    
  204.    tmp = err_flag;
  205.    err_flag = flag;
  206.    return tmp;
  207. }
  208.  
  209. /* count_errs -- sets cnt_errs (TRUE/FALSE) & returns old value */
  210. int    count_errs(flag)
  211. int    flag;
  212. {
  213.    int    tmp;
  214.    
  215.    tmp = cnt_errs;
  216.    cnt_errs = flag;
  217.    return tmp;
  218. }
  219.  
  220. /* ev_err -- reports error (err_num) in file "file" at line "line_num" and
  221.    returns to user error handler;
  222.    list_num is an error list number (0 is the basic list 
  223.    pointed by err_mesg, 1 is the basic list of warnings)
  224.  */
  225. int    ev_err(file,err_num,line_num,fn_name,list_num)
  226. char    *file, *fn_name;
  227. int    err_num, line_num,list_num;
  228. {
  229.    int    num;
  230.    
  231.    if ( err_num < 0 ) err_num = 0;
  232.    
  233.    if (list_num < 0 || list_num >= err_list_end ||
  234.        err_list[list_num].listp == (char **)NULL) {
  235.       fprintf(stderr,
  236.           "\n Not (properly) attached list of errors: list_num = %d\n",
  237.           list_num);
  238.       fprintf(stderr," Call \"err_list_attach\" in your program\n");
  239.       if ( ! isatty(fileno(stdout)) ) {
  240.      fprintf(stderr,
  241.          "\n Not (properly) attached list of errors: list_num = %d\n",
  242.          list_num);
  243.      fprintf(stderr," Call \"err_list_attach\" in your program\n");
  244.       }
  245.       printf("\nExiting program\n");
  246.       exit(0);
  247.    }
  248.    
  249.    num = err_num;
  250.    if ( num >= err_list[list_num].len ) num = 0;
  251.    
  252.    if ( cnt_errs && ++num_errs >= MAX_ERRS )    /* too many errors */
  253.    {
  254.       fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n",
  255.           file,line_num,err_list[list_num].listp[num],
  256.           isascii(*fn_name) ? fn_name : "???");
  257.       if ( ! isatty(fileno(stdout)) )
  258.     fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n",
  259.         file,line_num,err_list[list_num].listp[num],
  260.         isascii(*fn_name) ? fn_name : "???");
  261.       printf("Sorry, too many errors: %d\n",num_errs);
  262.       printf("Exiting program\n");
  263.       exit(0);
  264.    }
  265.    if ( err_list[list_num].warn )
  266.        switch ( err_flag )
  267.        {
  268.        case EF_SILENT: break;
  269.        default:
  270.        fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n\n",
  271.            file,line_num,err_list[list_num].listp[num],
  272.            isascii(*fn_name) ? fn_name : "???");
  273.        if ( ! isatty(fileno(stdout)) )
  274.            fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n\n",
  275.                file,line_num,err_list[list_num].listp[num],
  276.                isascii(*fn_name) ? fn_name : "???");
  277.        break;
  278.        }
  279.    else
  280.        switch ( err_flag )
  281.        {
  282.        case EF_SILENT:
  283.        longjmp(restart,(err_num==0)? -1 : err_num);
  284.        break;
  285.        case EF_ABORT:
  286.        fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n",
  287.            file,line_num,err_list[list_num].listp[num],
  288.            isascii(*fn_name) ? fn_name : "???");
  289.        if ( ! isatty(fileno(stdout)) )
  290.            fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n",
  291.                file,line_num,err_list[list_num].listp[num],
  292.                isascii(*fn_name) ? fn_name : "???");
  293.        abort();
  294.        break;
  295.        case EF_JUMP:
  296.        fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n",
  297.            file,line_num,err_list[list_num].listp[num],
  298.            isascii(*fn_name) ? fn_name : "???");
  299.        if ( ! isatty(fileno(stdout)) )
  300.            fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n",
  301.                file,line_num,err_list[list_num].listp[num],
  302.                isascii(*fn_name) ? fn_name : "???");
  303.        longjmp(restart,(err_num==0)? -1 : err_num);
  304.        break;
  305.        default:
  306.        fprintf(stderr,"\n\"%s\", line %d: %s in function %s()\n\n",
  307.            file,line_num,err_list[list_num].listp[num],
  308.            isascii(*fn_name) ? fn_name : "???");
  309.        if ( ! isatty(fileno(stdout)) )
  310.            fprintf(stdout,"\n\"%s\", line %d: %s in function %s()\n\n",
  311.                file,line_num,err_list[list_num].listp[num],
  312.                isascii(*fn_name) ? fn_name : "???");
  313.        
  314.        break;
  315.        }
  316.    
  317.    /* ensure exit if fall through */
  318.    if ( ! err_list[list_num].warn )  exit(0);
  319.  
  320.    return 0;
  321. }
  322.  
  323. /* float_error -- catches floating arithmetic signals */
  324. static void    float_error(num)
  325. int    num;
  326. {
  327.    signal(SIGFPE,float_error);
  328.    /* fprintf(stderr,"SIGFPE: signal #%d\n",num); */
  329.    /* fprintf(stderr,"errno = %d\n",errno); */
  330.    ev_err("???.c",E_SIGNAL,0,"???",0);
  331. }
  332.  
  333. /* catch_signal -- sets up float_error() to catch SIGFPE's */
  334. void    catch_FPE()
  335. {
  336.    signal(SIGFPE,float_error);
  337. }
  338.  
  339.