/[ascend]/trunk/base/generic/utilities/error.h
ViewVC logotype

Contents of /trunk/base/generic/utilities/error.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 978 - (show annotations) (download) (as text)
Wed Dec 20 10:26:04 2006 UTC (17 years, 7 months ago) by johnpye
File MIME type: text/x-chdr
File size: 11822 byte(s)
Failed 'ASSERT' statements in a METHOD now cause the statement to be output (as well as its location).
Improved code docs/GPL header for a few files.
Added support for 'ASSERT' in WriteStatement.
Added new WriteStatementError that included var-arg support.
Fixed ASC_ASSERT_RANGE in AscPanic.
1 /* ASCEND modelling environment
2 Copyright (C) 2006 Carnegie Mellon University
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
18 *//**
19 @file
20 This file provides error reporting to a callback function via
21 ASCEND's FPRINTF(ASCERR,...) syntax. It is anticipated that
22 this would gradually be expanded to including richer reporting
23 of errors with severity and source file name and line numbers.
24
25 Usage:
26 error_reporter_start(<error-severity>,<filepath>,<linenumber>);
27 FPRINTF(ASCERR,"half of ");
28 FPRINTF(ASCERR,"your message");
29 error_reporter_end_flush();
30
31 or:
32 error_reporter_start(<error-severity>,<filepath>,<linenumber>
33 ,"format string %s %d etc",<printf-args>,...");
34
35 The first form allows you to use multiple FPRINTF statements to
36 generate your error message. The second form assumes that your
37 entire message will be contained in a single statement.
38
39 Error severities are
40 ASC_(USER|PROG)_(NOTE|WARNING|ERROR)
41 and ASC_USER_SUCCESS
42 *//*
43 by John Pye
44 2005
45 */
46 #ifndef ASC_ERROR_H
47 #define ASC_ERROR_H
48
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <stdarg.h>
52
53 /**
54 ascConfig defines ASC_FPRINTF etc, the routines to provide
55 default 'real' printf behaviour on this platform. (As
56 opposed to the sneaky stuff that FPRINTF does in this header)
57 */
58 #include <utilities/ascConfig.h>
59 #include <utilities/ascPrint.h>
60
61 /**
62 FPRINTF(ASCERR,...) messages will by default be treated
63 by the error_reporter as ASC_PROG_NOTE messages. These will
64 gradually need to be replaced with error_severity_t values
65 that accurately reflect the nature of the error.
66 */
67 #define FPRINTF fprintf_error_reporter
68 #define FPUTC fputc_error_reporter
69 #define PUTC fputc_error_reporter
70 #define FFLUSH fflush_error_reporter
71
72 /*
73 By default, don't use coloured output on any terminals. We will reintroduce
74 this later, hopefully. It should be done using CURSES, instead of directly
75 using xterm codes. But that brings its own problems on MinGW and Windows...
76 */
77
78 /**
79 Error severity codes. This will be used to visually
80 the seriousness of errors. ASC_PROG_ERRORs for example
81 might be red, or be highlighted with a (!) icon, etc.
82 */
83 typedef enum error_severity_enum{
84 ASC_USER_SUCCESS=0
85 ,ASC_USER_NOTE=1 /**< a note to the user */
86 ,ASC_USER_WARNING=2 /**< the user has done something bad but tolerable */
87 ,ASC_USER_ERROR=4 /**< the user has done something wrong */
88 ,ASC_PROG_NOTE=8 /**< a note for the programmer */
89 ,ASC_PROG_WARNING=16/**< the program encounters an unexpected state */
90 ,ASC_PROG_ERROR=32 /**< the program has failed but can ignore and continue (maybe) */
91 ,ASC_PROG_FATAL=64 /**< fatal error, program will exit */
92 } error_severity_t;
93
94 #define ASC_ERR_ERR (ASC_PROG_ERROR | ASC_USER_ERROR | ASC_PROG_FATAL)
95
96 /**
97 Variadic macros to allow nice succint logging and error reporting
98 calls from C dialects that support them (GCC, C99 and others)
99
100 If you don't support variadic macros, you will still get the messages
101 but without the file/function/line number.
102 */
103 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
104 # define ERROR_REPORTER_DEBUG(args...) error_reporter(ASC_PROG_NOTE, __FILE__, __LINE__, __func__, ##args)
105 # define ERROR_REPORTER_HERE(SEV,args...) error_reporter(SEV,__FILE__, __LINE__, __func__, ##args)
106 # define ERROR_REPORTER_NOLINE(SEV,args...) error_reporter(SEV, NULL, 0, NULL, ##args)
107 # define CONSOLE_DEBUG(args...) ((void)(color_on(stderr,"0;34") + \
108 fprintf(stderr, "%s:%d ",__FILE__,__LINE__) + \
109 color_on(stderr,"0;31") + \
110 fprintf(stderr, "(%s)", __func__) + \
111 color_on(stderr,"0;34") + \
112 fprintf(stderr, ": ") + \
113 fprintf(stderr, ##args) + \
114 fprintf(stderr, "\n") + color_off(stderr)))
115
116 # define ERROR_REPORTER_START_HERE(SEV) error_reporter_start(SEV,__FILE__,__LINE__,__func__);
117
118 #elif defined(HAVE_C99)
119 # define ERROR_REPORTER_DEBUG(...) error_reporter(ASC_PROG_NOTE,__FILE__,__LINE__,__func__,## __VA_ARGS__)
120 # define ERROR_REPORTER_HERE(SEV,...) error_reporter(SEV,__FILE__,__LINE__,__func__, ## __VA_ARGS__)
121 # define ERROR_REPORTER_NOLINE(SEV,...) error_reporter(SEV,NULL,0,NULL, ## __VA_ARGS__)
122 # define CONSOLE_DEBUG(...) (color_on(stderr,"0;34") + fprintf(stderr, "%s:%d (%s): ", __FILE__,__LINE__,__func__) + \
123 fprintf(stderr, ##__VA_ARGS__) + \
124 fprintf(stderr, "\n") + color_off(stderr))
125
126 #elif defined(_MSC_VER) && _MSC_VER >= 1400 /* Microsoft Visual C++ 2005 or newer */
127 # define ERROR_REPORTER_START_HERE(SEV) error_reporter_start(SEV,__FILE__,__LINE__,__FUNCTION__);
128 # define ERROR_REPORTER_DEBUG(...) error_reporter(ASC_PROG_NOTE,__FILE__,__LINE__,__FUNCTION__, __VA_ARGS__)
129 # define ERROR_REPORTER_HERE(SEV,...) error_reporter(SEV,__FILE__,__LINE__,__FUNCTION__, __VA_ARGS__)
130 # define ERROR_REPORTER_NOLINE(SEV,...) error_reporter(SEV,NULL,0,NULL, __VA_ARGS__)
131 # define CONSOLE_DEBUG(...) (fprintf(stderr, "%s:%d (%s): ", __FILE__,__LINE__,__FUNCTION__) + \
132 fprintf(stderr, __VA_ARGS__) + \
133 fprintf(stderr, "\n"))
134 #else /* workaround for compilers without variadic macros: last resort */
135 # define NO_VARIADIC_MACROS
136 # define ERROR_REPORTER_DEBUG error_reporter_note_no_line
137 # define ERROR_REPORTER_HERE error_reporter_here
138 # define ERROR_REPORTER_NOLINE error_reporter_noline
139 # define CONSOLE_DEBUG console_debug
140 # define ERROR_REPORTER_START_HERE(SEV) error_reporter_start(SEV,__FILE__,__LINE__,"[function?]");
141 ASC_DLLSPEC(int) error_reporter_note_no_line(const char *fmt,...);
142 ASC_DLLSPEC(int) error_reporter_here(const error_severity_t sev, const char *fmt,...);
143 ASC_DLLSPEC(int) error_reporter_noline(const error_severity_t sev, const char *fmt,...);
144 ASC_DLLSPEC(int) console_debug(const char *fmt,...);
145 #endif
146
147 #define ERROR_REPORTER_START_NOLINE(SEV) error_reporter_start(SEV,NULL,0,NULL);
148
149 #define ERROR_REPORTER_STAT(sev,stat,msg) \
150 error_reporter(sev,Asc_ModuleFileName(stat->mod),stat->linenum,NULL,msg)
151
152 /** An alias for ASC_PROG_ERROR */
153 #define ASC_PROG_ERR ASC_PROG_ERROR
154
155 #define ERROR_REPORTER_MAX_MSG 4096 /* no particular reason */
156
157 typedef struct{
158 unsigned char iscaching; /** set to true for fprintf_error_reporter to do its work */
159 error_severity_t sev;
160 const char *filename;
161 int line;
162 const char *func;
163 char msg[ERROR_REPORTER_MAX_MSG];
164 } error_reporter_meta_t;
165
166 /**
167 This structure provides a means for caching errors so that they can be
168 reported back later in the manner of 'stack traces'. Should be useful
169 for more detailed reporting from parser, external calls, etc.
170
171 Usage will be
172
173 int res = 0;
174 error_reporter_tree_start();
175 do_subordinate_tasks();
176 error_reporter_tree_end();
177 if(error_reporter_tree_has_error()){
178 error_reporter_here(ASC_PROG_ERR,"Some errors occurred");
179 }else{
180 error_reporter_tree_clear();
181 }
182
183 The next 'error_reporter' call after an outermost 'error_reporter_tree_end'
184 will cause the error tree to be output to the error reporting channel.
185
186 If an 'error_reporter' is found *inside* an an 'error_reporter_tree_start'
187 and 'error_reporter_tree_end', the error message is kept and not output.
188
189 If the latest set of errors (those found inside the last start..end) are not
190 important, they can be discarded using error_reporter_tree_clear. This will
191 not clear the entire error tree, as there may be errors higher-up that we
192 don't want to discard.
193
194 After a call to error_reporter_tree_clear(), further errors can still be
195 added within the current TREECURRENT context.
196 */
197 typedef struct ErrorReporterTree{
198 error_reporter_meta_t *err;
199 struct ErrorReporterTree *head; /**< first on the list of child errors */
200 struct ErrorReporterTree *tail; /**< last on the list of child errors */
201 struct ErrorReporterTree *next; /**< next error in the present list */
202 struct ErrorReporterTree *parent; /**< parent error (or NULL) */
203 } error_reporter_tree_t;
204
205 ASC_DLLSPEC(int) error_reporter_tree_start();
206 ASC_DLLSPEC(int) error_reporter_tree_end();
207 ASC_DLLSPEC(void) error_reporter_tree_clear();
208 ASC_DLLSPEC(int) error_reporter_tree_has_error();
209
210 /**
211 This is the drop-in replacement for Asc_FPrintf. Anythin you attempt
212 to print to stderr will be captured and passed to the error_reporter_callback
213 function for handling.
214 */
215 ASC_DLLSPEC(int) fprintf_error_reporter(FILE *file, const char *fmt, ...);
216
217 /**
218 For use when implementing higher-level error handling routines
219 */
220 ASC_DLLSPEC(int) vfprintf_error_reporter(FILE *file, const char *fmt, const va_list args);
221
222 /**
223 If file!=stderr, this will do the usual thing. If file==stderr, it will output
224 the character via fprintf_error_reporter.
225 */
226 ASC_DLLSPEC(int) fputc_error_reporter(int c, FILE *file); /* just calls fprintf_error_reporter */
227
228 /**
229 This replaces the standard 'fflush' of Asc_FFlush. If file!=stderr, it will
230 call the standard fflush. If file==stderr, it will call error_reporter_end_flush.
231 */
232 ASC_DLLSPEC(int) fflush_error_reporter(FILE *file);
233
234 /**
235 Start a cached error report. This means that multiple frprintf_error_reporter calls will
236 be stored in a global string until an error_reporter_end_flush is encountered.
237 */
238 ASC_DLLSPEC(int) error_reporter_start(const error_severity_t sev, const char *filename, const int line, const char *func);
239
240 /**
241 Output the contents of the checked global string as an error report
242 */
243 ASC_DLLSPEC(int) error_reporter_end_flush();
244
245 /**
246 This #define saves you typing the list of arguments in your
247 callback function declarations.
248 */
249 #define ERROR_REPORTER_CALLBACK_ARGS \
250 const error_severity_t sev \
251 , const char *filename \
252 , const int line \
253 , const char *funcname \
254 , const char *fmt \
255 , const va_list args
256
257 /*
258 In you have functions which pass-through callback parameters,
259 this #define ensures that if their ordering/naming changes,
260 you won't have to go hunting and change stuff.
261 */
262 #define ERROR_REPORTER_CALLBACK_VARS \
263 sev, filename, line, funcname, fmt, args
264
265 /*
266 Define the type of the function pointer to be used for all
267 error reporting functions. The final argument is a va_list.
268 You should use 'vsnprintf' of 'vfprintf' to output your
269 message to the desired file or string, see <stdio.h> for these.
270 */
271 typedef int (*error_reporter_callback_t)(
272 ERROR_REPORTER_CALLBACK_ARGS
273 );
274
275 typedef int (*ErrorReporter_fptr_t)(
276 const error_severity_t sev
277 , const char *errfile
278 , const int errline
279 , const char *errfunc
280 , const char *fmt
281 , ...
282 );
283
284 /**
285 Use this function directly for 'richer' reporting of
286 of error messages.
287
288 @return follows the style of fprintf
289 */
290 ASC_DLLSPEC(int) error_reporter(
291 const error_severity_t sev
292 , const char *errfile
293 , const int errline
294 , const char *errfunc
295 , const char *fmt
296 , ...
297 );
298
299 /**
300 This format of the error reporter is useful if you must call it
301 from another variable-argument-list function.
302 */
303 ASC_DLLSPEC(int) va_error_reporter(ERROR_REPORTER_CALLBACK_ARGS);
304
305 /**
306 Set error reporting callback function using this
307 function. If left unset, errors will be printed
308 to standard error, which is effectively what the
309 hitherto FPRINTF has done.
310 */
311 ASC_DLLSPEC(void) error_reporter_set_callback(
312 const error_reporter_callback_t new_callback
313 );
314
315 #endif /* ASC_ERROR_H */

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22