Category : Miscellaneous Language Source Code
Archive   : ADA-LRM2.ZIP
Filename : CHAP11.DOC

 
Output of file : CHAP11.DOC contained in archive : ADA-LRM2.ZIP
11. Exceptions


This chapter defines the facilities for dealing with errors or other
exceptional situations that arise during program execution. Such a
situation is called an exception. To raise an exception is to abandon
normal program execution so as to draw attention to the fact that the
corresponding situation has arisen. Executing some actions, in response to
the arising of an exception, is called handling the exception.


An exception declaration declares a name for an exception. An exception
can be raised by a raise statement, or it can be raised by another
statement or operation that propagates the exception. When an exception
arises, control can be transferred to a user-provided exception handler at
the end of a block statement or at the end of the body of a subprogram,
package, or task unit.


References: block statement 5.6, error situation 1.6, exception handler
11.2, name 4.1, package body 7.1, propagation of an exception 11.4.1
11.4.2, raise statement 11.3, subprogram body 6.3, task body 9.1

11.1 Exception Declarations


An exception declaration declares a name for an exception. The name of an
exception can only be used in raise statements, exception handlers, and
renaming declarations.


exception_declaration ::= identifier_list : exception;


An exception declaration with several identifiers is equivalent to a
sequence of single exception declarations, as explained in section 3.2.
Each single exception declaration declares a name for a different
exception. In particular, if a generic unit includes an exception
declaration, the exception declarations implicitly generated by different
instantiations of the generic unit refer to distinct exceptions (but all
have the same identifier). The particular exception denoted by an
exception name is determined at compilation time and is the same regardless
of how many times the exception declaration is elaborated. Hence, if an
exception declaration occurs in a recursive subprogram, the exception name
denotes the same exception for all invocations of the recursive subprogram.


The following exceptions are predefined in the language; they are raised
when the situations described are detected.


CONSTRAINT_ERROR This exception is raised in any of the following
situations: upon an attempt to violate a range
constraint, an index constraint, or a discriminant
constraint; upon an attempt to use a record component
that does not exist for the current discriminant values;
and upon an attempt to use a selected component, an
indexed component, a slice, or an attribute, of an object
designated by an access value, if the object does not
exist because the access value is null.


NUMERIC_ERROR This exception is raised by the execution of a predefined
numeric operation that cannot deliver a correct result
(within the declared accuracy for real types); this
includes the case where an implementation uses a
predefined numeric operation for the execution,
evaluation, or elaboration of some construct. The rules
given in section 4.5.7 define the cases in which an
implementation is not required to raise this exception
when such an error situation arises; see also section
11.6.


PROGRAM_ERROR This exception is raised upon an attempt to call a
subprogram, to activate a task, or to elaborate a generic
instantiation, if the body of the corresponding unit has
not yet been elaborated. This exception is also raised
if the end of a function is reached (see 6.5); or during
the execution of a selective wait that has no else part,
if this execution determines that all alternatives are
closed (see 9.7.1). Finally, depending on the
implementation, this exception may be raised upon an
attempt to execute an action that is erroneous, and for
incorrect order dependences (see 1.6).


STORAGE_ERROR This exception is raised in any of the following
situations: when the dynamic storage allocated to a task
is exceeded; during the evaluation of an allocator, if
the space available for the collection of allocated
objects is exhausted; or during the elaboration of a
declarative item, or during the execution of a subprogram
call, if storage is not sufficient.


TASKING_ERROR This exception is raised when exceptions arise during
intertask communication (see 9 and 11.5).

Note:


The situations described above can arise without raising the corresponding
exceptions, if the pragma SUPPRESS has been used to give permission to omit
the corresponding checks (see 11.7).


Examples of user-defined exception declarations:

SINGULAR : exception;
ERROR : exception;
OVERFLOW, UNDERFLOW : exception;


References: access value 3.8, collection 3.8, declaration 3.1, exception
11, exception handler 11.2, generic body 12.2, generic instantiation 12.3,
generic unit 12, identifier 2.3, implicit declaration 12.3, instantiation
12.3, name 4.1, object 3.2, raise statement 11.3, real type 3.5.6, record
component 3.7, return statement 5.8, subprogram 6, subprogram body 6.3,
task 9, task body 9.1


Constraint_error exception contexts: aggregate 4.3.1 4.3.2, allocator 4.8,
assignment statement 5.2 5.2.1, constraint 3.3.2, discrete type attribute
3.5.5, discriminant constraint 3.7.2, elaboration of a generic formal
parameter 12.3.1 12.3.2 12.3.4 12.3.5, entry index 9.5, exponentiating
operator 4.5.6, index constraint 3.6.1, indexed component 4.1.1, logical
operator 4.5.1, null access value 3.8, object declaration 3.2.1, parameter
association 6.4.1, qualified expression 4.7, range constraint 3.5, selected
component 4.1.3, slice 4.1.2, subtype indication 3.3.2, type conversion 4.6


Numeric_error exception contexts: discrete type attribute 3.5.5, implicit
conversion 3.5.4 3.5.6 4.6, numeric operation 3.5.5 3.5.8 3.5.10, operator
of a numeric type 4.5 4.5.7


Program_error exception contexts: collection 3.8, elaboration 3.9,
elaboration check 3.9 7.3 9.3 12.2, erroneous 1.6, incorrect order
dependence 1.6, leaving a function 6.5, selective wait 9.7.1


Storage_error exception contexts: allocator 4.8


Tasking error exception contexts: abort statement 9.10, entry call 9.5
9.7.2 9.7.3, exceptions during task communication 11.5, task activation 9.3

11.2 Exception Handlers


The response to one or more exceptions is specified by an exception
handler.


exception_handler ::=
when exception_choice {| exception_choice} =>
sequence_of_statements

exception_choice ::= exception_name | others


An exception handler occurs in a construct that is either a block statement
or the body of a subprogram, package, task unit, or generic unit. Such a
construct will be called a frame in this chapter. In each case the syntax
of a frame that has exception handlers includes the following part:


begin
sequence_of_statements
exception
exception_handler
{exception_handler}
end


The exceptions denoted by the exception names given as exception choices of
a frame must all be distinct. The exception choice others is only allowed
for the last exception handler of a frame and as its only exception choice;
it stands for all exceptions not listed in previous handlers of the frame,
including exceptions whose names are not visible at the place of the
exception handler.


The exception handlers of a frame handle exceptions that are raised by the
execution of the sequence of statements of the frame. The exceptions
handled by a given exception handler are those named by the corresponding
exception choices.


Example:

begin
-- sequence of statements
exception
when SINGULAR | NUMERIC_ERROR =>
PUT(" MATRIX IS SINGULAR ");
when others =>
PUT(" FATAL ERROR ");
raise ERROR;
end;

Note:


The same kinds of statement are allowed in the sequence of statements of
each exception handler as are allowed in the sequence of statements of the
frame. For example, a return statement is allowed in a handler within a
function body.


References: block statement 5.6, declarative part 3.9, exception 11,
exception handling 11.4, function body 6.3, generic body 12.2, generic unit
12.1, name 4.1, package body 7.1, raise statement 11.3, return statement
5.8, sequence of statements 5.1, statement 5, subprogram body 6.3, task
body 9.1, task unit 9 9.1, visibility 8.3

11.3 Raise Statements


A raise statement raises an exception.


raise_statement ::= raise [exception_name];


For the execution of a raise statement with an exception name, the named
exception is raised. A raise statement without an exception name is only
allowed within an exception handler (but not within the sequence of
statements of a subprogram, package, task unit, or generic unit, enclosed
by the handler); it raises again the exception that caused transfer to the
innermost enclosing handler.


Examples:

raise SINGULAR;
raise NUMERIC_ERROR; -- explicitly raising a predefined exception

raise; -- only within an exception handler


References: exception 11, generic unit 12, name 4.1, package 7, sequence
of statements 5.1, subprogram 6, task unit 9

11.4 Exception Handling


When an exception is raised, normal program execution is abandoned and
control is transferred to an exception handler. The selection of this
handler depends on whether the exception is raised during the execution of
statements or during the elaboration of declarations.


References: declaration 3.1, elaboration 3.1 3.9, exception 11, exception
handler 11.2, raising of exceptions 11.3, statement 5

11.4.1 Exceptions Raised During the Execution of Statements


The handling of an exception raised by the execution of a sequence of
statements depends on whether the innermost frame or accept statement that
encloses the sequence of statements is a frame or an accept statement. The
case where an accept statement is innermost is described in section 11.5.
The case where a frame is innermost is presented here.


Different actions take place, depending on whether or not this frame has a
handler for the exception, and on whether the exception is raised in the
sequence of statements of the frame or in that of an exception handler.


If an exception is raised in the sequence of statements of a frame that has
a handler for the exception, execution of the sequence of statements of the
frame is abandoned and control is transferred to the exception handler.
The execution of the sequence of statements of the handler completes the
execution of the frame (or its elaboration if the frame is a package body).


If an exception is raised in the sequence of statements of a frame that
does not have a handler for the exception, execution of this sequence of
statements is abandoned. The next action depends on the nature of the
frame:


(a) For a subprogram body, the same exception is raised again at the point
of call of the subprogram, unless the subprogram is the main program
itself, in which case execution of the main program is abandoned.


(b) For a block statement, the same exception is raised again immediately
after the block statement (that is, within the innermost enclosing
frame or accept statement).


(c) For a package body that is a declarative item, the same exception is
raised again immediately after this declarative item (within the
enclosing declarative part). If the package body is that of a subunit,
the exception is raised again at the place of the corresponding body
stub. If the package is a library unit, execution of the main program
is abandoned.


(d) For a task body, the task becomes completed.


An exception that is raised again (as in the above cases (a), (b), and (c))
is said to be propagated, either by the execution of the subprogram, the
execution of the block statement, or the elaboration of the package body.
No propagation takes place in the case of a task body. If the frame is a
subprogram or a block statement and if it has dependent tasks, the
propagation of an exception takes place only after termination of the
dependent tasks.


Finally, if an exception is raised in the sequence of statements of an
exception handler, execution of this sequence of statements is abandoned.
Subsequent actions (including propagation, if any) are as in the cases (a)
to (d) above, depending on the nature of the frame.


Example:

function FACTORIAL (N : POSITIVE) return FLOAT is
begin
if N = 1 then
return 1.0;
else
return FLOAT(N) * FACTORIAL(N-1);
end if;
exception
when NUMERIC_ERROR => return FLOAT'SAFE_LARGE;
end FACTORIAL;


If the multiplication raises NUMERIC_ERROR, then FLOAT'SAFE_LARGE is
returned by the handler. This value will cause further NUMERIC_ERROR
exceptions to be raised by the evaluation of the expression in each of the
remaining invocations of the function, so that for large values of N the
function will ultimately return the value FLOAT'SAFE_LARGE.


Example:

procedure P is
ERROR : exception;
procedure R;

procedure Q is
begin
R;
... -- error situation (2)
exception
...
when ERROR => -- handler E2
...
end Q;

procedure R is
begin
... -- error situation (3)
end R;

begin
... -- error situation (1)
Q;
...
exception
...
when ERROR => -- handler E1
...
end P;


The following situations can arise:


(1) If the exception ERROR is raised in the sequence of statements of the
outer procedure P, the handler E1 provided within P is used to
complete the execution of P.


(2) If the exception ERROR is raised in the sequence of statements of Q,
the handler E2 provided within Q is used to complete the execution of
Q. Control will be returned to the point of call of Q upon completion
of the handler.


(3) If the exception ERROR is raised in the body of R, called by Q, the
execution of R is abandoned and the same exception is raised in the
body of Q. The handler E2 is then used to complete the execution of
Q, as in situation (2).


Note that in the third situation, the exception raised in R results in
(indirectly) transferring control to a handler that is part of Q and hence
not enclosed by R. Note also that if a handler were provided within R for
the exception choice others, situation (3) would cause execution of this
handler, rather than direct termination of R.


Lastly, if ERROR had been declared in R, rather than in P, the handlers E1
and E2 could not provide an explicit handler for ERROR since this
identifier would not be visible within the bodies of P and Q. In situation
(3), the exception could however be handled in Q by providing a handler for
the exception choice others.

Notes:


The language does not define what happens when the execution of the main
program is abandoned after an unhandled exception.


The predefined exceptions are those that can be propagated by the basic
operations and the predefined operators.


The case of a frame that is a generic unit is already covered by the rules
for subprogram and package bodies, since the sequence of statements of such
a frame is not executed but is the template for the corresponding sequences
of statements of the subprograms or packages obtained by generic
instantiation.


References: accept statement 9.5, basic operation 3.3.3, block statement
5.6, body stub 10.2, completion 9.4, declarative item 3.9, declarative part
3.9, dependent task 9.4, elaboration 3.1 3.9, exception 11, exception
handler 11.2, frame 11.2, generic instantiation 12.3, generic unit 12,
library unit 10.1, main program 10.1, numeric_error exception 11.1, package
7, package body 7.1, predefined operator 4.5, procedure 6.1, sequence of
statements 5.1, statement 5, subprogram 6, subprogram body 6.3, subprogram
call 6.4, subunit 10.2, task 9, task body 9.1

11.4.2 Exceptions Raised During the Elaboration of Declarations


If an exception is raised during the elaboration of the declarative part of
a given frame, this elaboration is abandoned. The next action depends on
the nature of the frame:


(a) For a subprogram body, the same exception is raised again at the point
of call of the subprogram, unless the subprogram is the main program
itself, in which case execution of the main program is abandoned.


(b) For a block statement, the same exception is raised again immediately
after the block statement.


(c) For a package body that is a declarative item, the same exception is
raised again immediately after this declarative item, in the enclosing
declarative part. If the package body is that of a subunit, the
exception is raised again at the place of the corresponding body stub.
If the package is a library unit, execution of the main program is
abandoned.


(d) For a task body, the task becomes completed, and the exception
TASKING_ERROR is raised at the point of activation of the task, as
explained in section 9.3.


Similarly, if an exception is raised during the elaboration of either a
package declaration or a task declaration, this elaboration is abandoned;
the next action depends on the nature of the declaration.


(e) For a package declaration or a task declaration, that is a declarative
item, the exception is raised again immediately after the declarative
item in the enclosing declarative part or package specification. For
the declaration of a library package, the execution of the main
program is abandoned.


An exception that is raised again (as in the above cases (a), (b), (c) and
(e)) is said to be propagated, either by the execution of the subprogram or
block statement, or by the elaboration of the package declaration, task
declaration or package body.


Example of an exception in the declarative part of a block statement (case
(b)):

procedure P is
...
begin
declare
N : INTEGER := F; -- the function F may raise ERROR
begin
...
exception
when ERROR => -- handler E1
end;
...
exception
when ERROR => -- handler E2
end P;

-- if the exception ERROR is raised in the declaration of N, it is handled by E2


References: activation 9.3, block statement 5.6, body stub 10.2, completed
task 9.4, declarative item 3.9, declarative part 3.9, elaboration 3.1 3.9,
exception 11, frame 11.2, library unit 10.1, main program 10.1, package
body 7.1, package declaration 7.1, package specification 7.1, subprogram 6,
subprogram body 6.3, subprogram call 6.4, subunit 10.2, task 9, task body
9.1, task declaration 9.1, tasking_error exception 11.1

11.5 Exceptions Raised During Task Communication


An exception can be propagated to a task communicating, or attempting to
communicate, with another task. An exception can also be propagated to a
calling task if the exception is raised during a rendezvous.


When a task calls an entry of another task, the exception TASKING_ERROR is
raised in the calling task, at the place of the call, if the called task is
completed before accepting the entry call or is already completed at the
time of the call.


A rendezvous can be completed abnormally in two cases:


(a) When an exception is raised within an accept statement, but not
handled within an inner frame. In this case, the execution of the
accept statement is abandoned and the same exception is raised again
immediately after the accept statement within the called task; the
exception is also propagated to the calling task at the point of the
entry call.


(b) When the task containing the accept statement is completed abnormally
as the result of an abort statement. In this case, the exception
TASKING_ERROR is raised in the calling task at the point of the entry
call.


On the other hand, if a task issuing an entry call becomes abnormal (as the
result of an abort statement) no exception is raised in the called task.
If the rendezvous has not yet started, the entry call is cancelled. If the
rendezvous is in progress, it completes normally, and the called task is
unaffected.


References: abnormal task 9.10, abort statement 9.10, accept statement
9.5, completed task 9.4, entry call 9.5, exception 11, frame 11.2,
rendezvous 9.5, task 9, task termination 9.4, tasking_error exception 11.1

11.6 Exceptions and Optimization


The purpose of this section is to specify the conditions under which an
implementation is allowed to perform certain actions either earlier or
later than specified by other rules of the language.


In general, when the language rules specify an order for certain actions
(the canonical order), an implementation may only use an alternative order
if it can guarantee that the effect of the program is not changed by the
reordering. In particular, no exception should arise for the execution of
the reordered program if none arises for the execution of the program in
the canonical order. When, on the other hand, the order of certain actions
is not defined by the language, any order can be used by the
implementation. (For example, the arguments of a predefined operator can
be evaluated in any order since the rules given in section 4.5 do not
require a specific order of evaluation.)


Additional freedom is left to an implementation for reordering actions
involving predefined operations that are either predefined operators or
basic operations other than assignments. This freedom is left, as defined
below, even in the case where the execution of these predefined operations
may propagate a (predefined) exception:


(a) For the purpose of establishing whether the same effect is obtained by
the execution of certain actions in the canonical and in an
alternative order, it can be assumed that none of the predefined
operations invoked by these actions propagates a (predefined)
exception, provided that the two following requirements are met by the
alternative order: first, an operation must not be invoked in the
alternative order if it is not invoked in the canonical order;
second, for each operation, the innermost enclosing frame or accept
statement must be the same in the alternative order as in the
canonical order, and the same exception handlers must apply.


(b) Within an expression, the association of operators with operands is
specified by the syntax. However, for a sequence of predefined
operators of the same precedence level (and in the absence of
parentheses imposing a specific association), any association of
operators with operands is allowed if it satisfies the following
requirement: an integer result must be equal to that given by the
canonical left-to-right order; a real result must belong to the
result model interval defined for the canonical left-to-right order
(see 4.5.7). Such a reordering is allowed even if it may remove an
exception, or introduce a further predefined exception.


Similarly, additional freedom is left to an implementation for the
evaluation of numeric simple expressions. For the evaluation of a
predefined operation, an implementation is allowed to use the operation of
a type that has a range wider than that of the base type of the operands,
provided that this delivers the exact result (or a result within the
declared accuracy, in the case of a real type), even if some intermediate
results lie outside the range of the base type. The exception
NUMERIC_ERROR need not be raised in such a case. In particular, if the
numeric expression is an operand of a predefined relational operator, the
exception NUMERIC_ERROR need not be raised by the evaluation of the
relation, provided that the correct BOOLEAN result is obtained.


A predefined operation need not be invoked at all, if its only possible
effect is to propagate a predefined exception. Similarly, a predefined
operation need not be invoked if the removal of subsequent operations by
the above rule renders this invocation ineffective.

Notes:


Rule (b) applies to predefined operators but not to the short-circuit
control forms.


The expression SPEED < 300_000.0 can be replaced by TRUE if the value
300_000.0 lies outside the base type of SPEED, even though the implicit
conversion of the numeric literal would raise the exception NUMERIC_ERROR.


Example:

declare
N : INTEGER;
begin
N := 0; -- (1)
for J in 1 .. 10 loop
N := N + J**A(K); -- A and K are global variables
end loop;
PUT(N);
exception
when others => PUT("Some error arose"); PUT(N);
end;


The evaluation of A(K) may be performed before the loop, and possibly
immediately before the assignment statement (1) even if this evaluation can
raise an exception. Consequently, within the exception handler, the value
of N is either the undefined initial value or a value later assigned. On
the other hand, the evaluation of A(K) cannot be moved before begin since
an exception would then be handled by a different handler. For this
reason, the initialization of N in the declaration itself would exclude the
possibility of having an undefined initial value of N in the handler.


References: accept statement 9.5, accuracy of real operations 4.5.7,
assignment 5.2, base type 3.3, basic operation 3.3.3, conversion 4.6, error
situation 11, exception 11, exception handler 11.2, frame 11.2,
numeric_error exception 11.1, predefined operator 4.5, predefined
subprogram 8.6, propagation of an exception 11.4, real type 3.5.6,
undefined value 3.2.1

11.7 Suppressing Checks


The presence of a SUPPRESS pragma gives permission to an implementation to
omit certain run-time checks. The form of this pragma is as follows:

pragma SUPPRESS(identifier [, [ON =>] name]);


The identifier is that of the check that can be omitted. The name (if
present) must be either a simple name or an expanded name and it must
denote either an object, a type or subtype, a task unit, or a generic unit;
alternatively the name can be a subprogram name, in which case it can stand
for several visible overloaded subprograms.


A pragma SUPPRESS is only allowed immediately within a declarative part or
immediately within a package specification. In the latter case, the only
allowed form is with a name that denotes an entity (or several overloaded
subprograms) declared immediately within the package specification. The
permission to omit the given check extends from the place of the pragma to
the end of the declarative region associated with the innermost enclosing
block statement or program unit. For a pragma given in a package
specification, the permission extends to the end of the scope of the named
entity.


If the pragma includes a name, the permission to omit the given check is
further restricted: it is given only for operations on the named object or
on all objects of the base type of a named type or subtype; for calls of a
named subprogram; for activations of tasks of the named task type; or for
instantiations of the given generic unit.


The following checks correspond to situations in which the exception
CONSTRAINT_ERROR may be raised; for these checks, the name (if present)
must denote either an object or a type.


ACCESS_CHECK When accessing a selected component, an indexed
component, a slice, or an attribute, of an object
designated by an access value, check that the access
value is not null.


DISCRIMINANT_CHECK Check that a discriminant of a composite value has
the value imposed by a discriminant constraint.
Also, when accessing a record component, check that
it exists for the current discriminant values.


INDEX_CHECK Check that the bounds of an array value are equal to
the corresponding bounds of an index constraint.
Also, when accessing a component of an array object,
check for each dimension that the given index value
belongs to the range defined by the bounds of the
array object. Also, when accessing a slice of an
array object, check that the given discrete range is
compatible with the range defined by the bounds of
the array object.


LENGTH_CHECK Check that there is a matching component for each
component of an array, in the case of array
assignments, type conversions, and logical operators
for arrays of boolean components.


RANGE_CHECK Check that a value satisfies a range constraint.
Also, for the elaboration of a subtype indication,
check that the constraint (if present) is compatible
with the type mark. Also, for an aggregate, check
that an index or discriminant value belongs to the
corresponding subtype. Finally, check for any
constraint checks performed by a generic
instantiation.


The following checks correspond to situations in which the exception
NUMERIC_ERROR is raised. The only allowed names in the corresponding
pragmas are names of numeric types.


DIVISION_CHECK Check that the second operand is not zero for the
operations /, rem and mod.


OVERFLOW_CHECK Check that the result of a numeric operation does not
overflow.


The following check corresponds to situations in which the exception
PROGRAM_ERROR is raised. The only allowed names in the corresponding
pragmas are names denoting task units, generic units, or subprograms.


ELABORATION_CHECK When either a subprogram is called, a task activation
is accomplished, or a generic instantiation is
elaborated, check that the body of the corresponding
unit has already been elaborated.


The following check corresponds to situations in which the exception
STORAGE_ERROR is raised. The only allowed names in the corresponding
pragmas are names denoting access types, task units, or subprograms.


STORAGE_CHECK Check that execution of an allocator does not require
more space than is available for a collection. Check
that the space available for a task or subprogram has
not been exceeded.


If an error situation arises in the absence of the corresponding run-time
checks, the execution of the program is erroneous (the results are not
defined by the language).


Examples:

pragma SUPPRESS(RANGE_CHECK);
pragma SUPPRESS(INDEX_CHECK, ON => TABLE);

Notes:


For certain implementations, it may be impossible or too costly to suppress
certain checks. The corresponding SUPPRESS pragma can be ignored. Hence,
the occurrence of such a pragma within a given unit does not guarantee that
the corresponding exception will not arise; the exceptions may also be
propagated by called units.


References:
access type 3.8, access value 3.8, activation 9.3, aggregate 4.3, allocator
4.8, array 3.6, attribute 4.1.4, block statement 5.6, collection 3.8,
compatible 3.3.2, component of an array 3.6, component of a record 3.7,
composite type 3.3, constraint 3.3, constraint_error exception 11.1,
declarative part 3.9, designate 3.8, dimension 3.6, discrete range 3.6,
discriminant 3.7.1, discriminant constraint 3.7.2, elaboration 3.1 3.9,
erroneous 1.6, error situation 11, expanded name 4.1.3, generic body 11.1,
generic instantiation 12.3, generic unit 12, identifier 2.3, index 3.6,
index constraint 3.6.1, indexed component 4.1.1, null access value 3.8,
numeric operation 3.5.5 3.5.8 3.5.10, numeric type 3.5, numeric_error
exception 11.1, object 3.2, operation 3.3.3, package body 7.1, package
specification 7.1, pragma 2.8, program_error exception 11.1, program unit
6, propagation of an exception 11.4, range constraint 3.5, record type 3.7,
simple name 4.1, slice 4.1.2, subprogram 6, subprogram body 6.3, subprogram
call 6.4, subtype 3.3, subunit 10.2, task 9, task body 9.1, task type 9.1,
task unit 9, type 3.3, type mark 3.3.2


  3 Responses to “Category : Miscellaneous Language Source Code
Archive   : ADA-LRM2.ZIP
Filename : CHAP11.DOC

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/