/[ascend]/branches/relerrorlist/ascend/utilities/error.c
ViewVC logotype

Annotation of /branches/relerrorlist/ascend/utilities/error.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3217 - (hide annotations) (download) (as text)
Sat Oct 28 07:01:00 2017 UTC (21 months, 3 weeks ago) by jpye
File MIME type: text/x-csrc
File size: 16638 byte(s)
fixing va_copy errors and snprintf warnings from gcc 7.2.0

1 johnpye 62 #include <string.h>
2    
3     #include "error.h"
4    
5 jpye 2244 #define ERROR_REPORTER_TREE_ACTIVE
6 johnpye 931
7     #ifdef ERROR_REPORTER_TREE_ACTIVE
8 jpye 2322 # include <ascend/general/ascMalloc.h>
9 jpye 2323 # include <ascend/general/panic.h>
10 johnpye 931 #endif
11    
12 jpye 3214 //#define ERROR_DEBUG
13 jpye 3197 #ifdef ERROR_DEBUG
14     # define MSG CONSOLE_DEBUG
15 jpye 3199 # define TREE_PRINT error_reporter_tree_print
16 jpye 3197 #else
17     # define MSG(ARGS...) ((void)0)
18 jpye 3199 # define TREE_PRINT(ARGS...) ((void)0)
19 jpye 3197 #endif
20    
21    
22 johnpye 62 /**
23     Global variable which stores the pointer to the callback
24     function being used.
25     */
26     static error_reporter_callback_t g_error_reporter_callback;
27    
28     /**
29 jpye 3196 Global variable which enables caching of *individual* error messages,
30     as used with error_reporter_start() and error_reporter_end_flush().
31     This is not the same as the caching performed by error_reporter_tree_start()
32     which holds/records multiple error messages depending on the iscaching
33     setting.
34 johnpye 62 */
35     static error_reporter_meta_t g_error_reporter_cache;
36    
37 johnpye 190 /**
38 jpye 3196 Default error reporter. This error reporter is used whenever the callback
39     pointer is NULL, but can be replaced with another callback (eg for GUI
40     reporting) using error_reporter_set_callback()
41 johnpye 62 */
42     int error_reporter_default_callback(ERROR_REPORTER_CALLBACK_ARGS){
43     char *sevmsg="";
44 jpye 2634 enum ConsoleColor color = 0;
45 johnpye 62 char *endtxt="\n";
46     int res=0;
47     switch(sev){
48 jpye 2530 case ASC_PROG_FATAL: color=ASC_FG_BRIGHTRED; sevmsg = "PROGRAM FATAL ERROR: "; break;
49 jpye 3196 case ASC_PROG_ERROR: color=ASC_FG_RED; sevmsg = "PROGRAM ERROR: "; break;
50 jpye 2530 case ASC_PROG_WARNING: color=ASC_FG_BROWN;sevmsg = "PROGRAM WARNING: "; break;
51     case ASC_PROG_NOTE: color=ASC_FG_BRIGHTGREEN; endtxt=""; break; /* default, keep unembellished for now */
52     case ASC_USER_ERROR: color=ASC_FG_BRIGHTRED; sevmsg = "ERROR: "; break;
53     case ASC_USER_WARNING: color=ASC_FG_BROWN; sevmsg = "WARNING: "; break;
54 johnpye 62 case ASC_USER_NOTE: sevmsg = "NOTE: "; break;
55 jpye 2530 case ASC_USER_SUCCESS: color=ASC_FG_BRIGHTGREEN; sevmsg = "SUCCESS: "; break;
56 johnpye 62 }
57 johnpye 586 color_on(ASCERR,color);
58 jpye 2005 res = ASC_FPRINTF(ASCERR,"%s",sevmsg);
59 johnpye 586 color_off(ASCERR);
60 jpye 3211 if(filename!=NULL){
61     //MSG("filename = '%s'",filename);
62     res += ASC_FPRINTF(ASCERR,"%s:",filename);
63     }
64 jpye 3196 if(line!=0)res += ASC_FPRINTF(ASCERR,"%d:",line);
65 jpye 3211 if(funcname!=NULL){
66     //MSG("funcname = '%s'",funcname);
67     res += ASC_FPRINTF(ASCERR,"%s:",funcname);
68     }else{
69     //MSG("funcname NULL");
70     }
71 jpye 3196 if ((filename!=NULL) || (line!=0) || (funcname!=NULL))res += ASC_FPRINTF(ASCERR," ");
72 jpye 3211 res += ASC_VFPRINTF(ASCERR,fmt,*args);
73 jpye 2005 res += ASC_FPRINTF(ASCERR,"%s",endtxt);
74 johnpye 62 return res;
75     }
76    
77 johnpye 931 /*---------------------------------------------------------------------------
78     ERROR REPORTER TREE (BRANCHABLE ERROR STACK) FUNCTIONALITY
79     */
80    
81     #ifdef ERROR_REPORTER_TREE_ACTIVE
82    
83     static error_reporter_tree_t *g_error_reporter_tree_current = NULL;
84 johnpye 932
85 jpye 3196 static error_reporter_meta_t *error_reporter_meta_new(){
86     error_reporter_meta_t *e;
87     e = ASC_NEW(error_reporter_meta_t);
88     e->sev = ASC_USER_SUCCESS;
89     e->iscaching = 0;
90     e->filename = NULL;
91     e->func = NULL;
92     e->line = 0;
93     e->msg[0] = '\0';
94     return e;
95     }
96 johnpye 931
97 jpye 3196 # define CURRENT g_error_reporter_tree_current
98    
99 jpye 3217 #ifdef ERROR_DEBUG
100 jpye 3213 static void error_reporter_tree_print(error_reporter_tree_t *t1);
101 jpye 3217 #endif
102    
103 johnpye 932 static int error_reporter_tree_write(error_reporter_tree_t *t);
104     static void error_reporter_tree_free(error_reporter_tree_t *t);
105    
106 jpye 3196 /// deprecated function for testing purpose only
107     error_reporter_tree_t *error_reporter_get_tree_current(){
108     return CURRENT;
109     }
110    
111     static error_reporter_tree_t *error_reporter_tree_new(int iscaching){
112 johnpye 931 error_reporter_tree_t *tnew = ASC_NEW(error_reporter_tree_t);
113 jpye 3196 tnew->iscaching = iscaching;
114 johnpye 931 tnew->next = NULL;
115 jpye 3197 tnew->prev = NULL;
116 johnpye 931 tnew->head = NULL;
117     tnew->tail = NULL;
118     tnew->err = NULL;
119 jpye 3196 tnew->parent = NULL;
120 jpye 3213 TREE_PRINT(tnew);
121 johnpye 931 return tnew;
122     }
123    
124 jpye 3196 static int error_reporter_tree_has_caching_parent(error_reporter_tree_t *t){
125     assert(t);
126     if(NULL == t->parent)return 0;
127     error_reporter_tree_t *t1 = t->parent;
128     int iscaching = 0;
129     while(t1){
130     iscaching = iscaching || t1->iscaching;
131     assert(t1->parent != t1);
132     t1 = t1->parent;
133 johnpye 932 }
134 jpye 3196 return iscaching;
135     }
136 johnpye 932
137 jpye 3199 #ifdef ERROR_DEBUG
138 jpye 3197 static void error_reporter_tree_print1(error_reporter_tree_t *t,int level){
139     if(t->head){
140     assert(t->err == NULL);
141 jpye 3198 MSG("%*s+%p%s (head=%p,tail=%p)",2+2*level,"",t,t==CURRENT?" (CURRENT)":"",t->head,t->tail);
142 jpye 3197 error_reporter_tree_print1(t->head,level+1);
143 jpye 3213 }else if(t->err){
144 jpye 3212 assert(t->err != NULL);
145 jpye 3198 MSG("%*s-%p %s:%d: %s (parent=%p,next=%p)",2+2*level,"",t,t->err->filename, t->err->line, t->err->msg,t->parent,t->next);
146 jpye 3213 }else{
147     MSG("%*s-%p EMPTY NODE",2+2*level,"",t);
148 jpye 3197 }
149    
150     if(t->next){
151     error_reporter_tree_print1(t->next,level);
152     }
153     }
154    
155     static void error_reporter_tree_print(error_reporter_tree_t *t1){
156     if(!t1){
157 jpye 3213 MSG("null tree");
158 jpye 3197 }else{
159 jpye 3212 MSG("finding top of tree, starting at %p",t1);
160 jpye 3197 while(t1->parent){
161     t1 = t1->parent;
162     }
163     MSG("top of tree is %p",t1);
164     error_reporter_tree_print1(t1,0);
165     }
166     }
167 jpye 3199 #endif
168 jpye 3197
169     error_reporter_tree_t *error_reporter_tree_start(int iscaching){
170 jpye 3196 error_reporter_tree_t *tnew = error_reporter_tree_new(iscaching);
171     if(CURRENT == NULL){
172 jpye 3197 MSG("creating tree (caching=%d)",iscaching);
173 jpye 3196 CURRENT = tnew;
174 johnpye 931 }else{
175 jpye 3197 MSG("creating sub-tree (caching=%d)",iscaching);
176 jpye 3196 if(CURRENT->head == NULL){
177 jpye 3197 MSG("adding at head");
178 jpye 3196 CURRENT->head = tnew;
179 johnpye 931 }else{
180 jpye 3197 MSG("adding at tail");
181 johnpye 931 /* link the new tree to the last in the child list */
182 jpye 3196 CURRENT->tail->next = tnew;
183 jpye 3197 tnew->prev = CURRENT->tail;
184 johnpye 931 }
185     /* update the tail of the list */
186 jpye 3196 CURRENT->tail = tnew;
187 johnpye 931 /* now switch the context to the sub-tree */
188 jpye 3196 tnew->parent = CURRENT;
189     CURRENT = tnew;
190 johnpye 931 }
191 jpye 3197 return CURRENT;
192 johnpye 931 }
193 johnpye 932
194 jpye 3197 int error_reporter_tree_end(error_reporter_tree_t *tree){
195 jpye 3196 assert(CURRENT);
196 jpye 3197 assert(tree==CURRENT);
197 jpye 3196 if(CURRENT->iscaching){
198     if(error_reporter_tree_has_caching_parent(CURRENT)){
199 jpye 3197 MSG("no output; caching parent");
200 jpye 3196 }else{
201 jpye 3197 MSG("outputting now, no caching parent");
202 jpye 3196 error_reporter_tree_write(CURRENT);
203     }
204 johnpye 931 }
205 jpye 3196 if(CURRENT->parent){
206 jpye 3197 MSG("ending sub-tree, NOT freeing structures");
207 jpye 3196 CURRENT = CURRENT->parent;
208     }else{
209 jpye 3197 MSG("ending top tree, freeing structures");
210 jpye 3199 TREE_PRINT(CURRENT);
211 jpye 3197 error_reporter_tree_free(CURRENT);
212 jpye 3196 CURRENT = NULL;
213     }
214 johnpye 931 return 0;
215 jpye 2524 }
216 johnpye 931
217 jpye 3197 /** recursive routine to deallocate error_reporter_tree_t structures. */
218 johnpye 931 static void error_reporter_tree_free(error_reporter_tree_t *t){
219 jpye 3197 assert(t);
220 jpye 3198 error_reporter_tree_t *n=NULL;
221 johnpye 932 if(t->head){
222 jpye 3197 assert(t->err == NULL);
223     MSG("freeing sub-nodes");
224 johnpye 932 error_reporter_tree_free(t->head);
225 jpye 3197 MSG("done freeing sub-nodes");
226 johnpye 932 }
227 jpye 3197 if(t->err){
228 jpye 3198 MSG("freeing error metadata ('%s')",t->err->msg);
229 jpye 3197 assert(t->head == NULL);
230     assert(t->tail == NULL);
231     ASC_FREE(t->err);
232     }
233 jpye 3198 if(t->next)n = t->next;
234    
235     MSG("freeing node %p%s",t,t==CURRENT?" (CURRENT)":"");
236     ASC_FREE(t);
237    
238     if(n){
239     MSG("freeing next node %p",n);
240     error_reporter_tree_free(n);
241 johnpye 932 }
242 johnpye 931 }
243    
244 jpye 3197 /** clear all errors nested within the current tree -- they won't be visible
245     to any parent trees after this; they never happened. Must be called INSTEAD OF
246     error_reporter_tree_end(). */
247     void error_reporter_tree_end_clear(error_reporter_tree_t *tree){
248     assert(CURRENT);
249     assert(tree==CURRENT);
250     error_reporter_tree_t *t1 = NULL, *tp, *tn;
251 jpye 3196 if(CURRENT->parent){
252 jpye 3198 MSG("ending/clearing sub-tree %p",CURRENT);
253 jpye 3199 TREE_PRINT(CURRENT);
254 jpye 3196 t1 = CURRENT->parent;
255 jpye 3197 tn = CURRENT->next;
256     tp = CURRENT->prev;
257     assert(tn==NULL); /* actually, we can't imagine a case where tn != NULL */
258 jpye 3198 if(tn){
259     MSG("%p->prev = %p",tn,tp);
260     tn->prev = tp;
261     }
262     if(tp){
263     MSG("%p->next = %p",tp,tn);
264     tp->next = tn;
265     }
266 jpye 3197 if(t1->head == CURRENT){
267 jpye 3198 MSG("fixing head");
268 jpye 3197 if(tp)t1->head = tp;
269     else if(tn)t1->head = tn;
270     else t1->head = NULL;
271     }
272     if(t1->tail == CURRENT){
273 jpye 3198 MSG("fixing tail");
274     if(tp)t1->tail = tp;
275     else t1->tail = NULL;
276 jpye 3197 }
277 jpye 3198 MSG("after pruning");
278 jpye 3199 TREE_PRINT(t1);
279 johnpye 931 }else{
280 jpye 3197 MSG("ending/clearing top tree");
281 johnpye 931 }
282 jpye 3196 error_reporter_tree_free(CURRENT);
283     CURRENT = t1;
284 jpye 3198 MSG("completed tree_end_clear, new current:");
285 jpye 3199 TREE_PRINT(CURRENT);
286 johnpye 931 }
287    
288     static int error_reporter_tree_match_sev(error_reporter_tree_t *t, unsigned match){
289 jpye 3197 assert(t);
290 johnpye 932 if(t->err && (t->err->sev & match)){
291 jpye 3197 /* MSG("SEVERITY MATCH FOR t = %p",t); */
292 johnpye 932 return 1;
293     }
294     if(t->next && error_reporter_tree_match_sev(t->next, match)){
295 jpye 3197 /* MSG("SEVERITY MATCH IN 'next' FOR t = %p",t); */
296 johnpye 932 return 1;
297     }
298     if(t->head && error_reporter_tree_match_sev(t->head, match)){
299 jpye 3197 /* MSG("SEVERITTY MATCH IN 'head' FOR t = %p",t); */
300 johnpye 932 return 1;
301     }
302 jpye 3197 /* MSG("NO MATCH FOR t = %p",t); */
303 johnpye 931 return 0;
304     }
305    
306     /**
307     traverse the tree, looking for ASC_PROG_ERR, ASC_USER_ERROR, or ASC_PROG_FATAL
308     @return 1 if errors found
309     */
310 jpye 3197 int error_reporter_tree_has_error(error_reporter_tree_t *tree){
311 johnpye 933 int res;
312 jpye 3197 assert(CURRENT);
313     assert(tree==CURRENT);
314     res = error_reporter_tree_match_sev(CURRENT,ASC_ERR_ERR);
315     if(res){
316     MSG("ERROR(S) FOUND IN CURRENT %p",CURRENT);
317 johnpye 931 }
318 jpye 3197 return res;
319 johnpye 931 }
320    
321     static int error_reporter_tree_write(error_reporter_tree_t *t){
322     int res = 0;
323 jpye 3196 assert(t != NULL);
324 jpye 3197
325 johnpye 931 if(t->err){
326 jpye 3196 // an a simple node -- just an error
327     assert(t->head == NULL);
328     assert(t->tail == NULL);
329 jpye 3212 MSG("WRITING MSG FROM CACHE");
330 jpye 3196 error_reporter_callback_t cb = g_error_reporter_callback ?
331     g_error_reporter_callback : error_reporter_default_callback;
332     res += (*cb)(t->err->sev,t->err->filename,t->err->line,t->err->func,t->err->msg,NULL);
333 johnpye 931 }else{
334 jpye 3196 // a parent node -- traverse the sub-nodes
335     assert(t->head);
336     assert(t->tail);
337     error_reporter_tree_t *t1 = t->head;
338     while(t1){
339     res += error_reporter_tree_write(t1);
340     t1 = t1->next;
341     }
342 johnpye 931 }
343     return res;
344     }
345    
346     #else /* ERROR_REPORTER_TREE_ACTIVE */
347 jpye 3197 error_reporter_tree_t *error_reporter_tree_start(int iscaching){
348     (void)iscaching;
349 johnpye 931 ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Error reporter 'tree' turned off at compile time");
350 jpye 3197 return NULL;
351     }
352     int error_reporter_tree_end(error_reporter_tree_t *tree){
353     assert(tree==NULL);
354 johnpye 932 return 0;
355 johnpye 931 }
356 jpye 3197 void error_reporter_tree_end_clear(error_reporter_tree_t *tree){
357     assert(tree==NULL);
358     }
359     int error_reporter_tree_has_error(error_reporter_tree_t *tree){
360     assert(tree==NULL);
361 jpye 3196 ERROR_REPORTER_HERE(ASC_PROG_FATAL,"Attempt to check 'tree_has_error' when 'tree' turned off at compile time");
362 johnpye 932 return 0;
363     }
364 johnpye 931 #endif /* ERROR_REPORTER_TREE_ACTIVE */
365    
366 johnpye 62 /*--------------------------
367 johnpye 931 REALLY WHERE THE REPORTING HAPPENS
368 johnpye 62 */
369 johnpye 931
370 johnpye 62 int
371     va_error_reporter(
372 johnpye 222 const error_severity_t sev
373     , const char *errfile
374     , const int errline
375     , const char *errfunc
376     , const char *fmt
377 jpye 3210 , va_list *args
378 johnpye 62 ){
379 jpye 3196 int res = 0;
380 jpye 3211 va_list args2;
381 johnpye 62
382 jpye 3211 error_reporter_callback_t cb = g_error_reporter_callback;
383     if(cb == NULL){
384     //MSG("using default error reporter callback, errfunc = '%s'",errfunc);
385     cb = error_reporter_default_callback;
386     }
387    
388 johnpye 931 #ifdef ERROR_REPORTER_TREE_ACTIVE
389     error_reporter_tree_t *t;
390 johnpye 932 if(sev != ASC_PROG_FATAL){
391 jpye 3196 if(CURRENT){
392 jpye 3211 va_copy(args2,*args);
393    
394     MSG("adding to tree");
395 johnpye 932 /* add the error to the tree, don't output anything now */
396 jpye 3196 t = error_reporter_tree_new(0);
397 johnpye 932 t->err = error_reporter_meta_new();
398 jpye 3211 vsnprintf(t->err->msg,ERROR_REPORTER_MAX_MSG,fmt,*args);
399     MSG("t->err->msg = \"%s\"",t->err->msg);
400 johnpye 932 t->err->filename = errfile;
401     t->err->func = errfunc;
402     t->err->line = errline;
403     t->err->sev = sev;
404 jpye 3196 if(!CURRENT->head){
405 jpye 3197 // current tree is empty
406 jpye 3196 CURRENT->head = CURRENT->tail = t;
407 jpye 3197 t->parent = CURRENT;
408 johnpye 932 }else{
409 jpye 3196 CURRENT->tail->next = t;
410 jpye 3197 t->prev = CURRENT->tail;
411 jpye 3196 CURRENT->tail = t;
412 jpye 3197 t->parent = CURRENT;
413 johnpye 932 }
414 jpye 3197 MSG("message '%s' added to tree",t->err->msg);
415 jpye 3211 //MSG("message has errfunc '%s'",t->err->func);
416 jpye 3196
417     if(CURRENT->iscaching || error_reporter_tree_has_caching_parent(CURRENT)){
418 jpye 3197 MSG("caching; no output");
419 jpye 3196 return res;
420 jpye 3211 }else{
421     MSG("non-caching; outputting again directly");
422     res = (*cb)(sev,errfile,errline,errfunc,fmt,&args2);
423     MSG("res = %d",res);
424     return res;
425 jpye 3196 }
426 jpye 3199 }else{
427 jpye 3211 MSG("no error tree; direct output");
428     return (*cb)(sev,errfile,errline,errfunc,fmt,args);
429 johnpye 931 }
430     }
431     #endif
432    
433 jpye 3211 MSG("fatal error message format = '%s'",fmt);
434     return (*cb)(sev,errfile,errline,errfunc,fmt,args);
435 johnpye 62 }
436    
437     /*----------------------------
438     DROP-IN replacements for stdio.h / ascPrint.h
439     */
440    
441 jpye 3210 int vfprintf_error_reporter(FILE *file, const char *fmt, va_list *args){
442 johnpye 62 char *msg;
443     int len;
444     int res;
445     if(file==stderr){
446     if(g_error_reporter_cache.iscaching){
447     msg = g_error_reporter_cache.msg;
448     len = strlen(msg);
449 jpye 3210 res = vsnprintf(msg+len,ERROR_REPORTER_MAX_MSG-len,fmt,*args);
450 jpye 3212 //MSG("Appended \"%s\" to message",msg+len);
451 johnpye 62 if(len+res+1>=ERROR_REPORTER_MAX_MSG){
452 jpye 3217 SNPRINTF(msg+ERROR_REPORTER_MAX_MSG-16,16,"... (truncated)");
453 johnpye 62 ASC_FPRINTF(stderr,"TRUNCATED MESSAGE, FULL MESSAGE FOLLOWS:\n----------START----------\n");
454 jpye 3211 ASC_VFPRINTF(stderr,fmt,*args);
455 johnpye 62 ASC_FPRINTF(stderr,"\n-----------END----------\n");
456     }
457     }else{
458 jpye 3211 MSG("Reporting msg directly, fmt = \"%s\"",fmt);
459 johnpye 62 /* Not caching: output all in one go as a ASC_PROG_NOTE */
460 jpye 3211 res = va_error_reporter(ASC_PROG_NOTE,NULL,0,NULL,fmt,args);
461 johnpye 62 }
462     }else{
463 jpye 3211 MSG("Printing directly, fmt = \"%s\"",fmt);
464 jpye 3210 res = ASC_VFPRINTF(file,fmt,*args);
465 johnpye 62 }
466 johnpye 978 return res;
467     }
468 jpye 2524
469 johnpye 978 /**
470     This function performs caching of the error text if the flag is set
471     */
472     int
473     fprintf_error_reporter(FILE *file, const char *fmt, ...){
474     va_list args;
475     int res;
476 johnpye 62
477 johnpye 978 va_start(args,fmt);
478 jpye 3210 res = vfprintf_error_reporter(file,fmt,&args);
479 johnpye 62 va_end(args);
480    
481     return res;
482     }
483    
484     int
485     fputc_error_reporter(int c, FILE *file){
486     if(file!=stderr){
487     return ASC_FPUTC(c,file);
488     }else if(fprintf_error_reporter(file,"%c",c) == 1){
489     return c;
490     }else{
491     return EOF;
492     }
493     }
494    
495     int
496     fflush_error_reporter(FILE *file){
497     if(file!=stderr){
498     return ASC_FFLUSH(file);
499     }else{
500     return error_reporter_end_flush();
501     }
502     }
503    
504     /*----------------------------
505     CACHING of multiple-FPRINTF error messages
506     */
507    
508 jpye 3196 int error_reporter_start(const error_severity_t sev, const char *filename
509     , const int line, const char *func
510     ){
511 johnpye 62 if(g_error_reporter_cache.iscaching){
512 jpye 3211 MSG("call to error_reporter_start before expected error_reporter_end_flush");
513 johnpye 62 error_reporter_end_flush();
514     }
515     g_error_reporter_cache.iscaching = 1;
516     *(g_error_reporter_cache.msg) = '\0';
517     g_error_reporter_cache.sev = sev;
518     g_error_reporter_cache.filename = filename;
519     g_error_reporter_cache.line = line;
520 johnpye 222 g_error_reporter_cache.func = func;
521 johnpye 62
522     return 1;
523     }
524    
525 jpye 3196 /**
526     This function will flush the output of a multi-line error message
527     (as written with multiple calls to FPRINTF(stderr,...))
528     */
529     int error_reporter_end_flush(){
530 johnpye 936 if(g_error_reporter_cache.iscaching){
531     error_reporter(
532     g_error_reporter_cache.sev
533     ,g_error_reporter_cache.filename
534     ,g_error_reporter_cache.line
535     ,g_error_reporter_cache.func
536     ,g_error_reporter_cache.msg
537     );
538     }else{
539 jpye 3197 /* MSG("IGNORING REPEATED CALL TO error_reporter_end_flush()"); */
540 johnpye 936 }
541 johnpye 62 g_error_reporter_cache.iscaching = 0;
542    
543     return 0; /* output must be compatible with fflush */
544     }
545    
546     /*--------------------------
547     REPORT the error
548     */
549     int
550     error_reporter(
551 johnpye 222 const error_severity_t sev
552     , const char *errfile
553     , const int errline
554     , const char *errfunc
555     , const char *fmt
556     , ...
557 johnpye 62 ){
558     int res;
559     va_list args;
560    
561     va_start(args,fmt);
562 jpye 3210 res = va_error_reporter(sev,errfile,errline,errfunc,fmt,&args);
563 johnpye 62 va_end(args);
564    
565     return res;
566     }
567    
568 johnpye 379 /*-------------------------
569     SET the callback function
570     */
571 jpye 3196 void error_reporter_set_callback(
572 johnpye 379 const error_reporter_callback_t new_callback
573     ){
574     g_error_reporter_callback = new_callback;
575     }
576    
577     /*-------------------------
578     OPTIONAL code for systems not supporting variadic macros.
579 jpye 3196 Your system probably does support variadic macros, it's just
580     a question of checking what your particular syntax is, and possibly
581     adding some stuff in error.h.
582 johnpye 379 */
583    
584 johnpye 427 #ifdef NO_VARIADIC_MACROS
585 jpye 3196 /** error reporter for compilers not supporting variadic macros */
586 johnpye 62 int error_reporter_note_no_line(const char *fmt,...){
587     int res;
588     va_list args;
589    
590     va_start(args,fmt);
591 jpye 3210 res = va_error_reporter(ASC_PROG_NOTE,"unknown-file",0,NULL,fmt,&args);
592 johnpye 62 va_end(args);
593    
594     return res;
595     }
596 johnpye 85
597 jpye 3196 /** error reporter 'here' for compilers not supporting variadic macros */
598 johnpye 1063 ASC_DLLSPEC int error_reporter_here(const error_severity_t sev, const char *fmt,...){
599 johnpye 188 int res;
600     va_list args;
601    
602     va_start(args,fmt);
603 jpye 3210 res = va_error_reporter(sev,"unknown-file",0,NULL,fmt,&args);
604 johnpye 188 va_end(args);
605    
606     return res;
607     }
608    
609 jpye 3196 /** error reporter for compilers not supporting variadic macros */
610 johnpye 190 int error_reporter_noline(const error_severity_t sev, const char *fmt,...){
611     int res;
612     va_list args;
613    
614     va_start(args,fmt);
615 jpye 3210 res = va_error_reporter(sev,NULL,0,NULL,fmt,&args);
616 johnpye 190 va_end(args);
617    
618     return res;
619     }
620    
621 jpye 3196 /** console debugging for compilers not supporting variadic macros */
622 johnpye 85 int console_debug(const char *fmt,...){
623     int res;
624     va_list args;
625    
626     va_start(args,fmt);
627 johnpye 86 res = Asc_VFPrintf(ASCERR,fmt,args);
628 johnpye 85 va_end(args);
629    
630     return res;
631 johnpye 86 }
632 johnpye 427 #endif /* NO_VARIADIC_MACROS */

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