Better makefile, restructured, more demos
This commit is contained in:
18
Makefile
18
Makefile
@@ -1,19 +1,23 @@
|
||||
CC=gcc
|
||||
LD=gcc
|
||||
EXECOBJ=
|
||||
OBJECTS=exclib.o exception_test.o
|
||||
LIBOBJECTS=src/exclib.o
|
||||
DEMOS=demo/single.exe demo/twolevel.exe demo/threelevel.exe demo/trypair.exe
|
||||
LIBTARGET=lib/libexc.a
|
||||
LIBS=
|
||||
CFLAGS=
|
||||
|
||||
all: exception_test
|
||||
all: $(LIBTARGET) $(DEMOS)
|
||||
|
||||
demo/%.exe: demo/%.o
|
||||
$(LD) -o $@ $(CFLAGS) -L./lib $< -lexc -ggdb -gstabs
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c -o $@ $(CFLAGS) -rdynamic -ggdb -gstabs $<
|
||||
$(CC) -c -o $@ $(CFLAGS) -ggdb -gstabs -I./include $<
|
||||
|
||||
exception_test: $(OBJECTS)
|
||||
$(LD) -o exception_test $(LIBS) $(OBJECTS)
|
||||
$(LIBTARGET): $(LIBOBJECTS)
|
||||
ar rcs $(LIBTARGET) $(LIBOBJECTS)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f *.o
|
||||
rm -f exception_test
|
||||
rm -f demo/*o $(LIBOBJECTS) $(DEMOS) $(LIBTARGET)
|
||||
|
||||
23
demo/single.c
Normal file
23
demo/single.c
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "exclib.h"
|
||||
|
||||
/*
|
||||
* What this demo shows:
|
||||
* 1- The general usage of this library
|
||||
* 2- That a basic usage example works
|
||||
*/
|
||||
|
||||
int main(void)
|
||||
{
|
||||
EXCLIB_TRACE("No stack to print?");
|
||||
|
||||
TRY {
|
||||
THROW(3, NULL);
|
||||
} CATCH(3) {
|
||||
EXCLIB_TRACE("Caught 3");
|
||||
} ETRY;
|
||||
|
||||
EXCLIB_TRACE("Exiting program");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
16
demo/threelevel.c
Normal file
16
demo/threelevel.c
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "exclib.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
TRY {
|
||||
TRY {
|
||||
THROW(3, NULL);
|
||||
} CATCH(5) {
|
||||
EXCLIB_TRACE("Caught 5");
|
||||
} ETRY;
|
||||
} CATCH(3) {
|
||||
EXCLIB_TRACE("Caught 3");
|
||||
} ETRY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
21
demo/trypair.c
Normal file
21
demo/trypair.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "exclib.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
TRY {
|
||||
THROW(3, NULL);
|
||||
} CATCH(3) {
|
||||
} ETRY;
|
||||
|
||||
TRY {
|
||||
THROW(3, NULL);
|
||||
} CATCH(3) {
|
||||
TRY {
|
||||
THROW(3, NULL);
|
||||
} ETRY;
|
||||
} ETRY;
|
||||
|
||||
EXCLIB_TRACE("Should never get here");
|
||||
return 0;
|
||||
|
||||
}
|
||||
21
demo/twolevel.c
Normal file
21
demo/twolevel.c
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "exclib.h"
|
||||
|
||||
/*
|
||||
* What this example shows:
|
||||
* 1- That an exception will propagate up out of the current TRY/CATCH context
|
||||
* 2- That an uncaught exception will generate an error
|
||||
*/
|
||||
|
||||
int main(void)
|
||||
{
|
||||
TRY {
|
||||
THROW(3, NULL);
|
||||
} CATCH(3) {
|
||||
THROW(3, NULL);
|
||||
} ETRY;
|
||||
|
||||
EXCLIB_TRACE("Should never get here");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
#include "exclib.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void nullfunc(int *something)
|
||||
{
|
||||
THROW_ZERO(something, EXC_NULLPOINTER, NULL);
|
||||
printf("nullfunc got %d\n", *something);
|
||||
}
|
||||
|
||||
void badfunc(void)
|
||||
{
|
||||
// This function represents a function that you think you can trust; but there's a null
|
||||
// pointer being passed here that you have no control over. Thankfully 'nullfunc' was
|
||||
// written to be safe, so it will illustrate the usefulness of TRY/CATCH/ETRY.
|
||||
int *ptr = NULL;
|
||||
nullfunc(ptr);
|
||||
}
|
||||
|
||||
void testfunc(void)
|
||||
{
|
||||
THROW(34, "Random test exception");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int x = 2;
|
||||
|
||||
printf("Stack frames are %d bytes in size\n\n", sizeof(struct exc_status));
|
||||
|
||||
TRY {
|
||||
fprintf(stdout, "Throwing %d\n", x);
|
||||
THROW(2, "First exception");
|
||||
} CATCH(-1) {
|
||||
printf("Caught -1\n");
|
||||
THROW(1, "1 Exception");
|
||||
} CATCH(1) {
|
||||
printf("Caught 1\n");
|
||||
} CATCH(2) {
|
||||
printf("Caught 2\n");
|
||||
TRY {
|
||||
testfunc();
|
||||
} CATCH(34) {
|
||||
printf("Caught 34!\n");
|
||||
printf("Throwing 34 Back Out\n");
|
||||
THROW(34, "Second-layer exception 34");
|
||||
} ETRY;
|
||||
} CATCH(34) {
|
||||
printf("Caught 34 in upper level!\n");
|
||||
printf("Using THROW_NONZERO\n");
|
||||
THROW_NONZERO(strcmp("a", "b"), 0, "String Compare Exception");
|
||||
} FINALLY {
|
||||
exclib_print_exception_stack("In finally clause", __FILE__, (char *)__func__, __LINE__);
|
||||
} ETRY;
|
||||
|
||||
TRY {
|
||||
badfunc();
|
||||
} ETRY;
|
||||
|
||||
/*printf("\nThrowing an exception with no toplevel TRY block, which should stacktrace and kill us...\n\n");
|
||||
|
||||
THROW(34, "Bad Exception");*/
|
||||
return 0;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
#include "exclib.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
EXCLIB_TRACE("No stack to print?");
|
||||
|
||||
TRY {
|
||||
EXCLIB_TRACE("Inside TRY");
|
||||
THROW(3, NULL);
|
||||
} CATCH(3) {
|
||||
EXCLIB_TRACE("Caught 3");
|
||||
THROW(5, NULL);
|
||||
} CATCH(5) {
|
||||
EXCLIB_TRACE("Caught 5");
|
||||
TRY {
|
||||
THROW(6, NULL);
|
||||
} CATCH (6) {
|
||||
EXCLIB_TRACE("Caught 6");
|
||||
THROW(7, NULL);
|
||||
} ETRY;
|
||||
} CATCH(7) {
|
||||
EXCLIB_TRACE("Caught 7");
|
||||
} FINALLY {
|
||||
EXCLIB_TRACE("In finally clause");
|
||||
} ETRY;
|
||||
|
||||
EXCLIB_TRACE("Exiting program");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -2,14 +2,10 @@
|
||||
#define __EXCLIB_H__
|
||||
|
||||
#include <setjmp.h>
|
||||
#ifdef WIN32
|
||||
#include "backtrace.h"
|
||||
#else
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
@@ -134,12 +130,19 @@ __exc_curidx--;
|
||||
|
||||
#define FINALLY \
|
||||
}; \
|
||||
if ( EXC_STATUS_LIST->caught ) {
|
||||
if ( EXC_STATUS_LIST && EXC_STATUS_LIST->caught ) {
|
||||
|
||||
#define THROW_NONZERO(x, y, z) int rc = (x); if ( rc != 0 ) THROW(rc + y, z);
|
||||
#define THROW_ZERO(x, y, z) if ( (x) == 0 ) THROW(y, z);
|
||||
|
||||
#define THROW(x, y) exclib_prep_throw(x, y, __FILE__, (char *)__func__, __LINE__); if ( EXC_STATUS_LIST ) { longjmp(EXC_STATUS_LIST->buf, x); } else { exclib_print_exception_stack("Unhandled Exception "#x"", __FILE__, (char *)__func__, __LINE__); };
|
||||
#define THROW(x, y) \
|
||||
exclib_prep_throw(x, y, __FILE__, (char *)__func__, __LINE__); \
|
||||
if ( EXC_STATUS_LIST->value > 0 ) { \
|
||||
longjmp(EXC_STATUS_LIST->buf, x); \
|
||||
} else { \
|
||||
exclib_print_exception_stack("Uncaught Exception "#x"", __FILE__, (char *)__func__, __LINE__); \
|
||||
exit(x); \
|
||||
}
|
||||
|
||||
#define EXCLIB_TRACE(x) exclib_print_exception_stack(x, __FILE__, (char *)__func__, __LINE__)
|
||||
|
||||
@@ -40,7 +40,8 @@ void exclib_print_exception_stack(char *mbuf, char *file, char *func, int line)
|
||||
|
||||
if ( ! cur )
|
||||
fprintf(stderr, "EXCLIB: #0: No exception stack\n");
|
||||
while ( cur != NULL ) {
|
||||
else {
|
||||
while ( cur != NULL ) {
|
||||
memset((char *)&buf, 0, 256);
|
||||
memset((char *)&flagbuf, 0, 256);
|
||||
if ( cur->catching == 1) {
|
||||
@@ -77,6 +78,7 @@ void exclib_print_exception_stack(char *mbuf, char *file, char *func, int line)
|
||||
fprintf(stderr, "%s", (char *)&buf);
|
||||
idx += 1;
|
||||
cur = cur->prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +125,7 @@ void exclib_prep_throw(int value, char *msg, char *file, char *func, int line)
|
||||
{
|
||||
char stbuf[256];
|
||||
memset((char *)&stbuf, 0, 256);
|
||||
|
||||
if ( EXC_STATUS_LIST && EXC_STATUS_LIST->tried == 1) {
|
||||
sprintf((char *)&stbuf, "Tried to THROW %d but couldn't create new exception frame", value);
|
||||
if ( EXC_STATUS_LIST->catching == 1 && EXC_STATUS_LIST->prev ) {
|
||||
@@ -131,26 +134,21 @@ void exclib_prep_throw(int value, char *msg, char *file, char *func, int line)
|
||||
exit(value);
|
||||
}
|
||||
memcpy(EXC_STATUS_LIST->buf, EXC_STATUS_LIST->prev->buf, sizeof(jmp_buf));
|
||||
} /*else if ( EXC_STATUS_LIST->catching == 1 && (EXC_STATUS_LIST->prev == NULL) ) {
|
||||
if ( exclib_new_exc_frame(&__exc_statuses[__exc_curidx++], file, func, line) ) {
|
||||
exclib_print_exception_stack((char *)&stbuf, file, func, line);
|
||||
exit(value);
|
||||
}
|
||||
EXCLIB_TRACE("Condition 2");
|
||||
} else if ( EXC_STATUS_LIST->catching == 1 && (EXC_STATUS_LIST->prev == NULL) ) {
|
||||
exclib_clear_exc_frame();
|
||||
__exc_curidx--;
|
||||
} */ else {
|
||||
return;
|
||||
} else {
|
||||
if ( exclib_new_exc_frame(EXC_STATUS_LIST, file, func, line) )
|
||||
exclib_print_exception_stack((char *)&stbuf, file, func, line);
|
||||
}
|
||||
EXC_STATUS_LIST->value = value;
|
||||
EXC_STATUS_LIST->name = __exc_names[value];
|
||||
EXC_STATUS_LIST->description = msg;
|
||||
} else {
|
||||
sprintf((char *)&stbuf, "Tried to THROW Exception %d but had no exception context. (Called outside of TRY block, or thrown while TRY was setting up?)", value);
|
||||
exclib_print_exception_stack((char *)&stbuf, file, func, line);
|
||||
exit(__exc_signals[value]);
|
||||
return;
|
||||
}
|
||||
sprintf((char *)&stbuf, "Tried to THROW Exception %d but had no exception context. (Called outside of TRY block, or thrown while TRY was setting up?)", value);
|
||||
exclib_print_exception_stack((char *)&stbuf, file, func, line);
|
||||
exit(__exc_signals[value]);
|
||||
}
|
||||
|
||||
|
||||
@@ -189,7 +187,7 @@ int exclib_clear_exc_frame()
|
||||
exit(1);
|
||||
}
|
||||
if ( es->prev )
|
||||
es->prev->next = NULL;
|
||||
es->prev->next = NULL;
|
||||
if ( es->value && !es->caught ) {
|
||||
// thrown exception was unhandled - do we have anywhere else to go?
|
||||
if ( !es->prev ) {
|
||||
@@ -198,23 +196,24 @@ int exclib_clear_exc_frame()
|
||||
exit(es->value);
|
||||
//kill(getpid(), SIGKILL);
|
||||
} else if ( es->tried && es->prev && (es->catching == 0)) {
|
||||
// copy this exception up into the upper frame and siglongjmp back to that
|
||||
EXC_STATUS_LIST = es->prev;
|
||||
EXC_STATUS_LIST->caught = 0;
|
||||
memcpy(&EXC_STATUS_LIST->bt_frames, &es->bt_frames, (sizeof(void *)*EXC_BT_FRAMES));
|
||||
EXC_STATUS_LIST->file = es->file;
|
||||
EXC_STATUS_LIST->function = es->function;
|
||||
EXC_STATUS_LIST->line = es->line;
|
||||
EXC_STATUS_LIST->name = es->name;
|
||||
EXC_STATUS_LIST->description = es->description;
|
||||
THROW(es->value, es->description);
|
||||
// copy this exception up into the upper frame and siglongjmp back to that
|
||||
EXC_STATUS_LIST = es->prev;
|
||||
EXC_STATUS_LIST->caught = 0;
|
||||
memcpy(&EXC_STATUS_LIST->bt_frames, &es->bt_frames, (sizeof(void *)*EXC_BT_FRAMES));
|
||||
EXC_STATUS_LIST->file = es->file;
|
||||
EXC_STATUS_LIST->function = es->function;
|
||||
EXC_STATUS_LIST->line = es->line;
|
||||
EXC_STATUS_LIST->name = es->name;
|
||||
EXC_STATUS_LIST->description = es->description;
|
||||
int val = es->value;
|
||||
memset((void *)es, 0x00, sizeof(struct exc_status));
|
||||
THROW(val, EXC_STATUS_LIST->description);
|
||||
}
|
||||
} else {
|
||||
if ( es->prev) {
|
||||
EXC_STATUS_LIST = es->prev;
|
||||
es->value = 0;
|
||||
es->caught = 0;
|
||||
es->tried = 0;
|
||||
es->catching = 0;
|
||||
}
|
||||
memset((void *)es, 0x00, sizeof(struct exc_status));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user