55 |
*/ |
*/ |
56 |
|
|
57 |
|
|
58 |
void Asc_Panic(CONST int status, CONST char *function, |
/** |
59 |
CONST char *format, ...) |
This static function does the actual output of a PANIC message. It aims |
60 |
{ |
to do a few things to ensure that the user always gets the message. |
61 |
char msg[PANIC_MSG_MAXLEN]; /* The message that will be printed */ |
|
62 |
size_t p; /* The current length of the msg array */ |
@TODO We could can improve even further by integrating with some crash |
63 |
FILE *outfile; /* The file to save the message into */ |
reporting facility in GNOME, etc? |
64 |
va_list args; /* The arguments to print */ |
*/ |
65 |
int cancel = FALSE; /* If non-zero, do not call exit(). Default is to exit() */ |
static void asc_va_panic(const int status, const char *filename, const int line |
66 |
|
, const char *function, const char *fmt, const va_list args |
67 |
/* Fail loudly if ASCERR isn't set to a file pointer -- can't use asc_assert here! */ |
){ |
68 |
assert(NULL != ASCERR); |
FILE *outfile; /* The file to save the message into */ |
69 |
|
int cancel = FALSE; /* If non-zero, do not call exit(). Default is to exit() */ |
70 |
/* Give the name of the function where the panic occurred */ |
char msg[PANIC_MSG_MAXLEN]; |
71 |
if( function != NULL ) { |
size_t p; |
72 |
snprintf( msg, PANIC_MSG_MAXLEN-2, "function '%s':", function ); |
|
73 |
}else{ |
/* Fail loudly if ASCERR isn't set to a file pointer -- can't use asc_assert here! */ |
74 |
snprintf(msg, PANIC_MSG_MAXLEN-2, " "); |
assert(NULL != ASCERR); |
75 |
} |
|
76 |
p = strlen(msg); |
p = snprintf(msg,PANIC_MSG_MAXLEN-2,"%s:%d (%s): ",filename,line,function); |
77 |
|
|
78 |
/* Add the variable args to the panic message using the format "format" */ |
/* Add the variable args to the panic message using the format "format" */ |
79 |
va_start(args, format); |
vsnprintf(msg+p, PANIC_MSG_MAXLEN-p-2, fmt, args ); |
80 |
vsnprintf( (msg+p), PANIC_MSG_MAXLEN-p-2, format, args ); |
|
81 |
va_end(args); |
p = strlen(msg); |
82 |
|
msg[p++] = '\n'; |
83 |
p = strlen(msg); |
msg[p++] = '\0'; |
84 |
msg[p++] = '\n'; |
|
85 |
msg[p++] = '\0'; |
/* |
86 |
|
Always write the message to g_panic_outfile if it is not empty |
87 |
|
and we can actually write to that location. Print a |
88 |
/* |
message on ASCERR (if valid) saying that we did that. |
89 |
Write the message to g_panic_outfile if it is not empty |
*/ |
90 |
and we can actually write to that location. Print a |
if(( *g_panic_outfile != '\0' ) |
91 |
message on ASCERR (if valid) saying that we did that. |
&& ( (outfile=fopen(g_panic_outfile,"w")) != NULL ) |
92 |
*/ |
){ |
93 |
if(( g_panic_outfile[0] != '\0' ) |
fprintf(outfile, msg); |
94 |
&& ( (outfile=fopen(g_panic_outfile,"w")) != NULL )) |
CONSOLE_DEBUG("Error message written to %s\n", g_panic_outfile); |
95 |
{ |
|
96 |
FPRINTF(outfile, msg); |
fclose(outfile); |
97 |
if( ASCERR != NULL ) { |
} |
98 |
CONSOLE_DEBUG("Error message written to %s\n", g_panic_outfile); |
|
99 |
} |
if (NULL == f_panic_callback_func) { |
100 |
fclose(outfile); |
/* No panic-callback, so we reset the error handler and output to console */ |
101 |
} |
error_reporter_set_callback(NULL); |
102 |
|
|
103 |
if (NULL == f_panic_callback_func) { |
/* Print the message to the default error reporter (ASCERR) */ |
104 |
/* if there is no callback function registered, reset the error handler, and |
fprintf(stderr,"\n\n"); |
105 |
output the message to the console. |
va_error_reporter(ASC_PROG_FATAL,filename,line,function,fmt,args); |
106 |
*/ |
fprintf(stderr,"\n"); |
107 |
|
|
108 |
/* |
}else{ |
109 |
Ensure that our messages don't get left in the GUI |
/* just use the callback, don't make any output */ |
110 |
that is about to vanish... |
cancel = (*f_panic_callback_func)(status); |
111 |
*/ |
if(cancel){ |
112 |
error_reporter_set_callback(NULL); |
ERROR_REPORTER_HERE(ASC_PROG_ERR, |
113 |
|
"AscPanic 'cancel' facility has been disabled, program will exit" |
114 |
/* Print the message to the default error reporter (ASCERR) */ |
); |
115 |
fprintf(stderr,"\n\n"); |
} |
|
ERROR_REPORTER_NOLINE(ASC_PROG_FATAL,msg); |
|
|
|
|
|
|
|
|
}else{ |
|
|
/* just use the callback, don't make any output */ |
|
|
|
|
|
cancel = (*f_panic_callback_func)(status); |
|
|
if(cancel){ |
|
|
ERROR_REPORTER_HERE(ASC_PROG_ERR, |
|
|
"AscPanic 'cancel' facility has been disabled, program will exit" |
|
|
); |
|
116 |
} |
} |
|
} |
|
117 |
|
|
118 |
/* Display msg in a MessageBox under Windows unless turned off */ |
/* Display msg in a MessageBox under Windows unless turned off */ |
119 |
#ifdef USE_WIN32_FATAL_MSGBOX |
#ifdef USE_WIN32_FATAL_MSGBOX |
120 |
if (FALSE != f_display_MessageBox) { |
if(FALSE != f_display_MessageBox) { |
121 |
(void)MessageBeep(MB_ICONEXCLAMATION); |
(void)MessageBeep(MB_ICONEXCLAMATION); |
122 |
MessageBox(NULL, msg, "Fatal Error in ASCEND", |
MessageBox(NULL, msg, "Fatal Error in ASCEND" |
123 |
(UINT)(MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND)); |
,(UINT)(MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND) |
124 |
} |
); |
125 |
ExitProcess((UINT)status); |
} |
126 |
|
#endif |
127 |
|
} |
128 |
|
|
129 |
|
/** |
130 |
|
This is a new replacement for Asc_Panic that handles error source |
131 |
|
details (line, file, function) itself. |
132 |
|
*/ |
133 |
|
void asc_panic_line(const int status, const char *filename, const int line |
134 |
|
, const char *function, const char *fmt, ... |
135 |
|
){ |
136 |
|
va_list args; |
137 |
|
|
138 |
|
va_start(args,fmt); |
139 |
|
asc_va_panic(status,filename,line,function,fmt,args); |
140 |
|
va_end(args); |
141 |
|
|
142 |
|
#ifdef USE_WIN32_FATAL_MSGBOX |
143 |
|
ExitProcess((UINT)status); |
144 |
#else |
#else |
145 |
# ifndef NDEBUG |
# ifndef NDEBUG |
146 |
abort(); |
abort(); |
147 |
# else |
# else |
148 |
exit(status); |
exit(status); |
149 |
# endif |
# endif |
150 |
#endif |
#endif |
151 |
} |
} |
152 |
|
|
153 |
|
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) |
154 |
|
/** |
155 |
|
we only need this function if our platform doesn't support var-arg macros |
156 |
|
*/ |
157 |
|
void asc_panic(CONST int status, CONST CONST char *function |
158 |
|
,CONST char *fmt, ... |
159 |
|
){ |
160 |
|
va_list args; |
161 |
|
|
162 |
|
va_start(args,fmt); |
163 |
|
asc_va_panic(status,NULL,0,function,fmt,args); |
164 |
|
va_end(args); |
165 |
|
# ifdef USE_WIN32_FATAL_MSGBOX |
166 |
|
ExitProcess((UINT)status); |
167 |
|
# else |
168 |
|
# ifndef NDEBUG |
169 |
|
abort(); |
170 |
|
# else |
171 |
|
exit(status); |
172 |
|
# endif |
173 |
|
# endif |
174 |
|
} |
175 |
|
#endif |
176 |
|
|
177 |
void Asc_PanicSetOutfile(CONST char *filename) |
void Asc_PanicSetOutfile(CONST char *filename) |
178 |
{ |
{ |