The Problem:
Write a definition of the declaration for the type jmp_buf and write
C (or Pascal or Ada or ...) code for longjup() and setjmp().
typedef long int jmp_buf[JMP_BUF_SIZE];
The type jmp_buf ought to be a structure or record type, but in C,
declaring it as an array allows instances to be statically instantiated
while at the same time allowing objects of type jmp_buf to be implicitly
passed by reference instead of by value, as would happen for any other
standard type in C. This is an awful feature of the C language, we use
it here to conform with the standard definition of jmp_buf. Therefore,
fields in what ought to be a record will be given by constant offsets into
the array:
#define JMP_BUF_RA 0 -- the return address
#define JMP_BUF_FP 1 -- the saved frame pointer
#define JMP_BUF_SIZE 2
The above description is absolutely minimal! With this, we can write the
following code:
int setjmp( jmp_buf b )
{
long int * h; -- a handle on the local variables;
h = &h + RA_OFFSET; -- h points to the return address;
b[JMP_BUF_RA] = *h;
h = &h + FP_OFFSET; -- h points to the saved frame pointer;
b[JMP_BUF_FP] = *h;
return 0;
}
int longjmp( jmp_buf b, int v )
{
long int * h; -- a handle on the local variables;
h = &h + RA_OFFSET; -- h points to the return address;
*h = b[JMP_BUF_RA];
h = &h + FP_OFFSET; -- h points to the saved frame pointer;
*h = b[JMP_BUF_FP];
return v;
}
This version will only work if nothing in registers needs to be saved between
setjmp and longjmp. Thus, if setjmp is called as a statement, it should
work, but if it is called from within an expression where the results of
evaluating other terms of the expression were saved in registers, it will
not work because these values will be lost.