SYS-EXCEPTION(2)                                 SYS-EXCEPTION(2)

     NAME
          Exception, raise, rescue, rescued, unrescue - exception
          handling

     SYNOPSIS
          include "sys.m";
          sys := load Sys Sys->PATH;

          Exception: adt
          {
            name: string;  # name of exception
            mod:  string;  # module
            pc:   int;     # program counter
          };

          raise:    fn(s: string);
          rescue:   fn(s: string, e: ref Exception): int;
          rescued:  fn(flag: int, s: string);
          unrescue: fn();

     DESCRIPTION
          These functions provide exception handling in Limbo.

          Exception communicates the nature of the exception.
          Exception.pc is the virtual machine program counter at the
          point of the raised exception, relative to the start of the
          module.

          Raise throws an exception with the name s, and sets the
          error string for sys-print(2) (the value of the format %r)
          to s.

          Rescue installs a rescue block for exceptions matched by s.
          If a matching exception occurs, rescue will return
          Sys->EXCEPTION; otherwise it returns Sys->HANDLER.  S
          matches an exception name when the two are equal, or s is a
          string (the prefix) followed by *, which matches any excep-
          tion name starting with the same prefix.  In particular, "*"
          matches all exceptions.  Rescue blocks can only handle
          exceptions that are raised in the same thread.  If an excep-
          tion needs to be handled in a spawned thread, a rescue block
          must be installed there.

               if(sys->rescue("fail:*", e) == Sys->EXCEPTION) {
                    # exception handling code ...
                    sys->rescued(Sys->EXIT, nil);
               }

          Rescued tells the system what to do after an exception has
          been handled, as specified by flag:

     Page 1                       Plan 9            (printed 11/17/24)

     SYS-EXCEPTION(2)                                 SYS-EXCEPTION(2)

          ACTIVE  Leave the handler installed; execution continues.

          RAISE   Re-raise this exception or raise a different one.
                  If s is nil, the current exception is re-raised;
                  otherwise, exception s is raised instead.

          EXIT    The thread exits.

          ONCE    Remove the handler; execution continues.  For exam-
                  ple:

                       if(sys->rescue("an exception", e) == Sys->HANDLER) {
                            # normal execution code here
                       } else {
                            # handler code here
                            sys->rescued(Sys->ONCE, nil);  # removes the handler
                       }

          Unrescue removes the most recently installed handler and
          continues execution.

     EXAMPLES
          The first example removes the handler if normal execution
          completes:

               if(sys->rescue("an exception", e) == Sys->HANDLER) {
                    # normal execution code here
                    sys->unrescue();
               } else {
                    # exception handling code here
               }

          The next example is a complete program that demonstrates the
          behaviour of exception handling by executing both the normal
          execution code and the handler code.

               implement Excep;
               include "sys.m";
                    sys: Sys;
               include "draw.m";
               Excep: module
               {
                    init:   fn(ctxt: ref Draw->Context, argv: list of string);
               };
               init(ctxt: ref Draw->Context, argv: list of string)
               {
                   sys = load Sys Sys->PATH;
                   e := ref sys->Exception;
                   if(sys->rescue("an exception", e) == Sys->EXCEPTION) {
                       sys->print("rescue: exception\n");
                       sys->print("e.name = %s\ne.mod = %s\ne.pc  = %d\n",
                              e.name, e.mod, e.pc);

     Page 2                       Plan 9            (printed 11/17/24)

     SYS-EXCEPTION(2)                                 SYS-EXCEPTION(2)

                       sys->rescued(Sys->ONCE, nil);
                   } else {
                       sys->print("rescue: normal execution\n");
                       sys->raise("an exception");
                  }
                  sys->print("raise: %r\n");
                  sys->raise("nasty thing"); # won't be handled
               }

     SEE ALSO
          sh(1), prog(3)

     Page 3                       Plan 9            (printed 11/17/24)