Added a CLEANUP mechanism to the exception handling library. Fixed a bug in the way setjmp() return codes were being handled that lead to infinite loops in some cases, exceptions getting missed in others. Made FINALLY {} a required element (unfortunately).
This commit is contained in:
9
Makefile
9
Makefile
@@ -2,18 +2,19 @@ CC=gcc
|
|||||||
LD=gcc
|
LD=gcc
|
||||||
EXECOBJ=
|
EXECOBJ=
|
||||||
LIBOBJECTS=src/exclib.o
|
LIBOBJECTS=src/exclib.o
|
||||||
DEMOS=demo/single.exe demo/twolevel.exe demo/trypair.exe demo/catchgroup.exe demo/finally.exe demo/default.exe demo/helpers.exe demo/deepuncaught.exe
|
DEMOS=demo/single.exe demo/twolevel.exe demo/trypair.exe demo/catchgroup.exe demo/finally.exe demo/default.exe demo/helpers.exe demo/deepuncaught.exe demo/cleanup.exe demo/skeleton.exe
|
||||||
LIBTARGET=lib/libexc.a
|
LIBTARGET=lib/libexc.a
|
||||||
LIBS=
|
LIBS=
|
||||||
CFLAGS=
|
#CFLAGS=-Wall -Wextra -std=c89 -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition
|
||||||
|
CFLAGS=-std=c89
|
||||||
|
|
||||||
all: lib demo
|
all: lib demo
|
||||||
|
|
||||||
demo/%.exe: demo/%.o lib
|
demo/%.exe: demo/%.o lib
|
||||||
$(LD) -o $@ $(CFLAGS) -L./lib $< -lexc -ggdb -gstabs
|
$(LD) -o $@ $(CFLAGS) -L./lib $< -lexc -ggdb
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
$(CC) -c -o $@ $(CFLAGS) -ggdb -gstabs -I./include $<
|
$(CC) -c -o $@ $(CFLAGS) -ggdb -I./include $<
|
||||||
|
|
||||||
.PHONY: demo
|
.PHONY: demo
|
||||||
demo: $(DEMOS)
|
demo: $(DEMOS)
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ int main(void)
|
|||||||
{
|
{
|
||||||
TRY {
|
TRY {
|
||||||
THROW(2, NULL);
|
THROW(2, NULL);
|
||||||
|
} EXCEPT {
|
||||||
} CATCH_GROUP(1) {
|
} CATCH_GROUP(1) {
|
||||||
} CATCH_GROUP(2) {
|
} CATCH_GROUP(2) {
|
||||||
} CATCH_GROUP(3) {
|
} CATCH_GROUP(3) {
|
||||||
EXCLIB_TRACE("Inside of CATCH_GROUP");
|
EXCLIB_TRACE("Inside of CATCH_GROUP");
|
||||||
|
} FINALLY {
|
||||||
} ETRY;
|
} ETRY;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
36
demo/cleanup.c
Normal file
36
demo/cleanup.c
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#include "exclib.h"
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
int val = 512;
|
||||||
|
int *ptr = &val;
|
||||||
|
|
||||||
|
TRY {
|
||||||
|
THROW(3, "Checking to ensure cleanup behavior executes before EXCEPT block");
|
||||||
|
} CLEANUP {
|
||||||
|
ptr = NULL;
|
||||||
|
} EXCEPT {
|
||||||
|
} CATCH(3) {
|
||||||
|
if ( ptr != NULL ) {
|
||||||
|
EXCLIB_TRACE("pointer was not reset to NULL in first CLEANUP block");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} FINALLY {
|
||||||
|
} ETRY;
|
||||||
|
|
||||||
|
ptr = &val;
|
||||||
|
TRY {
|
||||||
|
/* No exception thrown here, CLEANUP should still execute */
|
||||||
|
} CLEANUP {
|
||||||
|
ptr = NULL;
|
||||||
|
} EXCEPT {
|
||||||
|
} FINALLY {
|
||||||
|
} ETRY;
|
||||||
|
|
||||||
|
if ( ptr != NULL ) {
|
||||||
|
EXCLIB_TRACE("pointer was not reset to NULL in first TRY block");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -6,8 +6,17 @@ int main(void)
|
|||||||
TRY {
|
TRY {
|
||||||
TRY {
|
TRY {
|
||||||
THROW(3, NULL);
|
THROW(3, NULL);
|
||||||
|
} CLEANUP {
|
||||||
|
} EXCEPT {
|
||||||
|
} FINALLY {
|
||||||
} ETRY;
|
} ETRY;
|
||||||
|
} CLEANUP {
|
||||||
|
} EXCEPT {
|
||||||
|
} FINALLY {
|
||||||
} ETRY;
|
} ETRY;
|
||||||
|
} CLEANUP {
|
||||||
|
} EXCEPT {
|
||||||
|
} FINALLY {
|
||||||
} ETRY;
|
} ETRY;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -5,8 +5,12 @@ int main(void)
|
|||||||
{
|
{
|
||||||
TRY {
|
TRY {
|
||||||
THROW(2, NULL);
|
THROW(2, NULL);
|
||||||
|
} CLEANUP {
|
||||||
|
} EXCEPT {
|
||||||
} DEFAULT {
|
} DEFAULT {
|
||||||
EXCLIB_TRACE("Inside of DEFAULT - I catch everything!");
|
EXCLIB_TRACE("Inside of DEFAULT - I catch everything!");
|
||||||
} ETRY;
|
|
||||||
return 0;
|
return 0;
|
||||||
|
} FINALLY {
|
||||||
|
} ETRY;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ int main(void)
|
|||||||
{
|
{
|
||||||
TRY {
|
TRY {
|
||||||
THROW(2, NULL);
|
THROW(2, NULL);
|
||||||
|
} EXCEPT {
|
||||||
} FINALLY {
|
} FINALLY {
|
||||||
printf("I am in the finally clause, and I am about to issue an unhandled exception error.\n");
|
printf("I am in the finally clause, and I am about to issue an unhandled exception error.\n");
|
||||||
} ETRY;
|
} ETRY;
|
||||||
|
|||||||
@@ -4,10 +4,13 @@ int main(void)
|
|||||||
{
|
{
|
||||||
TRY {
|
TRY {
|
||||||
THROW_ZERO(NULL, EXC_NULLPOINTER, "I just threw with THROW_ZERO");
|
THROW_ZERO(NULL, EXC_NULLPOINTER, "I just threw with THROW_ZERO");
|
||||||
|
} CLEANUP {
|
||||||
|
} EXCEPT {
|
||||||
} CATCH ( EXC_NULLPOINTER ) {
|
} CATCH ( EXC_NULLPOINTER ) {
|
||||||
THROW_NONZERO(strcmp("not", "equal"),
|
THROW_NONZERO(strcmp("not", "equal"),
|
||||||
3,
|
3,
|
||||||
"strcmp was nonzero!");
|
"strcmp was nonzero!");
|
||||||
|
} FINALLY {
|
||||||
} ETRY;
|
} ETRY;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -12,8 +12,11 @@ int main(void)
|
|||||||
|
|
||||||
TRY {
|
TRY {
|
||||||
THROW(3, NULL);
|
THROW(3, NULL);
|
||||||
|
} CLEANUP {
|
||||||
|
} EXCEPT {
|
||||||
} CATCH(3) {
|
} CATCH(3) {
|
||||||
EXCLIB_TRACE("Caught 3");
|
EXCLIB_TRACE("Caught 3");
|
||||||
|
} FINALLY {
|
||||||
} ETRY;
|
} ETRY;
|
||||||
|
|
||||||
EXCLIB_TRACE("Exiting program");
|
EXCLIB_TRACE("Exiting program");
|
||||||
|
|||||||
10
demo/skeleton.c
Normal file
10
demo/skeleton.c
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "exclib.h"
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
TRY {
|
||||||
|
} CLEANUP {
|
||||||
|
} EXCEPT {
|
||||||
|
} FINALLY {
|
||||||
|
} ETRY;
|
||||||
|
}
|
||||||
@@ -5,11 +5,15 @@ int main(void)
|
|||||||
TRY {
|
TRY {
|
||||||
TRY {
|
TRY {
|
||||||
THROW(3, NULL);
|
THROW(3, NULL);
|
||||||
|
} EXCEPT {
|
||||||
} CATCH(5) {
|
} CATCH(5) {
|
||||||
EXCLIB_TRACE("Caught 5");
|
EXCLIB_TRACE("Caught 5");
|
||||||
|
} FINALLY {
|
||||||
} ETRY;
|
} ETRY;
|
||||||
|
} EXCEPT {
|
||||||
} CATCH(3) {
|
} CATCH(3) {
|
||||||
EXCLIB_TRACE("Caught 3");
|
EXCLIB_TRACE("Caught 3");
|
||||||
|
} FINALLY {
|
||||||
} ETRY;
|
} ETRY;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -4,15 +4,24 @@ int main(void)
|
|||||||
{
|
{
|
||||||
TRY {
|
TRY {
|
||||||
THROW(3, NULL);
|
THROW(3, NULL);
|
||||||
|
} CLEANUP {
|
||||||
|
} EXCEPT {
|
||||||
} CATCH(3) {
|
} CATCH(3) {
|
||||||
|
} FINALLY {
|
||||||
} ETRY;
|
} ETRY;
|
||||||
|
|
||||||
TRY {
|
TRY {
|
||||||
THROW(3, NULL);
|
THROW(3, NULL);
|
||||||
|
} CLEANUP {
|
||||||
|
} EXCEPT {
|
||||||
} CATCH(3) {
|
} CATCH(3) {
|
||||||
TRY {
|
TRY {
|
||||||
THROW(3, NULL);
|
THROW(3, NULL);
|
||||||
|
} CLEANUP {
|
||||||
|
} EXCEPT {
|
||||||
|
} FINALLY {
|
||||||
} ETRY;
|
} ETRY;
|
||||||
|
} FINALLY {
|
||||||
} ETRY;
|
} ETRY;
|
||||||
|
|
||||||
EXCLIB_TRACE("Should never get here");
|
EXCLIB_TRACE("Should never get here");
|
||||||
|
|||||||
@@ -10,8 +10,11 @@ int main(void)
|
|||||||
{
|
{
|
||||||
TRY {
|
TRY {
|
||||||
THROW(3, NULL);
|
THROW(3, NULL);
|
||||||
|
} CLEANUP {
|
||||||
|
} EXCEPT {
|
||||||
} CATCH(3) {
|
} CATCH(3) {
|
||||||
THROW(3, NULL);
|
THROW(3, NULL);
|
||||||
|
} FINALLY {
|
||||||
} ETRY;
|
} ETRY;
|
||||||
|
|
||||||
EXCLIB_TRACE("Should never get here");
|
EXCLIB_TRACE("Should never get here");
|
||||||
|
|||||||
@@ -34,12 +34,16 @@
|
|||||||
* TRY {
|
* TRY {
|
||||||
* ... do something here ...
|
* ... do something here ...
|
||||||
* THROW(int, "descriptive message")
|
* THROW(int, "descriptive message")
|
||||||
|
* } CLEANUP {
|
||||||
|
* ... do any cleanup from your TRY {} block here ...
|
||||||
|
* } EXCEPT {
|
||||||
* } CATCH(int) {
|
* } CATCH(int) {
|
||||||
* ... do error handling here ...
|
* ... do error handling here ...
|
||||||
* } DEFAULT {
|
* } DEFAULT {
|
||||||
* ... Do something with an exception here without caring about its value ...
|
* ... Do something with an exception here without caring about its value ...
|
||||||
* } FINALLY {
|
* } FINALLY {
|
||||||
* ... Do something here ...
|
* ... Do something here regardless of which exception occurred, but ONLY if an exception occurred ...
|
||||||
|
* }
|
||||||
* } ETRY;
|
* } ETRY;
|
||||||
*
|
*
|
||||||
* The syntax is fairly obvious. Code inside the TRY block is executed, and any exceptions are propagated out to the CATCH blocks.
|
* The syntax is fairly obvious. Code inside the TRY block is executed, and any exceptions are propagated out to the CATCH blocks.
|
||||||
@@ -47,10 +51,18 @@
|
|||||||
* integer exception. If DEFAULT is not present and there is no CATCH block, then the exception is propagated back up the stack to the
|
* integer exception. If DEFAULT is not present and there is no CATCH block, then the exception is propagated back up the stack to the
|
||||||
* first TRY() block encountered in the program. (Unhandled exceptions behave as in #5,6 in the bullet list above.)
|
* first TRY() block encountered in the program. (Unhandled exceptions behave as in #5,6 in the bullet list above.)
|
||||||
*
|
*
|
||||||
|
* DO NOT PLACE ANY CODE BETWEEN THE EXCEPT { AND THE FIRST CATCH {. IT WILL NEVER BE EXECUTED.
|
||||||
|
*
|
||||||
|
* The CLEANUP block is optional and is executed before any exceptions are processed. Use this to clean up any resources which must be
|
||||||
|
* handled before the EXCEPT{} block potentially sends control out of the currrent scope, orphaning resources like file handles and
|
||||||
|
* memory.
|
||||||
|
*
|
||||||
* The FINALLY clause is executed after the try block has executed, and after any applicable CATCH/DEFAULT blocks. If present, it will
|
* The FINALLY clause is executed after the try block has executed, and after any applicable CATCH/DEFAULT blocks. If present, it will
|
||||||
* be executed REGARDLESS of which exception was actually caught. This is useful to examine an exception as it passes through
|
* be executed REGARDLESS of which exception was actually caught. This is useful to examine an exception as it passes through
|
||||||
* without actually handling/modifying it, or to execute some generic action on exception, regardless of what type, but only after
|
* without actually handling/modifying it, or to execute some generic action on exception, regardless of what type, but only after
|
||||||
* specific exceptions have been handled
|
* specific exceptions have been handled. Beware, however, that FINALLY is executed AFTER CATCH blocks, therefore one of the CATCH blocks
|
||||||
|
* may have transferred control outside of the TRY {} statement, meaning that the FINALLY {} clause never actually gets executed.
|
||||||
|
* Cleaning up resources should be done in CLEANUP, not FINALLY.
|
||||||
*
|
*
|
||||||
* THROW_ZERO is a convenience function to replace blocks like this:
|
* THROW_ZERO is a convenience function to replace blocks like this:
|
||||||
*
|
*
|
||||||
@@ -79,7 +91,7 @@
|
|||||||
* ...
|
* ...
|
||||||
* } CATCH (EXC_NULLPOINTER) {
|
* } CATCH (EXC_NULLPOINTER) {
|
||||||
* ...
|
* ...
|
||||||
* }
|
* } ETRY;
|
||||||
*
|
*
|
||||||
* This example also highlights one of the problems of this library : You can't check for multiple exceptions on the same block,
|
* This example also highlights one of the problems of this library : You can't check for multiple exceptions on the same block,
|
||||||
* because it's all actually a hidden 'switch' statement. But you can use a mechanism like shown above; when you have multiple
|
* because it's all actually a hidden 'switch' statement. But you can use a mechanism like shown above; when you have multiple
|
||||||
@@ -87,6 +99,14 @@
|
|||||||
* does not provide a break in the flow between the previous case and the current one, so fallthrough is achieved. Just make
|
* does not provide a break in the flow between the previous case and the current one, so fallthrough is achieved. Just make
|
||||||
* sure to use a CATCH on any proceeding exceptions that don't need to fall through (like the EXC_NULLPOINTER above).
|
* sure to use a CATCH on any proceeding exceptions that don't need to fall through (like the EXC_NULLPOINTER above).
|
||||||
*
|
*
|
||||||
|
* You MUST use TRY / EXCEPT / FINALLY / ETRY. This is the minimal form:
|
||||||
|
*
|
||||||
|
* TRY {
|
||||||
|
* } EXCEPT {
|
||||||
|
* } FINALLY {
|
||||||
|
* } ETRY;
|
||||||
|
*
|
||||||
|
* Without this, the generated code will be syntactically incorrect for the preprocessor.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXC_STRBUF_SIZE
|
#ifndef EXC_STRBUF_SIZE
|
||||||
@@ -95,20 +115,25 @@
|
|||||||
|
|
||||||
#ifndef EXC_MAX_FRAMES
|
#ifndef EXC_MAX_FRAMES
|
||||||
#define EXC_MAX_FRAMES 50
|
#define EXC_MAX_FRAMES 50
|
||||||
#endif // EXC_MAX_FRAMES
|
#endif /* EXC_MAX_FRAMES */
|
||||||
|
|
||||||
#ifndef EXC_MAX_EXCEPTIONS
|
#ifndef EXC_MAX_EXCEPTIONS
|
||||||
#define EXC_MAX_EXCEPTIONS 4096
|
#define EXC_MAX_EXCEPTIONS 4096
|
||||||
#endif // EXC_MAX_EXCEPTIONS
|
#endif /* EXC_MAX_EXCEPTIONS */
|
||||||
|
|
||||||
#define TRY \
|
#define TRY \
|
||||||
if (__exclib_curidx >= EXC_MAX_FRAMES) \
|
if (__exclib_curidx >= EXC_MAX_FRAMES) \
|
||||||
exclib_print_exception_stack("No available exception stack context", __FILE__, (char *)__func__, __LINE__); \
|
exclib_print_exception_stack("No available exception stack context", __FILE__, (char *)__func__, __LINE__); \
|
||||||
if ( exclib_new_exc_frame(&__exclib_statuses[__exclib_curidx++], __FILE__, (char *)__func__, __LINE__) != 0) \
|
if ( exclib_new_exc_frame(&__exclib_statuses[__exclib_curidx++], __FILE__, (char *)__func__, __LINE__) != 0) \
|
||||||
exclib_print_exception_stack("Tried to TRY but couldn't create new exception frame", __FILE__, (char *)__func__, __LINE__); \
|
exclib_print_exception_stack("Tried to TRY but couldn't create new exception frame", __FILE__, (char *)__func__, __LINE__); \
|
||||||
EXCLIB_EXCEPTION->value = setjmp(EXCLIB_EXCEPTION->buf); \
|
EXCLIB_EXCEPTION->setjmpstatus = setjmp(EXCLIB_EXCEPTION->buf); \
|
||||||
EXCLIB_EXCEPTION->tried = 1;\
|
EXCLIB_EXCEPTION->tried = 1; \
|
||||||
switch( EXCLIB_EXCEPTION->value ) { \
|
|
||||||
|
#define CLEANUP
|
||||||
|
|
||||||
|
#define EXCEPT \
|
||||||
|
if ( EXCLIB_EXCEPTION && EXCLIB_EXCEPTION->setjmpstatus != 0 ) { \
|
||||||
|
switch( EXCLIB_EXCEPTION->value ) { \
|
||||||
case 0:
|
case 0:
|
||||||
|
|
||||||
#define CATCH(x) \
|
#define CATCH(x) \
|
||||||
@@ -128,22 +153,23 @@ switch( EXCLIB_EXCEPTION->value ) { \
|
|||||||
EXCLIB_EXCEPTION->caught = 1; \
|
EXCLIB_EXCEPTION->caught = 1; \
|
||||||
EXCLIB_EXCEPTION->catching = 1;
|
EXCLIB_EXCEPTION->catching = 1;
|
||||||
|
|
||||||
|
#define FINALLY \
|
||||||
|
}; \
|
||||||
|
|
||||||
#define ETRY \
|
#define ETRY \
|
||||||
}; \
|
}; \
|
||||||
exclib_clear_exc_frame(); \
|
exclib_clear_exc_frame(); \
|
||||||
__exclib_curidx--;
|
__exclib_curidx--;
|
||||||
|
|
||||||
#define FINALLY \
|
|
||||||
}; \
|
|
||||||
if ( EXCLIB_EXCEPTION && EXCLIB_EXCEPTION->value ) {
|
|
||||||
|
|
||||||
#define THROW_NONZERO(x, y, z) __exclib_rc = (x); if ( __exclib_rc != 0 ) { __exclib_rc += y; THROW(__exclib_rc, z); }
|
#define THROW_NONZERO(x, y, z) if ( (x) != 0 ) { THROW(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) \
|
#define THROW(x, y) \
|
||||||
THROW_EXPLICIT(x, y, __FILE__, (char *)__func__, __LINE__, 1);
|
THROW_EXPLICIT(x, y, __FILE__, (char *)__func__, __LINE__, 1)
|
||||||
|
|
||||||
#define THROW_EXPLICIT(x, y, file, func, line, setflag) \
|
#define THROW_EXPLICIT(x, y, file, func, line, setflag) \
|
||||||
|
if ( EXCLIB_EXCEPTION && EXCLIB_EXCEPTION->setjmpstatus == 0 ) { \
|
||||||
exclib_prep_throw(x, y, file, func, line, setflag); \
|
exclib_prep_throw(x, y, file, func, line, setflag); \
|
||||||
if ( EXCLIB_EXCEPTION->thrown > 0 ) { \
|
if ( EXCLIB_EXCEPTION->thrown > 0 ) { \
|
||||||
longjmp(EXCLIB_EXCEPTION->buf, x); \
|
longjmp(EXCLIB_EXCEPTION->buf, x); \
|
||||||
@@ -151,6 +177,7 @@ if ( EXCLIB_EXCEPTION && EXCLIB_EXCEPTION->value ) {
|
|||||||
sprintf((char *)&__exclib_strbuf, "Uncaught exception %d", x); \
|
sprintf((char *)&__exclib_strbuf, "Uncaught exception %d", x); \
|
||||||
exclib_print_exception_stack((char *)&__exclib_strbuf, file, func, line); \
|
exclib_print_exception_stack((char *)&__exclib_strbuf, file, func, line); \
|
||||||
exit(x); \
|
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__)
|
||||||
@@ -170,6 +197,7 @@ struct exclib_status {
|
|||||||
struct exclib_status *next;
|
struct exclib_status *next;
|
||||||
struct exclib_status *prev;
|
struct exclib_status *prev;
|
||||||
jmp_buf buf;
|
jmp_buf buf;
|
||||||
|
int setjmpstatus;
|
||||||
int value;
|
int value;
|
||||||
int caught;
|
int caught;
|
||||||
int tried;
|
int tried;
|
||||||
@@ -198,4 +226,4 @@ extern void exclib_print_exception_stack(char *mbuf, char *file, char *func, int
|
|||||||
extern int exclib_new_exc_frame(struct exclib_status *es, char *file, char *function, int line);
|
extern int exclib_new_exc_frame(struct exclib_status *es, char *file, char *function, int line);
|
||||||
extern int exclib_clear_exc_frame();
|
extern int exclib_clear_exc_frame();
|
||||||
|
|
||||||
#endif // __EXCLIB_H__
|
#endif /* __EXCLIB_H__ */
|
||||||
|
|||||||
18
src/exclib.c
18
src/exclib.c
@@ -21,7 +21,7 @@ struct exclib_name_data __exclib_exc_names[EXC_PREDEFINED_EXCEPTIONS] = {
|
|||||||
|
|
||||||
void exclib_print_exception_stack(char *mbuf, char *file, char *func, int line)
|
void exclib_print_exception_stack(char *mbuf, char *file, char *func, int line)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char buf[512];
|
||||||
char flagbuf[256];
|
char flagbuf[256];
|
||||||
char *excname = NULL;
|
char *excname = NULL;
|
||||||
struct exclib_status *cur = EXCLIB_EXCEPTION;
|
struct exclib_status *cur = EXCLIB_EXCEPTION;
|
||||||
@@ -72,9 +72,9 @@ void exclib_print_exception_stack(char *mbuf, char *file, char *func, int line)
|
|||||||
else
|
else
|
||||||
excname = "NULL";
|
excname = "NULL";
|
||||||
sprintf((char *)&buf,
|
sprintf((char *)&buf,
|
||||||
"EXCLIB: #%d[0x%x] %s:%d:%s:%s:%d:%s: %s\n",
|
"EXCLIB: #%d[0x%lx] %s:%d:%s:%s:%d:%s: %s\n",
|
||||||
idx,
|
idx,
|
||||||
cur,
|
(unsigned long int)cur,
|
||||||
cur->file,
|
cur->file,
|
||||||
cur->line,
|
cur->line,
|
||||||
cur->function,
|
cur->function,
|
||||||
@@ -93,7 +93,7 @@ void exclib_bulk_name_exceptions(struct exclib_name_data *exclib_exc_names, int
|
|||||||
{
|
{
|
||||||
struct exclib_name_data *ptr;
|
struct exclib_name_data *ptr;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
//THROW_ZERO(exclib_exc_names, EXC_NULLPOINTER, "Null Pointer");
|
/*THROW_ZERO(exclib_exc_names, EXC_NULLPOINTER, "Null Pointer");*/
|
||||||
ptr = exclib_exc_names;
|
ptr = exclib_exc_names;
|
||||||
for ( i = 0; i < size ; i++) {
|
for ( i = 0; i < size ; i++) {
|
||||||
exclib_name_exception(ptr->exc, ptr->name);
|
exclib_name_exception(ptr->exc, ptr->name);
|
||||||
@@ -113,7 +113,7 @@ void exclib_init()
|
|||||||
return;
|
return;
|
||||||
__exclib_inited = 1;
|
__exclib_inited = 1;
|
||||||
memset(&__exclib_statuses, 0x00, sizeof(struct exclib_status) * EXC_MAX_FRAMES);
|
memset(&__exclib_statuses, 0x00, sizeof(struct exclib_status) * EXC_MAX_FRAMES);
|
||||||
// for whatever reason memset isn't safe here, so ...
|
/* for whatever reason memset isn't safe here, so ... */
|
||||||
for ( i = 0 ; i < EXC_MAX_EXCEPTIONS; i++ ) {
|
for ( i = 0 ; i < EXC_MAX_EXCEPTIONS; i++ ) {
|
||||||
__exclib_names[i] = NULL;
|
__exclib_names[i] = NULL;
|
||||||
}
|
}
|
||||||
@@ -190,14 +190,13 @@ int exclib_clear_exc_frame()
|
|||||||
if ( es->prev )
|
if ( es->prev )
|
||||||
es->prev->next = NULL;
|
es->prev->next = NULL;
|
||||||
if ( es->thrown && !es->caught ) {
|
if ( es->thrown && !es->caught ) {
|
||||||
// thrown exception was unhandled - do we have anywhere else to go?
|
/* thrown exception was unhandled - do we have anywhere else to go? */
|
||||||
if ( !es->prev ) {
|
if ( !es->prev ) {
|
||||||
// No frame above us to propagate this into, stacktrace and kill ourselves
|
/* No frame above us to propagate this into, stacktrace and kill ourselves */
|
||||||
exclib_print_exception_stack("Uncaught exception", es->file, es->function, es->line);
|
exclib_print_exception_stack("Uncaught exception", es->file, es->function, es->line);
|
||||||
exit(es->value);
|
exit(es->value);
|
||||||
//kill(getpid(), SIGKILL);
|
|
||||||
} else if ( es->tried && es->prev && (es->catching == 0)) {
|
} else if ( es->tried && es->prev && (es->catching == 0)) {
|
||||||
// copy this exception up into the upper frame and siglongjmp back to that
|
/* copy this exception up into the upper frame and siglongjmp back to that */
|
||||||
EXCLIB_EXCEPTION = es->prev;
|
EXCLIB_EXCEPTION = es->prev;
|
||||||
EXCLIB_EXCEPTION->caught = 0;
|
EXCLIB_EXCEPTION->caught = 0;
|
||||||
EXCLIB_EXCEPTION->name = es->name;
|
EXCLIB_EXCEPTION->name = es->name;
|
||||||
@@ -216,5 +215,6 @@ int exclib_clear_exc_frame()
|
|||||||
}
|
}
|
||||||
memset((void *)es, 0x00, sizeof(struct exclib_status));
|
memset((void *)es, 0x00, sizeof(struct exclib_status));
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user