00001 /* errCatch - help catch errors so that errAborts aren't 00002 * fatal, and warn's don't necessarily get printed immediately. 00003 * Note that error conditions caught this way will tend to 00004 * leak resources unless there are additional wrappers. 00005 * 00006 * Typical usage is 00007 * errCatch = errCatchNew(); 00008 * if (errCatchStart(errCatch)) 00009 * doFlakyStuff(); 00010 * errCatchEnd(errCatch); 00011 * if (errCatch->gotError) 00012 * warn(errCatch->message->string); 00013 * errCatchFree(&errCatch); 00014 * cleanupFlakyStuff(); 00015 */ 00016 00017 #include "common.h" 00018 #include "errabort.h" 00019 #include "dystring.h" 00020 #include "errCatch.h" 00021 00022 static char const rcsid[] = "$Id: errCatch.c,v 1.2 2006/08/10 01:02:47 kent Exp $"; 00023 00024 00025 struct errCatch *errCatchNew() 00026 /* Return new error catching structure. */ 00027 { 00028 struct errCatch *errCatch; 00029 AllocVar(errCatch); 00030 errCatch->message = dyStringNew(0); 00031 return errCatch; 00032 } 00033 00034 void errCatchFree(struct errCatch **pErrCatch) 00035 /* Free up resources associated with errCatch */ 00036 { 00037 struct errCatch *errCatch = *pErrCatch; 00038 if (errCatch != NULL) 00039 { 00040 dyStringFree(&errCatch->message); 00041 freez(pErrCatch); 00042 } 00043 } 00044 00045 static struct errCatch *errCatchStack = NULL; 00046 00047 static void errCatchAbortHandler() 00048 /* semiAbort */ 00049 { 00050 errCatchStack->gotError = TRUE; 00051 longjmp(errCatchStack->jmpBuf, -1); 00052 } 00053 00054 static void errCatchWarnHandler(char *format, va_list args) 00055 /* Write an error to top of errCatchStack. */ 00056 { 00057 dyStringVaPrintf(errCatchStack->message, format, args); 00058 dyStringAppendC(errCatchStack->message, '\n'); 00059 } 00060 00061 boolean errCatchPushHandlers(struct errCatch *errCatch) 00062 /* Push error handlers. Not usually called directly. */ 00063 { 00064 pushAbortHandler(errCatchAbortHandler); 00065 pushWarnHandler(errCatchWarnHandler); 00066 slAddHead(&errCatchStack, errCatch); 00067 return TRUE; 00068 } 00069 00070 void errCatchEnd(struct errCatch *errCatch) 00071 /* Restore error handlers and pop self off of catching stack. */ 00072 { 00073 popWarnHandler(); 00074 popAbortHandler(); 00075 if (errCatch != errCatchStack) 00076 errAbort("Mismatch betweene errCatch and errCatchStack"); 00077 errCatchStack = errCatch->next; 00078 } 00079 00080 boolean errCatchFinish(struct errCatch **pErrCatch) 00081 /* Finish up error catching. Report error if there is a 00082 * problem and return FALSE. If no problem return TRUE. 00083 * This handles errCatchEnd and errCatchFree. */ 00084 { 00085 struct errCatch *errCatch = *pErrCatch; 00086 boolean ok = TRUE; 00087 if (errCatch != NULL) 00088 { 00089 errCatchEnd(errCatch); 00090 if (errCatch->gotError) 00091 { 00092 ok = FALSE; 00093 warn(errCatch->message->string); 00094 } 00095 errCatchFree(pErrCatch); 00096 } 00097 return ok; 00098 } 00099
1.5.2