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