首先,在函数a里面setjmp,将当前函数的env都存储起来,然后在函数b里面调用longjmp,这样会直接跳转到函数a的setjmp这个地方,longjmp的第二个值作用是在第二次返回a函数的时候setjmp会返回longjmp的第二个参数。

  有了这个方法,我们的程序好设计多了,由于设计多个函数的调用,所以设计的时候使用了链表来处理保存每个函数的env.

  全部实现代码如下:

#ifndef LIST_H
#define LIST_H
typedef struct list_head_tag
{
struct list_head_tag *prev;
struct list_head_tag *next;
}list_head;
#define list_for_each(pos, head)
for ( pos = (head)->next;
pos != (head);
pos = pos->next)
#define list_for_each_safe(pos,pos_next,head)
for ( pos = (head)->next, pos_next = pos->next;
pos != (head);
pos = pos_next, pos_next = pos->next)
#define list_empty(head) (head->next == head)
#define list_entry(ptr, type, member) ((type*)ptr)
#define init_list_head(ptr)
do{
(ptr)->prev = ptr;
(ptr)->next = ptr;
}while(0)
extern void list_add_before(list_head *node, list_head *pos);
extern void list_add_after(list_head *node, list_head *pos);
extern void list_del(list_head *node);
#endif
#include “list.h”
void list_add_before(list_head *node, list_head *pos)
{
node->prev = pos->prev;
node->next = pos;
pos->prev->next = node;
pos->prev = node;
}
void list_add_after(list_head *node, list_head *pos)
{
node->prev = pos;
node->next = pos->next;
pos->next->prev = node;
pos->next = node;
}
void list_del(list_head *node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
}
#ifndef EXC_H
#define EXC_H
char err = -1;
static char isJumpListInit = 0;
//jmp_buf jump_buffer;
typedef struct JumpBufListTag
{
struct list_head_tag list;
jmp_buf jump_buffer;
}JumpBufList, *JumpBufListPtr;
JumpBufList jumplist = {NULL, NULL};
JumpBufListPtr head = &jumplist;
JumpBufListPtr cur = &jumplist;
int SetCurJump(void)
{
JumpBufListPtr newPtr = (JumpBufList*)calloc(sizeof(JumpBufList));
if (!isJumpListInit)
{
init_list_head(&head->list);
isJumpListInit = 1;
}
list_add_after(&newPtr->list, &head->list);
cur = newPtr;
return 0;
}
void JumpCurLong(void)
{
longjmp(cur->jump_buffer, 1);
}
void DestoryCurJumpEnv( void )
{
list_del(&cur->list);
free(cur);
cur = head->list.next;
}
#define try SetCurJump();if(setjmp(cur->jump_buffer) == 0)
#define catch(N) DestoryCurJumpEnv();if(N>=0)
#define throw(N) err=N;JumpCurLong();
#endif