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

Diff of /trunk/base/generic/utilities/error.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 930 by johnpye, Wed Nov 22 11:01:06 2006 UTC revision 931 by johnpye, Thu Nov 23 04:31:19 2006 UTC
# Line 2  Line 2 
2    
3  #include "error.h"  #include "error.h"
4    
5    #define ERROR_REPORTER_TREE_ACTIVE
6    
7    #ifdef ERROR_REPORTER_TREE_ACTIVE
8    # include "ascMalloc.h"
9    #endif
10    
11  /**  /**
12      Global variable which stores the pointer to the callback      Global variable which stores the pointer to the callback
13      function being used.      function being used.
# Line 14  static error_reporter_callback_t g_error Line 20  static error_reporter_callback_t g_error
20  */  */
21  static error_reporter_meta_t g_error_reporter_cache;  static error_reporter_meta_t g_error_reporter_cache;
22    
23    static error_reporter_meta_t *error_reporter_meta_new(){
24        error_reporter_meta_t *e;
25        e = ASC_NEW(error_reporter_meta_t);
26        e->sev = ASC_USER_SUCCESS;
27        e->iscaching = 0;
28        e->filename = NULL;
29        e->func = NULL;
30        e->line = 0;
31        e->msg[0] = '\0';
32        return e;
33    }
34        
35  /**  /**
36      XTERM colour codes used to distinguish between errors of different types.      XTERM colour codes used to distinguish between errors of different types.
37  */  */
# Line 66  int error_reporter_default_callback(ERRO Line 84  int error_reporter_default_callback(ERRO
84      return res;      return res;
85  }  }
86    
87    /*---------------------------------------------------------------------------
88      ERROR REPORTER TREE (BRANCHABLE ERROR STACK) FUNCTIONALITY
89    */
90    
91    #ifdef ERROR_REPORTER_TREE_ACTIVE
92    
93    static error_reporter_tree_t *g_error_reporter_tree = NULL;
94    static error_reporter_tree_t *g_error_reporter_tree_current = NULL;
95    # define TREECURRENT g_error_reporter_tree_current
96    # define TREE g_error_reporter_tree
97    
98    static error_reporter_tree_t *error_reporter_tree_new(){
99        error_reporter_tree_t *tnew = ASC_NEW(error_reporter_tree_t);
100        tnew->next = NULL;
101        tnew->head = NULL;
102        tnew->tail = NULL;
103        tnew->err = NULL;
104        return tnew;
105    }
106    
107    int error_reporter_tree_start(){
108        error_reporter_tree_t *tnew;
109        tnew = error_reporter_tree_new();
110    
111        if(TREE == NULL){
112            CONSOLE_DEBUG("CREATING ROOT");
113            /* we're creating the root */
114            tnew->parent = NULL;
115            TREE = tnew;
116            TREECURRENT = tnew;
117        }else{
118            CONSOLE_DEBUG("CREATING SUBTREE");
119            if(TREECURRENT->head == NULL){
120                /* if the current tree has no elements, add it as the head */
121                TREECURRENT->head = tnew;
122            }else{
123                /* link the new tree to the last in the child list */
124                TREECURRENT->tail->next = tnew;
125            }
126            /* update the tail of the list */
127            TREECURRENT->tail = tnew;
128    
129            /* now switch the context to the sub-tree */
130            tnew->parent = TREECURRENT;
131            TREECURRENT = tnew;
132        }
133        return 0;
134    }
135        
136    int error_reporter_tree_end(){
137        CONSOLE_DEBUG("TREE END");
138        if(!TREECURRENT){
139            ERROR_REPORTER_HERE(ASC_PROG_ERR,"'end' without TREECURRENT set");
140            return 1;
141        }
142        TREECURRENT = TREECURRENT->parent;
143        return 0;
144    }  
145    
146    
147    static void error_reporter_tree_free(error_reporter_tree_t *t){
148        if(t->head)error_reporter_tree_free(t->head);
149        if(t->next)error_reporter_tree_free(t->next);
150        if(t->err)ASC_FREE(t->err);
151        ASC_FREE(t);
152    }
153    
154    void error_reporter_tree_clear(){
155        /* recursively free anything beneath the TREECURRENT node, return to the parent context */
156        error_reporter_tree_t *t;
157        if(!TREECURRENT){
158            /* CONSOLE_DEBUG("NOTHING TO CLEAR!"); */
159            return;
160        }
161        if(TREECURRENT->parent){
162            CONSOLE_DEBUG("MOVING UP TO PARENT");
163            t = TREECURRENT->parent;
164        }else{
165            CONSOLE_DEBUG("REACHED TOP LEVEL");
166            t = NULL;
167        }
168        error_reporter_tree_free(TREECURRENT);
169        TREECURRENT = t;
170    }
171    
172    static int error_reporter_tree_match_sev(error_reporter_tree_t *t, unsigned match){
173        if(t->err && (t->err->sev & match))return 1;
174        if(t->next && error_reporter_tree_match_sev(t->next, match))return 1;
175        if(t->head && error_reporter_tree_match_sev(t->head, match))return 1;
176        return 0;
177    }
178    
179    /**
180        traverse the tree, looking for ASC_PROG_ERR, ASC_USER_ERROR, or ASC_PROG_FATAL
181        @return 1 if errors found
182    */
183    int error_reporter_tree_has_error(){
184        if(TREECURRENT){
185            return error_reporter_tree_match_sev(TREECURRENT,ASC_ERR_ERR);
186        }else{
187            CONSOLE_DEBUG("NO TREE FOUND");
188            return 0;
189        }
190    }
191    
192    static int error_reporter_tree_write(error_reporter_tree_t *t){
193        int res = 0;
194        static int writecount = 0;
195    
196        if(++writecount > 30){
197            CONSOLE_DEBUG("TOO MUCH WRITING");
198            return 0;
199        }
200    
201        if(t->err){
202            res += error_reporter(t->err->sev, t->err->filename, t->err->line, t->err->func, t->err->msg);
203        }else{
204            CONSOLE_DEBUG("TREE HAS NO TOP-LEVEL ERROR");
205        }
206    
207        if(t->head){
208            res += error_reporter_tree_write(t->head);
209        }
210        if(t->next){
211            res += error_reporter_tree_write(t->next);
212        }
213        return res;
214    }
215    
216    #else /* ERROR_REPORTER_TREE_ACTIVE */
217    int error_reporter_tree_start(){
218        ERROR_REPORTER_HERE(ASC_PROG_WARNING,"Error reporter 'tree' turned off at compile time");
219    }
220    # define error_reporter_tree_end(){}
221    # define error_reporter_tree_clear(){}
222    #endif /* ERROR_REPORTER_TREE_ACTIVE */
223    
224  /*--------------------------  /*--------------------------
225    REPORT the error    REALLY WHERE THE REPORTING HAPPENS
226  */  */
227    
228  int  int
229  va_error_reporter(  va_error_reporter(
230        const error_severity_t sev        const error_severity_t sev
# Line 80  va_error_reporter( Line 236  va_error_reporter(
236  ){  ){
237      int res;      int res;
238    
239    #ifdef ERROR_REPORTER_TREE_ACTIVE
240        error_reporter_tree_t *t;
241        if(TREECURRENT){
242            /* add the error to the tree, don't output anything now */
243            t = error_reporter_tree_new();
244            t->err = error_reporter_meta_new();
245            res = vsnprintf(t->err->msg,ERROR_REPORTER_MAX_MSG,fmt,args);
246            t->err->filename = errfile;
247            t->err->func = errfunc;
248            t->err->line = errline;
249            t->err->sev = sev;
250            if(!TREECURRENT->head){
251                TREECURRENT->head = TREECURRENT->tail = t;
252            }else{
253                TREECURRENT->tail->next = t;
254                TREECURRENT->tail = t;
255            }
256            CONSOLE_DEBUG("Message (%d chars) added to tree",res);
257            return res;
258        }else if(TREE){
259            /* flush the tree before outputting current message */
260            CONSOLE_DEBUG("WRITING OUT TREE CONTENTS");
261            t = TREE;
262            TREE = NULL;
263            error_reporter_tree_write(t);
264            error_reporter_tree_free(t);
265        }
266    #endif
267    
268      if(g_error_reporter_callback==NULL){      if(g_error_reporter_callback==NULL){
269          /* fprintf(stderr,"CALLING VFPRINTF\n"); */          /* fprintf(stderr,"CALLING VFPRINTF\n"); */
270          res = error_reporter_default_callback(sev,errfile,errline,errfunc,fmt,args);          res = error_reporter_default_callback(sev,errfile,errline,errfunc,fmt,args);
# Line 280  int console_debug(const char *fmt,...){ Line 465  int console_debug(const char *fmt,...){
465    
466      return res;      return res;
467  }  }
468    
469  #endif /* NO_VARIADIC_MACROS */  #endif /* NO_VARIADIC_MACROS */

Legend:
Removed from v.930  
changed lines
  Added in v.931

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