Better makefile, restructured, more demos
This commit is contained in:
18
Makefile
18
Makefile
@@ -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
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__
|
#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__)
|
||||||
|
|
||||||
@@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user