home *** CD-ROM | disk | FTP | other *** search
/ ftptest.leeds.ac.uk / 2015.02.ftptest.leeds.ac.uk.tar / ftptest.leeds.ac.uk / bionet / CAE-GROUP / SCL-WIN3x / FED_PLUS.EXE / ERROR.C < prev    next >
C/C++ Source or Header  |  1994-07-23  |  13KB  |  537 lines

  1. static char rcsid[] = "$Id: error.c,v 1.9 1994/05/11 19:51:46 libes Exp $";
  2.  
  3. /************************************************************************
  4. ** Module:    Error
  5. ** Description:    This module implements the ERROR abstraction
  6. ************************************************************************/
  7.  
  8. /*
  9.  * Development of this code was funded by the United States Government,
  10.  * and is not subject to copyright.
  11.  *
  12.  * $Log: error.c,v $
  13.  * Revision 1.9  1994/05/11  19:51:46  libes
  14.  * numerous fixes
  15.  *
  16.  * Revision 1.8  1993/10/15  18:49:55  libes
  17.  * CADDETC certified
  18.  *
  19.  * Revision 1.6  1993/02/22  21:44:34  libes
  20.  * ANSI compat fixes
  21.  *
  22.  * Revision 1.5  1993/01/19  22:45:07  libes
  23.  * *** empty log message ***
  24.  *
  25.  * Revision 1.4  1992/08/18  17:16:22  libes
  26.  * rm'd extraneous error messages
  27.  *
  28.  * Revision 1.3  1992/06/08  18:08:05  libes
  29.  * prettied up interface to print_objects_when_running
  30.  */
  31.  
  32. #include "conf.h"
  33. #include <setjmp.h>
  34.  
  35. #define    ERROR_C
  36. #include <signal.h>
  37. #include "error.h"
  38. #include <string.h>
  39. #include "linklist.h"
  40. #ifdef __STDC__
  41. #include <stdarg.h>
  42. #else
  43. #include <varargs.h>
  44. #endif
  45. #include <stdlib.h>
  46. #include "express.h"
  47.  
  48. #define ERROR_MAX_ERRORS    100    /* max line-numbered errors */
  49. #define ERROR_MAX_SPACE        4000    /* max space for line-numbered errors */
  50. #define ERROR_MAX_STRLEN    200    /* assuming all error messages are */
  51.         /* less than this, if we have less than this much space */
  52.         /* remaining in the error string buffer, call it a day and */
  53.         /* dump the buffer */
  54.  
  55. static struct heap_element {
  56.     int line;
  57.     char *msg;
  58. } heap[ERROR_MAX_ERRORS+1];    /* NOTE!  element 0 is purposely ignored, and */
  59.         /* an additional element is at the end.  This allows the */
  60.         /* later heap calculations to be much simpler */
  61.  
  62. static int ERROR_with_lines = 0;    /* number of warnings & errors */
  63.                 /* that have occurred with a line number */
  64. static char *ERROR_string;
  65. static char *ERROR_string_base;
  66.  
  67. static char ERROR_unsafe = false;
  68. static jmp_buf ERROR_safe_env;
  69.  
  70. /* message buffer file */
  71. #define error_file stderr
  72.  
  73. /*
  74. ** Procedure:    ERRORinitialize
  75. ** Parameters:    -- none --
  76. ** Returns:    void
  77. ** Description:    Initialize the Error module
  78. */
  79.  
  80. void
  81. ERRORinitialize(void)
  82. {
  83.     ERROR_subordinate_failed =
  84.     ERRORcreate("A subordinate failed.", SEVERITY_ERROR);
  85.     ERROR_syntax_expecting =
  86.     ERRORcreate("%s, expecting %s in %s %s",SEVERITY_EXIT);
  87.  
  88.     ERROR_string_base = (char *)malloc(ERROR_MAX_SPACE);
  89.     ERROR_start_message_buffer();
  90.  
  91.  
  92. #ifdef SIGQUIT
  93.     signal(SIGQUIT,ERRORabort);
  94. #endif
  95. #ifdef SIGBUS
  96.     signal(SIGBUS, ERRORabort);
  97. #endif
  98. #ifdef SIGSEGV
  99.     signal(SIGSEGV,ERRORabort);
  100. #endif
  101. #ifdef SIGABRT
  102.     signal(SIGABRT,ERRORabort);
  103. #endif
  104. }
  105.  
  106. /* Need the LIST routines to complete ERROR initialization */
  107. void
  108. ERRORinitialize_after_LIST(void)
  109. {
  110.     ERRORwarnings = LISTcreate();
  111.  
  112.     MEMinitialize(&ERROR_OPT_fl,sizeof(struct Error_Warning),5,5);    
  113. }
  114.  
  115. /*VARARGS*/
  116. void
  117. ERRORcreate_warning(char *name,Error error)
  118. {
  119.     struct Error_Warning *o;
  120.  
  121.     /* first check if we know about this type of error */
  122.     LISTdo(ERRORwarnings, opt, Error_Warning)
  123.         if (streq(name,opt->name)) {
  124.             LISTadd(opt->errors,(Generic)error);
  125.             return;
  126.         }
  127.     LISTod
  128.  
  129.     /* new error */
  130.     o = ERROR_OPT_new();
  131.     o->name = name;
  132.     o->errors = LISTcreate();
  133.     LISTadd(o->errors,(Generic)error);
  134.     LISTadd(ERRORwarnings,(Generic)o);
  135. }
  136.  
  137. void
  138. ERRORset_warning(char *name,int set)
  139. {
  140.     int found = false;
  141.  
  142.     if (streq(name,"all")) ERRORset_all_warnings(set);
  143.     else if (streq(name,"none")) ERRORset_all_warnings(!set);
  144.     else {
  145.         LISTdo(ERRORwarnings, opt, Error_Warning)
  146.             if (streq(opt->name,name)) {
  147.                 found = true;
  148.                 LISTdo(opt->errors, err, Error)
  149.                     err->enabled = set;
  150.                 LISTod
  151.             }
  152.         LISTod
  153.         if (found) return;
  154.  
  155.         fprintf(stderr,"unknown warning: %s\n",name);
  156.         if (ERRORusage_function) {
  157.             (*ERRORusage_function)();
  158.         }
  159.     }
  160. }
  161.  
  162. void
  163. ERRORset_all_warnings(int set)
  164. {
  165.     LISTdo(ERRORwarnings, opts, Error_Warning)
  166.         LISTdo(opts->errors, err, Error)
  167.             err->enabled = set;
  168.         LISTod
  169.     LISTod
  170. }
  171.  
  172. /*
  173. ** Procedure:    ERRORdisable
  174. ** Parameters:    Error error    - error to disable
  175. ** Returns:    void
  176. ** Description:    Disable an error (ERRORreport*() will ignore it)
  177. */
  178.  
  179. /* this function is inlined in error.h */
  180.  
  181. /*
  182. ** Procedure:    ERRORenable
  183. ** Parameters:    Error error    - error to enable
  184. ** Returns:    void
  185. ** Description:    Enable an error (ERRORreport*() will report it)
  186. */
  187.  
  188. /* this function is inlined in error.h */
  189.  
  190. /*
  191. ** Procedure:    ERRORis_enabled
  192. ** Parameters:    Error error    - error to test
  193. ** Returns:    Boolean        - is reporting of the error enabled?
  194. ** Description:    Check whether an error is enabled
  195. */
  196.  
  197. /* this function is inlined in error.h */
  198.  
  199. /*
  200. ** Procedure:    ERRORreport
  201. ** Parameters:    Error what    - error to report
  202. **        ...        - arguments for error string
  203. ** Returns:    void
  204. ** Description:    Print a report of an error
  205. **
  206. ** Notes:    The second and subsequent arguments should match the
  207. **        format fields of the message generated by 'what.'
  208. */
  209.  
  210. /*VARARGS*/
  211. void
  212. #ifdef __STDC__
  213. ERRORreport(Error what, ...)
  214. {
  215. #else
  216. ERRORreport(va_alist)
  217. va_dcl
  218. {
  219.     Error what;
  220. #endif
  221. /*    extern void abort(void);*/
  222.     va_list args;
  223.  
  224. #ifdef __STDC__
  225.     va_start(args,what);
  226. #else
  227.     va_start(args);
  228.     what = va_arg(args,Error);
  229. #endif
  230.  
  231.     if ((what != ERROR_none) &&
  232.     (what != ERROR_subordinate_failed) &&
  233.     what->enabled) {
  234.         if (what->severity >= SEVERITY_ERROR) {
  235.         fprintf(error_file, "ERROR: ");
  236.         vfprintf(error_file, what->message, args);
  237.         fputc('\n', error_file);
  238.         ERRORoccurred = true;
  239.         } else if (what->severity >= SEVERITY_WARNING) {
  240.         fprintf(error_file, "WARNING: ", what->severity);
  241.         vfprintf(error_file, what->message, args);
  242.         fputc('\n', error_file);
  243.         }
  244.         if (what->severity >= SEVERITY_EXIT) {
  245.         ERROR_flush_message_buffer();
  246.         if (what->severity >= SEVERITY_DUMP)
  247.             {printf("Error, press any key to exit...");
  248.             getchar();
  249.             exit(0);}
  250.         else
  251.             exit(EXPRESS_fail((Express)0));
  252.         }
  253.     }
  254.     errc = ERROR_none;
  255.     va_end(args);
  256. }
  257.  
  258. /*
  259. ** Procedure:    ERRORreport_with_line
  260. ** Parameters:    Error what    - error to report
  261. **        int   line    - line number of error
  262. **        ...        - arguments for error string
  263. ** Returns:    void
  264. ** Description:    Print a report of an error, including a line number
  265. **
  266. ** Notes:    The third and subsequent arguments should match the
  267. **        format fields of the message generated by 'what.'
  268. */
  269.  
  270. /*VARARGS*/
  271. void
  272. #ifdef __STDC__
  273. ERRORreport_with_line(Error what, int line, ...)
  274. {
  275. #else
  276. ERRORreport_with_line(va_alist)
  277. va_dcl
  278. {
  279.     Error what;
  280.     int line;
  281. #endif
  282.  
  283.     char buf[BUFSIZ];
  284.     char *savemsg;    /* save what->message here while we fool */
  285.             /* ERRORreport_with_line */
  286.     Symbol sym;
  287.     va_list args;
  288. #ifdef __STDC__
  289.     va_start(args,line);
  290. #else
  291.     va_start(args);
  292.     what = va_arg(args,Error);
  293.     line = va_arg(args,int);
  294. #endif
  295.  
  296.     sym.filename = current_filename;
  297.     sym.line = line;
  298.  
  299.     vsprintf(buf,what->message,args);
  300.  
  301.     /* gross, but there isn't any way to do this more directly */
  302.     /* without writing yet another variant of ERRORreport_with_line */
  303.     savemsg = what->message;
  304.     what->message = "%s";
  305.     ERRORreport_with_symbol(what,&sym,buf);
  306.     what->message = savemsg;
  307. }
  308.  
  309. /*VARARGS*/
  310. void
  311. #ifdef __STDC__
  312. ERRORreport_with_symbol(Error what, Symbol *sym, ...)
  313. {
  314. #else
  315. ERRORreport_with_symbol(va_alist)
  316. va_dcl
  317. {
  318.     Error what;
  319.     Symbol *sym;
  320. #endif
  321. /*    extern void abort(void);*/
  322.     va_list args;
  323.  
  324. #ifdef __STDC__
  325.     va_start(args,sym);
  326. #else
  327.     va_start(args);
  328.     what = va_arg(args,Error);
  329.     sym = va_arg(args,Symbol *);
  330. #endif
  331.  
  332.     if ((what != ERROR_none) && (what != ERROR_subordinate_failed) && what->enabled) {
  333.     if (__ERROR_buffer_errors) {
  334.         int child, parent;
  335.  
  336.         /*
  337.          * add an element to the heap
  338.          * by (logically) storing the new value
  339.          * at the end of the array and bubbling
  340.          * it up as necessary
  341.          */
  342.  
  343.         child = ++ERROR_with_lines;
  344.         parent = child/2;
  345.         while (parent) {
  346.             if (sym->line < heap[parent].line) {
  347.                 heap[child] = heap[parent];
  348.             } else break;
  349.             child = parent;
  350.             parent = child/2;
  351.         }
  352.         heap[child].line = sym->line;
  353.         heap[child].msg = ERROR_string;
  354.  
  355.         if (what->severity >= SEVERITY_ERROR) {
  356.         sprintf(ERROR_string, "%s:%d: --ERROR: ",sym->filename,sym->line);
  357.         ERROR_string += strlen(ERROR_string);
  358.         vsprintf(ERROR_string, what->message, args);
  359.         ERROR_string += strlen(ERROR_string);
  360.         *ERROR_string++ = '\n';
  361.         *ERROR_string++ = '\0';
  362.         ERRORoccurred = true;
  363.         } else if (what->severity >= SEVERITY_WARNING) {
  364.         sprintf(ERROR_string, "%s:%d: WARNING: ",sym->filename,sym->line);
  365.         ERROR_string += strlen(ERROR_string);
  366.         vsprintf(ERROR_string, what->message, args);
  367.         ERROR_string += strlen(ERROR_string);
  368.         *ERROR_string++ = '\n';
  369.         *ERROR_string++ = '\0';
  370.         }
  371.         if (what->severity >= SEVERITY_EXIT ||
  372.         ERROR_string + ERROR_MAX_STRLEN > ERROR_string_base + ERROR_MAX_SPACE ||
  373.         ERROR_with_lines == ERROR_MAX_ERRORS) {
  374.         ERROR_flush_message_buffer();
  375.         if (what->severity >= SEVERITY_DUMP)
  376.             abort();
  377.         else
  378.             exit(EXPRESS_fail((Express)0));
  379.         }
  380.     } else {
  381.         if (what->severity >= SEVERITY_ERROR) {
  382.         fprintf(error_file, "%s:%d: --ERROR: ",sym->filename,sym->line);
  383.         vfprintf(error_file, what->message, args);
  384.         fprintf(error_file,"\n");
  385.         ERRORoccurred = true;
  386.         } else if (what->severity >= SEVERITY_WARNING) {
  387.         fprintf(error_file, "%s:%d: WARNING: ",sym->filename,sym->line);
  388.         ERROR_string += strlen(ERROR_string) + 1;
  389.         vfprintf(error_file, what->message, args);
  390.         fprintf(error_file,"\n");
  391.         }
  392.         if (what->severity >= SEVERITY_EXIT) {
  393.         if (what->severity >= SEVERITY_DUMP)
  394.             abort();
  395.         else
  396.             exit(EXPRESS_fail((Express)0));
  397.         }
  398.         }
  399.     }
  400.     errc = ERROR_none;
  401.     va_end(args);
  402. }
  403.  
  404. void
  405. ERRORnospace()
  406. {
  407.     fprintf(stderr,"%s: out of space\n",EXPRESSprogram_name);
  408.     ERRORabort(0);
  409. }
  410.  
  411. /*
  412. ** Procedure:    ERRORcreate
  413. ** Parameters:    String   message    - error message
  414. **        Severity severity    - severity of error
  415. ** Returns:    Error            - newly created error
  416. ** Description:    Create a new error
  417. */
  418.  
  419. Error
  420. ERRORcreate(char * message, Severity severity)
  421. {
  422.     Error n;
  423.  
  424.     n = (struct Error *)malloc(sizeof (struct Error));
  425.     n->message = message;
  426.     n->severity = severity;
  427.     n->enabled = true;
  428.     return n;
  429. }
  430.  
  431. /*
  432. ** Procedure:    ERRORbuffer_messages
  433. ** Parameters:    Boolean flag    - to buffer or not to buffer
  434. ** Returns:    void
  435. ** Description:    Selects buffering of error messages
  436. */
  437.  
  438. /* this function is inlined in error.h */
  439.  
  440. /*
  441. ** Procedure:    ERRORflush_messages
  442. ** Parameters:    void
  443. ** Returns:    void
  444. ** Description:    Flushes the error message buffer to standard output.
  445. **
  446. ** Notes:    The error messages are sorted by line number (which appears
  447. **        in the third column).
  448. */
  449.  
  450. /* this function is inlined in error.h */
  451.  
  452. /*
  453. ** Procedure:    ERROR_start_message_buffer
  454. ** Parameters:    -- none --
  455. ** Returns:    void
  456. ** Description:    
  457. */
  458.  
  459. void
  460. ERROR_start_message_buffer(void)
  461. {
  462.     ERROR_string = ERROR_string_base;
  463.     ERROR_with_lines = 0;
  464. }
  465.  
  466. /*
  467. ** Procedure:    ERROR_flush_message_buffer
  468. ** Parameters:    -- none --
  469. ** Returns:    void
  470. ** Description:    
  471. */
  472.  
  473. void
  474. ERROR_flush_message_buffer(void)
  475. {
  476.     if (__ERROR_buffer_errors == false) return;
  477.  
  478.     while (ERROR_with_lines) {
  479.         struct heap_element *replace;
  480.         int parent, child;
  481.  
  482.         /* pop off the top of the heap */
  483.         fprintf(stderr,heap[1].msg);
  484.  
  485.         replace = &heap[ERROR_with_lines--];
  486.  
  487.         child = 1;
  488.         while (1) {
  489.             parent = child;
  490.             child = 2*parent;
  491.             if (child > ERROR_with_lines) break;
  492.             if (child+1 <= ERROR_with_lines) {
  493.                 if (heap[child].line > heap[child+1].line) child++;
  494.             }
  495.             if (replace->line <= heap[child].line) break;
  496.             heap[parent] = heap[child];
  497. #if 0
  498.             if (replace->line > heap[child].line) {
  499.                 heap[parent] = heap[child];
  500.             }
  501. #endif
  502.         }
  503.         heap[parent] = *replace;
  504.     }
  505. }
  506.  
  507. /*ARGSUSED*/
  508. void
  509. ERRORabort(int sig)
  510. {
  511.     ERRORflush_messages();
  512.     if (!ERRORdebugging) {
  513.         if (ERROR_unsafe) {
  514.             longjmp(ERROR_safe_env,1);
  515.         }
  516. #ifdef SIGABRT
  517.         signal(SIGABRT,SIG_DFL);
  518. #endif
  519.         abort();
  520.     }
  521.  
  522.     fprintf(stderr,"pausing...press ^C now to enter debugger: ");
  523.     getchar();
  524. }
  525.  
  526. void
  527. ERRORsafe(jmp_buf env)
  528. {
  529.     memcpy(ERROR_safe_env,env,sizeof(jmp_buf));
  530. }
  531.  
  532. void
  533. ERRORunsafe()
  534. {
  535.     ERROR_unsafe = true;
  536. }
  537.