-
-
Save bcho/4507979 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include <assert.h> | |
#include "except.h" | |
#define T except_t | |
except_frame *except_stack = NULL; | |
void except_raise(const T *e, const char *file, int line) | |
{ | |
except_frame *p = except_stack; | |
assert(e); | |
if (p == NULL) { | |
fprintf(stderr, "Uncaught exception"); | |
if (e->reason) | |
fprintf(stderr, " %s", e->reason); | |
else | |
fprintf(stderr, " at 0x%p", e); | |
if (file && line > 0) | |
fprintf(stderr, " raised at %s:%d\n", file, line); | |
fprintf(stderr, "aborting...\n"); | |
fflush(stderr); | |
abort(); | |
} | |
p->exception = e; | |
p->file = file; | |
p->line = line; | |
except_stack = except_stack->prev; | |
longjmp(p->env, except_raised); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef EXCEPT_H | |
#define EXCEPT_H | |
#include <setjmp.h> | |
#define T except_t | |
typedef struct T { | |
const char *reason; | |
} T; | |
/* exported types */ | |
typedef struct except_frame except_frame; | |
struct except_frame { | |
except_frame *prev; | |
jmp_buf env; | |
const char *file; | |
int line; | |
const T *exception; | |
}; | |
enum { | |
except_entered = 0, | |
except_raised, | |
except_handled, | |
except_finalized | |
}; | |
/* exported variables */ | |
extern except_frame *except_stack; | |
/* exported functions */ | |
void except_raise(const T *e, const char *file, int line); | |
/* exported marcos */ | |
#define RAISE(e) except_raise(&(e), __FILE__, __LINE__) | |
#define RERAISE except_raise(_except_frame.exception, \ | |
_except_frame.file, _except_frame.line) | |
#define RETURN switch(except_stack = except_stack.prev, 0) default: return /* pop the except frame stack */ | |
#define TRY do { \ | |
volatile int _except_flag; \ | |
except_frame _except_frame; \ | |
_except_frame.prev = except_stack; \ | |
except_stack = &_except_frame; \ | |
_except_flag = setjmp(_except_frame.env); \ | |
if (_except_flag == except_entered) { | |
#define EXCEPT(e) \ | |
if (_except_flag == except_entered) \ | |
except_stack = except_stack->prev; \ | |
} else if (_except_frame.exception == &(e)) { \ | |
_except_flag = except_handled; | |
#define ELSE \ | |
if (_except_flag == except_entered) \ | |
except_stack = except_stack->prev; \ | |
} else { \ | |
_except_flag = except_handled; | |
#define FINALLY \ | |
if (_except_flag == except_entered) \ | |
except_stack = except_stack->prev; \ | |
} { \ | |
if (_except_flag == except_entered) \ | |
_except_flag = except_finalized; | |
#define END_TRY \ | |
if (_except_flag == except_entered) \ | |
except_stack = except_stack->prev; \ | |
} if (_except_flag == except_raised) RERAISE; \ | |
} while (0) | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment