Name: Anonymous 2008-06-14 8:02
i made an exception handling header for C and thought /prog/ could find a use for it, anyway, enjoy:
(simple usage below)
exception.h
usage:
(simple usage below)
exception.h
/**
* exception handling for ANSI C
* \note NOT thread-safe \br
* values of automatic variables are unspecified (look to longjmp(3) man page)
*/
#ifndef __EXCEPTION_H
#define __EXCEPTION_H
/// programmer can declare this to achive deeper recursion
#ifndef __EXMAXNEST
# define __EXMAXNEST 16
#endif
/// simple stack for environment buffers used by setjmp()
jmp_buf __exbuf[__EXMAXNEST];
/// simple stack for exit values of longjmp()
int __exvalue[__EXMAXNEST];
/**
* simple stack to check if current exception has been handled
* (needed for upward propagation)
*/
char __exhandled[__EXMAXNEST];
/// simple stack pointer
int __exnest = 0;
/// try block
#define try { \
if(__exnest >= __EXMAXNEST) { \
fprintf(stderr, "%s:%i: Too deep try (...) catch " \
"recursion. Aborting... \n", __FILE__, \
__LINE__); \
abort(); \
} \
__exhandled[__exnest] = 0; \
if ((__exvalue[__exnest] = \
setjmp(__exbuf[__exnest++])) == 0) {
/// catch block
#define catch(x) } else if (__exvalue[__exnest-1] == (x) ) { \
__exhandled[__exnest-1] = 1; \
--__exnest;
/**
* finally block
* \note must be always included, even if no code goes into finally block
*/
#define finally } else { \
__exhandled[__exnest-1] = 0; \
--__exnest; \
}
/// closing part for try block
#define end_try if( __exhandled[__exnest] == 0) \
if (__exnest != 0) { \
longjmp(__exbuf[__exnest-1], \
__exvalue[__exnest]); \
} else { \
fprintf(stderr, "%s:%i: Unhandled " \
"exception %i. Aborting...\n", \
__FILE__, __LINE__, \
__exvalue[__exnest]); \
abort(); \
} \
}
/// throws exception given as a parameter
#define throw(x) longjmp(__exbuf[__exnest-1], (x))
/**
* makes current exception unhandled (it will be propagated upwards), useful
* to just print debug mesages from local variables and continue
* unvinding the stack
* \note can be safely used only in catch() block
*/
#define unhandled __exhandled[__exnest] = 0
/**
* does basically the same thing as unhandled but can
* change exception type, better that throw in catch() because it doesn't make
* the finally block unexecuted
* \note can be safely used only in catch() block
*/
#define rethrow(x) __exhandled[__exnest] = 0; \
__exvalue[__exnest] = (x)
#else
extern jmp_buf __exbuf[__EXMAXNEST];
extern int __exvalue[__EXMAXNEST];
extern char __exhandled[__EXMAXNEST];
extern int __exnest;
#endifusage:
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include "exception.h"
int func(int a)
{
throw(1);
}
int main(int argc, char** argv)
{
try
func(2);
catch(2)
printf("exception catched\n");
catch(1)
printf("weird exception, make it unhandled\n");
unhandled;
finally
printf("always executed\n");
end_try
exit(0);
}