2.12 Exception handling

This section gives an example of exception handling and briefly describes its runtime behavior. The module below is written in the ISO dialect of Modula-2 and can be compiled with the command line:

$ gm2 -g -fiso -fsoft-check-all lazyunique.mod

The option ‘-fsoft-check-all’ generates checks for NIL pointer access violation. In turn this will call the exception handler.

MODULE lazyunique ;  (*!m2iso+gm2*)

FROM Storage IMPORT ALLOCATE ;
FROM libc IMPORT printf, exit ;

TYPE
   List = POINTER TO RECORD
                        next : List ;
                        value: INTEGER ;
                     END ;

   Array = ARRAY [0..3] OF INTEGER ;

CONST
   Unsorted = Array {0, 2, 1, 1} ;

VAR
   head: List ;
PROCEDURE Display ;
VAR
   p: List ;
BEGIN
   p := head^.next ;
   printf ("\nunique data\n");
   printf ("===========\n");
   WHILE p # NIL DO
      printf ("%d\n", p^.value);
      p := p^.next
   END
END Display ;
PROCEDURE Add (VAR p: List; val: INTEGER) ;
BEGIN
   NEW (p) ;
   WITH p^ DO
      value := val ;
      next := NIL
   END
END Add ;
PROCEDURE Unique (val: INTEGER) ;
VAR
   p: List ;
BEGIN
   printf ("new value %d\n", val);
   p := head ;
   (* The following line may cause an exception accessing next or
      value.  *)
   WHILE p^.next^.value # val DO
      p := p^.next
   END
EXCEPT
   (* Now fixup.  Determine the source of the exception and retry.  *)
   IF head = NIL
   THEN
      printf ("list was empty, add sentinal\n");
      Add (head, -1) ;
      RETRY  (* Jump back to the begin statement.  *)
   ELSIF p^.next = NIL
   THEN
      printf ("growing the list\n");
      Add (p^.next, val) ;
      RETRY  (* Jump back to the begin statement.  *)
   ELSE
      printf ("should never reach here!\n");
   END
END Unique ;
PROCEDURE unique ;
VAR
   i: CARDINAL ;
BEGIN
   FOR i := 0 TO HIGH (Unsorted) DO
      Unique (Unsorted[i])
   END ;
   Display
END unique ;

BEGIN
   head := NIL ;
   unique
END lazyunique.
new value 0
list was empty, add sentinal
new value 0
growing the list
new value 0
new value 2
growing the list
new value 2
new value 1
growing the list
new value 1
new value 1

unique data
===========
0
2
1