Better makefile, restructured, more demos

This commit is contained in:
2011-07-30 23:21:17 -04:00
parent b233356ad3
commit 1c280a8cde
9 changed files with 129 additions and 136 deletions

View File

@@ -1,19 +1,23 @@
CC=gcc CC=gcc
LD=gcc LD=gcc
EXECOBJ= 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= LIBS=
CFLAGS= CFLAGS=
all: exception_test all: $(LIBTARGET) $(DEMOS)
demo/%.exe: demo/%.o
$(LD) -o $@ $(CFLAGS) -L./lib $< -lexc -ggdb -gstabs
%.o: %.c %.o: %.c
$(CC) -c -o $@ $(CFLAGS) -rdynamic -ggdb -gstabs $< $(CC) -c -o $@ $(CFLAGS) -ggdb -gstabs -I./include $<
exception_test: $(OBJECTS) $(LIBTARGET): $(LIBOBJECTS)
$(LD) -o exception_test $(LIBS) $(OBJECTS) ar rcs $(LIBTARGET) $(LIBOBJECTS)
.PHONY: clean .PHONY: clean
clean: clean:
rm -f *.o rm -f demo/*o $(LIBOBJECTS) $(DEMOS) $(LIBTARGET)
rm -f exception_test

23
demo/single.c Normal file
View 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
View 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
View 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
View 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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -2,14 +2,10 @@
#define __EXCLIB_H__ #define __EXCLIB_H__
#include <setjmp.h> #include <setjmp.h>
#ifdef WIN32
#include "backtrace.h"
#else
#include <execinfo.h>
#endif
#include <signal.h> #include <signal.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h>
#include <sys/types.h> #include <sys/types.h>
/* /*
@@ -134,12 +130,19 @@ __exc_curidx--;
#define FINALLY \ #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_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_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__) #define EXCLIB_TRACE(x) exclib_print_exception_stack(x, __FILE__, (char *)__func__, __LINE__)

View File

@@ -40,6 +40,7 @@ void exclib_print_exception_stack(char *mbuf, char *file, char *func, int line)
if ( ! cur ) if ( ! cur )
fprintf(stderr, "EXCLIB: #0: No exception stack\n"); fprintf(stderr, "EXCLIB: #0: No exception stack\n");
else {
while ( cur != NULL ) { while ( cur != NULL ) {
memset((char *)&buf, 0, 256); memset((char *)&buf, 0, 256);
memset((char *)&flagbuf, 0, 256); memset((char *)&flagbuf, 0, 256);
@@ -79,6 +80,7 @@ void exclib_print_exception_stack(char *mbuf, char *file, char *func, int line)
cur = cur->prev; cur = cur->prev;
} }
} }
}
void exclib_bulk_name_exceptions(struct exc_name_data *exclib_exc_names, int size) void exclib_bulk_name_exceptions(struct exc_name_data *exclib_exc_names, int size)
{ {
@@ -123,6 +125,7 @@ void exclib_prep_throw(int value, char *msg, char *file, char *func, int line)
{ {
char stbuf[256]; char stbuf[256];
memset((char *)&stbuf, 0, 256); memset((char *)&stbuf, 0, 256);
if ( EXC_STATUS_LIST && EXC_STATUS_LIST->tried == 1) { if ( EXC_STATUS_LIST && EXC_STATUS_LIST->tried == 1) {
sprintf((char *)&stbuf, "Tried to THROW %d but couldn't create new exception frame", value); 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 ) { if ( EXC_STATUS_LIST->catching == 1 && EXC_STATUS_LIST->prev ) {
@@ -131,27 +134,22 @@ void exclib_prep_throw(int value, char *msg, char *file, char *func, int line)
exit(value); exit(value);
} }
memcpy(EXC_STATUS_LIST->buf, EXC_STATUS_LIST->prev->buf, sizeof(jmp_buf)); 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) ) { } 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");
exclib_clear_exc_frame(); exclib_clear_exc_frame();
__exc_curidx--; return;
} */ else { } else {
if ( exclib_new_exc_frame(EXC_STATUS_LIST, file, func, line) ) if ( exclib_new_exc_frame(EXC_STATUS_LIST, file, func, line) )
exclib_print_exception_stack((char *)&stbuf, file, func, line); exclib_print_exception_stack((char *)&stbuf, file, func, line);
} }
EXC_STATUS_LIST->value = value; EXC_STATUS_LIST->value = value;
EXC_STATUS_LIST->name = __exc_names[value]; EXC_STATUS_LIST->name = __exc_names[value];
EXC_STATUS_LIST->description = msg; EXC_STATUS_LIST->description = msg;
} else { 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); 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); exclib_print_exception_stack((char *)&stbuf, file, func, line);
exit(__exc_signals[value]); exit(__exc_signals[value]);
} }
}
int exclib_new_exc_frame(struct exc_status *es, char *file, char *function, int line) int exclib_new_exc_frame(struct exc_status *es, char *file, char *function, int line)
@@ -207,14 +205,15 @@ int exclib_clear_exc_frame()
EXC_STATUS_LIST->line = es->line; EXC_STATUS_LIST->line = es->line;
EXC_STATUS_LIST->name = es->name; EXC_STATUS_LIST->name = es->name;
EXC_STATUS_LIST->description = es->description; EXC_STATUS_LIST->description = es->description;
THROW(es->value, es->description); int val = es->value;
memset((void *)es, 0x00, sizeof(struct exc_status));
THROW(val, EXC_STATUS_LIST->description);
} }
} else { } else {
if ( es->prev) {
EXC_STATUS_LIST = es->prev; EXC_STATUS_LIST = es->prev;
es->value = 0; }
es->caught = 0; memset((void *)es, 0x00, sizeof(struct exc_status));
es->tried = 0;
es->catching = 0;
} }
} }