The GEF General Exception-Handling Library by Bruce W. Bigby Listing One typedef struct { int lowbound; int highbound; int size; int **data; int numberOfSlots; } *ArrayOfInt_t; static void AddHighInt(ArrayOfInt_t self, int i) { int old_highbound = self->highbound; gef_try { self->data[size++] = i; self->highbound++; } gef_invariants { gef_assert(self->highbound - self->lowbound + 1 == self->size); } gef_preconditions { gef_assert(self->data != NULL); gef_assert(self->numberOfSlots > self->size); } gef_postconditions { gef_assert(self->highbound == old_highbound + 1); } gef_end; } Listing Two #include #include #include #include #include /* Define exception values for program */ #define EXCEPT_FAILURE 0 /* This should never occur! */ #define EXCEPT_OS_VIOLATION 1 #define EXCEPT_INSUFFICIENT_MEMORY 2 #define EXCEPT_ASSERTION_VIOLATION 3 #define EXCEPT_ARITHMETIC_VIOLATION 4 static void InsufficientMemory() { gef_throw((void*) EXCEPT_INSUFFICIENT_MEMORY); } static void AssertionViolation(char* fileName, int lineNumber) { /* Can only transfer fileName and lineNumber info via a pointer to a */ /* structure. For now, simply throw the integer value, */ gef_throw((void*) EXCEPT_ASSERTION_VIOLATION); } static void UnhandledException(void* exceptionID) { fprintf(stderr, "\tUnhandled exception, %d, occurred, while executing process, %d.\n",((int) exceptionID), (int) getpid()); } static void* OSSignalToException(int signum) { switch(signum) { case SIGFPE: return((void*) EXCEPT_ARITHMETIC_VIOLATION); default: return((void*) EXCEPT_OS_VIOLATION); } } int matherr(struct exception* e) { /* This handler will catch all IEEE math violations */ gef_throw((void*) EXCEPT_ARITHMETIC_VIOLATION); } static double SquareRoot(double number) { /* Check for number < 0.0 for demonstration only. If math error occurs */ /* math library will call matherr, which will throw exception anyway. */ if (number < 0.0) gef_throw((void*) EXCEPT_ARITHMETIC_VIOLATION); return(sqrt(number)); } int main(int argc, char** argv) { double number, answer; int exitCode = 0; sigset_t osSignalSet; GEFAttr_t gefAttrs; if (argc != 2) { fprintf(stderr, "Usage: %s decimal\n", argv[0]); exit(1); } /* Configure GEF for process. */ sigemptyset(&osSignalSet); sigaddset(&osSignalSet, SIGFPE); GEFInitialize(osSignalSet); /* Configure GEF for thread */ GEFAttr_Init(&gefAttrs); GEFAttr_SetAssertionViolation(&gefAttrs, AssertionViolation); GEFAttr_SetUnhandledException(&gefAttrs, UnhandledException); GEFAttr_SetOutOfMemory(&gefAttrs, InsufficientMemory); GEFAttr_SetOSSignalToException(&gefAttrs, OSSignalToException); GEFInitializeThread(gefAttrs); gef_enable_assertions; gef_try { number = atof(argv[1]); answer = SquareRoot(number); printf("%f\n", answer); } gef_preconditions { gef_assert(argc == 2); } gef_catch(exception) { switch((int) exception) { case EXCEPT_ARITHMETIC_VIOLATION: fprintf(stderr,"%s: Cannot take square root of %f!\n",argv[0],number); exitCode = 1; gef_break; default: break; } } gef_end; GEFTerminate(); exit(exitCode); } Listing Three void PrintConcatenation(char* s1, char* s2, FILE* fp) { char* result = NULL; gef_try { result = malloc(strlen(s1) + strlen(s2) + 1); gef_assert(result != NULL); strcpy(result, s1); strcat(result, s2); fprintf(fp, "Concatenation of %s and %s is %s!\n", s1, s2, result); } gef_preconditions { gef_assert(result == NULL); gef_assert(s1 != NULL); gef_assert(s2 != NULL); } gef_finally { if (result != NULL) free((void*) result); result = NULL; } gef_end; } 3