/**********************************************************************
 *  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.
 *
 *********************************************************************/
#include 

jmp_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();
}