DEFINITION FOR C MODULE SetJmp ;

(* Set jump allows you to jump out of a deeply nested procedures call chain  *)
(* Although not as elegant as an exception handling mechanism it is capable  *)
(* of giving you the same functionality. longjump can be considered as	     *)
(* raising the exception and setjmp can be considered as catching it.	     *)

TYPE
  JumpBuffer    = ARRAY [0..15] OF LONGINT ;
  JumpBufferPtr = POINTER TO JumpBuffer ;

PROCEDURE setjmp ( VAR jb : JumpBuffer ) : LONGINT ;
(* loads jb with the current register state. setjmp always returns 0 *)

PROCEDURE longjmp( VAR jb : JumpBuffer ; int : LONGINT ) ;
(* returns just after the setjump that loaded JumpBuffer, as if setjmp had    *)
(* just returned int. 							      *)

END SetJmp.

(* The compiler allocates local variables into registers, therefore if	      *)
(*  you are using SetJmp, dont modify any locals between setjmp and the       *)
(* subsequent procedure call or otherwise use the (* @O *) comment to stop    *)
(* the compiler from allocating registers.				      *)
(*									      *)
(* (* @O *)								      *)
(* PROCEDURE foo(..);(* foo will not allocate any registers to local vars  *) *)
(*  VAR ...	     (* & parameters therefore its always safe to call     *) *)
(*		     (*  setjmp from inside it.				   *) *)

(* Heres an example of how to use the functions in SetJmp

MODULE testJmp ;

IMPORT SetJmp , StdIO ;

VAR
  buff : SetJmp.JumpBuffer ;

PROCEDURE b( x : LONGINT ) ;
BEGIN
  StdIO.printf("%d\n",x);
  IF x = 0 THEN
    SetJmp.longjmp( buff , 10 ) ;
    (* This call jumps directly back to the CASE statement in a( )	      *)
    (* The CASE index will be the second parameter of longjmp in this case 10 *)
  END;
  b(x-1)
END b ;

PROCEDURE a( ) ;
  VAR foo : LONGINT ;
BEGIN
  foo := 1 ;
  CASE SetJmp.setjmp( buff ) OF
  |0 : (* If we modified foo here then its value will be undefined when we  *)
       (* we lonjmp. Using the (* @O *) comment does not cause		    *)
       (* this problem as foo definitely WONT be in a register.             *)
       b(10) ;
  |10: StdIO.puts("back from b()")
  END ;
END a ;

BEGIN a( ) ;
END testJmp.

*)
