3 -- Grant of Unlimited Rights
5 -- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
6 -- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
7 -- unlimited rights in the software and documentation contained herein.
8 -- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
9 -- this public release, the Government intends to confer upon all
10 -- recipients unlimited rights equal to those held by the Government.
11 -- These rights include rights to use, duplicate, release or disclose the
12 -- released technical data and computer software in whole or in part, in
13 -- any manner and for any purpose whatsoever, and to have or permit others
18 -- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
19 -- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
20 -- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
21 -- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
22 -- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
23 -- PARTICULAR PURPOSE OF SAID MATERIAL.
27 -- Check that exceptions raised in non-generic code can be handled by
28 -- a procedure in a generic package. Check that the exception identity
29 -- can be properly retrieved from the generic code and used by the
33 -- This test models a possible usage paradigm for the type:
34 -- Ada.Exceptions.Exception_Occurrence.
36 -- A generic package takes access to procedure types (allowing it to
37 -- be used at any accessibility level) and defines a "fail soft"
38 -- procedure that takes designators to a procedure to call, a
39 -- procedure to call in the event that it fails, and a function to
40 -- call to determine the next action.
42 -- In the event an exception occurs on the call to the first procedure,
43 -- the exception is stored in a stack; along with the designator to the
44 -- procedure that caused it; allowing the procedure to be called again,
45 -- or the exception to be re-raised.
47 -- A full implementation of such a tool would use a more robust storage
48 -- mechanism, and would provide a more flexible interface.
52 -- 29 MAR 96 SAIC Initial version
53 -- 12 NOV 96 SAIC Revised for 2.1 release
57 ----------------------------------------------------------------- CB40005_0
61 type Proc_Pointer
is access procedure;
62 type Func_Pointer
is access function return Proc_Pointer
;
63 package CB40005_0
is -- Fail_Soft
66 procedure Fail_Soft_Call
( Proc_To_Call
: Proc_Pointer
;
67 Proc_To_Call_On_Exception
: Proc_Pointer
:= null;
68 Retry_Routine
: Func_Pointer
:= null );
70 function Top_Event_Exception
return Ada
.Exceptions
.Exception_Occurrence
;
72 function Top_Event_Procedure
return Proc_Pointer
;
76 function Event_Stack_Size
return Natural;
78 end CB40005_0
; -- Fail_Soft
80 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- CB40005_0
83 package body CB40005_0
is
85 type History_Event
is record
86 Exception_Event
: Ada
.Exceptions
.Exception_Occurrence_Access
;
87 Procedure_Called
: Proc_Pointer
;
90 procedure Store_Event
( Proc_Called
: Proc_Pointer
;
91 Error
: Ada
.Exceptions
.Exception_Occurrence
);
93 procedure Fail_Soft_Call
( Proc_To_Call
: Proc_Pointer
;
94 Proc_To_Call_On_Exception
: Proc_Pointer
:= null;
95 Retry_Routine
: Func_Pointer
:= null ) is
97 Current_Proc_To_Call
: Proc_Pointer
:= Proc_To_Call
;
100 while Current_Proc_To_Call
/= null loop
102 Current_Proc_To_Call
.all; -- call procedure through pointer
103 Current_Proc_To_Call
:= null;
105 when Capture
: others =>
106 Store_Event
( Current_Proc_To_Call
, Capture
);
107 if Proc_To_Call_On_Exception
/= null then
108 Proc_To_Call_On_Exception
.all;
110 if Retry_Routine
/= null then
111 Current_Proc_To_Call
:= Retry_Routine
.all;
113 Current_Proc_To_Call
:= null;
119 Stack
: array(1..10) of History_Event
; -- minimal, sufficient for testing
121 Stack_Top
: Natural := 0;
123 procedure Store_Event
( Proc_Called
: Proc_Pointer
;
124 Error
: Ada
.Exceptions
.Exception_Occurrence
)
127 Stack_Top
:= Stack_Top
+1;
128 Stack
(Stack_Top
) := ( Ada
.Exceptions
.Save_Occurrence
(Error
),
132 function Top_Event_Exception
return Ada
.Exceptions
.Exception_Occurrence
is
134 if Stack_Top
> 0 then
135 return Stack
(Stack_Top
).Exception_Event
.all;
137 return Ada
.Exceptions
.Null_Occurrence
;
139 end Top_Event_Exception
;
141 function Top_Event_Procedure
return Proc_Pointer
is
143 if Stack_Top
> 0 then
144 return Stack
(Stack_Top
).Procedure_Called
;
148 end Top_Event_Procedure
;
150 procedure Pop_Event
is
152 if Stack_Top
> 0 then
153 Stack_Top
:= Stack_Top
-1;
155 Report
.Failed
("Stack Error");
159 function Event_Stack_Size
return Natural is
162 end Event_Stack_Size
;
166 ------------------------------------------------------------------- CB40005
174 type Proc_Pointer
is access procedure;
175 type Func_Pointer
is access function return Proc_Pointer
;
177 package Fail_Soft
is new CB40005_0
(Proc_Pointer
, Func_Pointer
);
179 procedure Cause_Standard_Exception
;
181 procedure Cause_Visible_Exception
;
183 procedure Cause_Invisible_Exception
;
185 Exception_Procedure_Pointer
: Proc_Pointer
;
187 Visible_Exception
: exception;
189 procedure Action_On_Exception
;
191 function Retry_Procedure
return Proc_Pointer
;
193 Raise_Error
: Boolean;
195 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
197 procedure Cause_Standard_Exception
is
199 TCTouch
.Touch
('S'); --------------------------------------------------- S
201 raise Constraint_Error
;
203 end Cause_Standard_Exception
;
205 procedure Cause_Visible_Exception
is
207 TCTouch
.Touch
('V'); --------------------------------------------------- V
209 raise Visible_Exception
;
211 end Cause_Visible_Exception
;
213 procedure Cause_Invisible_Exception
is
214 Invisible_Exception
: exception;
216 TCTouch
.Touch
('I'); --------------------------------------------------- I
218 raise Invisible_Exception
;
220 end Cause_Invisible_Exception
;
222 procedure Action_On_Exception
is
224 TCTouch
.Touch
('A'); --------------------------------------------------- A
225 end Action_On_Exception
;
227 function Retry_Procedure
return Proc_Pointer
is
229 TCTouch
.Touch
('R'); --------------------------------------------------- R
230 return Action_On_Exception
'Access;
233 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
235 begin -- Main test procedure.
237 Report
.Test
("CB40005", "Check that exceptions raised in non-generic " &
238 "code can be handled by a procedure in a generic " &
239 "package. Check that the exception identity can " &
240 "be properly retrieved from the generic code and " &
241 "used by the non-generic code" );
243 -- first, check that the no exception cases cause no action on the stack
244 Raise_Error
:= False;
246 Fail_Soft
.Fail_Soft_Call
( Cause_Standard_Exception
'Access ); -- S
248 Fail_Soft
.Fail_Soft_Call
( Cause_Visible_Exception
'Access, -- V
249 Action_On_Exception
'Access,
250 Retry_Procedure
'Access );
252 Fail_Soft
.Fail_Soft_Call
( Cause_Invisible_Exception
'Access, -- I
254 Retry_Procedure
'Access );
256 TCTouch
.Assert
( Fail_Soft
.Event_Stack_Size
= 0, "Empty stack");
258 TCTouch
.Validate
( "SVI", "Non error case check" );
260 -- second, check that error cases add to the stack
263 Fail_Soft
.Fail_Soft_Call
( Cause_Standard_Exception
'Access ); -- S
265 Fail_Soft
.Fail_Soft_Call
( Cause_Visible_Exception
'Access, -- V
266 Action_On_Exception
'Access, -- A
267 Retry_Procedure
'Access ); -- RA
269 Fail_Soft
.Fail_Soft_Call
( Cause_Invisible_Exception
'Access, -- I
271 Retry_Procedure
'Access ); -- RA
273 TCTouch
.Assert
( Fail_Soft
.Event_Stack_Size
= 3, "Stack = 3");
275 TCTouch
.Validate
( "SVARAIRA", "Error case check" );
277 -- check that the exceptions and procedure were stored correctly
279 Raise_Error
:= False;
281 -- return procedure pointer from top of stack and call the procedure
282 -- through that pointer:
284 Fail_Soft
.Top_Event_Procedure
.all;
286 TCTouch
.Validate
( "I", "Invisible case unwind" );
289 Ada
.Exceptions
.Raise_Exception
(
290 Ada
.Exceptions
.Exception_Identity
(Fail_Soft
.Top_Event_Exception
) );
291 Report
.Failed
("1: Exception not raised");
293 when Constraint_Error
=> Report
.Failed
("1: Raised Constraint_Error");
294 when Visible_Exception
=> Report
.Failed
("1: Raised Visible_Exception");
295 when others => null; -- expected case
300 -- return procedure pointer from top of stack and call the procedure
301 -- through that pointer:
303 Fail_Soft
.Top_Event_Procedure
.all;
305 TCTouch
.Validate
( "V", "Visible case unwind" );
308 Ada
.Exceptions
.Raise_Exception
(
309 Ada
.Exceptions
.Exception_Identity
(Fail_Soft
.Top_Event_Exception
) );
310 Report
.Failed
("2: Exception not raised");
312 when Constraint_Error
=> Report
.Failed
("2: Raised Constraint_Error");
313 when Visible_Exception
=> null; -- expected case
314 when others => Report
.Failed
("2: Raised Invisible_Exception");
319 Fail_Soft
.Top_Event_Procedure
.all;
321 TCTouch
.Validate
( "S", "Standard case unwind" );
324 Ada
.Exceptions
.Raise_Exception
(
325 Ada
.Exceptions
.Exception_Identity
(Fail_Soft
.Top_Event_Exception
) );
326 Report
.Failed
("3: Exception not raised");
328 when Constraint_Error
=> null; -- expected case
329 when Visible_Exception
=> Report
.Failed
("3: Raised Visible_Exception");
330 when others => Report
.Failed
("3: Raised Invisible_Exception");
335 TCTouch
.Assert
( Fail_Soft
.Event_Stack_Size
= 0, "Stack empty after pops");