blob: 3f8293039f4aea7c044d9c91ef1e8c6114d78b1a [file] [log] [blame]
(* EXCEPTIONS.mod implement the ISO EXCEPTIONS specification.
Copyright (C) 2003-2025 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
This file is part of GNU Modula-2.
GNU Modula-2 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Modula-2 is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. *)
IMPLEMENTATION MODULE EXCEPTIONS ;
IMPORT RTExceptions ;
IMPORT M2EXCEPTION ;
IMPORT M2RTS ;
IMPORT ASCII ;
FROM SYSTEM IMPORT ADR ;
FROM Storage IMPORT ALLOCATE ;
TYPE
ExceptionSource = POINTER TO RECORD
eh: RTExceptions.EHBlock ;
END ;
(* values of this type are used within library modules to
identify the source of raised exceptions *)
PROCEDURE AllocateSource (VAR newSource: ExceptionSource) ;
(* Allocates a unique value of type ExceptionSource *)
BEGIN
NEW(newSource) ;
WITH newSource^ DO
eh := RTExceptions.InitExceptionBlock()
END
END AllocateSource ;
PROCEDURE RAISE (source: ExceptionSource;
number: ExceptionNumber;
message: ARRAY OF CHAR) ;
(* Associates the given values of source, number and message with
the current context and raises an exception.
*)
BEGIN
RTExceptions.SetExceptionSource(source) ;
RTExceptions.SetExceptionBlock(source^.eh) ;
RTExceptions.Raise(number, ADR(__FILE__), __LINE__, __COLUMN__, ADR(__FUNCTION__), ADR(message)) ;
(* we should never reach here as Raise should jump to the exception handler *)
M2RTS.Halt('should never return from RTException.Raise',
__FILE__, __FUNCTION__, __LINE__)
END RAISE ;
PROCEDURE CurrentNumber (source: ExceptionSource) : ExceptionNumber ;
(* If the current coroutine is in the exceptional execution state
because of the raising of an exception from source, returns the
corresponding number, and otherwise raises an exception.
*)
BEGIN
IF RTExceptions.IsInExceptionState()
THEN
RETURN( RTExceptions.GetNumber(source^.eh) )
ELSE
RTExceptions.Raise(ORD(M2EXCEPTION.coException),
ADR(__FILE__), __LINE__, __COLUMN__, ADR(__FUNCTION__),
ADR('current coroutine is not in the exceptional execution state')) ;
RETURN VAL (ExceptionNumber, M2EXCEPTION.exException)
END
END CurrentNumber ;
PROCEDURE GetMessage (VAR text: ARRAY OF CHAR) ;
(* If the current coroutine is in the exceptional execution state,
returns the possibly truncated string associated with the
current context. Otherwise, in normal execution state,
returns the empty string.
*)
VAR
p : POINTER TO CHAR ;
i, h: CARDINAL ;
BEGIN
IF RTExceptions.IsInExceptionState()
THEN
h := HIGH(text) ;
i := 0 ;
p := RTExceptions.GetTextBuffer(RTExceptions.GetExceptionBlock()) ;
WHILE (p#NIL) AND (p^#ASCII.nul) DO
text[i] := p^ ;
INC(i) ;
INC(p)
END ;
IF i<=h
THEN
text[i] := ASCII.nul
END
ELSE
text[0] := ASCII.nul
END
END GetMessage ;
PROCEDURE IsCurrentSource (source: ExceptionSource) : BOOLEAN ;
(* If the current coroutine is in the exceptional execution state
because of the raising of an exception from source, returns TRUE,
and otherwise returns FALSE.
*)
BEGIN
RETURN( RTExceptions.IsInExceptionState() AND (source=RTExceptions.GetExceptionSource()) )
END IsCurrentSource ;
PROCEDURE IsExceptionalExecution () : BOOLEAN ;
(* If the current coroutine is in the exceptional execution state
because of the raising of an exception, returns TRUE,
and otherwise returns FALSE.
*)
BEGIN
RETURN( RTExceptions.IsInExceptionState() )
END IsExceptionalExecution ;
END EXCEPTIONS.