Exceptions.h文件源码
/* Copyright 1989 Digital Equipment Corporation. */
/* Distributed only by permission. */
/**************************************************************************/
/* File: exception.h */
/* Last modified on Wed Mar 15 16:40:41 PST 1989 by roberts */
/* */
/* The exception package provides a general exception handling mechanism */
/* for use with C that is portable across a variety of compilers and */
/* operating systems. The design of this facility is based on the */
/* exception handling mechanism used in the Modula-2+ language at DEC/SRC */
/* and is described in detail in the paper in the documents directory. */
/* For more background on the underlying motivation for this design, see */
/* SRC Research Report #3. */
/**************************************************************************/
#include <setjmp.h>
#include <stdlib.h>
#define MaxExceptionsPerScope 10
#define ETooManyExceptClauses 101
#define EUnhandledException 102
#define ES_Initialize 0
#define ES_EvalBody 1
#define ES_Exception 2
typedef struct { char *name ;} exception;
typedef struct _ctx_block {
jmp_buf jmp;
int nx;
exception *array[MaxExceptionsPerScope];
exception *id;
int value;
int finally;
struct _ctx_block *link;
} context_block;
extern exception ANY;
extern context_block *exceptionStack;
extern void _RaiseException(exception *e, int v);
#define RAISE(e, v) _RaiseException(&e, v)
#define TRY \
{\
context_block _ctx;\
int _es = ES_Initialize;\
_ctx.nx = 0;\
_ctx.link= NULL;\
_ctx.finally = 0;\
_ctx.link = exceptionStack;\
exceptionStack = &_ctx;\
if (setjmp(_ctx.jmp) != 0) _es = ES_Exception;\
while (1) {\
if (_es == ES_EvalBody) {
#define EXCEPT(e) \
if(_es == ES_EvalBody) exceptionStack = _ctx.link;\
break;\
}\
if (_es == ES_Initialize) {\
if (_ctx.nx >= MaxExceptionsPerScope)\
exit(ETooManyExceptClauses);\
_ctx.array[_ctx.nx++] = &e;\
} else if (_ctx.id == &e || &e == &ANY) {\
int exception_value = _ctx.value;\
exceptionStack = _ctx.link;
#define FINALLY \
}\
if (_es == ES_Initialize) {\
if (_ctx.nx >= MaxExceptionsPerScope)\
exit(ETooManyExceptClauses);\
_ctx.finally = 1;\
} else {\
exceptionStack = _ctx.link;
#define ENDTRY \
if (_ctx.finally && _es == ES_Exception)\
_RaiseException(_ctx.id, _ctx.value);\
break;\
}\
_es = ES_EvalBody;\
}\
}
Exceptions.c文件源码
/* Copyright 1989 Digital Equipment Corporation. */
/* Distributed only by permission. */
/**************************************************************************/
/* File: exception.h */
/* Last modified on Wed Mar 15 16:40:42 PST 1989 by roberts */
/* */
/* Implementation of the C exception handler. Much of the real work is */
/* done in the exception.h header file. */
/**************************************************************************/
#include <stdio.h>
#include "exception.h"
context_block *exceptionStack = NULL;
exception ANY;
void _RaiseException(exception *e, int v){
context_block *cb, *xb;
exception *t;
int i, found;
found = 0;
for (xb = exceptionStack; xb != NULL; xb = xb->link) {
for (i = 0; i < xb->nx; i++) {
t = xb->array[i];
if (t == e || t == &ANY) {
found = 1;
break;
}
}
if (found) break;
}
if (xb == NULL) exit(EUnhandledException);
for (cb = exceptionStack; cb != xb && !cb->finally; cb = cb->link);
exceptionStack = cb;
cb->id = e;
cb->value = v;
longjmp(cb->jmp, ES_Exception);
}
test.c测试函数
#include "exception.h"
#include <stdio.h>
exception e = { "假装是个很严重的错误"};
void raiseE(exception *toRaise){
RAISE(*toRaise,100);
}
void main(){
int i = 0;
TRY
TRY
++i;
if(a == NULL)
raiseE(&e);
--i;
FINALLY
printf("FINAL\n");
ENDTRY
EXCEPT(e)
printf("捕获到异常e:%s;异常码:%d\n",e.name,exception_value);
ENDTRY
printf("i = %d\n",i);
system("pause");
}
异常可以从函数内部的抛出,并且跳过了–i这一句,所以最终i的值为1,并且运行了FINALLY语句块后继续抛出,并被EXCEPT(e)语句块捕获,然后成功获得了异常信息。