1 |
/* |
2 |
ASCEND Language Interpreter |
3 |
AscPanic by Mark Thomas, created 15 May 1997 |
4 |
Copyright (C) 2005 Carnegie-Mellon University |
5 |
|
6 |
This program is free software; you can redistribute it and/or modify |
7 |
it under the terms of the GNU General Public License as published by |
8 |
the Free Software Foundation; either version 2 of the License, or |
9 |
(at your option) any later version. |
10 |
|
11 |
This program is distributed in the hope that it will be useful, |
12 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
GNU General Public License for more details. |
15 |
|
16 |
You should have received a copy of the GNU General Public License |
17 |
along with this program; if not, write to the Free Software |
18 |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
19 |
This file is part of the SLV solver. |
20 |
*/ |
21 |
|
22 |
/* removed changelog -- please consult commit comments in ViewCVS */ |
23 |
|
24 |
#include <stdarg.h> |
25 |
#include "ascConfig.h" |
26 |
#include "ascPanic.h" |
27 |
|
28 |
#define PANIC_MSG_MAXLEN 2047 |
29 |
/**< The maximum length of the panic message. |
30 |
Used to create a buffer to hold the message. |
31 |
*/ |
32 |
|
33 |
static PanicCallbackFunc f_panic_callback_func = NULL; |
34 |
/**< Holds a pointer to a callback function if registered using |
35 |
Asc_PanicSetCallback(). If NULL (the default), nothing is called. |
36 |
*/ |
37 |
|
38 |
/* |
39 |
disable the windows message box... |
40 |
#if defined(__WIN32__) |
41 |
# define USE_WIN32_FATAL_MSGBOX |
42 |
#endif |
43 |
*/ |
44 |
|
45 |
#ifdef USE_WIN32_FATAL_MSGBOX |
46 |
static int f_display_MessageBox = TRUE; |
47 |
/**< On Windows only, flag to enable/disable display of the MessageBox |
48 |
in Asc_Panic(). |
49 |
*/ |
50 |
#endif |
51 |
|
52 |
static char g_panic_outfile[PATH_MAX]; |
53 |
/**< Holds the name of the file in which to write panic messages. |
54 |
Use the Asc_PanicSetOutfile(filename) function to set it. |
55 |
*/ |
56 |
|
57 |
|
58 |
void Asc_Panic(CONST int status, CONST char *function, |
59 |
CONST char *format, ...) |
60 |
{ |
61 |
char msg[PANIC_MSG_MAXLEN]; /* The message that will be printed */ |
62 |
size_t p; /* The current length of the msg array */ |
63 |
FILE *outfile; /* The file to save the message into */ |
64 |
va_list args; /* The arguments to print */ |
65 |
int cancel = FALSE; /* If non-zero, do not call exit(). Default is to exit() */ |
66 |
|
67 |
/* Fail loudly if ASCERR isn't set to a file pointer -- can't use asc_assert here! */ |
68 |
assert(NULL != ASCERR); |
69 |
|
70 |
/* Give the name of the function where the panic occurred */ |
71 |
if( function != NULL ) { |
72 |
snprintf( msg, PANIC_MSG_MAXLEN-2, "function '%s':", function ); |
73 |
}else{ |
74 |
snprintf(msg, PANIC_MSG_MAXLEN-2, " "); |
75 |
} |
76 |
p = strlen(msg); |
77 |
|
78 |
/* Add the variable args to the panic message using the format "format" */ |
79 |
va_start(args, format); |
80 |
vsnprintf( (msg+p), PANIC_MSG_MAXLEN-p-2, format, args ); |
81 |
va_end(args); |
82 |
|
83 |
p = strlen(msg); |
84 |
msg[p++] = '\n'; |
85 |
msg[p++] = '\0'; |
86 |
|
87 |
|
88 |
/* |
89 |
Write the message to g_panic_outfile if it is not empty |
90 |
and we can actually write to that location. Print a |
91 |
message on ASCERR (if valid) saying that we did that. |
92 |
*/ |
93 |
if(( g_panic_outfile[0] != '\0' ) |
94 |
&& ( (outfile=fopen(g_panic_outfile,"w")) != NULL )) |
95 |
{ |
96 |
FPRINTF(outfile, msg); |
97 |
if( ASCERR != NULL ) { |
98 |
CONSOLE_DEBUG("Error message written to %s\n", g_panic_outfile); |
99 |
} |
100 |
fclose(outfile); |
101 |
} |
102 |
|
103 |
if (NULL == f_panic_callback_func) { |
104 |
/* if there is no callback function registered, reset the error handler, and |
105 |
output the message to the console. |
106 |
*/ |
107 |
|
108 |
/* |
109 |
Ensure that our messages don't get left in the GUI |
110 |
that is about to vanish... |
111 |
*/ |
112 |
error_reporter_set_callback(NULL); |
113 |
|
114 |
/* Print the message to the default error reporter (ASCERR) */ |
115 |
fprintf(stderr,"\n\n"); |
116 |
ERROR_REPORTER_NOLINE(ASC_PROG_FATAL,msg); |
117 |
|
118 |
|
119 |
}else{ |
120 |
/* just use the callback, don't make any output */ |
121 |
|
122 |
cancel = (*f_panic_callback_func)(status); |
123 |
if(cancel){ |
124 |
ERROR_REPORTER_HERE(ASC_PROG_ERR, |
125 |
"AscPanic 'cancel' facility has been disabled, program will exit" |
126 |
); |
127 |
} |
128 |
} |
129 |
|
130 |
/* Display msg in a MessageBox under Windows unless turned off */ |
131 |
#ifdef USE_WIN32_FATAL_MSGBOX |
132 |
if (FALSE != f_display_MessageBox) { |
133 |
(void)MessageBeep(MB_ICONEXCLAMATION); |
134 |
MessageBox(NULL, msg, "Fatal Error in ASCEND", |
135 |
(UINT)(MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND)); |
136 |
} |
137 |
ExitProcess((UINT)status); |
138 |
#else |
139 |
# ifndef NDEBUG |
140 |
abort(); |
141 |
# else |
142 |
exit(status); |
143 |
# endif |
144 |
#endif |
145 |
} |
146 |
|
147 |
|
148 |
void Asc_PanicSetOutfile(CONST char *filename) |
149 |
{ |
150 |
if( filename != NULL ) { |
151 |
strncpy( g_panic_outfile, filename, PATH_MAX-1 ); |
152 |
g_panic_outfile[PATH_MAX-1] = '\0'; |
153 |
} else { |
154 |
g_panic_outfile[0] = '\0'; |
155 |
} |
156 |
} |
157 |
|
158 |
PanicCallbackFunc Asc_PanicSetCallback(PanicCallbackFunc func) |
159 |
{ |
160 |
PanicCallbackFunc old_func = f_panic_callback_func; |
161 |
f_panic_callback_func = func; |
162 |
return old_func; |
163 |
} |
164 |
|
165 |
|
166 |
void Asc_PanicDisplayMessageBox(int is_displayed) |
167 |
{ |
168 |
#ifdef USE_WIN32_FATAL_MSGBOX |
169 |
f_display_MessageBox = is_displayed; |
170 |
#else |
171 |
UNUSED_PARAMETER(is_displayed); |
172 |
#endif |
173 |
} |