/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 *
 * 

   Powerful (but dangerous) user-level control transfer mechanism (non-local goto)
   Transfers control to arbitrary location within stack (function that has been called but not yet completed)
	The saved stack context/env is invalidated if the function which called setjmp() returns
   Controlled way to break procedure call/return discipline
   	Useful for error recovery, interrupt and signal handling

   #include <setjmp.h>

   int setjmp(jmp_buf j): 			Called before longjmp to identify a return point for a subsequent longjmp
						Local variabless accessed by the function that calls setjmp after longjmp() must be qualified as volatile
			  			Implementation:
							Remember current register context, stack pointer, and PC value in jmp_buf
							The function retuns once (when set) or multiple times (each time longjmp returns)
								Return 0 if returning directly,  nonzero when returning from longjmp or siglongjmp

   int sigsetjmp(sigjmp_buf env, int savesigs): if savesigs is nonzero, the process's current signal mask is saved in env and will be restored with siglongjmp


   void longjmp(jmp_buf j, int i):  		Called after setjmp
						Called once, but never returns
						After longjmp, program execution continues as if the corresponding setjmp had returned the value val (if 0 given, 1 returned)

						Implementation:
							Restore register context from jump buffer j
							Set %eax (the return value) to i
							Jump to the location indicated by the PC stored in jump buf j

   void siglongjmp(sigjmp_buf env, int val):	Restore the environment if sigsetjmp call set the env with a nonzero savesigs flag

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

Example 1:
---------

jmp_buf buf;
 
void f(void) {
  if (setjmp(buf) == 0) {
	g();
  } else {
	// longjmp was invoked
  }
}

void g() {  
	... g1();  ... g2() ... h(); 
   }
 
void h(void) {
	... 
	longjmp(buf, 1);
}

   *** before longjmp: f g g1 g2 h
   *** after longjmp: f
p1

Example 2:
---------

jmp_buf buf;
 
void f(void) {

	volatile int i = 0;
	if (setjmp(buf) != 0) {
		printf("%i\n", i);
		... 
	}
	i = 2;
	g();
}
 
void g(void) {
	...
	longjmp(buf, 1);
}
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */

#include <stdio.h> 
#include <signal.h> 
#include <setjmp.h> 

sigjmp_buf buf; 
 
void handler(int sig) { 
	siglongjmp(buf, 1); 
} 
 
main() { 
	signal(SIGINT, handler); 
  
	if (!sigsetjmp(buf, 1))  
		printf("starting\n"); 
	else  
		printf("restarting\n"); 

	while(1) { 
		sleep(1); 
		printf("processing...\n"); 
	} 
} 
