???????????????????????????Allocation_handle????????????鷳??
??????Allocation_Failed??????????????????malloc???????????????allocate??????
????Except_T Allocate_Failed = {"Allocation failed"};
????void *allocate(unsigned n)
????{
????void *new = malloc(n);
????if(new)
????return new;
????RAISE(Allocation_Failed);
????assert(0);
????}
?????????????ó???????????????????????????TRY-EXCEPT????????allocate??
????extern Except_T Allocate_Failed;
????char *buf;
????TRY
????buf = allocate(4096);
????EXCEPT(Allocate_Failed)
????fprintf(stderr?? "could't allocate the buff ");
????exit(EXIT_FAILURE);
????END_TRY;
????TRY-EXCEPT???????setjmp??longjmp??????
????TRY-FINALLY????????:
????TRY
????S
????FINALLY
????S1
????END_TRY
???????S??в????κ???????????S1???????????END_TRY?????S?????????????S????б??ж?????????????S1??S1??????????S1??е??????2???????????????????????????????????????????S1????????????ж???????е??????????????RERAISE?????????????2?????
????#define RERAISE Except_raise(Except_frame.exception??
????Except_frame.file?? Except_frame.line)
????????е????????????:
????#define RETURN switch (Except_stack = Except_stack->prev??0) default: return
????RETURN?????????TRY?????????????????return???
???????
????Except????е?????????????????????????????????????????????????е????env??setjmp??longjmp???????jmp_buf?????????????????????
????typedef struct Except_Frame Except_Frame;
????struct Except_Frame {
????Except_Frame *prev;
????jmp_buf env;
????const char *file;
????int line;
????const T *exception;
????};
????extern Except_Frame *Except_stack;
????Except_stack?????????????????????prev?????????????????????????????????????exception????У????????file??line????б?????????????–???????????????к?
????TRY??佫????μ?Except_Frame??????????????setjmp????RAISE??RERAISE????Except_raise????????????exception??file??line????????е??????Exception_Frame????????longjmp??EXCEPT????????е?exception??Σ????????????????????FINALLY??????????????????2??????????????д洢??????
?????????TRY??EXCEPT??ELSE??FINALLY_TRY???TRY-EXCEPT????????????????????
????do {
????creat and push an Except_Frame
????if(first return from setjmp) {
????S
????} else if (exception is e1) {
????S1
????……
????} else if (exception is en) {
????Sn
????} else {
????S0
????}
????if(an exception occurrend and wasn’t handled)
????RERAISE;
????} while(0)
????Exception_Frame???????????????TRY?????do-while?????е???????????????????????????????????
????#define TRY do {
????volatile int Except_flag;
????Except_Frame Except_frame;
????Except_frame.prev = Except_stack;
????Except_stack = &Except_frame; 
????Except_flag = setjmp(Except_frame.env);
????if (Except_flag == Except_entered) {
??????TRY?????????????????????????????????
????enum { Except_entered=0?? Except_raised??
????Except_handled??   Except_finalized };
????setjmp?????????????Except_flag?????Except_entered?????????TRY??????????????????????Except_entered?????0?????setjmp??ε?????????0?????setjmp?????????????Except_raised??????????????????????Except_flag??????Except_handled?????????????????????????????
????#define TRY do {
????volatile int Except_flag;
????Except_Frame Except_frame;
????Except_frame.prev = Except_stack;
????Except_stack = &Except_frame; 
????Except_flag = setjmp(Except_frame.env);
????if (Except_flag == Except_entered) {
????#define EXCEPT(e)
????if (Except_flag == Except_entered) Except_stack = Except_stack->prev;
????} else if (Except_frame.exception == &(e)) {
????Except_flag = Except_handled;
????#define ELSE
????if (Except_flag == Except_entered) Except_stack = Except_stack->prev;
????} else {
????Except_flag = Except_handled;
????#define FINALLY
????if (Except_flag == Except_entered) Except_stack = Except_stack->prev;
????} {
????if (Except_flag == Except_entered)
????Except_flag = Except_finalized;
????#define END_TRY
????if (Except_flag == Except_entered) Except_stack = Except_stack->prev;
????} if (Except_flag == Except_raised) RERAISE;
????} while (0)
???????????????£?
????#include <stdlib.h>
????#include <stdio.h>
????#include "assert.h"
????#include "except.h"
????#define T Except_T
????#ifdef WIN32
????__declspec(thread)
????#endif
????Except_Frame *Except_stack = NULL;
????void Except_raise(const T *e?? const char *file??
????int line) {
????Except_Frame *p = Except_stack;
????assert(e);
????if (p == NULL) {
????fprintf(stderr?? "Uncaught exception");
????if (e->reason)
????fprintf(stderr?? " %s"?? e->reason);
????else
????fprintf(stderr?? " at 0x%p"?? e);
????if (file && line > 0)
????fprintf(stderr?? " raised at %s:%d "?? file?? line);
????fprintf(stderr?? "aborting... ");
????fflush(stderr);
????abort();
????}
????p->exception = e;
????p->file = file;
????p->line = line;
????Except_stack = Except_stack->prev;
????longjmp(p->env?? Except_raised);
????}