PageRenderTime 44ms CodeModel.GetById 2ms app.highlight 36ms RepoModel.GetById 2ms app.codeStats 0ms

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