/********************************************************************** * For C Fans - * * Here is a piece of code that uses longjmp and setjmp to switch * between functions. The code works as follows: it enters main() * and setjmp grabs a continuation called env1. Then f2() is invoked. * Space is created for this new invocation of f2() (in particular for * the local variable p). In f2() the address of local variable p is * printed, setjmp grabs a continuation called env2 and invokes longjmp * on the continuation env1 which passes control to the if statement in * main with the value 1. So, this time, from main, f1() is invoked. * In f1() setjmp grabs a continuation called env1 and, since setjmp is * always 0 the first time it is entered, control is passed to the * continuation env2 by the longjmp in f1(). But this continuation * is in the if statement of f2(). Since the value returned by the * longjmp is 1, the if statement results in f2() being invoked again. * But then a "new" setjmp grabs a continuation called env2 and the * longjmp is invoked passing control to f1(). Control switches back and * forth between f1() and f2() indefinitely. Each time through the cycle * f2() is called from itself and the address of local variable p is * displayed. We see that new locations are set aside for p on every * invocation of f2(). This leads one to believe that the machine is * continually making new copies of f2() as if f2() were calling itself * recursively. In fact, if setjmp is grabbing continuations correctly, * this is exactly what would be happening. Unfortunately, the "C" people * have not implemented continuations correctly and the above is not * happening at all because portions of the stack are destroyed as the new * invocations of f2() occur. Thus, if you tried to put a value in location * p on each invocation of f2(), it would be overwritten on a future * invocation of f1() or f2(). The response of the "C" people to all this * is the "program is wrong" - This statement is a surprise to me. The * purpose of the program is to display the control flow and locations of * p with time, nothing more. This closed minded attitude is possibly * the reason we never will see setjmp and longjmp developed to the point * where it can be useful without tremendous debugging. * * In some (very small) defense of the "C" people, the designers of "C" * had no intention of making setjmp grab continuations in the first * place. Apparently they just wanted an escape mechanism (a long distance * jump toward the top of the stack, throwing out everything in between. * * --The Concerned Professor * * The code below compiled correctly using cc on a Sparc Station. * *********************************************************************/ #includejmp_buf env1, env2; main() { if (setjmp(env1)) { printf("\nCalling f1 from main"); f1(); } else { printf("\nCalling f2 from main"); f2(); } } int f1() { ff: if (setjmp(env1) == 0) { printf("\nPassing control to f2 from f1"); longjmp(env2,1); } else goto ff; } int f2() { unsigned int p; printf("\nIn f2: %u",&p); if (setjmp(env2) == 0) { printf("\nPassing control from f2"); longjmp(env1,1); } else f2(); }