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 <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
#include <GEF.h>

/* 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


