PageRenderTime 65ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/brlcad/branches/dmtogl/src/other/step/src/express/error.c

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