dwww Home | Show directory contents | Find package


                                   Annex A
                                 (normative)

                       Predefined Language Environment


1   [ This Annex contains the specifications of library units that shall be
provided by every implementation. There are three root library units: Ada,
Interfaces, and System; other library units are children of these:]

2/3 {8652/0047} {AI95-00081-01} {AI95-00424-01} {AI05-0001-1} {AI05-0049-1}
{AI05-0069-1} {AI05-0111-3} {AI05-0136-1} {AI05-0137-1} {AI05-0166-1}
{AI05-0168-1}  
 

        [Standard - A.1
         Ada - A.2
           Assertions - 11.4.2
           Asynchronous_Task_Control - D.11
           Calendar - 9.6
             Arithmetic - 9.6.1
             Formatting - 9.6.1
             Time_Zones - 9.6.1
           Characters - A.3.1
             Conversions - A.3.4
             Handling - A.3.2
             Latin_1 - A.3.3
           Command_Line - A.15
           Complex_Text_IO - G.1.3
           Containers - A.18.1
             Bounded_Doubly_Linked_Lists
                   - A.18.20
             Bounded_Hashed_Maps - A.18.21
             Bounded_Hashed_Sets - A.18.23
             Bounded_Multiway_Trees - A.18.25
             Bounded_Ordered_Maps - A.18.22
             Bounded_Ordered_Sets - A.18.24
             Bounded_Priority_Queues - A.18.31
             Bounded_Synchronized_Queues
                    - A.18.29
             Bounded_Vectors - A.18.19
             Doubly_Linked_Lists - A.18.3
             Generic_Array_Sort - A.18.26
             Generic_Constrained_Array_Sort
                   - A.18.26
             Generic_Sort - A.18.26
             Hashed_Maps - A.18.5
             Hashed_Sets - A.18.8
             Indefinite_Doubly_Linked_Lists
                   - A.18.12
             Indefinite_Hashed_Maps - A.18.13
             Indefinite_Hashed_Sets - A.18.15
             Indefinite_Holders - A.18.18
             Indefinite_Multiway_Trees - A.18.17
             Indefinite_Ordered_Maps - A.18.14
             Indefinite_Ordered_Sets - A.18.16
             Indefinite_Vectors - A.18.11Standard (...continued)
         Ada (...continued)
           Containers (...continued)
             Multiway_Trees - A.18.10
             Ordered_Maps - A.18.6
             Ordered_Sets - A.18.9
             Synchronized_Queue_Interfaces
                   - A.18.27
             Unbounded_Priority_Queues
                   - A.18.30
             Unbounded_Synchronized_Queues
                   - A.18.28
             Vectors - A.18.2
           Decimal - F.2
           Direct_IO - A.8.4
           Directories - A.16
             Hierarchical_File_Names - A.16.1
             Information - A.16
           Dispatching - D.2.1
             EDF - D.2.6
             Non_Preemptive - D.2.4
             Round_Robin - D.2.5
           Dynamic_Priorities - D.5.1
           Environment_Variables - A.17
           Exceptions - 11.4.1
           Execution_Time - D.14
             Group_Budgets - D.14.2
             Interrupts - D.14.3
             Timers - D.14.1
           Finalization - 7.6
           Float_Text_IO - A.10.9
           Float_Wide_Text_IO - A.11
           Float_Wide_Wide_Text_IO - A.11
           Integer_Text_IO - A.10.8
           Integer_Wide_Text_IO - A.11
           Integer_Wide_Wide_Text_IO - A.11
           Interrupts - C.3.2
             Names - C.3.2
           IO_Exceptions - A.13
           Iterator_Interfaces - 5.5.1
           Locales - A.19
        Standard (...continued)
         Ada (...continued)
           Numerics - A.5
             Complex_Arrays - G.3.2
             Complex_Elementary_Functions - G.1.2
             Complex_Types - G.1.1
             Discrete_Random - A.5.2
             Elementary_Functions - A.5.1
             Float_Random - A.5.2
             Generic_Complex_Arrays - G.3.2
             Generic_Complex_Elementary_Functions
                   - G.1.2
             Generic_Complex_Types - G.1.1
             Generic_Elementary_Functions - A.5.1
             Generic_Real_Arrays - G.3.1
             Real_Arrays - G.3.1
           Real_Time - D.8
             Timing_Events - D.15
           Sequential_IO - A.8.1
           Storage_IO - A.9
           Streams - 13.13.1
             Stream_IO - A.12.1
           Strings - A.4.1
             Bounded - A.4.4
               Equal_Case_Insensitive - A.4.10
               Hash - A.4.9
               Hash_Case_Insensitive - A.4.9
               Less_Case_Insensitive - A.4.10
             Fixed - A.4.3
               Equal_Case_Insensitive - A.4.10
               Hash - A.4.9
               Hash_Case_Insensitive - A.4.9
               Less_Case_Insensitive - A.4.10
             Equal_Case_Insensitive - A.4.10
             Hash - A.4.9
             Hash_Case_Insensitive - A.4.9
             Less_Case_Insensitive - A.4.10
             Maps - A.4.2
               Constants - A.4.6
             Unbounded - A.4.5
               Equal_Case_Insensitive - A.4.10
               Hash - A.4.9
               Hash_Case_Insensitive - A.4.9
               Less_Case_Insensitive - A.4.10
             UTF_Encoding - A.4.11
               Conversions - A.4.11
               Strings - A.4.11
               Wide_Strings - A.4.11
               Wide_Wide_Strings - A.4.11
        Standard (...continued)
         Ada (...continued)
           Strings (...continued)
             Wide_Bounded - A.4.7
               Wide_Equal_Case_Insensitive
                     - A.4.7
               Wide_Hash - A.4.7
               Wide_Hash_Case_Insensitive - A.4.7
             Wide_Equal_Case_Insensitive - A.4.7
             Wide_Fixed - A.4.7
               Wide_Equal_Case_Insensitive
                     - A.4.7
               Wide_Hash - A.4.7
               Wide_Hash_Case_Insensitive - A.4.7
             Wide_Hash - A.4.7
             Wide_Hash_Case_Insensitive - A.4.7
             Wide_Maps - A.4.7
               Wide_Constants - A.4.7
             Wide_Unbounded - A.4.7
               Wide_Equal_Case_Insensitive
                     - A.4.7
               Wide_Hash - A.4.7
               Wide_Hash_Case_Insensitive - A.4.7
             Wide_Wide_Bounded - A.4.8
               Wide_Wide_Equal_Case_Insensitive
                     - A.4.8
               Wide_Wide_Hash - A.4.8
               Wide_Wide_Hash_Case_Insensitive
                     - A.4.8
             Wide_Wide_Equal_Case_Insensitive
                   - A.4.8
             Wide_Wide_Fixed - A.4.8
               Wide_Wide_Equal_Case_Insensitive
                     - A.4.8
               Wide_Wide_Hash - A.4.8
               Wide_Wide_Hash_Case_Insensitive
                     - A.4.8
             Wide_Wide_Hash - A.4.8
             Wide_Wide_Hash_Case_Insensitive
                     - A.4.8
             Wide_Wide_Maps - A.4.8
               Wide_Wide_Constants - A.4.8
             Wide_Wide_Unbounded - A.4.8
               Wide_Wide_Equal_Case_Insensitive
                     - A.4.8
               Wide_Wide_Hash - A.4.8
               Wide_Wide_Hash_Case_Insensitive
                     - A.4.8
           Synchronous_Barriers - D.10.1
           Synchronous_Task_Control - D.10
             EDF - D.10
        Standard (...continued)
         Ada (...continued)
           Tags - 3.9
             Generic_Dispatching_Constructor - 3.9
           Task_Attributes - C.7.2
           Task_Identification - C.7.1
           Task_Termination - C.7.3
           Text_IO - A.10.1
             Bounded_IO - A.10.11
             Complex_IO - G.1.3
             Editing - F.3.3
             Text_Streams - A.12.2
             Unbounded_IO - A.10.12
           Unchecked_Conversion - 13.9
           Unchecked_Deallocate_Subpool - 13.11.5
           Unchecked_Deallocation - 13.11.2
           Wide_Characters - A.3.1
             Handling - A.3.5
           Wide_Text_IO - A.11
             Complex_IO - G.1.4
             Editing - F.3.4
             Text_Streams - A.12.3
             Wide_Bounded_IO - A.11
             Wide_Unbounded_IO - A.11
           Wide_Wide_Characters - A.3.1
             Handling - A.3.6
           Wide_Wide_Text_IO - A.11
             Complex_IO - G.1.5
             Editing - F.3.5
             Text_Streams - A.12.4
             Wide_Wide_Bounded_IO - A.11
             Wide_Wide_Unbounded_IO - A.11

         Interfaces - B.2
           C - B.3
             Pointers - B.3.2
             Strings - B.3.1
           COBOL - B.4
           Fortran - B.5

         System - 13.7
           Address_To_Access_Conversions - 13.7.2
           Machine_Code - 13.8
           Multiprocessors - D.16
             Dispatching_Domains - D.16.1
           RPC - E.5
           Storage_Elements - 13.7.1
           Storage_Pools - 13.11
             Subpools - 13.11.4]

2.a         Discussion: In running text, we generally leave out the "Ada."
            when referring to a child of Ada.

2.b         Reason: We had no strict rule for which of Ada, Interfaces, or
            System should be the parent of a given library unit. However, we
            have tried to place as many things as possible under Ada, except
            that interfacing is a separate category, and we have tried to
            place library units whose use is highly nonportable under System.


                         Implementation Requirements

3/4 {AI95-00434-01} {AI12-0052-1} {AI12-0114-1} The implementation shall
ensure that each language-defined subprogram is reentrant in the sense that
concurrent calls on any language-defined subprogram perform as specified, so
long as all objects that are denoted by parameters that could be passed by
reference or designated by parameters of an access type are nonoverlapping.

3.a.1/4     Ramification: {AI12-0052-1} {AI12-0114-1} So long as the
            parameters are disjoint, concurrent calls on the same
            language-defined subprogram, and concurrent calls on two different
            language-defined subprograms are required to work. But concurrent
            calls operating on overlapping objects (be they of the same or
            different language-defined subprograms) are not required to work
            (being an erroneous use of shared variables) unless both
            subprograms are required to pass the associated parameter by-copy.

3.a         For example, simultaneous calls to Text_IO.Put will work properly,
            so long as they are going to two different files. On the other
            hand, simultaneous output to the same file constitutes erroneous
            use of shared variables.

3.b         To be honest: Here, "language defined subprogram" means a language
            defined library subprogram, a subprogram declared in the visible
            part of a language defined library package, an instance of a
            language defined generic library subprogram, or a subprogram
            declared in the visible part of an instance of a language defined
            generic library package.

3.b.1/4     Ramification: {AI12-0052-1} This rule applies to all
            language-defined subprograms, including those defined in packages
            that manage some global state (like environment variables or the
            current directory). Unless specified above, such subprograms need
            to work when the explicit parameters are not overlapping; in
            particular, the existence of the global state is not considered.

3.c/4       {AI12-0052-1} The rule implies that any data local to the private
            part or body of the package (including global state as described
            above) has to be somehow protected against simultaneous access.

3.1/4 {AI12-0052-1} {AI12-0159-1} For the purpose of determining whether
concurrent calls on text input-output subprograms are required to perform as
specified above, when calling a subprogram within Text_IO or its children that
implicitly operates on one of the default input-output files, the subprogram
is considered to have a parameter of Current_Input or Current_Output (as
appropriate).

3.2/3 {AI05-0048-1} If a descendant of a language-defined tagged type is
declared, the implementation shall ensure that each inherited language-defined
subprogram behaves as described in this International Standard. In particular,
overriding a language-defined subprogram shall not alter the effect of any
inherited language-defined subprogram.

3.d/3       Reason: This means that internally the implementation must not do
            redispatching unless it is required by the Standard. So when we
            say that some subprogram Bar is equivalent to Foo, overriding Foo
            for a derived type doesn't change the semantics of Bar, and in
            particular it means that Bar may no longer be equivalent to Foo.
            The word "equivalent" is always a bit of a lie anyway.


                         Implementation Permissions

4   The implementation may restrict the replacement of language-defined
compilation units. The implementation may restrict children of
language-defined library units (other than Standard).

4.a         Ramification: For example, the implementation may say, "you cannot
            compile a library unit called System" or "you cannot compile a
            child of package System" or "if you compile a library unit called
            System, it has to be a package, and it has to contain at least the
            following declarations: ...".


                         Wording Changes from Ada 83

4.b         Many of Ada 83's language-defined library units are now children
            of Ada or System. For upward compatibility, these are renamed as
            root library units (see J.1).

4.c         The order and lettering of the annexes has been changed.


                         Wording Changes from Ada 95

4.d/2       {8652/0047} {AI95-00081-01} Corrigendum: Units missing from the
            list of predefined units were added.

4.e/2       {AI95-00424-01} Added new units to the list of predefined units.


                        Wording Changes from Ada 2005

4.f/3       {AI05-0048-1} Correction: Added wording to ban redispatching
            unless it is explicitly required, in order to safeguard
            portability when overriding language-defined routines.

4.g/3       {AI05-0060-1} {AI05-0206-1} Correction: Added a permission to omit
            pragma Remote_Types from language-defined units if Annex E is not
            supported. This was later removed, as a better method of
            supporting the reason is now available. Note that this requires
            all implementations to provide minimal support for the
            Remote_Types categorization even if Annex E is not supported;
            being unable to compile language-defined units is not allowed.

4.h/3       {AI05-0001-1} {AI05-0049-1} {AI05-0069-1} {AI05-0111-3}
            {AI05-0136-1} {AI05-0137-1} {AI05-0166-1} {AI05-0168-1} Added
            various new units to the list of predefined units.


                        Wording Changes from Ada 2012

4.h.1/4     {AI12-0052-1} {AI12-0114-1} {AI12-0159-1} Corrigendum: The rules
            requiring concurrent access of language-defined subprograms were
            expanded to include implicit Text_IO objects, overlapping objects
            designated by parameters of an access type, and simultaneous calls
            on different language-defined subprograms. While this might change
            behavior of some programs, it would do so by eliminating erroneous
            execution, so we don't consider this an inconsistency.


A.1 The Package Standard


1/3 {AI05-0299-1} This subclause outlines the specification of the package
Standard containing all predefined identifiers in the language. The
corresponding package body is not specified by the language.

2   The operators that are predefined for the types declared in the package
Standard are given in comments since they are implicitly declared. Italics are
used for pseudo-names of anonymous types (such as root_real) and for undefined
information (such as implementation-defined).

2.a         Ramification: All of the predefined operators are of convention
            Intrinsic.


                              Static Semantics

3   The library package Standard has the following declaration:

3.a         Implementation defined: The names and characteristics of the
            numeric subtypes declared in the visible part of package Standard.

4       package Standard is
           pragma Pure(Standard);

5          type Boolean is (False, True);

6          -- The predefined relational operators for this type are as follows:

7/1     {8652/0028} {AI95-00145-01}
           -- function "="   (Left, Right : Boolean'Base) return Boolean;
           -- function "/="  (Left, Right : Boolean'Base) return Boolean;
           -- function "<"   (Left, Right : Boolean'Base) return Boolean;
           -- function "<="  (Left, Right : Boolean'Base) return Boolean;
           -- function ">"   (Left, Right : Boolean'Base) return Boolean;
           -- function ">="  (Left, Right : Boolean'Base) return Boolean;

8          -- The predefined logical operators and the predefined logical
           -- negation operator are as follows:

9/1     {8652/0028} {AI95-00145-01}
           -- function "and" (Left, Right : Boolean'Base) return Boolean'Base;
           -- function "or"  (Left, Right : Boolean'Base) return Boolean'Base;
           -- function "xor" (Left, Right : Boolean'Base) return Boolean'Base;

10/1    {8652/0028} {AI95-00145-01}
           -- function "not" (Right : Boolean'Base) return Boolean'Base;

11/2    {AI95-00434-01}    -- The integer type root_integer and the
           -- corresponding universal type universal_integer are predefined.

12         type Integer is range implementation-defined;

13         subtype Natural  is Integer range 0 .. Integer'Last;
           subtype Positive is Integer range 1 .. Integer'Last;

14         -- The predefined operators for type Integer are as follows:

15         -- function "="  (Left, Right : Integer'Base) return Boolean;
           -- function "/=" (Left, Right : Integer'Base) return Boolean;
           -- function "<"  (Left, Right : Integer'Base) return Boolean;
           -- function "<=" (Left, Right : Integer'Base) return Boolean;
           -- function ">"  (Left, Right : Integer'Base) return Boolean;
           -- function ">=" (Left, Right : Integer'Base) return Boolean;

16         -- function "+"   (Right : Integer'Base) return Integer'Base;
           -- function "-"   (Right : Integer'Base) return Integer'Base;
           -- function "abs" (Right : Integer'Base) return Integer'Base;

17         -- function "+"   (Left, Right : Integer'Base) return Integer'Base;
           -- function "-"   (Left, Right : Integer'Base) return Integer'Base;
           -- function "*"   (Left, Right : Integer'Base) return Integer'Base;
           -- function "/"   (Left, Right : Integer'Base) return Integer'Base;
           -- function "rem" (Left, Right : Integer'Base) return Integer'Base;
           -- function "mod" (Left, Right : Integer'Base) return Integer'Base;

18         -- function "**"  (Left : Integer'Base; Right : Natural)
           --                  return Integer'Base;

19         -- The specification of each operator for the type
           -- root_integer, or for any additional predefined integer
           -- type, is obtained by replacing Integer by the name of the type
           -- in the specification of the corresponding operator of the type
           -- Integer. The right operand of the exponentiation operator
           -- remains as subtype Natural.

20/2    {AI95-00434-01}    -- The floating point type root_real and the
           -- corresponding universal type universal_real are predefined.

21         type Float is digits implementation-defined;

22         -- The predefined operators for this type are as follows:

23         -- function "="   (Left, Right : Float) return Boolean;
           -- function "/="  (Left, Right : Float) return Boolean;
           -- function "<"   (Left, Right : Float) return Boolean;
           -- function "<="  (Left, Right : Float) return Boolean;
           -- function ">"   (Left, Right : Float) return Boolean;
           -- function ">="  (Left, Right : Float) return Boolean;

24         -- function "+"   (Right : Float) return Float;
           -- function "-"   (Right : Float) return Float;
           -- function "abs" (Right : Float) return Float;

25         -- function "+"   (Left, Right : Float) return Float;
           -- function "-"   (Left, Right : Float) return Float;
           -- function "*"   (Left, Right : Float) return Float;
           -- function "/"   (Left, Right : Float) return Float;

26         -- function "**"  (Left : Float; Right : Integer'Base) return Float;

27         -- The specification of each operator for the type root_real, or for
           -- any additional predefined floating point type, is obtained by
           -- replacing Float by the name of the type in the specification of the
           -- corresponding operator of the type Float.

28         -- In addition, the following operators are predefined for the root
           -- numeric types:

29         function "*" (Left : root_integer; Right : root_real)
             return root_real;

30         function "*" (Left : root_real;    Right : root_integer)
             return root_real;

31         function "/" (Left : root_real;    Right : root_integer)
             return root_real;

32         -- The type universal_fixed is predefined.
           -- The only multiplying operators defined between
           -- fixed point types are

33         function "*" (Left : universal_fixed; Right : universal_fixed)
             return universal_fixed;

34         function "/" (Left : universal_fixed; Right : universal_fixed)
             return universal_fixed;

34.1/2  {AI95-00230-01}    -- The type universal_access is predefined.
           -- The following equality operators are predefined:

34.2/2  {AI95-00230-01}
           function "="  (Left, Right: universal_access) return Boolean;
           function "/=" (Left, Right: universal_access) return Boolean;

35/3    {AI95-00415-01} {AI05-0181-1} {AI05-0248-1}
              -- The declaration of type Character is based on the standard ISO 8859-1 character set.
        
              -- There are no character literals corresponding to the positions for control characters.
              -- They are indicated in italics in this definition. See 3.5.2.
        
           type Character is
             (nul,      soh,     stx,     etx,       eot,     enq,    ack,     
        bel,   --0 (16#00#) .. 7 (16#07#)
              bs,       ht,      lf,      vt,        ff,      cr,     so,      
        si,    --8 (16#08#) .. 15 (16#0F#)
        
              dle,      dc1,     dc2,     dc3,       dc4,     nak,    syn,     
        etb,   --16 (16#10#) .. 23 (16#17#)
              can,      em,      sub,     esc,       fs,      gs,     rs,      
        us,    --24 (16#18#) .. 31 (16#1F#)
        
              ' ',      '!',     '"',     '#',       '$',     '%',    '&',     
        ''',   --32 (16#20#) .. 39 (16#27#)
              '(',      ')',     '*',     '+',       ',',     '-',    '.',     
        '/',   --40 (16#28#) .. 47 (16#2F#)
        
              '0',      '1',     '2',     '3',       '4',     '5',    '6',     
        '7',   --48 (16#30#) .. 55 (16#37#)
              '8',      '9',     ':',     ';',       '<',     '=',    '>',     
        '?',   --56 (16#38#) .. 63 (16#3F#)
        
              '@',      'A',     'B',     'C',       'D',     'E',    'F',     
        'G',   --64 (16#40#) .. 71 (16#47#)
              'H',      'I',     'J',     'K',       'L',     'M',    'N',     
        'O',   --72 (16#48#) .. 79 (16#4F#)
        
              'P',      'Q',     'R',     'S',       'T',     'U',    'V',     
        'W',   --80 (16#50#) .. 87 (16#57#)
              'X',      'Y',     'Z',     '[',       '\',     ']',    '^',     
        '_',   --88 (16#58#) .. 95 (16#5F#)
        
              '`',      'a',     'b',     'c',       'd',     'e',    'f',     
        'g',   --96 (16#60#) .. 103 (16#67#)
              'h',      'i',     'j',     'k',       'l',     'm',    'n',     
        'o',   --104 (16#68#) .. 111 (16#6F#)
        
              'p',      'q',     'r',     's',       't',     'u',    'v',     
        'w',   --112 (16#70#) .. 119 (16#77#)
              'x',      'y',     'z',     '{',       '|',     '}',    '~',     
        del,   --120 (16#78#) .. 127 (16#7F#)
        
              reserved_128,      reserved_129,       bph,     nbh,                     
        --128 (16#80#) .. 131 (16#83#)
              reserved_132,      nel,     ssa,       esa,                              
        --132 (16#84#) .. 135 (16#87#)
              hts,      htj,     vts,     pld,       plu,     ri,     ss2,     
        ss3,   --136 (16#88#) .. 143 (16#8F#)
        
              dcs,      pu1,     pu2,     sts,       cch,     mw,     spa,     
        epa,   --144 (16#90#) .. 151 (16#97#)
              sos,      reserved_153,     sci,       csi,                              
        --152 (16#98#) .. 155 (16#9B#)
              st,       osc,     pm,      apc,                                         
        --156 (16#9C#) .. 159 (16#9F#)
        
              ' ',      '¡',     '¢',     '£',       '¤',     '¥',    '¦',     
        '§',   --160 (16#A0#) .. 167 (16#A7#)
              '¨',      '©',     'ª',     '«',                                         
        --168 (16#A8#) .. 171 (16#AB#)
              ¬',       soft_hyphen,      '®',       '¯',                              
        --172 (16#AC#) .. 175 (16#AF#)
        
              '°',      '±',     '²',     '³',       '´',     'µ',    '¶',     
        '·',   --176 (16#B0#) .. 183 (16#B7#)
              '¸',      '¹',     'º',     '»',       '¼',     '½',    '¾',     
        '¿',   --184 (16#B8#) .. 191 (16#BF#)
        
              'À',      'Á',     'Â',     'Ã',       'Ä',     'Å',    'Æ',     
        'Ç',   --192 (16#C0#) .. 199 (16#C7#)
              'È',      'É',     'Ê',     'Ë',       'Ì',     'Í',    'Î',     
        'Ï',   --200 (16#C8#) .. 207 (16#CF#)
        
              'Ð',      'Ñ',     'Ò',     'Ó',       'Ô',     'Õ',    'Ö',     
        '×',   --208 (16#D0#) .. 215 (16#D7#)
              'Ø',      'Ù',     'Ú',     'Û',       'Ü',     'Ý',    'Þ',     
        'ß',   --216 (16#D8#) .. 223 (16#DF#)
        
              'à',      'á',     'â',     'ã',       'ä',     'å',    'æ',     
        'ç',   --224 (16#E0#) .. 231 (16#E7#)
              'è',      'é',     'ê',     'ë',       'ì',     'í',    'î',     
        'ï',   --232 (16#E8#) .. 239 (16#EF#)
        
              'ð',      'ñ',     'ò',     'ó',       'ô',     'õ',    'ö',     
        '÷',   --240 (16#F0#) .. 247 (16#F7#)
              'ø',      'ù',     'ú',     'û',       'ü',     'ý',    'þ',     
        'ÿ');--248 (16#F8#) .. 255 (16#FF#)

36         -- The predefined operators for the type Character are the same as for
           -- any enumeration type.
        

36.1/3  {AI95-00395-01} {AI05-0266-1}
           -- The declaration of type Wide_Character is based on the standard ISO/IEC 10646:2011 BMP character
           -- set. The first 256 positions have the same contents as type Character. See 3.5.2
        .
        
           type Wide_Character is (nul, soh ... Hex_0000FFFE, Hex_0000FFFF);

36.2/3  {AI95-00285-01} {AI95-00395-01} {AI05-0266-1}
           -- The declaration of type Wide_Wide_Character is based on the full
           -- ISO/IEC 10646:2011 character set. The first 65536 positions have the
           -- same contents as type Wide_Character. See 3.5.2.
        
           type Wide_Wide_Character
         is (nul, soh ... Hex_7FFFFFFE, Hex_7FFFFFFF);
           for Wide_Wide_Character'Size use 32;

36.3/2     package ASCII is ... end ASCII;  --Obsolescent; see J.5
        
        

37/3    {AI05-0229-1}    -- Predefined string types:
        
           type String is array(Positive range <>) of Character
              with Pack;

38         -- The predefined operators for this type are as follows:

39         --     function "="  (Left, Right: String) return Boolean;
           --     function "/=" (Left, Right: String) return Boolean;
           --     function "<"  (Left, Right: String) return Boolean;
           --     function "<=" (Left, Right: String) return Boolean;
           --     function ">"  (Left, Right: String) return Boolean;
           --     function ">=" (Left, Right: String) return Boolean;

40         --     function "&" (Left: String;    Right: String)    return String;
           --     function "&" (Left: Character; Right: String)    return String;
           --     function "&" (Left: String;    Right: Character) return String;
           --     function "&" (Left: Character; Right: Character) return String;

41/3    {AI05-0229-1}    type Wide_String
         is array(Positive range <>) of Wide_Character
              with Pack;

42         -- The predefined operators for this type correspond to those for String.

42.1/3  {AI95-00285-01} {AI05-0229-1}    type Wide_Wide_String
         is array (Positive range <>)
              of Wide_Wide_Character
                 with Pack;

42.2/2  {AI95-00285-01}
           -- The predefined operators for this type correspond to those for String.

43         type Duration
         is delta implementation-defined range implementation-defined;

44            -- The predefined operators for the type Duration are the same as for
              -- any fixed point type.

45         -- The predefined exceptions:

46         Constraint_Error: exception;
           Program_Error   : exception;
           Storage_Error   : exception;
           Tasking_Error   : exception;

47      end Standard;

48  Standard has no private part.

48.a        Reason: This is important for portability. All library packages
            are children of Standard, and if Standard had a private part then
            it would be visible to all of them.

49/2 {AI95-00285-01} In each of the types Character, Wide_Character, and
Wide_Wide_Character, the character literals for the space character (position
32) and the non-breaking space character (position 160) correspond to
different values. Unless indicated otherwise, each occurrence of the character
literal ' ' in this International Standard refers to the space character.
Similarly, the character literals for hyphen (position 45) and soft hyphen
(position 173) correspond to different values. Unless indicated otherwise,
each occurrence of the character literal '-' in this International Standard
refers to the hyphen character.


                              Dynamic Semantics

50  Elaboration of the body of Standard has no effect.

50.a        Discussion: Note that the language does not define where this body
            appears in the environment declarative_part - see 10, "
            Program Structure and Compilation Issues".


                         Implementation Permissions

51  An implementation may provide additional predefined integer types and
additional predefined floating point types. Not all of these types need have
names.

51.a        To be honest: An implementation may add representation items to
            package Standard, for example to specify the internal codes of
            type Boolean, or the Small of type Duration.


                            Implementation Advice

52  If an implementation provides additional named predefined integer types,
then the names should end with "Integer" as in "Long_Integer". If an
implementation provides additional named predefined floating point types, then
the names should end with "Float" as in "Long_Float".

52.a/2      Implementation Advice: If an implementation provides additional
            named predefined integer types, then the names should end with "
            Integer". If an implementation provides additional named
            predefined floating point types, then the names should end with
            "Float".

        NOTES

53      1  Certain aspects of the predefined entities cannot be completely
        described in the language itself. For example, although the
        enumeration type Boolean can be written showing the two enumeration
        literals False and True, the short-circuit control forms cannot be
        expressed in the language.

54      2  As explained in 8.1, "Declarative Region" and 10.1.4, "
        The Compilation Process", the declarative region of the package
        Standard encloses every library unit and consequently the main
        subprogram; the declaration of every library unit is assumed to occur
        within this declarative region. Library_items are assumed to be
        ordered in such a way that there are no forward semantic dependences.
        However, as explained in 8.3, "Visibility", the only library units
        that are visible within a given compilation unit are the library units
        named by all with_clauses that apply to the given unit, and moreover,
        within the declarative region of a given library unit, that library
        unit itself.

55      3  If all block_statements of a program are named, then the name of
        each program unit can always be written as an expanded name starting
        with Standard (unless Standard is itself hidden). The name of a
        library unit cannot be a homograph of a name (such as Integer) that is
        already declared in Standard.

56      4  The exception Standard.Numeric_Error is defined in J.6.

56.a        Discussion: The declaration of Natural needs to appear between the
            declaration of Integer and the (implicit) declaration of the "**"
            operator for Integer, because a formal parameter of "**" is of
            subtype Natural. This would be impossible in normal code, because
            the implicit declarations for a type occur immediately after the
            type declaration, with no possibility of intervening explicit
            declarations. But we're in Standard, and Standard is somewhat
            magic anyway.

56.b        Using Natural as the subtype of the formal of "**" seems natural;
            it would be silly to have a textual rule about Constraint_Error
            being raised when there is a perfectly good subtype that means
            just that. Furthermore, by not using Integer for that formal, it
            helps remind the reader that the exponent remains Natural even
            when the left operand is replaced with the derivative of Integer.
            It doesn't logically imply that, but it's still useful as a
            reminder.

56.c        In any case, declaring these general-purpose subtypes of Integer
            close to Integer seems more readable than declaring them much
            later.


                            Extensions to Ada 83

56.d        Package Standard is declared to be pure.

56.e        Discussion: The introduction of the types Wide_Character and
            Wide_String is not an Ada 95 extension to Ada 83, since ISO WG9
            has approved these as an authorized extension of the original Ada
            83 standard that is part of that standard.


                         Wording Changes from Ada 83

56.f        Numeric_Error is made obsolescent.

56.g        The declarations of Natural and Positive are moved to just after
            the declaration of Integer, so that "**" can refer to Natural
            without a forward reference. There's no real need to move
            Positive, too - it just came along for the ride.


                            Extensions to Ada 95

56.h/2      {AI95-00285-01} Types Wide_Wide_Character and Wide_Wide_String are
            new.

56.i/2      Discussion: The inconsistencies associated with these types are
            documented in 3.5.2 and 3.6.3.

56.j/2      {AI95-00230-01} Type universal_access and the equality operations
            for it are new.


                         Wording Changes from Ada 95

56.k/2      {8652/0028} {AI95-00145-01} Corrigendum: Corrected the parameter
            type for the Boolean operators declared in Standard..


                        Wording Changes from Ada 2005

56.l/3      {AI05-0181-1} Correction: Since soft_hyphen (position 173) is
            defined to be nongraphic, gave it a name.

56.m/3      Discussion: The inconsistencies associated with this change are
            documented in 3.5.


A.2 The Package Ada



                              Static Semantics

1   The following language-defined library package exists:

2       package Ada is
            pragma Pure(Ada);
        end Ada;

3   Ada serves as the parent of most of the other language-defined library
units; its declaration is empty (except for the pragma Pure).


                               Legality Rules

4   In the standard mode, it is illegal to compile a child of package Ada.

4.a         Reason: The intention is that mentioning, say, Ada.Text_IO in a
            with_clause is guaranteed (at least in the standard mode) to refer
            to the standard version of Ada.Text_IO. The user can compile a
            root library unit Text_IO that has no relation to the standard
            version of Text_IO.

4.b         Ramification: Note that Ada can have non-language-defined
            grandchildren, assuming the implementation allows it. Also,
            packages System and Interfaces can have children, assuming the
            implementation allows it.

4.c         Implementation Note: An implementation will typically support a
            nonstandard mode in which compiling the language defined library
            units is allowed. Whether or not this mode is made available to
            users is up to the implementer.

4.d         An implementation could theoretically have private children of
            Ada, since that would be semantically neutral. However, a
            programmer cannot compile such a library unit.


                            Extensions to Ada 83

4.e/3       {AI05-0299-1} This subclause is new to Ada 95.


A.3 Character Handling


1/3 {AI95-00285-01} {AI05-0243-1} {AI05-0299-1} This subclause presents the
packages related to character processing: an empty declared pure package
Characters and child packages Characters.Handling and Characters.Latin_1. The
package Characters.Handling provides classification and conversion functions
for Character data, and some simple functions for dealing with Wide_Character
and Wide_Wide_Character data. The child package Characters.Latin_1 declares a
set of constants initialized to values of type Character.


                            Extensions to Ada 83

1.a/3       {AI05-0299-1} This subclause is new to Ada 95.


                         Wording Changes from Ada 95

1.b/2       {AI95-00285-01} Included Wide_Wide_Character in this description;
            the individual changes are documented as extensions as needed.


A.3.1 The Packages Characters, Wide_Characters, and Wide_Wide_Characters



                              Static Semantics

1   The library package Characters has the following declaration:

2       package Ada.Characters is
          pragma Pure(Characters);
        end Ada.Characters;

3/2 {AI95-00395-01} The library package Wide_Characters has the following
declaration:

4/2     package Ada.Wide_Characters is
          pragma Pure(Wide_Characters);
        end Ada.Wide_Characters;

5/2 {AI95-00395-01} The library package Wide_Wide_Characters has the following
declaration:

6/2     package Ada.Wide_Wide_Characters is
          pragma Pure(Wide_Wide_Characters);
        end Ada.Wide_Wide_Characters;


                            Implementation Advice

7/3 {AI95-00395-01} {AI05-0185-1} If an implementation chooses to provide
implementation-defined operations on Wide_Character or Wide_String (such as
collating and sorting, etc.) it should do so by providing child units of
Wide_Characters. Similarly if it chooses to provide implementation-defined
operations on Wide_Wide_Character or Wide_Wide_String it should do so by
providing child units of Wide_Wide_Characters.

7.a/2       Implementation Advice: Implementation-defined operations on
            Wide_Character, Wide_String, Wide_Wide_Character, and
            Wide_Wide_String should be child units of Wide_Characters or
            Wide_Wide_Characters.


                            Extensions to Ada 95

7.b/2       {AI95-00395-01} The packages Wide_Characters and
            Wide_Wide_Characters are new.


A.3.2 The Package Characters.Handling



                              Static Semantics

1   The library package Characters.Handling has the following declaration:

2/2     {AI95-00362-01} {AI95-00395-01} with Ada.Characters.Conversions;
        package Ada.Characters.Handling is
          pragma Pure(Handling);

3       --Character classification functions

4/3     {AI05-0185-1}   function Is_Control
                   (Item : in Character) return Boolean;
          function Is_Graphic           (Item : in Character) return Boolean;
          function Is_Letter            (Item : in Character) return Boolean;
          function Is_Lower             (Item : in Character) return Boolean;
          function Is_Upper             (Item : in Character) return Boolean;
          function Is_Basic             (Item : in Character) return Boolean;
          function Is_Digit             (Item : in Character) return Boolean;
          function Is_Decimal_Digit     (Item : in Character) return Boolean
                             renames Is_Digit;
          function Is_Hexadecimal_Digit (Item : in Character) return Boolean;
          function Is_Alphanumeric      (Item : in Character) return Boolean;
          function Is_Special           (Item : in Character) return Boolean;
          function Is_Line_Terminator   (Item : in Character) return Boolean;
          function Is_Mark              (Item : in Character) return Boolean;
          function Is_Other_Format      (Item : in Character) return Boolean;
          function Is_Punctuation_Connector
         (Item : in Character) return Boolean;
          function Is_Space             (Item : in Character) return Boolean;

5       --Conversion functions for Character and String

6         function To_Lower (Item : in Character) return Character;
          function To_Upper (Item : in Character) return Character;
          function To_Basic (Item : in Character) return Character;

7         function To_Lower (Item : in String) return String;
          function To_Upper (Item : in String) return String;
          function To_Basic (Item : in String) return String;

8       --Classifications of and conversions between Character and ISO 646

9         subtype ISO_646 is
            Character range Character'Val(0) .. Character'Val(127);

10        function Is_ISO_646 (Item : in Character) return Boolean;
          function Is_ISO_646 (Item : in String)    return Boolean;

11        function To_ISO_646 (Item       : in Character;
                               Substitute : in ISO_646 := ' ')
            return ISO_646;

12        function To_ISO_646 (Item       : in String;
                               Substitute : in ISO_646 := ' ')
            return String;

13/2    {AI95-00285-01} {AI95-00395-01}
        -- The functions Is_Character, Is_String, To_Character, To_String, To_Wide_Character,
        -- and To_Wide_String are obsolescent; see J.14.

        Paragraphs 14 through 18 were deleted.

19      end Ada.Characters.Handling;

19.a/2      Discussion: {AI95-00395-01} The with_clause for
            Ada.Characters.Conversions is needed for the definition of the
            obsolescent functions (see J.14). It would be odd to put this
            clause into J.14 as it was not present in Ada 95, and
            with_clauses are semantically neutral to clients anyway.

20  In the description below for each function that returns a Boolean result,
the effect is described in terms of the conditions under which the value True
is returned. If these conditions are not met, then the function returns False.

21  Each of the following classification functions has a formal Character
parameter, Item, and returns a Boolean result.

22  Is_Control  True if Item is a control character. A control character is a
                character whose position is in one of the ranges 0..31 or
                127..159.

23  Is_Graphic  True if Item is a graphic character. A graphic character is a
                character whose position is in one of the ranges 32..126 or
                160..255.

24  Is_Letter   True if Item is a letter. A letter is a character that is in
                one of the ranges 'A'..'Z' or 'a'..'z', or whose position is
                in one of the ranges 192..214, 216..246, or 248..255.

25  Is_Lower    True if Item is a lower-case letter. A lower-case letter is a
                character that is in the range 'a'..'z', or whose position is
                in one of the ranges 223..246 or 248..255.

26  Is_Upper    True if Item is an upper-case letter. An upper-case letter is
                a character that is in the range 'A'..'Z' or whose position is
                in one of the ranges 192..214 or 216.. 222.

27  Is_Basic    True if Item is a basic letter. A basic letter is a character
                that is in one of the ranges 'A'..'Z' and 'a'..'z', or that is
                one of the following: 'Æ', 'æ', 'Ð', 'ð', 'Þ', 'þ', or 'ß'.

28  Is_Digit    True if Item is a decimal digit. A decimal digit is a
                character in the range '0'..'9'.

29  Is_Decimal_Digit
                A renaming of Is_Digit.

30  Is_Hexadecimal_Digit
                True if Item is a hexadecimal digit. A hexadecimal digit is a
                character that is either a decimal digit or that is in one of
                the ranges 'A' .. 'F' or 'a' .. 'f'.

31  Is_Alphanumeric
                True if Item is an alphanumeric character. An alphanumeric
                character is a character that is either a letter or a decimal
                digit.

32  Is_Special  True if Item is a special graphic character. A special graphic
                character is a graphic character that is not alphanumeric.

32.1/3 {AI05-0185-1} Is_Line_Terminator
                True if Item is a character with position 10 .. 13 (Line_Feed,
                Line_Tabulation, Form_Feed, Carriage_Return) or 133
                (Next_Line).

32.2/3 {AI05-0185-1} Is_Mark
                Never True (no value of type Character has categories Mark,
                Non-Spacing or Mark, Spacing Combining).

32.3/3 {AI05-0185-1} Is_Other_Format
                True if Item is a character with position 173 (Soft_Hyphen).

32.4/3 {AI05-0185-1} Is_Punctuation_Connector
                True if Item is a character with position 95 ('_', known as
                Low_Line or Underscore).

32.5/3 {AI05-0185-1} Is_Space
                True if Item is a character with position 32 (' ') or 160
                (No_Break_Space).

33  Each of the names To_Lower, To_Upper, and To_Basic refers to two
functions: one that converts from Character to Character, and the other that
converts from String to String. The result of each Character-to-Character
function is described below, in terms of the conversion applied to Item, its
formal Character parameter. The result of each String-to-String conversion is
obtained by applying to each element of the function's String parameter the
corresponding Character-to-Character conversion; the result is the null String
if the value of the formal parameter is the null String. The lower bound of
the result String is 1.

34  To_Lower    Returns the corresponding lower-case value for Item if
                Is_Upper(Item), and returns Item otherwise.

35  To_Upper    Returns the corresponding upper-case value for Item if
                Is_Lower(Item) and Item has an upper-case form, and returns
                Item otherwise. The lower case letters 'ß' and 'ÿ' do not have
                upper case forms.

36  To_Basic    Returns the letter corresponding to Item but with no
                diacritical mark, if Item is a letter but not a basic letter;
                returns Item otherwise.

37  The following set of functions test for membership in the ISO 646
character range, or convert between ISO 646 and Character.

38  Is_ISO_646  The function whose formal parameter, Item, is of type
                Character returns True if Item is in the subtype ISO_646.

39  Is_ISO_646  The function whose formal parameter, Item, is of type String
                returns True if Is_ISO_646(Item(I)) is True for each I in
                Item'Range.

40  To_ISO_646  The function whose first formal parameter, Item, is of type
                Character returns Item if Is_ISO_646(Item), and returns the
                Substitute ISO_646 character otherwise.

41  To_ISO_646  The function whose first formal parameter, Item, is of type
                String returns the String whose Range is 1..Item'Length and
                each of whose elements is given by To_ISO_646 of the
                corresponding element in Item.

Paragraphs 42 through 49 were deleted.

        NOTES

50      5  A basic letter is a letter without a diacritical mark.

51      6  Except for the hexadecimal digits, basic letters, and ISO_646
        characters, the categories identified in the classification functions
        form a strict hierarchy:

52          - Control characters

53          - Graphic characters

54             - Alphanumeric characters

55                 - Letters

56                     - Upper-case letters

57                     - Lower-case letters

58                 - Decimal digits

59             - Special graphic characters

59.a        Ramification: Thus each Character value is either a control
            character or a graphic character but not both; each graphic
            character is either an alphanumeric or special graphic but not
            both; each alphanumeric is either a letter or decimal digit but
            not both; each letter is either upper case or lower case but not
            both.

60/3    7  {AI05-0114-1} There are certain characters which are defined to be
        lower case letters by ISO 10646 and are therefore allowed in
        identifiers, but are not considered lower case letters by
        Ada.Characters.Handling.

60.a/3      Reason: This is to maintain runtime compatibility with the Ada 95
            definitions of these functions. We don't list the exact characters
            involved because they're likely to change in future character set
            standards; the list for ISO 10646:2011 can be found in
            AI05-0114-1.

60.b/3      Ramification: No version of Characters.Handling is intended to do
            portable (Ada-version independent) manipulation of Ada
            identifiers. The classification given by Wide_Characters.Handling
            will be correct for the current implementation for Ada 2012
            identifiers, but it might not be correct for a different
            implementation or version of Ada.


                            Extensions to Ada 95

60.c/2      {AI95-00362-01} Characters.Handling is now Pure, so it can be used
            in pure units.


                       Incompatibilities With Ada 2005

60.d/3      {AI05-0185-1} Added additional classification routines so that
            Characters.Handling has all of the routines available in
            Wide_Characters.Handling. If Characters.Handling is referenced in
            a use_clause, and an entity E with a defining_identifier that is
            the same as one of the new functions is defined in a package that
            is also referenced in a use_clause, the entity E may no longer be
            use-visible, resulting in errors. This should be rare and is
            easily fixed if it does occur.


                         Wording Changes from Ada 95

60.e/2      {AI95-00285-01} {AI95-00395-01} The conversion functions are made
            obsolescent; a more complete set is available in
            Characters.Conversions - see A.3.4.

60.f/3      {AI95-00285-01} {AI05-0248-1} We no longer talk about localized
            character sets; these are a nonstandard mode, which is none of our
            business.


                        Wording Changes from Ada 2005

60.g/3      {AI05-0114-1} Correction: Added a note to clarify that these
            functions don't have any relationship to the characters allowed in
            identifiers.


A.3.3 The Package Characters.Latin_1


1   The package Characters.Latin_1 declares constants for characters in ISO
8859-1.

1.a         Reason: The constants for the ISO 646 characters could have been
            declared as renamings of objects declared in package ASCII, as
            opposed to explicit constants. The main reason for explicit
            constants was for consistency of style with the upper-half
            constants, and to avoid emphasizing the package ASCII.


                              Static Semantics

2   The library package Characters.Latin_1 has the following declaration:

3       package Ada.Characters.Latin_1 is
            pragma Pure(Latin_1);

4       -- Control characters:

5           NUL                  : constant Character := Character'Val(0);
            SOH                  : constant Character := Character'Val(1);
            STX                  : constant Character := Character'Val(2);
            ETX                  : constant Character := Character'Val(3);
            EOT                  : constant Character := Character'Val(4);
            ENQ                  : constant Character := Character'Val(5);
            ACK                  : constant Character := Character'Val(6);
            BEL                  : constant Character := Character'Val(7);
            BS                   : constant Character := Character'Val(8);
            HT                   : constant Character := Character'Val(9);
            LF                   : constant Character := Character'Val(10);
            VT                   : constant Character := Character'Val(11);
            FF                   : constant Character := Character'Val(12);
            CR                   : constant Character := Character'Val(13);
            SO                   : constant Character := Character'Val(14);
            SI                   : constant Character := Character'Val(15);

6           DLE                  : constant Character := Character'Val(16);
            DC1                  : constant Character := Character'Val(17);
            DC2                  : constant Character := Character'Val(18);
            DC3                  : constant Character := Character'Val(19);
            DC4                  : constant Character := Character'Val(20);
            NAK                  : constant Character := Character'Val(21);
            SYN                  : constant Character := Character'Val(22);
            ETB                  : constant Character := Character'Val(23);
            CAN                  : constant Character := Character'Val(24);
            EM                   : constant Character := Character'Val(25);
            SUB                  : constant Character := Character'Val(26);
            ESC                  : constant Character := Character'Val(27);
            FS                   : constant Character := Character'Val(28);
            GS                   : constant Character := Character'Val(29);
            RS                   : constant Character := Character'Val(30);
            US                   : constant Character := Character'Val(31);

7       -- ISO 646 graphic characters:

8           Space
                        : constant Character := ' ';  -- Character'Val(32)
            Exclamation
                  : constant Character := '!';  -- Character'Val(33)
            Quotation
                    : constant Character := '"';  -- Character'Val(34)
            Number_Sign
                  : constant Character := '#';  -- Character'Val(35)
            Dollar_Sign
                  : constant Character := '$';  -- Character'Val(36)
            Percent_Sign
                 : constant Character := '%';  -- Character'Val(37)
            Ampersand
                    : constant Character := '&';  -- Character'Val(38)
            Apostrophe
                   : constant Character := ''';  -- Character'Val(39)
            Left_Parenthesis
             : constant Character := '(';  -- Character'Val(40)
            Right_Parenthesis
            : constant Character := ')';  -- Character'Val(41)
            Asterisk
                     : constant Character := '*';  -- Character'Val(42)
            Plus_Sign
                    : constant Character := '+';  -- Character'Val(43)
            Comma
                        : constant Character := ',';  -- Character'Val(44)
            Hyphen
                       : constant Character := '-';  -- Character'Val(45)
            Minus_Sign           : Character renames Hyphen;
            Full_Stop
                    : constant Character := '.';  -- Character'Val(46)
            Solidus
                      : constant Character := '/';  -- Character'Val(47)

9           -- Decimal digits '0' though '9' are at positions 48 through 57

10          Colon
                        : constant Character := ':';  -- Character'Val(58)
            Semicolon
                    : constant Character := ';';  -- Character'Val(59)
            Less_Than_Sign
               : constant Character := '<';  -- Character'Val(60)
            Equals_Sign
                  : constant Character := '=';  -- Character'Val(61)
            Greater_Than_Sign
            : constant Character := '>';  -- Character'Val(62)
            Question
                     : constant Character := '?';  -- Character'Val(63)
            Commercial_At
                : constant Character := '@';  -- Character'Val(64)

11          -- Letters 'A' through 'Z' are at positions 65 through 90

12          Left_Square_Bracket
          : constant Character := '[';  -- Character'Val(91)
            Reverse_Solidus
              : constant Character := '\';  -- Character'Val(92)
            Right_Square_Bracket
         : constant Character := ']';  -- Character'Val(93)
            Circumflex
                   : constant Character := '^';  -- Character'Val(94)
            Low_Line
                     : constant Character := '_';  -- Character'Val(95)

13          Grave
                        : constant Character := '`';  -- Character'Val(96)
            LC_A
                         : constant Character := 'a';  -- Character'Val(97)
            LC_B
                         : constant Character := 'b';  -- Character'Val(98)
            LC_C
                         : constant Character := 'c';  -- Character'Val(99)
            LC_D
                         : constant Character := 'd';  -- Character'Val(100)
            LC_E
                         : constant Character := 'e';  -- Character'Val(101)
            LC_F
                         : constant Character := 'f';  -- Character'Val(102)
            LC_G
                         : constant Character := 'g';  -- Character'Val(103)
            LC_H
                         : constant Character := 'h';  -- Character'Val(104)
            LC_I
                         : constant Character := 'i';  -- Character'Val(105)
            LC_J
                         : constant Character := 'j';  -- Character'Val(106)
            LC_K
                         : constant Character := 'k';  -- Character'Val(107)
            LC_L
                         : constant Character := 'l';  -- Character'Val(108)
            LC_M
                         : constant Character := 'm';  -- Character'Val(109)
            LC_N
                         : constant Character := 'n';  -- Character'Val(110)
            LC_O
                         : constant Character := 'o';  -- Character'Val(111)

14          LC_P
                         : constant Character := 'p';  -- Character'Val(112)
            LC_Q
                         : constant Character := 'q';  -- Character'Val(113)
            LC_R
                         : constant Character := 'r';  -- Character'Val(114)
            LC_S
                         : constant Character := 's';  -- Character'Val(115)
            LC_T
                         : constant Character := 't';  -- Character'Val(116)
            LC_U
                         : constant Character := 'u';  -- Character'Val(117)
            LC_V
                         : constant Character := 'v';  -- Character'Val(118)
            LC_W
                         : constant Character := 'w';  -- Character'Val(119)
            LC_X
                         : constant Character := 'x';  -- Character'Val(120)
            LC_Y
                         : constant Character := 'y';  -- Character'Val(121)
            LC_Z
                         : constant Character := 'z';  -- Character'Val(122)
            Left_Curly_Bracket
           : constant Character := '{';  -- Character'Val(123)
            Vertical_Line
                : constant Character := '|';  -- Character'Val(124)
            Right_Curly_Bracket
          : constant Character := '}';  -- Character'Val(125)
            Tilde
                        : constant Character := '~';  -- Character'Val(126)
            DEL                  : constant Character := Character'Val(127);

15      -- ISO 6429 control characters:

16          IS4                  : Character renames FS;
            IS3                  : Character renames GS;
            IS2                  : Character renames RS;
            IS1                  : Character renames US;

17          Reserved_128         : constant Character := Character'Val(128);
            Reserved_129         : constant Character := Character'Val(129);
            BPH                  : constant Character := Character'Val(130);
            NBH                  : constant Character := Character'Val(131);
            Reserved_132         : constant Character := Character'Val(132);
            NEL                  : constant Character := Character'Val(133);
            SSA                  : constant Character := Character'Val(134);
            ESA                  : constant Character := Character'Val(135);
            HTS                  : constant Character := Character'Val(136);
            HTJ                  : constant Character := Character'Val(137);
            VTS                  : constant Character := Character'Val(138);
            PLD                  : constant Character := Character'Val(139);
            PLU                  : constant Character := Character'Val(140);
            RI                   : constant Character := Character'Val(141);
            SS2                  : constant Character := Character'Val(142);
            SS3                  : constant Character := Character'Val(143);

18          DCS                  : constant Character := Character'Val(144);
            PU1                  : constant Character := Character'Val(145);
            PU2                  : constant Character := Character'Val(146);
            STS                  : constant Character := Character'Val(147);
            CCH                  : constant Character := Character'Val(148);
            MW                   : constant Character := Character'Val(149);
            SPA                  : constant Character := Character'Val(150);
            EPA                  : constant Character := Character'Val(151);

19          SOS                  : constant Character := Character'Val(152);
            Reserved_153         : constant Character := Character'Val(153);
            SCI                  : constant Character := Character'Val(154);
            CSI                  : constant Character := Character'Val(155);
            ST                   : constant Character := Character'Val(156);
            OSC                  : constant Character := Character'Val(157);
            PM                   : constant Character := Character'Val(158);
            APC                  : constant Character := Character'Val(159);

20      -- Other graphic characters:

21/3    {AI05-0181-1} -- Character positions 160 (16#A0#) .. 175 (16#AF#):
            No_Break_Space
                     : constant Character := ' '; --Character'Val(160)
            NBSP                       : Character renames No_Break_Space;
            Inverted_Exclamation
               : constant Character := '¡'; --Character'Val(161)
            Cent_Sign
                          : constant Character := '¢'; --Character'Val(162)
            Pound_Sign
                         : constant Character := '£'; --Character'Val(163)
            Currency_Sign
                      : constant Character := '¤'; --Character'Val(164)
            Yen_Sign
                           : constant Character := '¥'; --Character'Val(165)
            Broken_Bar
                         : constant Character := '¦'; --Character'Val(166)
            Section_Sign
                       : constant Character := '§'; --Character'Val(167)
            Diaeresis
                          : constant Character := '¨'; --Character'Val(168)
            Copyright_Sign
                     : constant Character := '©'; --Character'Val(169)
            Feminine_Ordinal_Indicator
         : constant Character := 'ª'; --Character'Val(170)
            Left_Angle_Quotation
               : constant Character := '«'; --Character'Val(171)
            Not_Sign
                           : constant Character := '¬'; --Character'Val(172)
            Soft_Hyphen
                        : constant Character := Character'Val(173);
            Registered_Trade_Mark_Sign
         : constant Character := '®'; --Character'Val(174)
            Macron
                             : constant Character := '¯'; --Character'Val(175)

22      -- Character positions 176 (16#B0#) .. 191 (16#BF#):
            Degree_Sign
                        : constant Character := '°'; --Character'Val(176)
            Ring_Above                 : Character renames Degree_Sign;
            Plus_Minus_Sign
                    : constant Character := '±'; --Character'Val(177)
            Superscript_Two
                    : constant Character := '²'; --Character'Val(178)
            Superscript_Three
                  : constant Character := '³'; --Character'Val(179)
            Acute
                              : constant Character := '´'; --Character'Val(180)
            Micro_Sign
                         : constant Character := 'µ'; --Character'Val(181)
            Pilcrow_Sign
                       : constant Character := '¶'; --Character'Val(182)
            Paragraph_Sign             : Character renames Pilcrow_Sign;
            Middle_Dot
                         : constant Character := '·'; --Character'Val(183)
            Cedilla
                            : constant Character := '¸'; --Character'Val(184)
            Superscript_One
                    : constant Character := '¹'; --Character'Val(185)
            Masculine_Ordinal_Indicator
        : constant Character := 'º'; --Character'Val(186)
            Right_Angle_Quotation
              : constant Character := '»'; --Character'Val(187)
            Fraction_One_Quarter
               : constant Character := '¼'; --Character'Val(188)
            Fraction_One_Half
                  : constant Character := '½'; --Character'Val(189)
            Fraction_Three_Quarters
            : constant Character := '¾'; --Character'Val(190)
            Inverted_Question
                  : constant Character := '¿'; --Character'Val(191)

23      -- Character positions 192 (16#C0#) .. 207 (16#CF#):
            UC_A_Grave
                         : constant Character := 'À'; --Character'Val(192)
            UC_A_Acute
                         : constant Character := 'Á'; --Character'Val(193)
            UC_A_Circumflex
                    : constant Character := 'Â'; --Character'Val(194)
            UC_A_Tilde
                         : constant Character := 'Ã'; --Character'Val(195)
            UC_A_Diaeresis
                     : constant Character := 'Ä'; --Character'Val(196)
            UC_A_Ring
                          : constant Character := 'Å'; --Character'Val(197)
            UC_AE_Diphthong
                    : constant Character := 'Æ'; --Character'Val(198)
            UC_C_Cedilla
                       : constant Character := 'Ç'; --Character'Val(199)
            UC_E_Grave
                         : constant Character := 'È'; --Character'Val(200)
            UC_E_Acute
                         : constant Character := 'É'; --Character'Val(201)
            UC_E_Circumflex
                    : constant Character := 'Ê'; --Character'Val(202)
            UC_E_Diaeresis
                     : constant Character := 'Ë'; --Character'Val(203)
            UC_I_Grave
                         : constant Character := 'Ì'; --Character'Val(204)
            UC_I_Acute
                         : constant Character := 'Í'; --Character'Val(205)
            UC_I_Circumflex
                    : constant Character := 'Î'; --Character'Val(206)
            UC_I_Diaeresis
                     : constant Character := 'Ï'; --Character'Val(207)

24      -- Character positions 208 (16#D0#) .. 223 (16#DF#):
            UC_Icelandic_Eth
                   : constant Character := 'Ð'; --Character'Val(208)
            UC_N_Tilde
                         : constant Character := 'Ñ'; --Character'Val(209)
            UC_O_Grave
                         : constant Character := 'Ò'; --Character'Val(210)
            UC_O_Acute
                         : constant Character := 'Ó'; --Character'Val(211)
            UC_O_Circumflex
                    : constant Character := 'Ô'; --Character'Val(212)
            UC_O_Tilde
                         : constant Character := 'Õ'; --Character'Val(213)
            UC_O_Diaeresis
                     : constant Character := 'Ö'; --Character'Val(214)
            Multiplication_Sign
                : constant Character := '×'; --Character'Val(215)
            UC_O_Oblique_Stroke
                : constant Character := 'Ø'; --Character'Val(216)
            UC_U_Grave
                         : constant Character := 'Ù'; --Character'Val(217)
            UC_U_Acute
                         : constant Character := 'Ú'; --Character'Val(218)
            UC_U_Circumflex
                    : constant Character := 'Û'; --Character'Val(219)
            UC_U_Diaeresis
                     : constant Character := 'Ü'; --Character'Val(220)
            UC_Y_Acute
                         : constant Character := 'Ý'; --Character'Val(221)
            UC_Icelandic_Thorn
                 : constant Character := 'Þ'; --Character'Val(222)
            LC_German_Sharp_S
                  : constant Character := 'ß'; --Character'Val(223)

25      -- Character positions 224 (16#E0#) .. 239 (16#EF#):
            LC_A_Grave
                         : constant Character := 'à'; --Character'Val(224)
            LC_A_Acute
                         : constant Character := 'á'; --Character'Val(225)
            LC_A_Circumflex
                    : constant Character := 'â'; --Character'Val(226)
            LC_A_Tilde
                         : constant Character := 'ã'; --Character'Val(227)
            LC_A_Diaeresis
                     : constant Character := 'ä'; --Character'Val(228)
            LC_A_Ring
                          : constant Character := 'å'; --Character'Val(229)
            LC_AE_Diphthong
                    : constant Character := 'æ'; --Character'Val(230)
            LC_C_Cedilla
                       : constant Character := 'ç'; --Character'Val(231)
            LC_E_Grave
                         : constant Character := 'è'; --Character'Val(232)
            LC_E_Acute
                         : constant Character := 'é'; --Character'Val(233)
            LC_E_Circumflex
                    : constant Character := 'ê'; --Character'Val(234)
            LC_E_Diaeresis
                     : constant Character := 'ë'; --Character'Val(235)
            LC_I_Grave
                         : constant Character := 'ì'; --Character'Val(236)
            LC_I_Acute
                         : constant Character := 'í'; --Character'Val(237)
            LC_I_Circumflex
                    : constant Character := 'î'; --Character'Val(238)
            LC_I_Diaeresis
                     : constant Character := 'ï'; --Character'Val(239)

26      -- Character positions 240 (16#F0#) .. 255 (16#FF#):
            LC_Icelandic_Eth
                   : constant Character := 'ð'; --Character'Val(240)
            LC_N_Tilde
                         : constant Character := 'ñ'; --Character'Val(241)
            LC_O_Grave
                         : constant Character := 'ò'; --Character'Val(242)
            LC_O_Acute
                         : constant Character := 'ó'; --Character'Val(243)
            LC_O_Circumflex
                    : constant Character := 'ô'; --Character'Val(244)
            LC_O_Tilde
                         : constant Character := 'õ'; --Character'Val(245)
            LC_O_Diaeresis
                     : constant Character := 'ö'; --Character'Val(246)
            Division_Sign
                      : constant Character := '÷'; --Character'Val(247)
            LC_O_Oblique_Stroke
                : constant Character := 'ø'; --Character'Val(248)
            LC_U_Grave
                         : constant Character := 'ù'; --Character'Val(249)
            LC_U_Acute
                         : constant Character := 'ú'; --Character'Val(250)
            LC_U_Circumflex
                    : constant Character := 'û'; --Character'Val(251)
            LC_U_Diaeresis
                     : constant Character := 'ü'; --Character'Val(252)
            LC_Y_Acute
                         : constant Character := 'ý'; --Character'Val(253)
            LC_Icelandic_Thorn
                 : constant Character := 'þ'; --Character'Val(254)
            LC_Y_Diaeresis
                     : constant Character := 'ÿ'; --Character'Val(255)
        end Ada.Characters.Latin_1;


                         Implementation Permissions

27  An implementation may provide additional packages as children of
Ada.Characters, to declare names for the symbols of the local character set or
other character sets.


                        Wording Changes from Ada 2005

27.a/3      {AI05-0181-1} Correction: Soft_Hyphen is not a graphic character,
            and thus a character literal for it is illegal. So we have to use
            the position value. This makes no semantic change to users of the
            constant.


A.3.4 The Package Characters.Conversions



                              Static Semantics

1/2 {AI95-00395-01} The library package Characters.Conversions has the
following declaration:

2/2     package Ada.Characters.Conversions is
           pragma Pure(Conversions);

3/2        function Is_Character
         (Item : in Wide_Character)      return Boolean;
           function Is_String
            (Item : in Wide_String)         return Boolean;
           function Is_Character
         (Item : in Wide_Wide_Character) return Boolean;
           function Is_String
            (Item : in Wide_Wide_String)    return Boolean;
           function Is_Wide_Character (Item : in Wide_Wide_Character)
              return Boolean;
           function Is_Wide_String    (Item : in Wide_Wide_String)
              return Boolean;

4/2        function To_Wide_Character
         (Item : in Character) return Wide_Character;
           function To_Wide_String
            (Item : in String)    return Wide_String;
           function To_Wide_Wide_Character (Item : in Character)
              return Wide_Wide_Character;
           function To_Wide_Wide_String    (Item : in String)
              return Wide_Wide_String;
           function To_Wide_Wide_Character (Item : in Wide_Character)
              return Wide_Wide_Character;
           function To_Wide_Wide_String    (Item : in Wide_String)
              return Wide_Wide_String;

5/2        function To_Character (Item       : in Wide_Character;
                                 Substitute : in Character := ' ')
              return Character;
           function To_String    (Item       : in Wide_String;
                                  Substitute : in Character := ' ')
              return String;
           function To_Character (Item :       in Wide_Wide_Character;
                                  Substitute : in Character := ' ')
              return Character;
           function To_String    (Item :       in Wide_Wide_String;
                                  Substitute : in Character := ' ')
              return String;
           function To_Wide_Character (Item :       in Wide_Wide_Character;
                                       Substitute : in Wide_Character := ' ')
              return Wide_Character;
           function To_Wide_String    (Item :       in Wide_Wide_String;
                                       Substitute : in Wide_Character := ' ')
              return Wide_String;

6/2     end Ada.Characters.Conversions;

7/2 {AI95-00395-01} The functions in package Characters.Conversions test
Wide_Wide_Character or Wide_Character values for membership in Wide_Character
or Character, or convert between corresponding characters of
Wide_Wide_Character, Wide_Character, and Character.

8/2     function Is_Character (Item : in Wide_Character) return Boolean;

9/2         {AI95-00395-01} Returns True if Wide_Character'Pos(Item) <=
            Character'Pos(Character'Last).

10/2    function Is_Character (Item : in Wide_Wide_Character) return Boolean;

11/2        {AI95-00395-01} Returns True if Wide_Wide_Character'Pos(Item) <=
            Character'Pos(Character'Last).

12/2    function Is_Wide_Character (Item : in Wide_Wide_Character) return Boolean;

13/2        {AI95-00395-01} Returns True if Wide_Wide_Character'Pos(Item) <=
            Wide_Character'Pos(Wide_Character'Last).

14/2    function Is_String (Item : in Wide_String)      return Boolean;
        function Is_String (Item : in Wide_Wide_String) return Boolean;

15/2        {AI95-00395-01} Returns True if Is_Character(Item(I)) is True for
            each I in Item'Range.

16/2    function Is_Wide_String (Item : in Wide_Wide_String) return Boolean;

17/2        {AI95-00395-01} Returns True if Is_Wide_Character(Item(I)) is True
            for each I in Item'Range.

18/2    function To_Character (Item :       in Wide_Character;
                               Substitute : in Character := ' ') return Character;
        function To_Character (Item :       in Wide_Wide_Character;
                               Substitute : in Character := ' ') return Character;

19/2        {AI95-00395-01} Returns the Character corresponding to Item if
            Is_Character(Item), and returns the Substitute Character otherwise.

20/2    function To_Wide_Character (Item : in Character) return Wide_Character;

21/2        {AI95-00395-01} Returns the Wide_Character X such that
            Character'Pos(Item) = Wide_Character'Pos (X).

22/2    function To_Wide_Character (Item :       in Wide_Wide_Character;
                                    Substitute : in Wide_Character := ' ')
           return Wide_Character;

23/2        {AI95-00395-01} Returns the Wide_Character corresponding to Item
            if Is_Wide_Character(Item), and returns the Substitute
            Wide_Character otherwise.

24/2    function To_Wide_Wide_Character (Item : in Character)
           return Wide_Wide_Character;

25/2        {AI95-00395-01} Returns the Wide_Wide_Character X such that
            Character'Pos(Item) = Wide_Wide_Character'Pos (X).

26/2    function To_Wide_Wide_Character (Item : in Wide_Character)
           return Wide_Wide_Character;

27/2        {AI95-00395-01} Returns the Wide_Wide_Character X such that
            Wide_Character'Pos(Item) = Wide_Wide_Character'Pos (X).

28/2    function To_String (Item :       in Wide_String;
                            Substitute : in Character := ' ') return String;
        function To_String (Item :       in Wide_Wide_String;
                            Substitute : in Character := ' ') return String;

29/2        {AI95-00395-01} Returns the String whose range is 1..Item'Length
            and each of whose elements is given by To_Character of the
            corresponding element in Item.

30/2    function To_Wide_String (Item : in String) return Wide_String;

31/2        {AI95-00395-01} Returns the Wide_String whose range is
            1..Item'Length and each of whose elements is given by
            To_Wide_Character of the corresponding element in Item.

32/2    function To_Wide_String (Item :       in Wide_Wide_String;
                                 Substitute : in Wide_Character := ' ')
           return Wide_String;

33/2        {AI95-00395-01} Returns the Wide_String whose range is
            1..Item'Length and each of whose elements is given by
            To_Wide_Character of the corresponding element in Item with the
            given Substitute Wide_Character.

34/2    function To_Wide_Wide_String (Item : in String) return Wide_Wide_String;
        function To_Wide_Wide_String (Item : in Wide_String)
           return Wide_Wide_String;

35/2        {AI95-00395-01} Returns the Wide_Wide_String whose range is
            1..Item'Length and each of whose elements is given by
            To_Wide_Wide_Character of the corresponding element in Item.


                            Extensions to Ada 95

35.a/2      {AI95-00395-01} The package Characters.Conversions is new,
            replacing functions previously found in Characters.Handling.


A.3.5 The Package Wide_Characters.Handling


1/3 {AI05-0185-1} The package Wide_Characters.Handling provides operations for
classifying Wide_Characters and case folding for Wide_Characters.


                              Static Semantics

2/3 {AI05-0185-1} The library package Wide_Characters.Handling has the
following declaration:

3/3     {AI05-0185-1} {AI05-0266-1} package Ada.Wide_Characters.Handling is
           pragma Pure(Handling);

4/3     {AI05-0266-1}    function Character_Set_Version return String;

5/3        function Is_Control (Item : Wide_Character) return Boolean;

6/3        function Is_Letter (Item : Wide_Character) return Boolean;

7/3        function Is_Lower (Item : Wide_Character) return Boolean;

8/3        function Is_Upper (Item : Wide_Character) return Boolean;

9/3        function Is_Digit (Item : Wide_Character) return Boolean;

10/3       function Is_Decimal_Digit (Item : Wide_Character) return Boolean
              renames Is_Digit;

11/3       function Is_Hexadecimal_Digit
         (Item : Wide_Character) return Boolean;

12/3       function Is_Alphanumeric (Item : Wide_Character) return Boolean;

13/3       function Is_Special (Item : Wide_Character) return Boolean;

14/3       function Is_Line_Terminator (Item : Wide_Character) return Boolean;

15/3       function Is_Mark (Item : Wide_Character) return Boolean;

16/3       function Is_Other_Format (Item : Wide_Character) return Boolean;

17/3       function Is_Punctuation_Connector
         (Item : Wide_Character) return Boolean;

18/3       function Is_Space (Item : Wide_Character) return Boolean;

19/3       function Is_Graphic (Item : Wide_Character) return Boolean;

20/3       function To_Lower (Item : Wide_Character) return Wide_Character;
           function To_Upper (Item : Wide_Character) return Wide_Character;

21/3       function To_Lower (Item : Wide_String) return Wide_String;
           function To_Upper (Item : Wide_String) return Wide_String;

22/3    end Ada.Wide_Characters.Handling;

23/3 {AI05-0185-1} The subprograms defined in Wide_Characters.Handling are
locale independent.

24/3    function Character_Set_Version return String;

25/3        {AI05-0266-1} Returns an implementation-defined identifier that
            identifies the version of the character set standard that is used
            for categorizing characters by the implementation.

26/3    function Is_Control (Item : Wide_Character) return Boolean;

27/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as other_control; otherwise returns False.

28/3    function Is_Letter (Item : Wide_Character) return Boolean;

29/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as letter_uppercase, letter_lowercase,
            letter_titlecase, letter_modifier, letter_other, or number_letter;
            otherwise returns False.

30/3    function Is_Lower (Item : Wide_Character) return Boolean;

31/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as letter_lowercase; otherwise returns False.

32/3    function Is_Upper (Item : Wide_Character) return Boolean;

33/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as letter_uppercase; otherwise returns False.

34/3    function Is_Digit (Item : Wide_Character) return Boolean;

35/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as number_decimal; otherwise returns False.

36/3    function Is_Hexadecimal_Digit (Item : Wide_Character) return Boolean;

37/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as number_decimal, or is in the range 'A' ..
            'F' or 'a' .. 'f'; otherwise returns False.

38/3    function Is_Alphanumeric (Item : Wide_Character) return Boolean;

39/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as letter_uppercase, letter_lowercase,
            letter_titlecase, letter_modifier, letter_other, number_letter, or
            number_decimal; otherwise returns False.

40/3    function Is_Special (Item : Wide_Character) return Boolean;

41/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as graphic_character, but not categorized as
            letter_uppercase, letter_lowercase, letter_titlecase,
            letter_modifier, letter_other, number_letter, or number_decimal;
            otherwise returns False.

42/3    function Is_Line_Terminator (Item : Wide_Character) return Boolean;

43/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as separator_line or separator_paragraph, or
            if Item is a conventional line terminator character (Line_Feed,
            Line_Tabulation, Form_Feed, Carriage_Return, Next_Line); otherwise
            returns False.

44/3    function Is_Mark (Item : Wide_Character) return Boolean;

45/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as mark_non_spacing or mark_spacing_combining;
            otherwise returns False.

46/3    function Is_Other_Format (Item : Wide_Character) return Boolean;

47/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as other_format; otherwise returns False.

48/3    function Is_Punctuation_Connector (Item : Wide_Character) return Boolean;

49/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as punctuation_connector; otherwise returns
            False.

50/3    function Is_Space (Item : Wide_Character) return Boolean;

51/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as separator_space; otherwise returns False.

52/3    function Is_Graphic (Item : Wide_Character) return Boolean;

53/3        {AI05-0185-1} Returns True if the Wide_Character designated by
            Item is categorized as graphic_character; otherwise returns False.

54/3    function To_Lower (Item : Wide_Character) return Wide_Character;

55/3        {AI05-0185-1} {AI05-0266-1} {AI05-0299-1} Returns the Simple
            Lowercase Mapping as defined by documents referenced in the note
            in Clause 1 of ISO/IEC 10646:2011 of the Wide_Character designated
            by Item. If the Simple Lowercase Mapping does not exist for the
            Wide_Character designated by Item, then the value of Item is
            returned.

55.a/3      Discussion: The case mappings come from Unicode as ISO/IEC
            10646:2011 does not include case mappings (but rather references
            the Unicode ones as above).

56/3    function To_Lower (Item : Wide_String) return Wide_String;

57/3        {AI05-0185-1} Returns the result of applying the To_Lower
            conversion to each Wide_Character element of the Wide_String
            designated by Item. The result is the null Wide_String if the
            value of the formal parameter is the null Wide_String. The lower
            bound of the result Wide_String is 1.

58/3    function To_Upper (Item : Wide_Character) return Wide_Character;

59/3        {AI05-0185-1} {AI05-0266-1} {AI05-0299-1} Returns the Simple
            Uppercase Mapping as defined by documents referenced in the note
            in Clause 1 of ISO/IEC 10646:2011 of the Wide_Character designated
            by Item. If the Simple Uppercase Mapping does not exist for the
            Wide_Character designated by Item, then the value of Item is
            returned.

60/3    function To_Upper (Item : Wide_String) return Wide_String;

61/3        {AI05-0185-1} Returns the result of applying the To_Upper
            conversion to each Wide_Character element of the Wide_String
            designated by Item. The result is the null Wide_String if the
            value of the formal parameter is the null Wide_String. The lower
            bound of the result Wide_String is 1.


                            Implementation Advice

62/3 {AI05-0266-1} The string returned by Character_Set_Version should include
either "10646:" or "Unicode".

62.a.1/3    Implementation Advice: The string returned by
            Wide_Characters.Handling.Character_Set_Version should include
            either "10646:" or "Unicode".

62.a/3      Discussion: The intent is that the returned string include the
            year for 10646 (as in "10646:2011"), and the version number for
            Unicode (as in "Unicode 6.0"). We don't try to specify that
            further so we don't need to decide how to represent Corrigenda for
            10646, nor which of these is preferred. (Giving a Unicode version
            is more accurate, as the case folding and mapping rules always
            come from a Unicode version [10646 just tells one to look at
            Unicode to get those], and the character classifications ought to
            be the same for equivalent versions, but we don't want to talk
            about non-ISO standards in an ISO standard.)

        NOTES

63/3    8  {AI05-0266-1} The results returned by these functions may depend on
        which particular version of the 10646 standard is supported by the
        implementation (see 2.1).

64/3    9  {AI05-0286-1} The case insensitive equality comparison routines
        provided in A.4.10, "String Comparison" are also available for wide
        strings (see A.4.7).


                           Extensions to Ada 2005

64.a/3      {AI05-0185-1} {AI05-0266-1} The package Wide_Characters.Handling
            is new.


A.3.6 The Package Wide_Wide_Characters.Handling


1/3 {AI05-0185-1} The package Wide_Wide_Characters.Handling has the same
contents as Wide_Characters.Handling except that each occurrence of
Wide_Character is replaced by Wide_Wide_Character, and each occurrence of
Wide_String is replaced by Wide_Wide_String.


                           Extensions to Ada 2005

1.a/3       {AI05-0185-1} The package Wide_Wide_Characters.Handling is new.


A.4 String Handling


1/3 {AI95-00285-01} {AI05-0299-1} This subclause presents the specifications
of the package Strings and several child packages, which provide facilities
for dealing with string data. Fixed-length, bounded-length, and
unbounded-length strings are supported, for String, Wide_String, and
Wide_Wide_String. The string-handling subprograms include searches for pattern
strings and for characters in program-specified sets, translation (via a
character-to-character mapping), and transformation (replacing, inserting,
overwriting, and deleting of substrings).


                            Extensions to Ada 83

1.a/3       {AI05-0299-1} This subclause is new to Ada 95.


                         Wording Changes from Ada 95

1.b/2       {AI95-00285-01} Included Wide_Wide_String in this description; the
            individual changes are documented as extensions as needed.


A.4.1 The Package Strings


1   The package Strings provides declarations common to the string handling
packages.


                              Static Semantics

2   The library package Strings has the following declaration:

3       package Ada.Strings is
           pragma Pure(Strings);

4/2     {AI95-00285-01}    Space      : constant Character      := ' ';
           Wide_Space : constant Wide_Character := ' ';
           Wide_Wide_Space : constant Wide_Wide_Character := ' ';

5          Length_Error, Pattern_Error, Index_Error, Translation_Error
         : exception;

6          type Alignment  is (Left, Right, Center);
           type Truncation is (Left, Right, Error);
           type Membership is (Inside, Outside);
           type Direction  is (Forward, Backward);
           type Trim_End   is (Left, Right, Both);
        end Ada.Strings;


                        Incompatibilities With Ada 95

6.a/3       {AI95-00285-01} {AI05-0005-1} Constant Wide_Wide_Space is added to
            Ada.Strings. If Ada.Strings is referenced in a use_clause, and an
            entity E with a defining_identifier of Wide_Wide_Space is defined
            in a package that is also referenced in a use_clause, the entity E
            may no longer be use-visible, resulting in errors. This should be
            rare and is easily fixed if it does occur.


A.4.2 The Package Strings.Maps


1   The package Strings.Maps defines the types, operations, and other entities
needed for character sets and character-to-character mappings.


                              Static Semantics

2   The library package Strings.Maps has the following declaration:

3/2     {AI95-00362-01} package Ada.Strings.Maps is
           pragma Pure(Maps);

4/2     {AI95-00161-01}    -- Representation for a set of character values:
           type Character_Set is private;
           pragma Preelaborable_Initialization(Character_Set);

5          Null_Set : constant Character_Set;

6          type Character_Range is
             record
                Low  : Character;
                High : Character;
             end record;
           -- Represents Character range Low..High

7          type Character_Ranges
         is array (Positive range <>) of Character_Range;

8          function To_Set
            (Ranges : in Character_Ranges)return Character_Set;

9          function To_Set
            (Span   : in Character_Range)return Character_Set;

10         function To_Ranges
         (Set    : in Character_Set)  return Character_Ranges;

11         function "="   (Left, Right : in Character_Set) return Boolean;

12         function "not" (Right : in Character_Set)       return Character_Set;
           function "and" (Left, Right : in Character_Set) return Character_Set;
           function "or"  (Left, Right : in Character_Set) return Character_Set;
           function "xor" (Left, Right : in Character_Set) return Character_Set;
           function "-"   (Left, Right : in Character_Set) return Character_Set;

13         function Is_In (Element : in Character;
                           Set     : in Character_Set)
              return Boolean;

14         function Is_Subset (Elements : in Character_Set;
                               Set      : in Character_Set)
              return Boolean;

15         function "<=" (Left  : in Character_Set;
                          Right : in Character_Set)
              return Boolean renames Is_Subset;

16         -- Alternative representation for a set of character values:
           subtype Character_Sequence is String;

17         function To_Set
         (Sequence  : in Character_Sequence)return Character_Set;

18         function To_Set
         (Singleton : in Character)     return Character_Set;

19         function To_Sequence
         (Set  : in Character_Set) return Character_Sequence;

20/2    {AI95-00161-01}
           -- Representation for a character to character mapping:
           type Character_Mapping is private;
           pragma Preelaborable_Initialization(Character_Mapping);

21         function Value (Map     : in Character_Mapping;
                           Element : in Character)
              return Character;

22         Identity : constant Character_Mapping;

23         function To_Mapping (From, To : in Character_Sequence)
              return Character_Mapping;

24         function To_Domain (Map : in Character_Mapping)
              return Character_Sequence;
           function To_Range  (Map : in Character_Mapping)
              return Character_Sequence;

25         type Character_Mapping_Function is
              access function (From : in Character) return Character;

26      private
           ... -- not specified by the language
        end Ada.Strings.Maps;

27  An object of type Character_Set represents a set of characters.

28  Null_Set represents the set containing no characters.

29  An object Obj of type Character_Range represents the set of characters in
the range Obj.Low .. Obj.High.

30  An object Obj of type Character_Ranges represents the union of the sets
corresponding to Obj(I) for I in Obj'Range.

31      function To_Set (Ranges : in Character_Ranges) return Character_Set;

32/3        {AI05-0264-1} If Ranges'Length=0 then Null_Set is returned;
            otherwise, the returned value represents the set corresponding to
            Ranges.

33      function To_Set (Span : in Character_Range) return Character_Set;

34          The returned value represents the set containing each character in
            Span.

35      function To_Ranges (Set : in Character_Set) return Character_Ranges;

36/3        {AI05-0264-1} If Set = Null_Set, then an empty Character_Ranges
            array is returned; otherwise, the shortest array of contiguous
            ranges of Character values in Set, in increasing order of Low, is
            returned.

37      function "=" (Left, Right : in Character_Set) return Boolean;

38          The function "=" returns True if Left and Right represent
            identical sets, and False otherwise.

39  Each of the logical operators "not", "and", "or", and "xor" returns a
Character_Set value that represents the set obtained by applying the
corresponding operation to the set(s) represented by the parameter(s) of the
operator. "-"(Left, Right) is equivalent to "and"(Left, "not"(Right)).

39.a        Reason: The set minus operator is provided for efficiency.

40      function Is_In (Element : in Character;
                        Set     : in Character_Set);
           return Boolean;

41          Is_In returns True if Element is in Set, and False otherwise.

42      function Is_Subset (Elements : in Character_Set;
                            Set      : in Character_Set)
           return Boolean;

43          Is_Subset returns True if Elements is a subset of Set, and False
            otherwise.

44      subtype Character_Sequence is String;

45          The Character_Sequence subtype is used to portray a set of
            character values and also to identify the domain and range of a
            character mapping.

45.a        Reason: Although a named subtype is redundant - the predefined
            type String could have been used for the parameter to To_Set and
            To_Mapping below - the use of a differently named subtype
            identifies the intended purpose of the parameter.

46      function To_Set (Sequence  : in Character_Sequence) return Character_Set;
        
        function To_Set (Singleton : in Character)          return Character_Set;

47          Sequence portrays the set of character values that it explicitly
            contains (ignoring duplicates). Singleton portrays the set
            comprising a single Character. Each of the To_Set functions
            returns a Character_Set value that represents the set portrayed by
            Sequence or Singleton.

48      function To_Sequence (Set : in Character_Set) return Character_Sequence;

49          The function To_Sequence returns a Character_Sequence value
            containing each of the characters in the set represented by Set,
            in ascending order with no duplicates.

50      type Character_Mapping is private;

51          An object of type Character_Mapping represents a
            Character-to-Character mapping.

52      function Value (Map     : in Character_Mapping;
                        Element : in Character)
           return Character;

53          The function Value returns the Character value to which Element
            maps with respect to the mapping represented by Map.

54  A character C matches a pattern character P with respect to a given
Character_Mapping value Map if Value(Map, C) = P. A string S matches a pattern
string P with respect to a given Character_Mapping if their lengths are the
same and if each character in S matches its corresponding character in the
pattern string P.

54.a        Discussion: In an earlier version of the string handling packages,
            the definition of matching was symmetrical, namely C matches P if
            Value(Map,C) = Value(Map,P). However, applying the mapping to the
            pattern was confusing according to some reviewers. Furthermore, if
            the symmetrical version is needed, it can be achieved by applying
            the mapping to the pattern (via translation) prior to passing it
            as a parameter.

55  String handling subprograms that deal with character mappings have
parameters whose type is Character_Mapping.

56      Identity : constant Character_Mapping;

57          Identity maps each Character to itself.

58      function To_Mapping (From, To : in Character_Sequence)
            return Character_Mapping;

59          To_Mapping produces a Character_Mapping such that each element of
            From maps to the corresponding element of To, and each other
            character maps to itself. If From'Length /= To'Length, or if some
            character is repeated in From, then Translation_Error is
            propagated.

60      function To_Domain (Map : in Character_Mapping) return Character_Sequence;

61          To_Domain returns the shortest Character_Sequence value D such
            that each character not in D maps to itself, and such that the
            characters in D are in ascending order. The lower bound of D is 1.

62      function To_Range  (Map : in Character_Mapping) return Character_Sequence;

63/1        {8652/0048} {AI95-00151-01} To_Range returns the
            Character_Sequence value R, such that if D = To_Domain(Map), then
            R has the same bounds as D, and D(I) maps to R(I) for each I in
            D'Range.

64  An object F of type Character_Mapping_Function maps a Character value C to
the Character value F.all(C), which is said to match C with respect to mapping
function F.

        NOTES

65      10  Character_Mapping and Character_Mapping_Function are used both for
        character equivalence mappings in the search subprograms (such as for
        case insensitivity) and as transformational mappings in the Translate
        subprograms.

66      11  To_Domain(Identity) and To_Range(Identity) each returns the null
        string.

66.a        Reason: Package Strings.Maps is not pure, since it declares an
            access-to-subprogram type.


                                  Examples

67  To_Mapping("ABCD", "ZZAB") returns a Character_Mapping that maps 'A' and
'B' to 'Z', 'C' to 'A', 'D' to 'B', and each other Character to itself.


                            Extensions to Ada 95

67.a/2      {AI95-00161-01} Amendment Correction: Added pragma
            Preelaborable_Initialization to types Character_Set and
            Character_Mapping, so that they can be used to declare
            default-initialized objects in preelaborated units.

67.b/2      {AI95-00362-01} Strings.Maps is now Pure, so it can be used in
            pure units.


                         Wording Changes from Ada 95

67.c/2      {8652/0048} {AI95-00151-01} Corrigendum: Corrected the definition
            of the range of the result of To_Range, since the Ada 95
            definition makes no sense.


A.4.3 Fixed-Length String Handling


1   The language-defined package Strings.Fixed provides string-handling
subprograms for fixed-length strings; that is, for values of type
Standard.String. Several of these subprograms are procedures that modify the
contents of a String that is passed as an out or an in out parameter; each has
additional parameters to control the effect when the logical length of the
result differs from the parameter's length.

2   For each function that returns a String, the lower bound of the returned
value is 1.

2.a/2       Discussion: {AI95-00114-01} Most operations that yield a String
            are provided both as a function and as a procedure. The functional
            form is possibly a more aesthetic style but may introduce overhead
            due to extra copying or dynamic memory usage in some
            implementations. Thus a procedural form, with an in out parameter
            so that all copying is done `in place', is also supplied.

3   The basic model embodied in the package is that a fixed-length string
comprises significant characters and possibly padding (with space characters)
on either or both ends. When a shorter string is copied to a longer string,
padding is inserted, and when a longer string is copied to a shorter one,
padding is stripped. The Move procedure in Strings.Fixed, which takes a String
as an out parameter, allows the programmer to control these effects. Similar
control is provided by the string transformation procedures.


                              Static Semantics

4   The library package Strings.Fixed has the following declaration:

5       with Ada.Strings.Maps;
        package Ada.Strings.Fixed is
           pragma Preelaborate(Fixed);

6       -- "Copy" procedure for strings of possibly different lengths

7          procedure Move (Source  : in  String;
                           Target  : out String;
                           Drop    : in  Truncation := Error;
                           Justify : in  Alignment  := Left;
                           Pad     : in  Character  := Space);

8       -- Search subprograms

8.1/2   {AI95-00301-01}    function Index (Source  : in String;
                           Pattern : in String;
                           From    : in Positive;
                           Going   : in Direction := Forward;
                           Mapping : in Maps.Character_Mapping := Maps.Identity)
              return Natural;

8.2/2   {AI95-00301-01}    function Index (Source  : in String;
                           Pattern : in String;
                           From    : in Positive;
                           Going   : in Direction := Forward;
                           Mapping : in Maps.Character_Mapping_Function)
              return Natural;

9          function Index (Source   : in String;
                           Pattern  : in String;
                           Going    : in Direction := Forward;
                           Mapping  : in Maps.Character_Mapping
                                        := Maps.Identity)
              return Natural;

10         function Index (Source   : in String;
                           Pattern  : in String;
                           Going    : in Direction := Forward;
                           Mapping  : in Maps.Character_Mapping_Function)
              return Natural;

10.1/2  {AI95-00301-01}    function Index (Source  : in String;
                           Set     : in Maps.Character_Set;
                           From    : in Positive;
                           Test    : in Membership := Inside;
                           Going   : in Direction := Forward)
              return Natural;

11         function Index (Source : in String;
                           Set    : in Maps.Character_Set;
                           Test   : in Membership := Inside;
                           Going  : in Direction  := Forward)
              return Natural;

11.1/2  {AI95-00301-01}    function Index_Non_Blank (Source : in String;
                                     From   : in Positive;
                                     Going  : in Direction := Forward)
              return Natural;

12         function Index_Non_Blank (Source : in String;
                                     Going  : in Direction := Forward)
              return Natural;

13         function Count (Source   : in String;
                           Pattern  : in String;
                           Mapping  : in Maps.Character_Mapping
                                         := Maps.Identity)
              return Natural;

14         function Count (Source   : in String;
                           Pattern  : in String;
                           Mapping  : in Maps.Character_Mapping_Function)
              return Natural;

15         function Count (Source   : in String;
                           Set      : in Maps.Character_Set)
              return Natural;

15.1/3  {AI05-0031-1}    procedure Find_Token (Source : in String;
                                 Set    : in Maps.Character_Set;
                                 From   : in Positive;
                                 Test   : in Membership;
                                 First  : out Positive;
                                 Last   : out Natural);

16         procedure Find_Token (Source : in String;
                                 Set    : in Maps.Character_Set;
                                 Test   : in Membership;
                                 First  : out Positive;
                                 Last   : out Natural);

17      -- String translation subprograms

18         function Translate (Source  : in String;
                               Mapping : in Maps.Character_Mapping)
              return String;

19         procedure Translate (Source  : in out String;
                                Mapping : in Maps.Character_Mapping);

20         function Translate (Source  : in String;
                               Mapping : in Maps.Character_Mapping_Function)
              return String;

21         procedure Translate (Source  : in out String;
                                Mapping : in Maps.Character_Mapping_Function);

22      -- String transformation subprograms

23         function Replace_Slice (Source   : in String;
                                   Low      : in Positive;
                                   High     : in Natural;
                                   By       : in String)
              return String;

24         procedure Replace_Slice (Source   : in out String;
                                    Low      : in Positive;
                                    High     : in Natural;
                                    By       : in String;
                                    Drop     : in Truncation := Error;
                                    Justify  : in Alignment  := Left;
                                    Pad      : in Character  := Space);

25         function Insert (Source   : in String;
                            Before   : in Positive;
                            New_Item : in String)
              return String;

26         procedure Insert (Source   : in out String;
                             Before   : in Positive;
                             New_Item : in String;
                             Drop     : in Truncation := Error);

27         function Overwrite (Source   : in String;
                               Position : in Positive;
                               New_Item : in String)
              return String;

28         procedure Overwrite (Source   : in out String;
                                Position : in Positive;
                                New_Item : in String;
                                Drop     : in Truncation := Right);

29         function Delete (Source  : in String;
                            From    : in Positive;
                            Through : in Natural)
              return String;

30         procedure Delete (Source  : in out String;
                             From    : in Positive;
                             Through : in Natural;
                             Justify : in Alignment := Left;
                             Pad     : in Character := Space);

31       --String selector subprograms
           function Trim (Source : in String;
                          Side   : in Trim_End)
              return String;

32         procedure Trim (Source  : in out String;
                           Side    : in Trim_End;
                           Justify : in Alignment := Left;
                           Pad     : in Character := Space);

33         function Trim (Source : in String;
                          Left   : in Maps.Character_Set;
                          Right  : in Maps.Character_Set)
              return String;

34         procedure Trim (Source  : in out String;
                           Left    : in Maps.Character_Set;
                           Right   : in Maps.Character_Set;
                           Justify : in Alignment := Strings.Left;
                           Pad     : in Character := Space);

35         function Head (Source : in String;
                          Count  : in Natural;
                          Pad    : in Character := Space)
              return String;

36         procedure Head (Source  : in out String;
                           Count   : in Natural;
                           Justify : in Alignment := Left;
                           Pad     : in Character := Space);

37         function Tail (Source : in String;
                          Count  : in Natural;
                          Pad    : in Character := Space)
              return String;

38         procedure Tail (Source  : in out String;
                           Count   : in Natural;
                           Justify : in Alignment := Left;
                           Pad     : in Character := Space);

39      --String constructor functions

40         function "*" (Left  : in Natural;
                         Right : in Character) return String;

41         function "*" (Left  : in Natural;
                         Right : in String) return String;

42      end Ada.Strings.Fixed;

43  The effects of the above subprograms are as follows.

44      procedure Move (Source  : in  String;
                        Target  : out String;
                        Drop    : in  Truncation := Error;
                        Justify : in  Alignment  := Left;
                        Pad     : in  Character  := Space);

45/3        {AI05-0264-1} The Move procedure copies characters from Source to
            Target. If Source has the same length as Target, then the effect
            is to assign Source to Target. If Source is shorter than Target,
            then:

46            * If Justify=Left, then Source is copied into the first
                Source'Length characters of Target.

47            * If Justify=Right, then Source is copied into the last
                Source'Length characters of Target.

48            * If Justify=Center, then Source is copied into the middle
                Source'Length characters of Target. In this case, if the
                difference in length between Target and Source is odd, then
                the extra Pad character is on the right.

49            * Pad is copied to each Target character not otherwise assigned.

50          If Source is longer than Target, then the effect is based on Drop.

51            * If Drop=Left, then the rightmost Target'Length characters of
                Source are copied into Target.

52            * If Drop=Right, then the leftmost Target'Length characters of
                Source are copied into Target.

53            * If Drop=Error, then the effect depends on the value of the
                Justify parameter and also on whether any characters in Source
                other than Pad would fail to be copied:

54                * If Justify=Left, and if each of the rightmost
                    Source'Length-Target'Length characters in Source is Pad,
                    then the leftmost Target'Length characters of Source are
                    copied to Target.

55                * If Justify=Right, and if each of the leftmost
                    Source'Length-Target'Length characters in Source is Pad,
                    then the rightmost Target'Length characters of Source are
                    copied to Target.

56                * Otherwise, Length_Error is propagated.

56.a        Ramification: The Move procedure will work even if Source and
            Target overlap.

56.b        Reason: The order of parameters (Source before Target) corresponds
            to the order in COBOL's MOVE verb.

56.1/2  function Index (Source  : in String;
                        Pattern : in String;
                        From    : in Positive;
                        Going   : in Direction := Forward;
                        Mapping : in Maps.Character_Mapping := Maps.Identity)
           return Natural;
        
        function Index (Source  : in String;
                        Pattern : in String;
                        From    : in Positive;
                        Going   : in Direction := Forward;
                        Mapping : in Maps.Character_Mapping_Function)
           return Natural;

56.2/3      {AI95-00301-01} {AI05-0056-1} Each Index function searches,
            starting from From, for a slice of Source, with length
            Pattern'Length, that matches Pattern with respect to Mapping; the
            parameter Going indicates the direction of the lookup. If Source
            is the null string, Index returns 0; otherwise, if From is not in
            Source'Range, then Index_Error is propagated. If Going = Forward,
            then Index returns the smallest index I which is greater than or
            equal to From such that the slice of Source starting at I matches
            Pattern. If Going = Backward, then Index returns the largest index
            I such that the slice of Source starting at I matches Pattern and
            has an upper bound less than or equal to From. If there is no such
            slice, then 0 is returned. If Pattern is the null string, then
            Pattern_Error is propagated.

56.c/2      Discussion: There is no default parameter for From; the default
            value would need to depend on other parameters (the bounds of
            Source and the direction Going). It is better to use overloaded
            functions rather than a special value to represent the default.

56.d/2      There is no default value for the Mapping parameter that is a
            Character_Mapping_Function; if there were, a call would be
            ambiguous since there is also a default for the Mapping parameter
            that is a Character_Mapping.

56.e/3      {AI05-0056-1} The language does not define when the Pattern_Error
            check is made. (That's because many common searching
            implementations require a nonempty pattern) That means that the
            result for a call like Index ("", "") could be 0 or could raise
            Pattern_Error. Similarly, in the call Index ("", "", From => 2),
            the language does not define whether Pattern_Error or Index_Error
            is raised.

57      function Index (Source   : in String;
                        Pattern  : in String;
                        Going    : in Direction := Forward;
                        Mapping  : in Maps.Character_Mapping
                                      := Maps.Identity)
           return Natural;
        
        function Index (Source   : in String;
                        Pattern  : in String;
                        Going    : in Direction := Forward;
                        Mapping  : in Maps.Character_Mapping_Function)
           return Natural;

58/2        {AI95-00301-01} If Going = Forward, returns

58.1/2        Index (Source, Pattern, Source'First, Forward, Mapping);

58.2/3      {AI05-0264-1} otherwise, returns

58.3/2        Index (Source, Pattern, Source'Last, Backward, Mapping);

58.a/2      This paragraph was deleted.There is no default value for the
            Mapping parameter that is a Character_Mapping_Function; if there
            were, a call would be ambiguous since there is also a default for
            the Mapping parameter that is a Character_Mapping.

58.4/2  function Index (Source  : in String;
                        Set     : in Maps.Character_Set;
                        From    : in Positive;
                        Test    : in Membership := Inside;
                        Going   : in Direction := Forward)
           return Natural;

58.5/3      {AI95-00301-01} {AI05-0056-1} Index searches for the first or last
            occurrence of any of a set of characters (when Test=Inside), or
            any of the complement of a set of characters (when Test=Outside).
            If Source is the null string, Index returns 0; otherwise, if From
            is not in Source'Range, then Index_Error is propagated. Otherwise,
            it returns the smallest index I >= From (if Going=Forward) or the
            largest index I <= From (if Going=Backward) such that Source(I)
            satisfies the Test condition with respect to Set; it returns 0 if
            there is no such Character in Source.

59      function Index (Source : in String;
                        Set    : in Maps.Character_Set;
                        Test   : in Membership := Inside;
                        Going  : in Direction  := Forward)
           return Natural;

60/2        {AI95-00301-01} If Going = Forward, returns

60.1/2        Index (Source, Set, Source'First, Test, Forward);

60.2/3      {AI05-0264-1} otherwise, returns

60.3/2        Index (Source, Set, Source'Last, Test, Backward);

60.4/2  function Index_Non_Blank (Source : in String;
                                  From   : in Positive;
                                  Going  : in Direction := Forward)
           return Natural;

60.5/2      {AI95-00301-01} Returns Index (Source, Maps.To_Set(Space), From,
            Outside, Going);

61      function Index_Non_Blank (Source : in String;
                                  Going  : in Direction := Forward)
           return Natural;

62          Returns Index(Source, Maps.To_Set(Space), Outside, Going)

63      function Count (Source   : in String;
                        Pattern  : in String;
                        Mapping  : in Maps.Character_Mapping
                                     := Maps.Identity)
           return Natural;
        
        function Count (Source   : in String;
                        Pattern  : in String;
                        Mapping  : in Maps.Character_Mapping_Function)
           return Natural;

64          Returns the maximum number of nonoverlapping slices of Source that
            match Pattern with respect to Mapping. If Pattern is the null
            string then Pattern_Error is propagated.

64.a        Reason: We say `maximum number' because it is possible to slice a
            source string in different ways yielding different numbers of
            matches. For example if Source is "ABABABA" and Pattern is "ABA",
            then Count yields 2, although there is a partitioning of Source
            that yields just 1 match, for the middle slice. Saying `maximum
            number' is equivalent to saying that the pattern match starts
            either at the low index or the high index position.

65      function Count (Source   : in String;
                        Set      : in Maps.Character_Set)
           return Natural;

66          Returns the number of occurrences in Source of characters that are
            in Set.

66.1/3  procedure Find_Token (Source : in String;
                              Set    : in Maps.Character_Set;
                              From   : in Positive;
                              Test   : in Membership;
                              First  : out Positive;
                              Last   : out Natural);

66.2/3      {AI05-0031-1} If Source is not the null string and From is not in
            Source'Range, then Index_Error is raised. Otherwise, First is set
            to the index of the first character in Source(From .. Source'Last)
            that satisfies the Test condition. Last is set to the largest
            index such that all characters in Source(First .. Last) satisfy
            the Test condition. If no characters in Source(From ..
            Source'Last) satisfy the Test condition, First is set to From, and
            Last is set to 0.

67      procedure Find_Token (Source : in String;
                              Set    : in Maps.Character_Set;
                              Test   : in Membership;
                              First  : out Positive;
                              Last   : out Natural);

68/3        {8652/0049} {AI95-00128-01} {AI05-0031-1} Equivalent to Find_Token
            (Source, Set, Source'First, Test, First, Last).

68.a/3      Ramification: {AI05-0031-1} If Source'First is not in Positive,
            which can only happen for an empty string, this will raise
            Constraint_Error.

69      function Translate (Source  : in String;
                            Mapping : in Maps.Character_Mapping)
           return String;
        
        function Translate (Source  : in String;
                            Mapping : in Maps.Character_Mapping_Function)
           return String;

70          Returns the string S whose length is Source'Length and such that
            S(I) is the character to which Mapping maps the corresponding
            element of Source, for I in 1..Source'Length.

71      procedure Translate (Source  : in out String;
                             Mapping : in Maps.Character_Mapping);
        
        procedure Translate (Source  : in out String;
                             Mapping : in Maps.Character_Mapping_Function);

72          Equivalent to Source := Translate(Source, Mapping).

73      function Replace_Slice (Source   : in String;
                                Low      : in Positive;
                                High     : in Natural;
                                By       : in String)
           return String;

74/1        {8652/0049} {AI95-00128-01} If Low > Source'Last+1, or High <
            Source'First-1, then Index_Error is propagated. Otherwise:

74.1/1        * {8652/0049} {AI95-00128-01} If High >= Low, then the returned
                string comprises Source(Source'First..Low-1) & By &
                Source(High+1..Source'Last), but with lower bound 1.

74.2/1        * {8652/0049} {AI95-00128-01} If High < Low, then the returned
                string is Insert(Source, Before=>Low, New_Item=>By).

75      procedure Replace_Slice (Source   : in out String;
                                 Low      : in Positive;
                                 High     : in Natural;
                                 By       : in String;
                                 Drop     : in Truncation := Error;
                                 Justify  : in Alignment  := Left;
                                 Pad      : in Character  := Space);

76          Equivalent to Move(Replace_Slice(Source, Low, High, By), Source,
            Drop, Justify, Pad).

77      function Insert (Source   : in String;
                         Before   : in Positive;
                         New_Item : in String)
           return String;

78/3        {AI05-0264-1} Propagates Index_Error if Before is not in
            Source'First .. Source'Last+1; otherwise, returns
            Source(Source'First..Before-1) & New_Item &
            Source(Before..Source'Last), but with lower bound 1.

79      procedure Insert (Source   : in out String;
                          Before   : in Positive;
                          New_Item : in String;
                          Drop     : in Truncation := Error);

80          Equivalent to Move(Insert(Source, Before, New_Item), Source, Drop).

81      function Overwrite (Source   : in String;
                            Position : in Positive;
                            New_Item : in String)
           return String;

82/3        {AI05-0264-1} Propagates Index_Error if Position is not in
            Source'First .. Source'Last+1; otherwise, returns the string
            obtained from Source by consecutively replacing characters
            starting at Position with corresponding characters from New_Item.
            If the end of Source is reached before the characters in New_Item
            are exhausted, the remaining characters from New_Item are appended
            to the string.

83      procedure Overwrite (Source   : in out String;
                             Position : in Positive;
                             New_Item : in String;
                             Drop     : in Truncation := Right);

84          Equivalent to Move(Overwrite(Source, Position, New_Item), Source,
            Drop).

85      function Delete (Source  : in String;
                         From    : in Positive;
                         Through : in Natural)
           return String;

86/3        {8652/0049} {AI95-00128-01} {AI05-0264-1} If From <= Through, the
            returned string is Replace_Slice(Source, From, Through, "");
            otherwise, it is Source with lower bound 1.

87      procedure Delete (Source  : in out String;
                          From    : in Positive;
                          Through : in Natural;
                          Justify : in Alignment := Left;
                          Pad     : in Character := Space);

88          Equivalent to Move(Delete(Source, From, Through), Source, Justify
            => Justify, Pad => Pad).

89      function Trim (Source : in String;
                       Side   : in Trim_End)
          return String;

90          Returns the string obtained by removing from Source all leading
            Space characters (if Side = Left), all trailing Space characters
            (if Side = Right), or all leading and trailing Space characters
            (if Side = Both).

91      procedure Trim (Source  : in out String;
                        Side    : in Trim_End;
                        Justify : in Alignment := Left;
                        Pad     : in Character := Space);

92          Equivalent to Move(Trim(Source, Side), Source, Justify=>Justify,
            Pad=>Pad).

93      function Trim (Source : in String;
                       Left   : in Maps.Character_Set;
                       Right  : in Maps.Character_Set)
           return String;

94          Returns the string obtained by removing from Source all leading
            characters in Left and all trailing characters in Right.

95      procedure Trim (Source  : in out String;
                        Left    : in Maps.Character_Set;
                        Right   : in Maps.Character_Set;
                        Justify : in Alignment := Strings.Left;
                        Pad     : in Character := Space);

96          Equivalent to Move(Trim(Source, Left, Right), Source, Justify =>
            Justify, Pad=>Pad).

97      function Head (Source : in String;
                       Count  : in Natural;
                       Pad    : in Character := Space)
           return String;

98/3        {AI05-0264-1} Returns a string of length Count. If Count <=
            Source'Length, the string comprises the first Count characters of
            Source. Otherwise, its contents are Source concatenated with
            Count-Source'Length Pad characters.

99      procedure Head (Source  : in out String;
                        Count   : in Natural;
                        Justify : in Alignment := Left;
                        Pad     : in Character := Space);

100         Equivalent to Move(Head(Source, Count, Pad), Source, Drop=>Error,
            Justify=>Justify, Pad=>Pad).

101     function Tail (Source : in String;
                       Count  : in Natural;
                       Pad    : in Character := Space)
           return String;

102/3       {AI05-0264-1} Returns a string of length Count. If Count <=
            Source'Length, the string comprises the last Count characters of
            Source. Otherwise, its contents are Count-Source'Length Pad
            characters concatenated with Source.

103     procedure Tail (Source  : in out String;
                        Count   : in Natural;
                        Justify : in Alignment := Left;
                        Pad     : in Character := Space);

104         Equivalent to Move(Tail(Source, Count, Pad), Source, Drop=>Error,
            Justify=>Justify, Pad=>Pad).

105     function "*" (Left  : in Natural;
                      Right : in Character) return String;
        
        function "*" (Left  : in Natural;
                      Right : in String) return String;

106/1       {8652/0049} {AI95-00128-01} These functions replicate a character
            or string a specified number of times. The first function returns
            a string whose length is Left and each of whose elements is Right.
            The second function returns a string whose length is
            Left*Right'Length and whose value is the null string if Left = 0
            and otherwise is (Left-1)*Right & Right with lower bound 1.

        NOTES

107/3   12  {AI05-0264-1} In the Index and Count functions taking Pattern and
        Mapping parameters, the actual String parameter passed to Pattern
        should comprise characters occurring as target characters of the
        mapping. Otherwise, the pattern will not match.

108     13  In the Insert subprograms, inserting at the end of a string is
        obtained by passing Source'Last+1 as the Before parameter.

109     14  If a null Character_Mapping_Function is passed to any of the
        string handling subprograms, Constraint_Error is propagated.


                        Incompatibilities With Ada 95

109.a/3     {AI95-00301-01} {AI05-0005-1} Overloaded versions of Index and
            Index_Non_Blank are added to Strings.Fixed. If Strings.Fixed is
            referenced in a use_clause, and an entity E with a
            defining_identifier of Index or Index_Non_Blank is defined in a
            package that is also referenced in a use_clause, the entity E may
            no longer be use-visible, resulting in errors. This should be rare
            and is easily fixed if it does occur.


                         Wording Changes from Ada 95

109.b/2     {8652/0049} {AI95-00128-01} Corrigendum: Clarified that Find_Token
            may raise Constraint_Error if Source'First is not in Positive
            (which is only possible for a null string).

109.c/2     {8652/0049} {AI95-00128-01} Corrigendum: Clarified that
            Replace_Slice, Delete, and "*" always return a string with lower
            bound 1.


                       Incompatibilities With Ada 2005

109.d/3     {AI05-0031-1} An overloaded version of Find_Token is added to
            Strings.Fixed. If Strings.Fixed is referenced in a use_clause, and
            an entity E with a defining_identifier of Find_Token is defined in
            a package that is also referenced in a use_clause, the entity E
            may no longer be use-visible, resulting in errors. This should be
            rare and is easily fixed if it does occur.


                        Wording Changes from Ada 2005

109.e/3     {AI05-0056-1} Correction: Clarified that Index never raises
            Index_Error if the source string is null.


A.4.4 Bounded-Length String Handling


1   The language-defined package Strings.Bounded provides a generic package
each of whose instances yields a private type Bounded_String and a set of
operations. An object of a particular Bounded_String type represents a String
whose low bound is 1 and whose length can vary conceptually between 0 and a
maximum size established at the generic instantiation. The subprograms for
fixed-length string handling are either overloaded directly for
Bounded_String, or are modified as needed to reflect the variability in
length. Additionally, since the Bounded_String type is private, appropriate
constructor and selector operations are provided.

1.a         Reason: Strings.Bounded declares an inner generic package, versus
            itself being directly a generic child of Strings, in order to
            retain compatibility with a version of the string-handling
            packages that is generic with respect to the character and string
            types.

1.b         Reason: The bound of a bounded-length string is specified as a
            parameter to a generic, versus as the value for a discriminant,
            because of the inappropriateness of assignment and equality of
            discriminated types for the copying and comparison of bounded
            strings.


                              Static Semantics

2   The library package Strings.Bounded has the following declaration:

3       with Ada.Strings.Maps;
        package Ada.Strings.Bounded is
           pragma Preelaborate(Bounded);

4          generic
              Max   : Positive;    -- Maximum length of a Bounded_String
           package Generic_Bounded_Length is

5             Max_Length : constant Positive := Max;

6             type Bounded_String is private;

7             Null_Bounded_String : constant Bounded_String;

8             subtype Length_Range is Natural range 0 .. Max_Length;

9             function Length
         (Source : in Bounded_String) return Length_Range;

10         -- Conversion, Concatenation, and Selection functions

11            function To_Bounded_String (Source : in String;
                                          Drop   : in Truncation := Error)
                 return Bounded_String;

12            function To_String (Source : in Bounded_String) return String;

12.1/2  {AI95-00301-01}       procedure Set_Bounded_String
                 (Target :    out Bounded_String;
                  Source : in     String;
                  Drop   : in     Truncation := Error);

13            function Append (Left, Right : in Bounded_String;
                               Drop        : in Truncation  := Error)
                 return Bounded_String;

14            function Append (Left  : in Bounded_String;
                               Right : in String;
                               Drop  : in Truncation := Error)
                 return Bounded_String;

15            function Append (Left  : in String;
                               Right : in Bounded_String;
                               Drop  : in Truncation := Error)
                 return Bounded_String;

16            function Append (Left  : in Bounded_String;
                               Right : in Character;
                               Drop  : in Truncation := Error)
                 return Bounded_String;

17            function Append (Left  : in Character;
                               Right : in Bounded_String;
                               Drop  : in Truncation := Error)
                 return Bounded_String;

18            procedure Append (Source   : in out Bounded_String;
                                New_Item : in Bounded_String;
                                Drop     : in Truncation  := Error);

19            procedure Append (Source   : in out Bounded_String;
                                New_Item : in String;
                                Drop     : in Truncation  := Error);

20            procedure Append (Source   : in out Bounded_String;
                                New_Item : in Character;
                                Drop     : in Truncation  := Error);

21            function "&" (Left, Right : in Bounded_String)
                 return Bounded_String;

22            function "&" (Left : in Bounded_String; Right : in String)
                 return Bounded_String;

23            function "&" (Left : in String; Right : in Bounded_String)
                 return Bounded_String;

24            function "&" (Left : in Bounded_String; Right : in Character)
                 return Bounded_String;

25            function "&" (Left : in Character; Right : in Bounded_String)
                 return Bounded_String;

26            function Element (Source : in Bounded_String;
                                Index  : in Positive)
                 return Character;

27            procedure Replace_Element (Source : in out Bounded_String;
                                         Index  : in Positive;
                                         By     : in Character);

28            function Slice (Source : in Bounded_String;
                              Low    : in Positive;
                              High   : in Natural)
                 return String;

28.1/2  {AI95-00301-01}       function Bounded_Slice
                 (Source : in Bounded_String;
                  Low    : in Positive;
                  High   : in Natural)
                     return Bounded_String;

28.2/2  {AI95-00301-01}       procedure Bounded_Slice
                 (Source : in     Bounded_String;
                  Target :    out Bounded_String;
                  Low    : in     Positive;
                  High   : in     Natural);

29            function "="  (Left, Right : in Bounded_String) return Boolean;
              function "="  (Left : in Bounded_String; Right : in String)
                return Boolean;

30            function "="  (Left : in String; Right : in Bounded_String)
                return Boolean;

31            function "<"  (Left, Right : in Bounded_String) return Boolean;

32            function "<"  (Left : in Bounded_String; Right : in String)
                return Boolean;

33            function "<"  (Left : in String; Right : in Bounded_String)
                return Boolean;

34            function "<=" (Left, Right : in Bounded_String) return Boolean;

35            function "<="  (Left : in Bounded_String; Right : in String)
                return Boolean;

36            function "<="  (Left : in String; Right : in Bounded_String)
                return Boolean;

37            function ">"  (Left, Right : in Bounded_String) return Boolean;

38            function ">"  (Left : in Bounded_String; Right : in String)
                return Boolean;

39            function ">"  (Left : in String; Right : in Bounded_String)
                return Boolean;

40            function ">=" (Left, Right : in Bounded_String) return Boolean;

41            function ">="  (Left : in Bounded_String; Right : in String)
                return Boolean;

42            function ">="  (Left : in String; Right : in Bounded_String)
                return Boolean;

43/2    {AI95-00301-01}    -- Search subprograms

43.1/2  {AI95-00301-01}       function Index (Source  : in Bounded_String;
                              Pattern : in String;
                              From    : in Positive;
                              Going   : in Direction := Forward;
                              Mapping : in Maps.Character_Mapping := Maps.Identity)
                 return Natural;

43.2/2  {AI95-00301-01}       function Index (Source  : in Bounded_String;
                              Pattern : in String;
                              From    : in Positive;
                              Going   : in Direction := Forward;
                              Mapping : in Maps.Character_Mapping_Function)
                 return Natural;

44            function Index (Source   : in Bounded_String;
                              Pattern  : in String;
                              Going    : in Direction := Forward;
                              Mapping  : in Maps.Character_Mapping
                                         := Maps.Identity)
                 return Natural;

45            function Index (Source   : in Bounded_String;
                              Pattern  : in String;
                              Going    : in Direction := Forward;
                              Mapping  : in Maps.Character_Mapping_Function)
                 return Natural;

45.1/2  {AI95-00301-01}       function Index (Source  : in Bounded_String;
                              Set     : in Maps.Character_Set;
                              From    : in Positive;
                              Test    : in Membership := Inside;
                              Going   : in Direction := Forward)
                 return Natural;

46            function Index (Source : in Bounded_String;
                              Set    : in Maps.Character_Set;
                              Test   : in Membership := Inside;
                              Going  : in Direction  := Forward)
                 return Natural;

46.1/2  {AI95-00301-01}       function Index_Non_Blank
         (Source : in Bounded_String;
                                        From   : in Positive;
                                        Going  : in Direction := Forward)
                 return Natural;

47            function Index_Non_Blank (Source : in Bounded_String;
                                        Going  : in Direction := Forward)
                 return Natural;

48            function Count (Source   : in Bounded_String;
                              Pattern  : in String;
                              Mapping  : in Maps.Character_Mapping
                                           := Maps.Identity)
                 return Natural;

49            function Count (Source   : in Bounded_String;
                              Pattern  : in String;
                              Mapping  : in Maps.Character_Mapping_Function)
                 return Natural;

50            function Count (Source   : in Bounded_String;
                              Set      : in Maps.Character_Set)
                 return Natural;

50.1/3  {AI05-0031-1}       procedure Find_Token (Source : in Bounded_String;
                                    Set    : in Maps.Character_Set;
                                    From   : in Positive;
                                    Test   : in Membership;
                                    First  : out Positive;
                                    Last   : out Natural);

51            procedure Find_Token (Source : in Bounded_String;
                                    Set    : in Maps.Character_Set;
                                    Test   : in Membership;
                                    First  : out Positive;
                                    Last   : out Natural);

52         -- String translation subprograms

53            function Translate (Source  : in Bounded_String;
                                  Mapping : in Maps.Character_Mapping)
                 return Bounded_String;

54            procedure Translate (Source  : in out Bounded_String;
                                   Mapping : in Maps.Character_Mapping);

55            function Translate (Source  : in Bounded_String;
                                  Mapping : in Maps.Character_Mapping_Function)
                 return Bounded_String;

56            procedure Translate (Source  : in out Bounded_String;
                                   Mapping : in Maps.Character_Mapping_Function);

57         -- String transformation subprograms

58            function Replace_Slice (Source   : in Bounded_String;
                                      Low      : in Positive;
                                      High     : in Natural;
                                      By       : in String;
                                      Drop     : in Truncation := Error)
                 return Bounded_String;

59            procedure Replace_Slice (Source   : in out Bounded_String;
                                       Low      : in Positive;
                                       High     : in Natural;
                                       By       : in String;
                                       Drop     : in Truncation := Error);

60            function Insert (Source   : in Bounded_String;
                               Before   : in Positive;
                               New_Item : in String;
                               Drop     : in Truncation := Error)
                 return Bounded_String;

61            procedure Insert (Source   : in out Bounded_String;
                                Before   : in Positive;
                                New_Item : in String;
                                Drop     : in Truncation := Error);

62            function Overwrite (Source    : in Bounded_String;
                                  Position  : in Positive;
                                  New_Item  : in String;
                                  Drop      : in Truncation := Error)
                 return Bounded_String;

63            procedure Overwrite (Source    : in out Bounded_String;
                                   Position  : in Positive;
                                   New_Item  : in String;
                                   Drop      : in Truncation := Error);

64            function Delete (Source  : in Bounded_String;
                               From    : in Positive;
                               Through : in Natural)
                 return Bounded_String;

65            procedure Delete (Source  : in out Bounded_String;
                                From    : in Positive;
                                Through : in Natural);

66         --String selector subprograms

67            function Trim (Source : in Bounded_String;
                             Side   : in Trim_End)
                 return Bounded_String;
              procedure Trim (Source : in out Bounded_String;
                              Side   : in Trim_End);

68            function Trim (Source : in Bounded_String;
                             Left   : in Maps.Character_Set;
                             Right  : in Maps.Character_Set)
                 return Bounded_String;

69            procedure Trim (Source : in out Bounded_String;
                              Left   : in Maps.Character_Set;
                              Right  : in Maps.Character_Set);

70            function Head (Source : in Bounded_String;
                             Count  : in Natural;
                             Pad    : in Character  := Space;
                             Drop   : in Truncation := Error)
                 return Bounded_String;

71            procedure Head (Source : in out Bounded_String;
                              Count  : in Natural;
                              Pad    : in Character  := Space;
                              Drop   : in Truncation := Error);

72            function Tail (Source : in Bounded_String;
                             Count  : in Natural;
                             Pad    : in Character  := Space;
                             Drop   : in Truncation := Error)
                 return Bounded_String;

73            procedure Tail (Source : in out Bounded_String;
                              Count  : in Natural;
                              Pad    : in Character  := Space;
                              Drop   : in Truncation := Error);

74         --String constructor subprograms

75            function "*" (Left  : in Natural;
                            Right : in Character)
                 return Bounded_String;

76            function "*" (Left  : in Natural;
                            Right : in String)
                 return Bounded_String;

77            function "*" (Left  : in Natural;
                            Right : in Bounded_String)
                 return Bounded_String;

78            function Replicate (Count : in Natural;
                                  Item  : in Character;
                                  Drop  : in Truncation := Error)
                 return Bounded_String;

79            function Replicate (Count : in Natural;
                                  Item  : in String;
                                  Drop  : in Truncation := Error)
                 return Bounded_String;

80            function Replicate (Count : in Natural;
                                  Item  : in Bounded_String;
                                  Drop  : in Truncation := Error)
                 return Bounded_String;

81         private
               ... -- not specified by the language
           end Generic_Bounded_Length;

82      end Ada.Strings.Bounded;

82.a.1/2    This paragraph was deleted.{8652/0097} {AI95-00115-01}
            {AI95-00344-01}

83  Null_Bounded_String represents the null string. If an object of type
Bounded_String is not otherwise initialized, it will be initialized to the
same value as Null_Bounded_String.

84      function Length (Source : in Bounded_String) return Length_Range;

85          The Length function returns the length of the string represented
            by Source.

86      function To_Bounded_String (Source : in String;
                                    Drop   : in Truncation := Error)
           return Bounded_String;

87/3        {AI05-0264-1} If Source'Length <= Max_Length, then this function
            returns a Bounded_String that represents Source. Otherwise, the
            effect depends on the value of Drop:

88            * If Drop=Left, then the result is a Bounded_String that
                represents the string comprising the rightmost Max_Length
                characters of Source.

89            * If Drop=Right, then the result is a Bounded_String that
                represents the string comprising the leftmost Max_Length
                characters of Source.

90            * If Drop=Error, then Strings.Length_Error is propagated.

91      function To_String (Source : in Bounded_String) return String;

92          To_String returns the String value with lower bound 1 represented
            by Source. If B is a Bounded_String, then B =
            To_Bounded_String(To_String(B)).

92.1/2  procedure Set_Bounded_String
           (Target :    out Bounded_String;
            Source : in     String;
            Drop   : in     Truncation := Error);

92.2/2      {AI95-00301-01} Equivalent to Target := To_Bounded_String (Source,
            Drop);

93  Each of the Append functions returns a Bounded_String obtained by
concatenating the string or character given or represented by one of the
parameters, with the string or character given or represented by the other
parameter, and applying To_Bounded_String to the concatenation result string,
with Drop as provided to the Append function.

94  Each of the procedures Append(Source, New_Item, Drop) has the same effect
as the corresponding assignment Source := Append(Source, New_Item, Drop).

95  Each of the "&" functions has the same effect as the corresponding Append
function, with Error as the Drop parameter.

96      function Element (Source : in Bounded_String;
                          Index  : in Positive)
           return Character;

97          Returns the character at position Index in the string represented
            by Source; propagates Index_Error if Index > Length(Source).

98      procedure Replace_Element (Source : in out Bounded_String;
                                   Index  : in Positive;
                                   By     : in Character);

99          Updates Source such that the character at position Index in the
            string represented by Source is By; propagates Index_Error if
            Index > Length(Source).

100     function Slice (Source : in Bounded_String;
                        Low    : in Positive;
                        High   : in Natural)
           return String;

101/1       {8652/0049} {AI95-00128-01} {AI95-00238-01} Returns the slice at
            positions Low through High in the string represented by Source;
            propagates Index_Error if Low > Length(Source)+1 or High >
            Length(Source). The bounds of the returned string are Low and
            High..

101.1/2 function Bounded_Slice
           (Source : in Bounded_String;
            Low    : in Positive;
            High   : in Natural)
               return Bounded_String;

101.2/2     {AI95-00301-01} Returns the slice at positions Low through High in
            the string represented by Source as a bounded string; propagates
            Index_Error if Low > Length(Source)+1 or High > Length(Source).

101.3/2 procedure Bounded_Slice
           (Source : in     Bounded_String;
            Target :    out Bounded_String;
            Low    : in     Positive;
            High   : in     Natural);

101.4/2     {AI95-00301-01} Equivalent to Target := Bounded_Slice (Source,
            Low, High);

102 Each of the functions "=", "<", ">", "<=", and ">=" returns the same
result as the corresponding String operation applied to the String values
given or represented by the two parameters.

103 Each of the search subprograms (Index, Index_Non_Blank, Count, Find_Token)
has the same effect as the corresponding subprogram in Strings.Fixed applied
to the string represented by the Bounded_String parameter.

104 Each of the Translate subprograms, when applied to a Bounded_String, has
an analogous effect to the corresponding subprogram in Strings.Fixed. For the
Translate function, the translation is applied to the string represented by
the Bounded_String parameter, and the result is converted (via
To_Bounded_String) to a Bounded_String. For the Translate procedure, the
string represented by the Bounded_String parameter after the translation is
given by the Translate function for fixed-length strings applied to the string
represented by the original value of the parameter.

105/1 {8652/0049} {AI95-00128-01} Each of the transformation subprograms
(Replace_Slice, Insert, Overwrite, Delete), selector subprograms (Trim, Head,
Tail), and constructor functions ("*") has an effect based on its
corresponding subprogram in Strings.Fixed, and Replicate is based on
Fixed."*". In the case of a function, the corresponding fixed-length string
subprogram is applied to the string represented by the Bounded_String
parameter. To_Bounded_String is applied the result string, with Drop (or Error
in the case of Generic_Bounded_Length."*") determining the effect when the
string length exceeds Max_Length. In the case of a procedure, the
corresponding function in Strings.Bounded.Generic_Bounded_Length is applied,
with the result assigned into the Source parameter.

105.a/2     Ramification: {AI95-00114-01} The "/=" operations between
            Bounded_String and String, and between String and Bounded_String,
            are automatically defined based on the corresponding "="
            operations.


                            Implementation Advice

106 Bounded string objects should not be implemented by implicit pointers and
dynamic allocation.

106.a.1/2   Implementation Advice: Bounded string objects should not be
            implemented by implicit pointers and dynamic allocation.

106.a       Implementation Note: The following is a possible implementation of
            the private part of the package:

106.b           type Bounded_String_Internals (Length : Length_Range := 0) is
                   record
                      Data : String(1..Length);
                   end record;

106.c           type Bounded_String is
                   record
                      Data : Bounded_String_Internals;  -- Unconstrained
                   end record;

106.d           Null_Bounded_String : constant Bounded_String :=
                   (Data => (Length => 0,
                             Data   => (1..0 => ' ')));


                         Inconsistencies With Ada 95

106.e/2     {AI95-00238-01} Amendment Correction: The bounds of the string
            returned from Slice are now defined. This is technically an
            inconsistency; if a program depended on some other lower bound for
            the string returned from Slice, it could fail when compiled with
            Ada 2005. Such code is not portable even between Ada 95
            implementations, so it should be very rare.


                        Incompatibilities With Ada 95

106.f/3     {AI95-00301-01} {AI05-0005-1} Procedure Set_Bounded_String, two
            Bounded_Slice subprograms, and overloaded versions of Index and
            Index_Non_Blank are added to
            Strings.Bounded.Generic_Bounded_Length. If an instance of
            Generic_Bounded_Length is referenced in a use_clause, and an
            entity E with the defining_identifier as a new entity in
            Generic_Bounded_Length is defined in a package that is also
            referenced in a use_clause, the entity E may no longer be
            use-visible, resulting in errors. This should be rare and is
            easily fixed if it does occur.


                         Wording Changes from Ada 95

106.g/2     {8652/0049} {AI95-00128-01} Corrigendum: Corrected the conditions
            for which Slice raises Index_Error.

106.h/2     {8652/0049} {AI95-00128-01} Corrigendum: Clarified the meaning of
            transformation, selector, and constructor subprograms by
            describing the effects of procedures and functions separately.


                       Incompatibilities With Ada 2005

106.i/3     {AI05-0031-1} An overloaded version of Find_Token is added to
            Strings.Bounded.Generic_Bounded_Length. If an instance of
            Generic_Bounded_Length is referenced in a use_clause, and an
            entity E with a defining_identifier of Find_Token is defined in a
            package that is also referenced in a use_clause, the entity E may
            no longer be use-visible, resulting in errors. This should be rare
            and is easily fixed if it does occur.


A.4.5 Unbounded-Length String Handling


1   The language-defined package Strings.Unbounded provides a private type
Unbounded_String and a set of operations. An object of type Unbounded_String
represents a String whose low bound is 1 and whose length can vary
conceptually between 0 and Natural'Last. The subprograms for fixed-length
string handling are either overloaded directly for Unbounded_String, or are
modified as needed to reflect the flexibility in length. Since the
Unbounded_String type is private, relevant constructor and selector operations
are provided.

1.a         Reason: The transformation operations for fixed- and
            bounded-length strings that are not necessarily length preserving
            are supplied for Unbounded_String as procedures as well as
            functions. This allows an implementation to do an initial
            allocation for an unbounded string and to avoid further
            allocations as long as the length does not exceed the allocated
            length.


                              Static Semantics

2   The library package Strings.Unbounded has the following declaration:

3       with Ada.Strings.Maps;
        package Ada.Strings.Unbounded is
           pragma Preelaborate(Unbounded);

4/2     {AI95-00161-01}    type Unbounded_String is private;
           pragma Preelaborable_Initialization(Unbounded_String);

5          Null_Unbounded_String : constant Unbounded_String;

6          function Length (Source : in Unbounded_String) return Natural;

7          type String_Access is access all String;
           procedure Free (X : in out String_Access);

8       -- Conversion, Concatenation, and Selection functions

9          function To_Unbounded_String (Source : in String)
              return Unbounded_String;

10         function To_Unbounded_String (Length : in Natural)
              return Unbounded_String;

11         function To_String (Source : in Unbounded_String) return String;

11.1/2  {AI95-00301-01}    procedure Set_Unbounded_String
             (Target :    out Unbounded_String;
              Source : in     String);

12         procedure Append (Source   : in out Unbounded_String;
                             New_Item : in Unbounded_String);

13         procedure Append (Source   : in out Unbounded_String;
                             New_Item : in String);

14         procedure Append (Source   : in out Unbounded_String;
                             New_Item : in Character);

15         function "&" (Left, Right : in Unbounded_String)
              return Unbounded_String;

16         function "&" (Left : in Unbounded_String; Right : in String)
              return Unbounded_String;

17         function "&" (Left : in String; Right : in Unbounded_String)
              return Unbounded_String;

18         function "&" (Left : in Unbounded_String; Right : in Character)
              return Unbounded_String;

19         function "&" (Left : in Character; Right : in Unbounded_String)
              return Unbounded_String;

20         function Element (Source : in Unbounded_String;
                             Index  : in Positive)
              return Character;

21         procedure Replace_Element (Source : in out Unbounded_String;
                                      Index  : in Positive;
                                      By     : in Character);

22         function Slice (Source : in Unbounded_String;
                           Low    : in Positive;
                           High   : in Natural)
              return String;

22.1/2  {AI95-00301-01}    function Unbounded_Slice
              (Source : in Unbounded_String;
               Low    : in Positive;
               High   : in Natural)
                  return Unbounded_String;

22.2/2  {AI95-00301-01}    procedure Unbounded_Slice
              (Source : in     Unbounded_String;
               Target :    out Unbounded_String;
               Low    : in     Positive;
               High   : in     Natural);

23         function "="  (Left, Right : in Unbounded_String) return Boolean;

24         function "="  (Left : in Unbounded_String; Right : in String)
             return Boolean;

25         function "="  (Left : in String; Right : in Unbounded_String)
             return Boolean;

26         function "<"  (Left, Right : in Unbounded_String) return Boolean;

27         function "<"  (Left : in Unbounded_String; Right : in String)
             return Boolean;

28         function "<"  (Left : in String; Right : in Unbounded_String)
             return Boolean;

29         function "<=" (Left, Right : in Unbounded_String) return Boolean;

30         function "<="  (Left : in Unbounded_String; Right : in String)
             return Boolean;

31         function "<="  (Left : in String; Right : in Unbounded_String)
             return Boolean;

32         function ">"  (Left, Right : in Unbounded_String) return Boolean;

33         function ">"  (Left : in Unbounded_String; Right : in String)
             return Boolean;

34         function ">"  (Left : in String; Right : in Unbounded_String)
             return Boolean;

35         function ">=" (Left, Right : in Unbounded_String) return Boolean;

36         function ">="  (Left : in Unbounded_String; Right : in String)
             return Boolean;

37         function ">="  (Left : in String; Right : in Unbounded_String)
             return Boolean;

38      -- Search subprograms

38.1/2  {AI95-00301-01}    function Index (Source  : in Unbounded_String;
                           Pattern : in String;
                           From    : in Positive;
                           Going   : in Direction := Forward;
                           Mapping : in Maps.Character_Mapping := Maps.Identity)
              return Natural;

38.2/2  {AI95-00301-01}    function Index (Source  : in Unbounded_String;
                           Pattern : in String;
                           From    : in Positive;
                           Going   : in Direction := Forward;
                           Mapping : in Maps.Character_Mapping_Function)
              return Natural;

39         function Index (Source   : in Unbounded_String;
                           Pattern  : in String;
                           Going    : in Direction := Forward;
                           Mapping  : in Maps.Character_Mapping
                                        := Maps.Identity)
              return Natural;

40         function Index (Source   : in Unbounded_String;
                           Pattern  : in String;
                           Going    : in Direction := Forward;
                           Mapping  : in Maps.Character_Mapping_Function)
              return Natural;

40.1/2  {AI95-00301-01}    function Index (Source  : in Unbounded_String;
                           Set     : in Maps.Character_Set;
                           From    : in Positive;
                           Test    : in Membership := Inside;
                           Going    : in Direction := Forward)
              return Natural;

41         function Index (Source : in Unbounded_String;
                           Set    : in Maps.Character_Set;
                           Test   : in Membership := Inside;
                           Going  : in Direction  := Forward) return Natural;

41.1/2  {AI95-00301-01}    function Index_Non_Blank
         (Source : in Unbounded_String;
                                     From   : in Positive;
                                     Going  : in Direction := Forward)
              return Natural;

42         function Index_Non_Blank (Source : in Unbounded_String;
                                     Going  : in Direction := Forward)
              return Natural;

43         function Count (Source   : in Unbounded_String;
                           Pattern  : in String;
                           Mapping  : in Maps.Character_Mapping
                                        := Maps.Identity)
              return Natural;

44         function Count (Source   : in Unbounded_String;
                           Pattern  : in String;
                           Mapping  : in Maps.Character_Mapping_Function)
              return Natural;

45         function Count (Source   : in Unbounded_String;
                           Set      : in Maps.Character_Set)
              return Natural;

45.1/3  {AI05-0031-1}    procedure Find_Token (Source : in Unbounded_String;
                                 Set    : in Maps.Character_Set;
                                 From   : in Positive;
                                 Test   : in Membership;
                                 First  : out Positive;
                                 Last   : out Natural);

46         procedure Find_Token (Source : in Unbounded_String;
                                 Set    : in Maps.Character_Set;
                                 Test   : in Membership;
                                 First  : out Positive;
                                 Last   : out Natural);

47      -- String translation subprograms

48         function Translate (Source  : in Unbounded_String;
                               Mapping : in Maps.Character_Mapping)
              return Unbounded_String;

49         procedure Translate (Source  : in out Unbounded_String;
                                Mapping : in Maps.Character_Mapping);

50         function Translate (Source  : in Unbounded_String;
                               Mapping : in Maps.Character_Mapping_Function)
              return Unbounded_String;

51         procedure Translate (Source  : in out Unbounded_String;
                                Mapping : in Maps.Character_Mapping_Function);

52      -- String transformation subprograms

53         function Replace_Slice (Source   : in Unbounded_String;
                                   Low      : in Positive;
                                   High     : in Natural;
                                   By       : in String)
              return Unbounded_String;

54         procedure Replace_Slice (Source   : in out Unbounded_String;
                                    Low      : in Positive;
                                    High     : in Natural;
                                    By       : in String);

55         function Insert (Source   : in Unbounded_String;
                            Before   : in Positive;
                            New_Item : in String)
              return Unbounded_String;

56         procedure Insert (Source   : in out Unbounded_String;
                             Before   : in Positive;
                             New_Item : in String);

57         function Overwrite (Source    : in Unbounded_String;
                               Position  : in Positive;
                               New_Item  : in String)
              return Unbounded_String;

58         procedure Overwrite (Source    : in out Unbounded_String;
                                Position  : in Positive;
                                New_Item  : in String);

59         function Delete (Source  : in Unbounded_String;
                            From    : in Positive;
                            Through : in Natural)
              return Unbounded_String;

60         procedure Delete (Source  : in out Unbounded_String;
                             From    : in Positive;
                             Through : in Natural);

61         function Trim (Source : in Unbounded_String;
                          Side   : in Trim_End)
              return Unbounded_String;

62         procedure Trim (Source : in out Unbounded_String;
                           Side   : in Trim_End);

63         function Trim (Source : in Unbounded_String;
                          Left   : in Maps.Character_Set;
                          Right  : in Maps.Character_Set)
              return Unbounded_String;

64         procedure Trim (Source : in out Unbounded_String;
                           Left   : in Maps.Character_Set;
                           Right  : in Maps.Character_Set);

65         function Head (Source : in Unbounded_String;
                          Count  : in Natural;
                          Pad    : in Character := Space)
              return Unbounded_String;

66         procedure Head (Source : in out Unbounded_String;
                           Count  : in Natural;
                           Pad    : in Character := Space);

67         function Tail (Source : in Unbounded_String;
                          Count  : in Natural;
                          Pad    : in Character := Space)
              return Unbounded_String;

68         procedure Tail (Source : in out Unbounded_String;
                           Count  : in Natural;
                           Pad    : in Character := Space);

69         function "*" (Left  : in Natural;
                         Right : in Character)
              return Unbounded_String;

70         function "*" (Left  : in Natural;
                         Right : in String)
              return Unbounded_String;

71         function "*" (Left  : in Natural;
                         Right : in Unbounded_String)
              return Unbounded_String;

72      private
           ... -- not specified by the language
        end Ada.Strings.Unbounded;

72.1/2 {AI95-00360-01} The type Unbounded_String needs finalization (see 7.6).

73  Null_Unbounded_String represents the null String. If an object of type
Unbounded_String is not otherwise initialized, it will be initialized to the
same value as Null_Unbounded_String.

74  The function Length returns the length of the String represented by Source.

75  The type String_Access provides a (nonprivate) access type for explicit
processing of unbounded-length strings. The procedure Free performs an
unchecked deallocation of an object of type String_Access.

76  The function To_Unbounded_String(Source : in String) returns an
Unbounded_String that represents Source. The function
To_Unbounded_String(Length : in Natural) returns an Unbounded_String that
represents an uninitialized String whose length is Length.

77  The function To_String returns the String with lower bound 1 represented
by Source. To_String and To_Unbounded_String are related as follows:

78    * If S is a String, then To_String(To_Unbounded_String(S)) = S.

79    * If U is an Unbounded_String, then To_Unbounded_String(To_String(U)) =
        U.

79.1/2 {AI95-00301-01} The procedure Set_Unbounded_String sets Target to an
Unbounded_String that represents Source.

80  For each of the Append procedures, the resulting string represented by the
Source parameter is given by the concatenation of the original value of Source
and the value of New_Item.

81  Each of the "&" functions returns an Unbounded_String obtained by
concatenating the string or character given or represented by one of the
parameters, with the string or character given or represented by the other
parameter, and applying To_Unbounded_String to the concatenation result string.

82  The Element, Replace_Element, and Slice subprograms have the same effect
as the corresponding bounded-length string subprograms.

82.1/3 {AI95-00301-01} {AI05-0262-1} The function Unbounded_Slice returns the
slice at positions Low through High in the string represented by Source as an
Unbounded_String. The procedure Unbounded_Slice sets Target to the
Unbounded_String representing the slice at positions Low through High in the
string represented by Source. Both subprograms propagate Index_Error if Low >
Length(Source)+1 or High > Length(Source).

83  Each of the functions "=", "<", ">", "<=", and ">=" returns the same
result as the corresponding String operation applied to the String values
given or represented by Left and Right.

84  Each of the search subprograms (Index, Index_Non_Blank, Count, Find_Token)
has the same effect as the corresponding subprogram in Strings.Fixed applied
to the string represented by the Unbounded_String parameter.

85  The Translate function has an analogous effect to the corresponding
subprogram in Strings.Fixed. The translation is applied to the string
represented by the Unbounded_String parameter, and the result is converted
(via To_Unbounded_String) to an Unbounded_String.

86  Each of the transformation functions (Replace_Slice, Insert, Overwrite,
Delete), selector functions (Trim, Head, Tail), and constructor functions
("*") is likewise analogous to its corresponding subprogram in Strings.Fixed.
For each of the subprograms, the corresponding fixed-length string subprogram
is applied to the string represented by the Unbounded_String parameter, and
To_Unbounded_String is applied the result string.

87  For each of the procedures Translate, Replace_Slice, Insert, Overwrite,
Delete, Trim, Head, and Tail, the resulting string represented by the Source
parameter is given by the corresponding function for fixed-length strings
applied to the string represented by Source's original value.


                         Implementation Requirements

88  No storage associated with an Unbounded_String object shall be lost upon
assignment or scope exit.

88.a/2      Implementation Note: {AI95-00301-01} A sample implementation of
            the private part of the package and several of the subprograms
            appears in the Ada 95 Rationale.


                        Incompatibilities With Ada 95

88.b/2      {AI95-00360-01} Amendment Correction: Type Unbounded_String is
            defined to need finalization. If the restriction
            No_Nested_Finalization (see D.7) applies to the partition, and
            Unbounded_String does not have a controlled part, it will not be
            allowed in local objects in Ada 2005 whereas it would be allowed
            in original Ada 95. Such code is not portable, as most Ada
            compilers have a controlled part in Unbounded_String, and thus
            would be illegal.

88.c/3      {AI95-00301-01} {AI05-0005-1} Procedure Set_Unbounded_String, two
            Unbounded_Slice subprograms, and overloaded versions of Index and
            Index_Non_Blank are added to Strings.Unbounded. If
            Strings.Unbounded is referenced in a use_clause, and an entity E
            with the same defining_identifier as a new entity in
            Strings.Unbounded is defined in a package that is also referenced
            in a use_clause, the entity E may no longer be use-visible,
            resulting in errors. This should be rare and is easily fixed if it
            does occur.


                            Extensions to Ada 95

88.d/2      {AI95-00161-01} Amendment Correction: Added a pragma
            Preelaborable_Initialization to type Unbounded_String, so that it
            can be used to declare default-initialized objects in
            preelaborated units.


                       Incompatibilities With Ada 2005

88.e/3      {AI05-0031-1} An overloaded version of Find_Token is added to
            Strings.Unbounded. If Strings.Unbounded is referenced in a
            use_clause, and an entity E with a defining_identifier of
            Find_Token is defined in a package that is also referenced in a
            use_clause, the entity E may no longer be use-visible, resulting
            in errors. This should be rare and is easily fixed if it does
            occur.


A.4.6 String-Handling Sets and Mappings


1   The language-defined package Strings.Maps.Constants declares Character_Set
and Character_Mapping constants corresponding to classification and conversion
functions in package Characters.Handling.

1.a         Discussion: The Constants package is a child of Strings.Maps since
            it needs visibility of the private part of Strings.Maps in order
            to initialize the constants in a preelaborable way (i.e. via
            aggregates versus function calls).


                              Static Semantics

2   The library package Strings.Maps.Constants has the following declaration:

3/2     {AI95-00362-01} package Ada.Strings.Maps.Constants is
           pragma Pure(Constants);

4          Control_Set           : constant Character_Set;
           Graphic_Set           : constant Character_Set;
           Letter_Set            : constant Character_Set;
           Lower_Set             : constant Character_Set;
           Upper_Set             : constant Character_Set;
           Basic_Set             : constant Character_Set;
           Decimal_Digit_Set     : constant Character_Set;
           Hexadecimal_Digit_Set : constant Character_Set;
           Alphanumeric_Set      : constant Character_Set;
           Special_Set           : constant Character_Set;
           ISO_646_Set           : constant Character_Set;

5          Lower_Case_Map        : constant Character_Mapping;
             --Maps to lower case for letters, else identity
           Upper_Case_Map        : constant Character_Mapping;
             --Maps to upper case for letters, else identity
           Basic_Map             : constant Character_Mapping;
             --Maps to basic letter for letters, else identity

6       private
           ... -- not specified by the language
        end Ada.Strings.Maps.Constants;

7   Each of these constants represents a correspondingly named set of
characters or character mapping in Characters.Handling (see A.3.2).

        NOTES

8/3     15  {AI05-0114-1} There are certain characters which are defined to be
        lower case letters by ISO 10646 and are therefore allowed in
        identifiers, but are not considered lower case letters by
        Ada.Strings.Maps.Constants.

8.a/3       Reason: This is to maintain runtime compatibility with the Ada 95
            definitions of these constants; existing correct programs could
            break if the definitions were changed in a way the programs did
            not anticipate.


                            Extensions to Ada 95

8.b/2       {AI95-00362-01} Strings.Maps.Constants is now Pure, so it can be
            used in pure units.


                        Wording Changes from Ada 2005

8.c/3       {AI05-0114-1} Correction: Added a note to clarify that these
            constants don't have any relationship to the characters allowed in
            identifiers.


A.4.7 Wide_String Handling


1/3 {AI95-00302-03} {AI05-0286-1} Facilities for handling strings of
Wide_Character elements are found in the packages Strings.Wide_Maps, Strings.-
Wide_Fixed, Strings.Wide_Bounded, Strings.Wide_Unbounded, and
Strings.Wide_Maps.Wide_Constants, and in the library functions Strings.-
Wide_Hash, Strings.Wide_Fixed.Wide_Hash, Strings.Wide_Bounded.Wide_Hash,
Strings.Wide_Unbounded.Wide_Hash, Strings.Wide_Hash_Case_Insensitive, Strings.-
Wide_Fixed.Wide_Hash_Case_Insensitive, Strings.Wide_Bounded.Wide_Hash_Case_-
Insensitive, Strings.Wide_Unbounded.Wide_Hash_Case_Insensitive, Strings.-
Wide_Equal_Case_Insensitive, Strings.Wide_Fixed.Wide_Equal_Case_Insensitive,
Strings.Wide_Bounded.Wide_Equal_Case_Insensitive, and
Strings.Wide_Unbounded.Wide_Equal_Case_Insensitive. They provide the same
string-handling operations as the corresponding packages and functions for
strings of Character elements.


                              Static Semantics

2   The package Strings.Wide_Maps has the following declaration.

3       package Ada.Strings.Wide_Maps is
           pragma Preelaborate(Wide_Maps);

4/2     {AI95-00161-01}
           -- Representation for a set of Wide_Character values:
           type Wide_Character_Set is private;
           pragma Preelaborable_Initialization(Wide_Character_Set);

5          Null_Set : constant Wide_Character_Set;

6          type Wide_Character_Range is
             record
                 Low  : Wide_Character;
                 High : Wide_Character;
             end record;
           -- Represents Wide_Character range Low..High

7          type Wide_Character_Ranges is array (Positive range <>)
              of Wide_Character_Range;

8          function To_Set    (Ranges : in Wide_Character_Ranges)
              return Wide_Character_Set;

9          function To_Set    (Span   : in Wide_Character_Range)
              return Wide_Character_Set;

10         function To_Ranges (Set    : in Wide_Character_Set)
              return Wide_Character_Ranges;

11         function "="   (Left, Right : in Wide_Character_Set) return Boolean;

12         function "not" (Right : in Wide_Character_Set)
              return Wide_Character_Set;
           function "and" (Left, Right : in Wide_Character_Set)
              return Wide_Character_Set;
           function "or"  (Left, Right : in Wide_Character_Set)
              return Wide_Character_Set;
           function "xor" (Left, Right : in Wide_Character_Set)
              return Wide_Character_Set;
           function "-"   (Left, Right : in Wide_Character_Set)
              return Wide_Character_Set;

13         function Is_In (Element : in Wide_Character;
                           Set     : in Wide_Character_Set)
              return Boolean;

14         function Is_Subset (Elements : in Wide_Character_Set;
                               Set      : in Wide_Character_Set)
              return Boolean;

15         function "<=" (Left  : in Wide_Character_Set;
                          Right : in Wide_Character_Set)
              return Boolean renames Is_Subset;

16         -- Alternative representation for a set of Wide_Character values:
           subtype Wide_Character_Sequence is Wide_String;

17         function To_Set (Sequence  : in Wide_Character_Sequence)
              return Wide_Character_Set;

18         function To_Set (Singleton : in Wide_Character)
              return Wide_Character_Set;

19         function To_Sequence (Set  : in Wide_Character_Set)
              return Wide_Character_Sequence;

20/2    {AI95-00161-01}
           -- Representation for a Wide_Character to Wide_Character mapping:
           type Wide_Character_Mapping is private;
           pragma Preelaborable_Initialization(Wide_Character_Mapping);

21         function Value (Map     : in Wide_Character_Mapping;
                           Element : in Wide_Character)
              return Wide_Character;

22         Identity : constant Wide_Character_Mapping;

23         function To_Mapping (From, To : in Wide_Character_Sequence)
              return Wide_Character_Mapping;

24         function To_Domain (Map : in Wide_Character_Mapping)
              return Wide_Character_Sequence;

25         function To_Range  (Map : in Wide_Character_Mapping)
              return Wide_Character_Sequence;

26         type Wide_Character_Mapping_Function is
              access function (From : in Wide_Character) return Wide_Character;

27      private
           ... -- not specified by the language
        end Ada.Strings.Wide_Maps;

28  The context clause for each of the packages Strings.Wide_Fixed,
Strings.Wide_Bounded, and Strings.Wide_Unbounded identifies Strings.Wide_Maps
instead of Strings.Maps.

28.1/3 {AI05-0223-1} Types Wide_Character_Set and Wide_Character_Mapping need
finalization.

29/3 {AI95-00302-03} {AI05-0286-1} For each of the packages Strings.Fixed,
Strings.Bounded, Strings.Unbounded, and Strings.Maps.Constants, and for
library functions Strings.Hash, Strings.Fixed.Hash, Strings.Bounded.Hash,
Strings.Unbounded.Hash, Strings.Hash_Case_Insensitive, Strings.Fixed.Hash_-
Case_Insensitive, Strings.Bounded.Hash_Case_Insensitive,
Strings.Unbounded.Hash_Case_Insensitive, Strings.Equal_Case_Insensitive,
Strings.Fixed.Equal_Case_Insensitive, Strings.Bounded.Equal_Case_Insensitive,
and Strings.Unbounded.Equal_Case_Insensitive, the corresponding wide string
package or function has the same contents except that

30    * Wide_Space replaces Space

31    * Wide_Character replaces Character

32    * Wide_String replaces String

33    * Wide_Character_Set replaces Character_Set

34    * Wide_Character_Mapping replaces Character_Mapping

35    * Wide_Character_Mapping_Function replaces Character_Mapping_Function

36    * Wide_Maps replaces Maps

37    * Bounded_Wide_String replaces Bounded_String

38    * Null_Bounded_Wide_String replaces Null_Bounded_String

39    * To_Bounded_Wide_String replaces To_Bounded_String

40    * To_Wide_String replaces To_String

40.1/2   * {AI95-00301-01} Set_Bounded_Wide_String replaces Set_Bounded_String

41    * Unbounded_Wide_String replaces Unbounded_String

42    * Null_Unbounded_Wide_String replaces Null_Unbounded_String

43    * Wide_String_Access replaces String_Access

44    * To_Unbounded_Wide_String replaces To_Unbounded_String

44.1/2   * {AI95-00301-01} Set_Unbounded_Wide_String replaces
        Set_Unbounded_String

45  The following additional declaration is present in
Strings.Wide_Maps.Wide_Constants:

46/2    {AI95-00285-01} {AI95-00395-01} Character_Set
         : constant Wide_Maps.Wide_Character_Set;
        --Contains each Wide_Character value WC such that
        --Characters.Conversions.Is_Character(WC) is True

46.1/2 {AI95-00395-01} Each Wide_Character_Set constant in the package
Strings.Wide_Maps.Wide_Constants contains no values outside the Character
portion of Wide_Character. Similarly, each Wide_Character_Mapping constant in
this package is the identity mapping when applied to any element outside the
Character portion of Wide_Character.

46.2/2 {AI95-00362-01} Pragma Pure is replaced by pragma Preelaborate in
Strings.Wide_Maps.Wide_Constants.

        NOTES

47      16  If a null Wide_Character_Mapping_Function is passed to any of the
        Wide_String handling subprograms, Constraint_Error is propagated.


                        Incompatibilities With Ada 95

48.a/2      {AI95-00301-01} Various new operations are added to
            Strings.Wide_Fixed, Strings.Wide_Bounded, and
            Strings.Wide_Unbounded. If one of these packages is referenced in
            a use_clause, and an entity E with the same defining_identifier as
            a new entity is defined in a package that is also referenced in a
            use_clause, the entity E may no longer be use-visible, resulting
            in errors. This should be rare and is easily fixed if it does
            occur.


                            Extensions to Ada 95

48.b/2      {AI95-00161-01} Amendment Correction: Added pragma
            Preelaborable_Initialization to types Wide_Character_Set and
            Wide_Character_Mapping, so that they can be used to declare
            default-initialized objects in preelaborated units.


                         Wording Changes from Ada 95

48.c/2      {AI95-00285-01} Corrected the description of Character_Set.

48.d/2      {AI95-00302-03} Added wide versions of Strings.Hash and
            Strings.Unbounded.Hash.

48.e/2      {AI95-00362-01} Added wording so that
            Strings.Wide_Maps.Wide_Constants does not change to Pure.

48.f/2      {AI95-00395-01} The second Note is now normative text, since there
            is no way to derive it from the other rules. It's a little weird
            given the use of Unicode character classifications in Ada 2005;
            but changing it would be inconsistent with Ada 95 and a one-to-one
            mapping isn't necessarily correct anyway.


                           Extensions to Ada 2005

48.g/3      {AI05-0286-1} The case insenstive library functions (Strings.Wide_-
            Equal_Case_Insensitive, Strings.Wide_Fixed.Wide_Equal_Case_-
            Insensitive, Strings.Wide_Bounded.Wide_Equal_Case_Insensitive,
            Strings.Wide_Unbounded.Wide_Equal_Case_Insensitive, Strings.Wide_-
            Hash_Case_Insensitive, Strings.Wide_Fixed.Wide_Hash_Case_Insensitive,
            Strings.Wide_Bounded.Wide_Hash_Case_Insensitive, and Strings.Wide_-
            Unbounded.Wide_Hash_Case_Insensitive) are new.


                        Wording Changes from Ada 2005

48.h/3      {AI05-0223-1} Correction: Identified Wide_Character_Set and
            Wide_Character_Mapping as needing finalization. It is likely that
            they are implemented with a controlled type, so this change is
            unlikely to make any difference in practice.


A.4.8 Wide_Wide_String Handling


1/3 {AI95-00285-01} {AI95-00395-01} {AI05-0286-1} Facilities for handling
strings of Wide_Wide_Character elements are found in the packages Strings.-
Wide_Wide_Maps, Strings.Wide_Wide_Fixed, Strings.Wide_Wide_Bounded, Strings.-
Wide_Wide_Unbounded, and Strings.Wide_Wide_Maps.Wide_Wide_Constants, and in
the library functions Strings.Wide_Wide_Hash,
Strings.Wide_Wide_Fixed.Wide_Wide_Hash, Strings.Wide_Wide_Bounded.Wide_-
Wide_Hash, Strings.Wide_Wide_Unbounded.Wide_Wide_Hash, Strings.Wide_Wide_-
Hash_Case_Insensitive, Strings.Wide_Wide_Fixed.Wide_Wide_Hash_Case_Insensitive,
Strings.Wide_Wide_Bounded.Wide_Wide_Hash_Case_Insensitive, Strings.Wide_Wide_-
Unbounded.Wide_Wide_Hash_Case_Insensitive, Strings.Wide_Wide_Equal_Case_-
Insensitive, Strings.Wide_Wide_Fixed.Wide_Wide_Equal_Case_Insensitive, Strings.-
Wide_Wide_Bounded.Wide_Wide_Equal_Case_Insensitive, and Strings.Wide_Wide_-
Unbounded.Wide_Wide_Equal_Case_Insensitive. They provide the same
string-handling operations as the corresponding packages and functions for
strings of Character elements.


                              Static Semantics

2/2 {AI95-00285-01} The library package Strings.Wide_Wide_Maps has the
following declaration.

3/2     package Ada.Strings.Wide_Wide_Maps is
           pragma Preelaborate(Wide_Wide_Maps);

4/2        -- Representation for a set of Wide_Wide_Character values:
           type Wide_Wide_Character_Set is private;
           pragma Preelaborable_Initialization(Wide_Wide_Character_Set);

5/2        Null_Set : constant Wide_Wide_Character_Set;

6/2        type Wide_Wide_Character_Range is
              record
                 Low  : Wide_Wide_Character;
                 High : Wide_Wide_Character;
              end record;
           -- Represents Wide_Wide_Character range Low..High

7/2        type Wide_Wide_Character_Ranges is array (Positive range <>)
                 of Wide_Wide_Character_Range;

8/2        function To_Set (Ranges : in Wide_Wide_Character_Ranges)
                 return Wide_Wide_Character_Set;

9/2        function To_Set (Span : in Wide_Wide_Character_Range)
                 return Wide_Wide_Character_Set;

10/2       function To_Ranges (Set : in Wide_Wide_Character_Set)
                 return Wide_Wide_Character_Ranges;

11/2       function "=" (Left, Right : in Wide_Wide_Character_Set) return Boolean;

12/2       function "not" (Right : in Wide_Wide_Character_Set)
                 return Wide_Wide_Character_Set;
           function "and" (Left, Right : in Wide_Wide_Character_Set)
                 return Wide_Wide_Character_Set;
           function "or" (Left, Right : in Wide_Wide_Character_Set)
                 return Wide_Wide_Character_Set;
           function "xor" (Left, Right : in Wide_Wide_Character_Set)
                 return Wide_Wide_Character_Set;
           function "-" (Left, Right : in Wide_Wide_Character_Set)
                 return Wide_Wide_Character_Set;

13/2       function Is_In (Element : in Wide_Wide_Character;
                           Set     : in Wide_Wide_Character_Set)
                 return Boolean;

14/2       function Is_Subset (Elements : in Wide_Wide_Character_Set;
                               Set      : in Wide_Wide_Character_Set)
                 return Boolean;

15/2       function "<=" (Left  : in Wide_Wide_Character_Set;
                          Right : in Wide_Wide_Character_Set)
                 return Boolean renames Is_Subset;

16/2       -- Alternative representation for a set of Wide_Wide_Character values:
           subtype Wide_Wide_Character_Sequence is Wide_Wide_String;

17/2       function To_Set (Sequence : in Wide_Wide_Character_Sequence)
                 return Wide_Wide_Character_Set;

18/2       function To_Set (Singleton : in Wide_Wide_Character)
                 return Wide_Wide_Character_Set;

19/2       function To_Sequence (Set : in Wide_Wide_Character_Set)
                 return Wide_Wide_Character_Sequence;

20/2       -- Representation for a Wide_Wide_Character to Wide_Wide_Character
           -- mapping:
           type Wide_Wide_Character_Mapping is private;
           pragma Preelaborable_Initialization(Wide_Wide_Character_Mapping);

21/2       function Value (Map     : in Wide_Wide_Character_Mapping;
                           Element : in Wide_Wide_Character)
                 return Wide_Wide_Character;

22/2       Identity : constant Wide_Wide_Character_Mapping;

23/2       function To_Mapping (From, To : in Wide_Wide_Character_Sequence)
                 return Wide_Wide_Character_Mapping;

24/2       function To_Domain (Map : in Wide_Wide_Character_Mapping)
                 return Wide_Wide_Character_Sequence;

25/2       function To_Range (Map : in Wide_Wide_Character_Mapping)
                 return Wide_Wide_Character_Sequence;

26/2       type Wide_Wide_Character_Mapping_Function is
                 access function (From : in Wide_Wide_Character)
                 return Wide_Wide_Character;

27/2    private
           ... -- not specified by the language
        end Ada.Strings.Wide_Wide_Maps;

28/2 {AI95-00285-01} The context clause for each of the packages
Strings.Wide_Wide_Fixed, Strings.Wide_Wide_Bounded, and
Strings.Wide_Wide_Unbounded identifies Strings.Wide_Wide_Maps instead of
Strings.Maps.

28.1/3 {AI05-0223-1} Types Wide_Wide_Character_Set and
Wide_Wide_Character_Mapping need finalization.

29/3 {AI95-00285-01} {AI05-0286-1} For each of the packages Strings.Fixed,
Strings.Bounded, Strings.Unbounded, and Strings.Maps.Constants, and for
library functions Strings.Hash, Strings.Fixed.Hash, Strings.Bounded.Hash,
Strings.Unbounded.Hash, Strings.Hash_Case_Insensitive, Strings.Fixed.Hash_-
Case_Insensitive, Strings.Bounded.Hash_Case_Insensitive,
Strings.Unbounded.Hash_Case_Insensitive, Strings.Equal_Case_Insensitive,
Strings.Fixed.Equal_Case_Insensitive, Strings.Bounded.Equal_Case_Insensitive,
and Strings.Unbounded.Equal_Case_Insensitive, the corresponding wide wide
string package or function has the same contents except that

30/2   * Wide_Wide_Space replaces Space

31/2   * Wide_Wide_Character replaces Character

32/2   * Wide_Wide_String replaces String

33/2   * Wide_Wide_Character_Set replaces Character_Set

34/2   * Wide_Wide_Character_Mapping replaces Character_Mapping

35/2   * Wide_Wide_Character_Mapping_Function replaces
        Character_Mapping_Function

36/2   * Wide_Wide_Maps replaces Maps

37/2   * Bounded_Wide_Wide_String replaces Bounded_String

38/2   * Null_Bounded_Wide_Wide_String replaces Null_Bounded_String

39/2   * To_Bounded_Wide_Wide_String replaces To_Bounded_String

40/2   * To_Wide_Wide_String replaces To_String

41/2   * {AI95-00301-01} Set_Bounded_Wide_Wide_String replaces
        Set_Bounded_String

42/2   * Unbounded_Wide_Wide_String replaces Unbounded_String

43/2   * Null_Unbounded_Wide_Wide_String replaces Null_Unbounded_String

44/2   * Wide_Wide_String_Access replaces String_Access

45/2   * To_Unbounded_Wide_Wide_String replaces To_Unbounded_String

46/2   * {AI95-00301-01} Set_Unbounded_Wide_Wide_String replaces
        Set_Unbounded_String

47/2 {AI95-00285-01} {AI95-00395-01} The following additional declarations are
present in Strings.Wide_Wide_Maps.Wide_Wide_Constants:

48/2    Character_Set : constant Wide_Wide_Maps.Wide_Wide_Character_Set;
        -- Contains each Wide_Wide_Character value WWC such that
        -- Characters.Conversions.Is_Character(WWC) is True
        Wide_Character_Set : constant Wide_Wide_Maps.Wide_Wide_Character_Set;
        -- Contains each Wide_Wide_Character value WWC such that
        -- Characters.Conversions.Is_Wide_Character(WWC) is True

49/2 {AI95-00395-01} Each Wide_Wide_Character_Set constant in the package
Strings.Wide_Wide_Maps.Wide_Wide_Constants contains no values outside the
Character portion of Wide_Wide_Character. Similarly, each Wide_Wide_Character_-
Mapping constant in this package is the identity mapping when applied to any
element outside the Character portion of Wide_Wide_Character.

50/2 {AI95-00395-01} Pragma Pure is replaced by pragma Preelaborate in
Strings.Wide_Wide_Maps.Wide_Wide_Constants.

        NOTES

51/2    17  {AI95-00285-01} If a null Wide_Wide_Character_Mapping_Function is
        passed to any of the Wide_Wide_String handling subprograms,
        Constraint_Error is propagated.


                            Extensions to Ada 95

51.a/2      {AI95-00285-01} {AI95-00395-01} The double-wide string-handling
            packages (Strings.Wide_Wide_Maps, Strings.Wide_Wide_Fixed,
            Strings.Wide_Wide_Bounded, Strings.Wide_Wide_Unbounded, and
            Strings.Wide_Wide_Maps.Wide_Wide_Constants), and functions
            Strings.Wide_Wide_Hash and
            Strings.Wide_Wide_Unbounded.Wide_Wide_Hash are new.


                           Extensions to Ada 2005

51.b/3      {AI05-0286-1} The case insenstive library functions
            (Strings.Wide_Wide_Equal_Case_Insensitive, Strings.Wide_Wide_-
            Fixed.Wide_Wide_Equal_Case_Insensitive, Strings.Wide_Wide_Bounded.Wide_Wide_-
            Equal_Case_Insensitive, Strings.Wide_Wide_Unbounded.Wide_Wide_-
            Equal_Case_Insensitive, Strings.Wide_Wide_Hash_Case_Insensitive,
            Strings.Wide_Wide_Fixed.Wide_Wide_Hash_Case_Insensitive, Strings.Wide_Wide_-
            Bounded.Wide_Wide_Hash_Case_Insensitive, and Strings.Wide_Wide_-
            Unbounded.Wide_Wide_Hash_Case_Insensitive) are new.


                        Wording Changes from Ada 2005

51.c/3      {AI05-0223-1} Correction: Identified Wide_Wide_Character_Set and
            Wide_Wide_Character_Mapping as needing finalization. It is likely
            that they are implemented with a controlled type, so this change
            is unlikely to make any difference in practice.


A.4.9 String Hashing



                              Static Semantics

1/2 {AI95-00302-03} The library function Strings.Hash has the following
declaration:

2/3     {AI05-0298-1} with Ada.Containers;
        function Ada.Strings.Hash (Key : String) return Containers.Hash_Type;
        pragma Pure(Ada.Strings.Hash);

3/2         Returns an implementation-defined value which is a function of the
            value of Key. If A and B are strings such that A equals B, Hash(A)
            equals Hash(B).

3.a/2       Implementation defined: The values returned by Strings.Hash.

4/2 {AI95-00302-03} The library function Strings.Fixed.Hash has the following
declaration:

5/3     {AI05-0298-1} with Ada.Containers, Ada.Strings.Hash;
        function Ada.Strings.Fixed.Hash (Key : String) return Containers.Hash_Type
           renames Ada.Strings.Hash;

6/2 {AI95-00302-03} The generic library function Strings.Bounded.Hash has the
following declaration:

7/3     {AI05-0298-1} with Ada.Containers;
        generic
           with package Bounded is
              new Ada.Strings.Bounded.Generic_Bounded_Length (<>);
        function Ada.Strings.Bounded.Hash (Key : Bounded.Bounded_String)
           return Containers.Hash_Type;
        pragma Preelaborate(Ada.Strings.Bounded.Hash);

8/3         {AI05-0001-1} Equivalent to Strings.Hash (Bounded.To_String (Key));

9/2 {AI95-00302-03} The library function Strings.Unbounded.Hash has the
following declaration:

10/3    {AI05-0298-1} with Ada.Containers;
        function Ada.Strings.Unbounded.Hash (Key : Unbounded_String)
           return Containers.Hash_Type;
        pragma Preelaborate(Ada.Strings.Unbounded.Hash);

11/3        {AI05-0001-1} Equivalent to Strings.Hash (To_String (Key));

11.1/3 {AI05-0001-1} {AI05-0298-1} The library function
Strings.Hash_Case_Insensitive has the following declaration:

11.2/3  with Ada.Containers;
        function Ada.Strings.Hash_Case_Insensitive (Key : String)
           return Containers.Hash_Type;
        pragma Pure(Ada.Strings.Hash_Case_Insensitive);

11.3/3      Returns an implementation-defined value which is a function of the
            value of Key, converted to lower case. If A and B are strings such
            that Strings.Equal_Case_Insensitive (A, B) (see A.4.10) is True,
            then Hash_Case_Insensitive(A) equals Hash_Case_Insensitive(B).

11.4/3 {AI05-0001-1} {AI05-0298-1} The library function
Strings.Fixed.Hash_Case_Insensitive has the following declaration:

11.5/3  with Ada.Containers, Ada.Strings.Hash_Case_Insensitive;
        function Ada.Strings.Fixed.Hash_Case_Insensitive (Key : String)
           return Containers.Hash_Type renames Ada.Strings.Hash_Case_Insensitive;

11.6/3 {AI05-0001-1} {AI05-0298-1} The generic library function
Strings.Bounded.Hash_Case_Insensitive has the following declaration:

11.7/3  with Ada.Containers;
        generic
           with package Bounded is
              new Ada.Strings.Bounded.Generic_Bounded_Length (<>);
        function Ada.Strings.Bounded.Hash_Case_Insensitive
           (Key : Bounded.Bounded_String) return Containers.Hash_Type;
        pragma Preelaborate(Ada.Strings.Bounded.Hash_Case_Insensitive);

11.8/3      Equivalent to Strings.Hash_Case_Insensitive (Bounded.To_String
            (Key));

11.9/3 {AI05-0001-1} {AI05-0298-1} The library function
Strings.Unbounded.Hash_Case_Insensitive has the following declaration:

11.10/3 with Ada.Containers;
        function Ada.Strings.Unbounded.Hash_Case_Insensitive
           (Key : Unbounded_String) return Containers.Hash_Type;
        pragma Preelaborate(Ada.Strings.Unbounded.Hash_Case_Insensitive);

11.11/3     Equivalent to Strings.Hash_Case_Insensitive (To_String (Key));


                            Implementation Advice

12/2 {AI95-00302-03} The Hash functions should be good hash functions,
returning a wide spread of values for different string values. It should be
unlikely for similar strings to return the same value.

12.a/2      Implementation Advice: Strings.Hash should be good a hash
            function, returning a wide spread of values for different string
            values, and similar strings should rarely return the same value.

12.b/2      Ramification: The other functions are defined in terms of
            Strings.Hash, so they don't need separate advice in the Annex.


                            Extensions to Ada 95

12.c/2      {AI95-00302-03} The Strings.Hash, Strings.Fixed.Hash,
            Strings.Bounded.Hash, and Strings.Unbounded.Hash functions are
            new.


                           Extensions to Ada 2005

12.d/3      {AI05-0001-1} The Strings.Hash_Case_Insensitive,
            Strings.Fixed.Hash_Case_Insensitive, Strings.Bounded.Hash_Case_Insensitive,
            and Strings.Unbounded.Hash_Case_Insensitive functions are new.


A.4.10 String Comparison



                              Static Semantics

1/3 {AI05-0001-1} {AI05-0286-1} {AI05-0298-1} The library function
Strings.Equal_Case_Insensitive has the following declaration:

2/3     function Ada.Strings.Equal_Case_Insensitive (Left, Right : String)
           return Boolean;
        pragma Pure(Ada.Strings.Equal_Case_Insensitive);

3/3         Returns True if the strings consist of the same sequence of
            characters after applying locale-independent simple case folding,
            as defined by documents referenced in the note in Clause 1 of
            ISO/IEC 10646:2011. Otherwise, returns False. This function uses
            the same method as is used to determine whether two identifiers
            are the same.

3.a/3       Discussion: {AI05-0286-1} For String, this is equivalent to
            converting to lower case and comparing. Not so for other string
            types. For Wide_Strings and Wide_Wide_Strings, note that this
            result is a more accurate comparison than converting the strings
            to lower case and comparing the results; it is possible that the
            lower case conversions are the same but this routine will report
            the strings as different. Additionally, Unicode says that the
            result of this function will never change for strings made up
            solely of defined code points; there is no such guarantee for case
            conversion to lower case.

4/3 {AI05-0001-1} {AI05-0248-1} {AI05-0298-1} The library function
Strings.Fixed.Equal_Case_Insensitive has the following declaration:

5/3     with Ada.Strings.Equal_Case_Insensitive;
        function Ada.Strings.Fixed.Equal_Case_Insensitive
           (Left, Right : String) return Boolean
              renames Ada.Strings.Equal_Case_Insensitive;

6/3 {AI05-0001-1} {AI05-0248-1} {AI05-0298-1} The generic library function
Strings.Bounded.Equal_Case_Insensitive has the following declaration:

7/3     generic
           with package Bounded is
              new Ada.Strings.Bounded.Generic_Bounded_Length (<>);
        function Ada.Strings.Bounded.Equal_Case_Insensitive
           (Left, Right : Bounded.Bounded_String) return Boolean;
        pragma Preelaborate(Ada.Strings.Bounded.Equal_Case_Insensitive);

8/3         Equivalent to Strings.Equal_Case_Insensitive (Bounded.To_String
            (Left), Bounded.To_String (Right));

9/3 {AI05-0001-1} {AI05-0248-1} {AI05-0298-1} The library function
Strings.Unbounded.Equal_Case_Insensitive has the following declaration:

10/3    function Ada.Strings.Unbounded.Equal_Case_Insensitive
           (Left, Right : Unbounded_String) return Boolean;
        pragma Preelaborate(Ada.Strings.Unbounded.Equal_Case_Insensitive);

11/3        Equivalent to Strings.Equal_Case_Insensitive (To_String (Left),
            To_String (Right));

12/3 {AI05-0001-1} {AI05-0298-1} The library function
Strings.Less_Case_Insensitive has the following declaration:

13/3    function Ada.Strings.Less_Case_Insensitive (Left, Right : String)
           return Boolean;
        pragma Pure(Ada.Strings.Less_Case_Insensitive);

14/3        Performs a lexicographic comparison of strings Left and Right,
            converted to lower case.

15/3 {AI05-0001-1} {AI05-0248-1} {AI05-0298-1} The library function
Strings.Fixed.Less_Case_Insensitive has the following declaration:

16/3    with Ada.Strings.Less_Case_Insensitive;
        function Ada.Strings.Fixed.Less_Case_Insensitive
           (Left, Right : String) return Boolean
              renames Ada.Strings.Less_Case_Insensitive;

17/3 {AI05-0001-1} {AI05-0248-1} {AI05-0298-1} The generic library function
Strings.Bounded.Less_Case_Insensitive has the following declaration:

18/3    generic
           with package Bounded is
              new Ada.Strings.Bounded.Generic_Bounded_Length (<>);
        function Ada.Strings.Bounded.Less_Case_Insensitive
          (Left, Right : Bounded.Bounded_String) return Boolean;
        pragma Preelaborate(Ada.Strings.Bounded.Less_Case_Insensitive);

19/3        Equivalent to Strings.Less_Case_Insensitive (Bounded.To_String
            (Left), Bounded.To_String (Right));

20/3 {AI05-0001-1} {AI05-0248-1} {AI05-0298-1} The library function
Strings.Unbounded.Less_Case_Insensitive has the following declaration:

21/3    function Ada.Strings.Unbounded.Less_Case_Insensitive
          (Left, Right : Unbounded_String) return Boolean;
        pragma Preelaborate(Ada.Strings.Unbounded.Less_Case_Insensitive);

22/3        Equivalent to Strings.Less_Case_Insensitive (To_String (Left),
            To_String (Right));


                           Extensions to Ada 2005

22.a/3      {AI05-0001-1} {AI05-0286-1} The Strings.Equal_Case_Insensitive,
            Strings.Fixed.Equal_Case_Insensitive, Strings.Bounded.Equal_Case_Insensitive,
            Strings.Unbounded.Equal_Case_Insensitive, Strings.Less_Case_Insensitive,
            Strings.Fixed.Less_Case_Insensitive, Strings.Bounded.Less_Case_Insensitive,
            Strings.Unbounded.Less_Case_Insensitive functions are new.


A.4.11 String Encoding


1/3 {AI05-0137-2} Facilities for encoding, decoding, and converting strings in
various character encoding schemes are provided by packages
Strings.UTF_Encoding, Strings.UTF_Encoding.Conversions, Strings.UTF_Encoding.-
Strings, Strings.UTF_Encoding.Wide_Strings, and
Strings.UTF_Encoding.Wide_Wide_Strings.


                              Static Semantics

2/3 {AI05-0137-2} The encoding library packages have the following
declarations:

3/3     {AI05-0137-2} package Ada.Strings.UTF_Encoding is
           pragma Pure (UTF_Encoding);

4/3        -- Declarations common to the string encoding packages
           type Encoding_Scheme is (UTF_8, UTF_16BE, UTF_16LE);

5/3        subtype UTF_String is String;

6/3        subtype UTF_8_String is String;

7/3        subtype UTF_16_Wide_String is Wide_String;

8/3        Encoding_Error : exception;

9/3        BOM_8    : constant UTF_8_String :=
                        Character'Val(16#EF#) &
                        Character'Val(16#BB#) &
                        Character'Val(16#BF#);

10/3       BOM_16BE : constant UTF_String :=
                        Character'Val(16#FE#) &
                        Character'Val(16#FF#);

11/3       BOM_16LE : constant UTF_String :=
                        Character'Val(16#FF#) &
                        Character'Val(16#FE#);

12/3       BOM_16   : constant UTF_16_Wide_String :=
                       (1 => Wide_Character'Val(16#FEFF#));

13/3       function Encoding (Item    : UTF_String;
                              Default : Encoding_Scheme := UTF_8)
              return Encoding_Scheme;

14/3    end Ada.Strings.UTF_Encoding;

15/3    {AI05-0137-2} package Ada.Strings.UTF_Encoding.Conversions is
           pragma Pure (Conversions);

16/3       -- Conversions between various encoding schemes
           function Convert (Item          : UTF_String;
                             Input_Scheme  : Encoding_Scheme;
                             Output_Scheme : Encoding_Scheme;
                             Output_BOM    : Boolean := False) return UTF_String;

17/3       function Convert (Item          : UTF_String;
                             Input_Scheme  : Encoding_Scheme;
                             Output_BOM    : Boolean := False)
              return UTF_16_Wide_String;

18/3       function Convert (Item          : UTF_8_String;
                             Output_BOM    : Boolean := False)
              return UTF_16_Wide_String;

19/3       function Convert (Item          : UTF_16_Wide_String;
                             Output_Scheme : Encoding_Scheme;
                             Output_BOM    : Boolean := False) return UTF_String;

20/3       function Convert (Item          : UTF_16_Wide_String;
                             Output_BOM    : Boolean := False) return UTF_8_String;

21/3    end Ada.Strings.UTF_Encoding.Conversions;

22/3    {AI05-0137-2} package Ada.Strings.UTF_Encoding.Strings is
           pragma Pure (Strings);

23/3       -- Encoding / decoding between String and various encoding schemes
           function Encode (Item          : String;
                            Output_Scheme : Encoding_Scheme;
                            Output_BOM    : Boolean  := False) return UTF_String;

24/3       function Encode (Item       : String;
                            Output_BOM : Boolean  := False) return UTF_8_String;

25/3       function Encode (Item       : String;
                            Output_BOM : Boolean  := False)
              return UTF_16_Wide_String;

26/3       function Decode (Item         : UTF_String;
                            Input_Scheme : Encoding_Scheme) return String;

27/3       function Decode (Item : UTF_8_String) return String;

28/3       function Decode (Item : UTF_16_Wide_String) return String;

29/3    end Ada.Strings.UTF_Encoding.Strings;

30/3    {AI05-0137-2} package Ada.Strings.UTF_Encoding.Wide_Strings is
           pragma Pure (Wide_Strings);

31/3       -- Encoding / decoding between Wide_String and various encoding schemes
           function Encode (Item          : Wide_String;
                            Output_Scheme : Encoding_Scheme;
                            Output_BOM    : Boolean  := False) return UTF_String;

32/3       function Encode (Item       : Wide_String;
                            Output_BOM : Boolean  := False) return UTF_8_String;

33/3       function Encode (Item       : Wide_String;
                            Output_BOM : Boolean  := False)
              return UTF_16_Wide_String;

34/3       function Decode (Item         : UTF_String;
                            Input_Scheme : Encoding_Scheme) return Wide_String;

35/3       function Decode (Item : UTF_8_String) return Wide_String;

36/3       function Decode (Item : UTF_16_Wide_String) return Wide_String;

37/3    end Ada.Strings.UTF_Encoding.Wide_Strings;

38/3    {AI05-0137-2} package Ada.Strings.UTF_Encoding.Wide_Wide_Strings is
           pragma Pure (Wide_Wide_Strings);

39/3       -- Encoding / decoding between Wide_Wide_String and various encoding schemes
           function Encode (Item          : Wide_Wide_String;
                            Output_Scheme : Encoding_Scheme;
                            Output_BOM    : Boolean  := False) return UTF_String;

40/3       function Encode (Item       : Wide_Wide_String;
                            Output_BOM : Boolean  := False) return UTF_8_String;

41/3       function Encode (Item       : Wide_Wide_String;
                            Output_BOM : Boolean  := False)
              return UTF_16_Wide_String;

42/3       function Decode (Item         : UTF_String;
                            Input_Scheme : Encoding_Scheme) return Wide_Wide_String;

43/3       function Decode (Item : UTF_8_String) return Wide_Wide_String;

44/3       function Decode
         (Item : UTF_16_Wide_String) return Wide_Wide_String;

45/3    end Ada.Strings.UTF_Encoding.Wide_Wide_Strings;

46/3 {AI05-0137-2} {AI05-0262-1} The type Encoding_Scheme defines encoding
schemes. UTF_8 corresponds to the UTF-8 encoding scheme defined by Annex D of
ISO/IEC 10646. UTF_16BE corresponds to the UTF-16 encoding scheme defined by
Annex C of ISO/IEC 10646 in 8 bit, big-endian order; and UTF_16LE corresponds
to the UTF-16 encoding scheme in 8 bit, little-endian order.

47/3 {AI05-0137-2} The subtype UTF_String is used to represent a String of
8-bit values containing a sequence of values encoded in one of three ways
(UTF-8, UTF-16BE, or UTF-16LE). The subtype UTF_8_String is used to represent
a String of 8-bit values containing a sequence of values encoded in UTF-8. The
subtype UTF_16_Wide_String is used to represent a Wide_String of 16-bit values
containing a sequence of values encoded in UTF-16.

48/3 {AI05-0137-2} {AI05-0262-1} The BOM_8, BOM_16BE, BOM_16LE, and BOM_16
constants correspond to values used at the start of a string to indicate the
encoding.

49/3 {AI05-0262-1} {AI05-0269-1} Each of the Encode functions takes a String,
Wide_String, or Wide_Wide_String Item parameter that is assumed to be an array
of unencoded characters. Each of the Convert functions takes a UTF_String,
UTF_8_String, or UTF_16_String Item parameter that is assumed to contain
characters whose position values correspond to a valid encoding sequence
according to the encoding scheme required by the function or specified by its
Input_Scheme parameter.

50/3 {AI05-0137-2} {AI05-0262-1} {AI05-0269-1} Each of the Convert and Encode
functions returns a UTF_String, UTF_8_String, or UTF_16_String value whose
characters have position values that correspond to the encoding of the Item
parameter according to the encoding scheme required by the function or
specified by its Output_Scheme parameter. For UTF_8, no overlong encoding is
returned. A BOM is included at the start of the returned string if the
Output_BOM parameter is set to True. The lower bound of the returned string is
1.

51/3 {AI05-0137-2} {AI05-0262-1} Each of the Decode functions takes a
UTF_String, UTF_8_String, or UTF_16_String Item parameter which is assumed to
contain characters whose position values correspond to a valid encoding
sequence according to the encoding scheme required by the function or
specified by its Input_Scheme parameter, and returns the corresponding String,
Wide_String, or Wide_Wide_String value. The lower bound of the returned string
is 1.

52/3 {AI05-0137-2} {AI05-0262-1} For each of the Convert and Decode functions,
an initial BOM in the input that matches the expected encoding scheme is
ignored, and a different initial BOM causes Encoding_Error to be propagated.

53/3 {AI05-0137-2} The exception Encoding_Error is also propagated in the
following situations:

54/4   * {AI12-0088-1} By a Convert or Decode function when a UTF encoded
        string contains an invalid encoding sequence.

54.a/4      To be honest: {AI12-0088-1} An overlong encoding is not invalid
            for the purposes of this check, and this does not depend on the
            character set version in use. Some recent character set standards
            declare overlong encodings to be invalid; it would be unnecessary
            and unfriendly to users for Convert or Decode to raise an
            exception for an overlong encoding.

55/4   * {AI12-0088-1} By a Convert or Decode function when the expected
        encoding is UTF-16BE or UTF-16LE and the input string has an odd
        length.

56/3   * {AI05-0262-1} By a Decode function yielding a String when the
        decoding of a sequence results in a code point whose value exceeds
        16#FF#.

57/3   * By a Decode function yielding a Wide_String when the decoding of a
        sequence results in a code point whose value exceeds 16#FFFF#.

58/3   * {AI05-0262-1} By an Encode function taking a Wide_String as input
        when an invalid character appears in the input. In particular, the
        characters whose position is in the range 16#D800# .. 16#DFFF# are
        invalid because they conflict with UTF-16 surrogate encodings, and the
        characters whose position is 16#FFFE# or 16#FFFF# are also invalid
        because they conflict with BOM codes.

59/3    {AI05-0137-2} function Encoding (Item    : UTF_String;
                           Default : Encoding_Scheme := UTF_8)
           return Encoding_Scheme;

60/3        {AI05-0137-2} {AI05-0269-1} Inspects a UTF_String value to
            determine whether it starts with a BOM for UTF-8, UTF-16BE, or
            UTF_16LE. If so, returns the scheme corresponding to the BOM;
            otherwise, returns the value of Default.

61/3    {AI05-0137-2} function Convert (Item          : UTF_String;
                          Input_Scheme  : Encoding_Scheme;
                          Output_Scheme : Encoding_Scheme;
                          Output_BOM    : Boolean := False) return UTF_String;

62/3        Returns the value of Item (originally encoded in UTF-8, UTF-16LE,
            or UTF-16BE as specified by Input_Scheme) encoded in one of these
            three schemes as specified by Output_Scheme.

63/3    {AI05-0137-2} function Convert (Item          : UTF_String;
                          Input_Scheme  : Encoding_Scheme;
                          Output_BOM    : Boolean := False)
           return UTF_16_Wide_String;

64/3        Returns the value of Item (originally encoded in UTF-8, UTF-16LE,
            or UTF-16BE as specified by Input_Scheme) encoded in UTF-16.

65/3    {AI05-0137-2} function Convert (Item          : UTF_8_String;
                          Output_BOM    : Boolean := False)
           return UTF_16_Wide_String;

66/3        Returns the value of Item (originally encoded in UTF-8) encoded in
            UTF-16.

67/3    {AI05-0137-2} function Convert (Item          : UTF_16_Wide_String;
                          Output_Scheme : Encoding_Scheme;
                          Output_BOM    : Boolean := False) return UTF_String;

68/3        Returns the value of Item (originally encoded in UTF-16) encoded
            in UTF-8, UTF-16LE, or UTF-16BE as specified by Output_Scheme.

69/3    {AI05-0137-2} function Convert (Item          : UTF_16_Wide_String;
                          Output_BOM    : Boolean := False) return UTF_8_String;

70/3        Returns the value of Item (originally encoded in UTF-16) encoded
            in UTF-8.

71/3    {AI05-0137-2} function Encode (Item          : String;
                         Output_Scheme : Encoding_Scheme;
                         Output_BOM    : Boolean  := False) return UTF_String;

72/3        {AI05-0262-1} Returns the value of Item encoded in UTF-8,
            UTF-16LE, or UTF-16BE as specified by Output_Scheme.

73/3    {AI05-0137-2} function Encode (Item       : String;
                         Output_BOM : Boolean  := False) return UTF_8_String;

74/3        Returns the value of Item encoded in UTF-8.

75/3    {AI05-0137-2} function Encode (Item       : String;
                         Output_BOM : Boolean  := False) return UTF_16_Wide_String;

76/3        Returns the value of Item encoded in UTF_16.

77/3    {AI05-0137-2} function Decode (Item         : UTF_String;
                         Input_Scheme : Encoding_Scheme) return String;

78/3        Returns the result of decoding Item, which is encoded in UTF-8,
            UTF-16LE, or UTF-16BE as specified by Input_Scheme.

79/3    {AI05-0137-2} function Decode (Item : UTF_8_String) return String;

80/3        Returns the result of decoding Item, which is encoded in UTF-8.

81/3    {AI05-0137-2}
        function Decode (Item : UTF_16_Wide_String) return String;

82/3        Returns the result of decoding Item, which is encoded in UTF-16.

83/3    {AI05-0137-2} function Encode (Item          : Wide_String;
                         Output_Scheme : Encoding_Scheme;
                         Output_BOM    : Boolean  := False) return UTF_String;

84/3        {AI05-0262-1} Returns the value of Item encoded in UTF-8,
            UTF-16LE, or UTF-16BE as specified by Output_Scheme.

85/3    {AI05-0137-2} function Encode (Item       : Wide_String;
                         Output_BOM : Boolean  := False) return UTF_8_String;

86/3        Returns the value of Item encoded in UTF-8.

87/3    {AI05-0137-2} function Encode (Item       : Wide_String;
                         Output_BOM : Boolean  := False) return UTF_16_Wide_String;

88/3        Returns the value of Item encoded in UTF_16.

89/3    {AI05-0137-2} function Decode (Item         : UTF_String;
                         Input_Scheme : Encoding_Scheme) return Wide_String;

90/3        Returns the result of decoding Item, which is encoded in UTF-8,
            UTF-16LE, or UTF-16BE as specified by Input_Scheme.

91/3    {AI05-0137-2} function Decode (Item : UTF_8_String) return Wide_String;

92/3        Returns the result of decoding Item, which is encoded in UTF-8.

93/3    {AI05-0137-2}
        function Decode (Item : UTF_16_Wide_String) return Wide_String;

94/3        Returns the result of decoding Item, which is encoded in UTF-16.

95/3    {AI05-0137-2} function Encode (Item          : Wide_Wide_String;
                         Output_Scheme : Encoding_Scheme;
                         Output_BOM    : Boolean  := False) return UTF_String;

96/3        {AI05-0262-1} Returns the value of Item encoded in UTF-8,
            UTF-16LE, or UTF-16BE as specified by Output_Scheme.

97/3    {AI05-0137-2} function Encode (Item       : Wide_Wide_String;
                         Output_BOM : Boolean  := False) return UTF_8_String;

98/3        Returns the value of Item encoded in UTF-8.

99/3    {AI05-0137-2} function Encode (Item       : Wide_Wide_String;
                         Output_BOM : Boolean  := False) return UTF_16_Wide_String;

100/3       Returns the value of Item encoded in UTF_16.

101/3   {AI05-0137-2} function Decode (Item         : UTF_String;
                         Input_Scheme : Encoding_Scheme) return Wide_Wide_String;

102/3       Returns the result of decoding Item, which is encoded in UTF-8,
            UTF-16LE, or UTF-16BE as specified by Input_Scheme.

103/3   {AI05-0137-2}
        function Decode (Item : UTF_8_String) return Wide_Wide_String;

104/3       Returns the result of decoding Item, which is encoded in UTF-8.

105/3   {AI05-0137-2}
        function Decode (Item : UTF_16_Wide_String) return Wide_Wide_String;

106/3       Returns the result of decoding Item, which is encoded in UTF-16.


                            Implementation Advice

107/3 {AI05-0137-2} If an implementation supports other encoding schemes,
another similar child of Ada.Strings should be defined.

107.a.1/3   Implementation Advice: If an implementation supports other string
            encoding schemes, a child of Ada.Strings similar to UTF_Encoding
            should be defined.

        NOTES

108/3   18  {AI05-0137-2} A BOM (Byte-Order Mark, code position 16#FEFF#) can
        be included in a file or other entity to indicate the encoding; it is
        skipped when decoding. Typically, only the first line of a file or
        other entity contains a BOM. When decoding, the Encoding function can
        be called on the first line to determine the encoding; this encoding
        will then be used in subsequent calls to Decode to convert all of the
        lines to an internal format.


                           Extensions to Ada 2005

108.a/3     {AI05-0137-2} The packages Strings.UTF_Encoding,
            Strings.UTF_Encoding.Conversions, Strings.UTF_Encoding.Strings,
            Strings.UTF_Encoding.Wide_Strings, and
            Strings.UTF_Encoding.Wide_Wide_Strings are new.


                        Wording Changes from Ada 2012

108.b/4     {AI12-0088-1} Corrigendum: Fixed the omission that Convert
            routines make the same checks on input as Decode routines.


A.5 The Numerics Packages


1   The library package Numerics is the parent of several child units that
provide facilities for mathematical computation. One child, the generic
package Generic_Elementary_Functions, is defined in A.5.1, together with
nongeneric equivalents; two others, the package Float_Random and the generic
package Discrete_Random, are defined in A.5.2. Additional (optional) children
are defined in Annex G, "Numerics".


                              Static Semantics

2/1 This paragraph was deleted.

3/2     {AI95-00388-01} package Ada.Numerics is
           pragma Pure(Numerics);
           Argument_Error : exception;
           Pi : constant :=
                  3.14159_26535_89793_23846_26433_83279_50288_41971_69399_37511;
           PI  : constant := Pi;
           e  : constant :=
                  2.71828_18284_59045_23536_02874_71352_66249_77572_47093_69996;
        end Ada.Numerics;

4   The Argument_Error exception is raised by a subprogram in a child unit of
Numerics to signal that one or more of the actual subprogram parameters are
outside the domain of the corresponding mathematical function.


                         Implementation Permissions

5   The implementation may specify the values of Pi and e to a larger number
of significant digits.

5.a         Reason: 51 digits seem more than adequate for all present
            computers; converted to binary, the values given above are
            accurate to more than 160 bits. Nevertheless, the permission
            allows implementations to accommodate unforeseen hardware
            advances.


                            Extensions to Ada 83

5.b         Numerics and its children were not predefined in Ada 83.


                            Extensions to Ada 95

5.c/2       {AI95-00388-01} The alternative declaration of PI is new.


A.5.1 Elementary Functions


1   Implementation-defined approximations to the mathematical functions known
as the "elementary functions" are provided by the subprograms in Numerics.-
Generic_Elementary_Functions. Nongeneric equivalents of this generic package
for each of the predefined floating point types are also provided as children
of Numerics.

1.a         Implementation defined: The accuracy actually achieved by the
            elementary functions.


                              Static Semantics

2   The generic library package Numerics.Generic_Elementary_Functions has the
following declaration:

3       generic
           type Float_Type is digits <>;
        
        package Ada.Numerics.Generic_Elementary_Functions is
           pragma Pure(Generic_Elementary_Functions);

4          function Sqrt
            (X           : Float_Type'Base) return Float_Type'Base;
           function Log
             (X           : Float_Type'Base) return Float_Type'Base;
           function Log
             (X, Base     : Float_Type'Base) return Float_Type'Base;
           function Exp
             (X           : Float_Type'Base) return Float_Type'Base;
           function "**"    (Left, Right : Float_Type'Base) return Float_Type'Base;

5          function Sin
             (X           : Float_Type'Base) return Float_Type'Base;
           function Sin
             (X, Cycle    : Float_Type'Base) return Float_Type'Base;
           function Cos
             (X           : Float_Type'Base) return Float_Type'Base;
           function Cos
             (X, Cycle    : Float_Type'Base) return Float_Type'Base;
           function Tan
             (X           : Float_Type'Base) return Float_Type'Base;
           function Tan
             (X, Cycle    : Float_Type'Base) return Float_Type'Base;
           function Cot
             (X           : Float_Type'Base) return Float_Type'Base;
           function Cot
             (X, Cycle    : Float_Type'Base) return Float_Type'Base;

6          function Arcsin
          (X           : Float_Type'Base) return Float_Type'Base;
           function Arcsin
          (X, Cycle    : Float_Type'Base) return Float_Type'Base;
           function Arccos
          (X           : Float_Type'Base) return Float_Type'Base;
           function Arccos
          (X, Cycle    : Float_Type'Base) return Float_Type'Base;
           function Arctan  (Y           : Float_Type'Base;
                             X           : Float_Type'Base := 1.0)
                                                            return Float_Type'Base;
           function Arctan  (Y           : Float_Type'Base;
                             X           : Float_Type'Base := 1.0;
                             Cycle       : Float_Type'Base) return Float_Type'Base;
           function Arccot  (X           : Float_Type'Base;
                             Y           : Float_Type'Base := 1.0)
                                                            return Float_Type'Base;
           function Arccot  (X           : Float_Type'Base;
                             Y           : Float_Type'Base := 1.0;
                             Cycle       : Float_Type'Base) return Float_Type'Base;

7          function Sinh
            (X           : Float_Type'Base) return Float_Type'Base;
           function Cosh
            (X           : Float_Type'Base) return Float_Type'Base;
           function Tanh
            (X           : Float_Type'Base) return Float_Type'Base;
           function Coth
            (X           : Float_Type'Base) return Float_Type'Base;
           function Arcsinh
         (X           : Float_Type'Base) return Float_Type'Base;
           function Arccosh
         (X           : Float_Type'Base) return Float_Type'Base;
           function Arctanh
         (X           : Float_Type'Base) return Float_Type'Base;
           function Arccoth
         (X           : Float_Type'Base) return Float_Type'Base;

8       end Ada.Numerics.Generic_Elementary_Functions;

9/1 {8652/0020} {AI95-00126-01} The library package
Numerics.Elementary_Functions is declared pure and defines the same
subprograms as Numerics.Generic_Elementary_Functions, except that the
predefined type Float is systematically substituted for Float_Type'Base
throughout. Nongeneric equivalents of Numerics.Generic_Elementary_Functions
for each of the other predefined floating point types are defined similarly,
with the names Numerics.Short_Elementary_Functions, Numerics.Long_Elementary_-
Functions, etc.

9.a         Reason: The nongeneric equivalents are provided to allow the
            programmer to construct simple mathematical applications without
            being required to understand and use generics.

10  The functions have their usual mathematical meanings. When the Base
parameter is specified, the Log function computes the logarithm to the given
base; otherwise, it computes the natural logarithm. When the Cycle parameter
is specified, the parameter X of the forward trigonometric functions (Sin,
Cos, Tan, and Cot) and the results of the inverse trigonometric functions
(Arcsin, Arccos, Arctan, and Arccot) are measured in units such that a full
cycle of revolution has the given value; otherwise, they are measured in
radians.

11  The computed results of the mathematically multivalued functions are
rendered single-valued by the following conventions, which are meant to imply
the principal branch:

12    * The results of the Sqrt and Arccosh functions and that of the
        exponentiation operator are nonnegative.

13    * The result of the Arcsin function is in the quadrant containing the
        point (1.0, x), where x is the value of the parameter X. This quadrant
        is I or IV; thus, the range of the Arcsin function is approximately
        -PI/2.0 to PI/2.0 (-Cycle/4.0 to Cycle/4.0, if the parameter Cycle is
        specified).

14    * The result of the Arccos function is in the quadrant containing the
        point (x, 1.0), where x is the value of the parameter X. This quadrant
        is I or II; thus, the Arccos function ranges from 0.0 to approximately
        PI (Cycle/2.0, if the parameter Cycle is specified).

15    * The results of the Arctan and Arccot functions are in the quadrant
        containing the point (x, y), where x and y are the values of the
        parameters X and Y, respectively. This may be any quadrant (I through
        IV) when the parameter X (resp., Y) of Arctan (resp., Arccot) is
        specified, but it is restricted to quadrants I and IV (resp., I and
        II) when that parameter is omitted. Thus, the range when that
        parameter is specified is approximately -PI to PI (-Cycle/2.0 to
        Cycle/2.0, if the parameter Cycle is specified); when omitted, the
        range of Arctan (resp., Arccot) is that of Arcsin (resp., Arccos), as
        given above. When the point (x, y) lies on the negative x-axis, the
        result approximates

16        * PI (resp., -PI) when the sign of the parameter Y is positive
            (resp., negative), if Float_Type'Signed_Zeros is True;

17        * PI, if Float_Type'Signed_Zeros is False.

18  (In the case of the inverse trigonometric functions, in which a result
lying on or near one of the axes may not be exactly representable, the
approximation inherent in computing the result may place it in an adjacent
quadrant, close to but on the wrong side of the axis.)


                              Dynamic Semantics

19  The exception Numerics.Argument_Error is raised, signaling a parameter
value outside the domain of the corresponding mathematical function, in the
following cases:

20    * by any forward or inverse trigonometric function with specified cycle,
        when the value of the parameter Cycle is zero or negative;

21    * by the Log function with specified base, when the value of the
        parameter Base is zero, one, or negative;

22    * by the Sqrt and Log functions, when the value of the parameter X is
        negative;

23    * by the exponentiation operator, when the value of the left operand is
        negative or when both operands have the value zero;

24    * by the Arcsin, Arccos, and Arctanh functions, when the absolute value
        of the parameter X exceeds one;

25    * by the Arctan and Arccot functions, when the parameters X and Y both
        have the value zero;

26    * by the Arccosh function, when the value of the parameter X is less
        than one; and

27    * by the Arccoth function, when the absolute value of the parameter X is
        less than one.

28  The exception Constraint_Error is raised, signaling a pole of the
mathematical function (analogous to dividing by zero), in the following cases,
provided that Float_Type'Machine_Overflows is True:

29    * by the Log, Cot, and Coth functions, when the value of the parameter X
        is zero;

30    * by the exponentiation operator, when the value of the left operand is
        zero and the value of the exponent is negative;

31    * by the Tan function with specified cycle, when the value of the
        parameter X is an odd multiple of the quarter cycle;

32    * by the Cot function with specified cycle, when the value of the
        parameter X is zero or a multiple of the half cycle; and

33    * by the Arctanh and Arccoth functions, when the absolute value of the
        parameter X is one.

34  [Constraint_Error can also be raised when a finite result overflows (see
G.2.4); this may occur for parameter values sufficiently near poles, and, in
the case of some of the functions, for parameter values with sufficiently
large magnitudes.] When Float_Type'Machine_Overflows is False, the result at
poles is unspecified.

34.a        Reason: The purpose of raising Constraint_Error (rather than
            Numerics.Argument_Error) at the poles of a function, when
            Float_Type'Machine_Overflows is True, is to provide continuous
            behavior as the actual parameters of the function approach the
            pole and finally reach it.

34.b        Discussion: It is anticipated that an Ada binding to IEC 559:1989
            will be developed in the future. As part of such a binding, the
            Machine_Overflows attribute of a conformant floating point type
            will be specified to yield False, which will permit both the
            predefined arithmetic operations and implementations of the
            elementary functions to deliver signed infinities (and set the
            overflow flag defined by the binding) instead of raising
            Constraint_Error in overflow situations, when traps are disabled.
            Similarly, it is appropriate for the elementary functions to
            deliver signed infinities (and set the zero-divide flag defined by
            the binding) instead of raising Constraint_Error at poles, when
            traps are disabled. Finally, such a binding should also specify
            the behavior of the elementary functions, when sensible, given
            parameters with infinite values.

35  When one parameter of a function with multiple parameters represents a
pole and another is outside the function's domain, the latter takes precedence
(i.e., Numerics.Argument_Error is raised).


                         Implementation Requirements

36  In the implementation of Numerics.Generic_Elementary_Functions, the range
of intermediate values allowed during the calculation of a final result shall
not be affected by any range constraint of the subtype Float_Type.

36.a        Implementation Note: Implementations of
            Numerics.Generic_Elementary_Functions written in Ada should
            therefore avoid declaring local variables of subtype Float_Type;
            the subtype Float_Type'Base should be used instead.

37  In the following cases, evaluation of an elementary function shall yield
the prescribed result, provided that the preceding rules do not call for an
exception to be raised:

38    * When the parameter X has the value zero, the Sqrt, Sin, Arcsin, Tan,
        Sinh, Arcsinh, Tanh, and Arctanh functions yield a result of zero, and
        the Exp, Cos, and Cosh functions yield a result of one.

39    * When the parameter X has the value one, the Sqrt function yields a
        result of one, and the Log, Arccos, and Arccosh functions yield a
        result of zero.

40    * When the parameter Y has the value zero and the parameter X has a
        positive value, the Arctan and Arccot functions yield a result of zero.

41    * The results of the Sin, Cos, Tan, and Cot functions with specified
        cycle are exact when the mathematical result is zero; those of the
        first two are also exact when the mathematical result is ± 1.0.

42    * Exponentiation by a zero exponent yields the value one. Exponentiation
        by a unit exponent yields the value of the left operand.
        Exponentiation of the value one yields the value one. Exponentiation
        of the value zero yields the value zero.

43  Other accuracy requirements for the elementary functions, which apply only
in implementations conforming to the Numerics Annex, and then only in the "
strict" mode defined there (see G.2), are given in G.2.4.

44  When Float_Type'Signed_Zeros is True, the sign of a zero result shall be
as follows:

45    * A prescribed zero result delivered at the origin by one of the odd
        functions (Sin, Arcsin, Sinh, Arcsinh, Tan, Arctan or Arccot as a
        function of Y when X is fixed and positive, Tanh, and Arctanh) has the
        sign of the parameter X (Y, in the case of Arctan or Arccot).

46    * A prescribed zero result delivered by one of the odd functions away
        from the origin, or by some other elementary function, has an
        implementation-defined sign.

46.a        Implementation defined: The sign of a zero result from some of the
            operators or functions in Numerics.Generic_Elementary_Functions,
            when Float_Type'Signed_Zeros is True.

47    * [A zero result that is not a prescribed result (i.e., one that results
        from rounding or underflow) has the correct mathematical sign.]

47.a        Reason: This is a consequence of the rules specified in IEC
            559:1989 as they apply to underflow situations with traps
            disabled.


                         Implementation Permissions

48  The nongeneric equivalent packages may, but need not, be actual
instantiations of the generic package for the appropriate predefined type.


                         Wording Changes from Ada 83

48.a        The semantics of Numerics.Generic_Elementary_Functions differs
            from Generic_Elementary_Functions as defined in ISO/IEC DIS 11430
            (for Ada 83) in the following ways:

48.b          * The generic package is a child unit of the package defining
                the Argument_Error exception.

48.c          * DIS 11430 specified names for the nongeneric equivalents, if
                provided. Here, those nongeneric equivalents are required.

48.d          * Implementations are not allowed to impose an optional
                restriction that the generic actual parameter associated with
                Float_Type be unconstrained. (In view of the ability to
                declare variables of subtype Float_Type'Base in
                implementations of Numerics.Generic_Elementary_Functions, this
                flexibility is no longer needed.)

48.e          * The sign of a prescribed zero result at the origin of the odd
                functions is specified, when Float_Type'Signed_Zeros is True.
                This conforms with recommendations of Kahan and other
                numerical analysts.

48.f          * The dependence of Arctan and Arccot on the sign of a parameter
                value of zero is tied to the value of Float_Type'Signed_Zeros.

48.g          * Sqrt is prescribed to yield a result of one when its parameter
                has the value one. This guarantee makes it easier to achieve
                certain prescribed results of the complex elementary functions
                (see G.1.2, "Complex Elementary Functions").

48.h          * Conformance to accuracy requirements is conditional.


                         Wording Changes from Ada 95

48.i/2      {8652/0020} {AI95-00126-01} Corrigendum: Explicitly stated that
            the nongeneric equivalents of Generic_Elementary_Functions are
            pure.


A.5.2 Random Number Generation


1   [Facilities for the generation of pseudo-random floating point numbers are
provided in the package Numerics.Float_Random; the generic package
Numerics.Discrete_Random provides similar facilities for the generation of
pseudo-random integers and pseudo-random values of enumeration types. For
brevity, pseudo-random values of any of these types are called random numbers.

2   Some of the facilities provided are basic to all applications of random
numbers. These include a limited private type each of whose objects serves as
the generator of a (possibly distinct) sequence of random numbers; a function
to obtain the "next" random number from a given sequence of random numbers
(that is, from its generator); and subprograms to initialize or reinitialize a
given generator to a time-dependent state or a state denoted by a single
integer.

3   Other facilities are provided specifically for advanced applications.
These include subprograms to save and restore the state of a given generator;
a private type whose objects can be used to hold the saved state of a
generator; and subprograms to obtain a string representation of a given
generator state, or, given such a string representation, the corresponding
state.]

3.a         Discussion: These facilities support a variety of requirements
            ranging from repeatable sequences (for debugging) to unique
            sequences in each execution of a program.


                              Static Semantics

4   The library package Numerics.Float_Random has the following declaration:

5       package Ada.Numerics.Float_Random is

6          -- Basic facilities

7          type Generator is limited private;

8          subtype Uniformly_Distributed is Float range 0.0 .. 1.0;
           function Random (Gen : Generator) return Uniformly_Distributed;

9          procedure Reset (Gen       : in Generator;
                            Initiator : in Integer);
           procedure Reset (Gen       : in Generator);

10         -- Advanced facilities

11         type State is private;

12         procedure Save  (Gen        : in  Generator;
                            To_State   : out State);
           procedure Reset (Gen        : in  Generator;
                            From_State : in  State);

13         Max_Image_Width : constant := implementation-defined integer value;

14         function Image (Of_State    : State)  return String;
           function Value (Coded_State : String) return State;

15      private
           ... -- not specified by the language
        end Ada.Numerics.Float_Random;

15.1/2 {AI95-00360-01} The type Generator needs finalization (see 7.6).

16  The generic library package Numerics.Discrete_Random has the following
declaration:

17      
        generic
           type Result_Subtype is (<>);
        package Ada.Numerics.Discrete_Random is

18         -- Basic facilities

19         type Generator is limited private;

20         function Random (Gen : Generator) return Result_Subtype;

21         procedure Reset (Gen       : in Generator;
                            Initiator : in Integer);
           procedure Reset (Gen       : in Generator);

22         -- Advanced facilities

23         type State is private;

24         procedure Save  (Gen        : in  Generator;
                            To_State   : out State);
           procedure Reset (Gen        : in  Generator;
                            From_State : in  State);

25         Max_Image_Width : constant := implementation-defined integer value;

26         function Image (Of_State    : State)  return String;
           function Value (Coded_State : String) return State;

27      private
           ... -- not specified by the language
        end Ada.Numerics.Discrete_Random;

27.a        Implementation defined: The value of
            Numerics.Float_Random.Max_Image_Width.

27.b        Implementation defined: The value of
            Numerics.Discrete_Random.Max_Image_Width.

27.c/1      Implementation Note: {8652/0097} {AI95-00115-01} The following is
            a possible implementation of the private part of
            Numerics.Float_Random (assuming the presence of "with
            Ada.Finalization;" as a context clause):

27.d            type State is ...;
                type Access_State is access State;
                type Generator is new Finalization.Limited_Controlled with
                   record
                      S : Access_State := new State'(...);
                   end record;
                procedure Finalize (G : in out Generator);

27.d.1/2    {8652/0097} {AI95-00115-01} {AI95-00344-01}
            Numerics.Discrete_Random.Generator also can be implemented this
            way.

27.e        Clearly some level of indirection is required in the
            implementation of a Generator, since the parameter mode is in for
            all operations on a Generator. For this reason,
            Numerics.Float_Random and Numerics.Discrete_Random cannot be
            declared pure.

27.1/2 {AI95-00360-01} The type Generator needs finalization (see 7.6) in
every instantiation of Numerics.Discrete_Random.

28  An object of the limited private type Generator is associated with a
sequence of random numbers. Each generator has a hidden (internal) state,
which the operations on generators use to determine the position in the
associated sequence. All generators are implicitly initialized to an
unspecified state that does not vary from one program execution to another;
they may also be explicitly initialized, or reinitialized, to a time-dependent
state, to a previously saved state, or to a state uniquely denoted by an
integer value.

28.a        Discussion: The repeatability provided by the implicit
            initialization may be exploited for testing or debugging purposes.

29/3 {AI05-0280-1} An object of the private type State can be used to hold the
internal state of a generator. Such objects are only needed if the application
is designed to save and restore generator states or to examine or manufacture
them. The implicit initial value of type State corresponds to the implicit
initial value of all generators.

29.a/3      Discussion: {AI05-0280-1} All generators are implicitly
            initialized to the same unchanging value, and using Reset on a
            default initialized object of type State will produce a generator
            with that same value.

30  The operations on generators affect the state and therefore the future
values of the associated sequence. The semantics of the operations on
generators and states are defined below.

31      function Random (Gen : Generator) return Uniformly_Distributed;
        function Random (Gen : Generator) return Result_Subtype;

32          Obtains the "next" random number from the given generator,
            relative to its current state, according to an
            implementation-defined algorithm. The result of the function in
            Numerics.Float_Random is delivered as a value of the subtype
            Uniformly_Distributed, which is a subtype of the predefined type
            Float having a range of 0.0 .. 1.0. The result of the function in
            an instantiation of Numerics.Discrete_Random is delivered as a
            value of the generic formal subtype Result_Subtype.

32.a/2      This paragraph was deleted.

32.a.1/2    Discussion: The algorithm is the subject of a
            Documentation Requirement, so we don't separately summarize this
            implementation-defined item.

32.b        Reason: The requirement for a level of indirection in accessing
            the internal state of a generator arises from the desire to make
            Random a function, rather than a procedure.

33      procedure Reset (Gen       : in Generator;
                         Initiator : in Integer);
        procedure Reset (Gen       : in Generator);

34          Sets the state of the specified generator to one that is an
            unspecified function of the value of the parameter Initiator (or
            to a time-dependent state, if only a generator parameter is
            specified). The latter form of the procedure is known as the
            time-dependent Reset procedure.

34.a        Implementation Note: The time-dependent Reset procedure can be
            implemented by mapping the current time and date as determined by
            the system clock into a state, but other implementations are
            possible. For example, a white-noise generator or a radioactive
            source can be used to generate time-dependent states.

35      procedure Save  (Gen        : in  Generator;
                         To_State   : out State);
        procedure Reset (Gen        : in  Generator;
                         From_State : in  State);

36          Save obtains the current state of a generator. Reset gives a
            generator the specified state. A generator that is reset to a
            state previously obtained by invoking Save is restored to the
            state it had when Save was invoked.

37      function Image (Of_State    : State)  return String;
        function Value (Coded_State : String) return State;

38          Image provides a representation of a state coded (in an
            implementation-defined way) as a string whose length is bounded by
            the value of Max_Image_Width. Value is the inverse of Image:
            Value(Image(S)) = S for each state S that can be obtained from a
            generator by invoking Save.

38.a        Implementation defined: The string representation of a random
            number generator's state.


                              Dynamic Semantics

39  Instantiation of Numerics.Discrete_Random with a subtype having a null
range raises Constraint_Error.

40/1 This paragraph was deleted.{8652/0050} {AI95-00089}


                          Bounded (Run-Time) Errors

40.1/1 {8652/0050} {AI95-00089} It is a bounded error to invoke Value with a
string that is not the image of any generator state. If the error is detected,
Constraint_Error or Program_Error is raised. Otherwise, a call to Reset with
the resulting state will produce a generator such that calls to Random with
this generator will produce a sequence of values of the appropriate subtype,
but which might not be random in character. That is, the sequence of values
might not fulfill the implementation requirements of this subclause.


                         Implementation Requirements

41  A sufficiently long sequence of random numbers obtained by successive
calls to Random is approximately uniformly distributed over the range of the
result subtype.

42  The Random function in an instantiation of Numerics.Discrete_Random is
guaranteed to yield each value in its result subtype in a finite number of
calls, provided that the number of such values does not exceed 2 (15).

43  Other performance requirements for the random number generator, which
apply only in implementations conforming to the Numerics Annex, and then only
in the "strict" mode defined there (see G.2), are given in G.2.5.


                         Documentation Requirements

44  No one algorithm for random number generation is best for all
applications. To enable the user to determine the suitability of the random
number generators for the intended application, the implementation shall
describe the algorithm used and shall give its period, if known exactly, or a
lower bound on the period, if the exact period is unknown. Periods that are so
long that the periodicity is unobservable in practice can be described in such
terms, without giving a numerical bound.

44.a/2      Documentation Requirement: The algorithm used for random number
            generation, including a description of its period.

45  The implementation also shall document the minimum time interval between
calls to the time-dependent Reset procedure that are guaranteed to initiate
different sequences, and it shall document the nature of the strings that
Value will accept without raising Constraint_Error.

45.a/2      This paragraph was deleted.

45.b/2      Documentation Requirement: The minimum time interval between calls
            to the time-dependent Reset procedure that is guaranteed to
            initiate different random number sequences.


                            Implementation Advice

46  Any storage associated with an object of type Generator should be
reclaimed on exit from the scope of the object.

46.a.1/2    Implementation Advice: Any storage associated with an object of
            type Generator of the random number packages should be reclaimed
            on exit from the scope of the object.

46.a        Ramification: A level of indirection is implicit in the semantics
            of the operations, given that they all take parameters of mode in.
            This implies that the full type of Generator probably should be a
            controlled type, with appropriate finalization to reclaim any
            heap-allocated storage.

47  If the generator period is sufficiently long in relation to the number of
distinct initiator values, then each possible value of Initiator passed to
Reset should initiate a sequence of random numbers that does not, in a
practical sense, overlap the sequence initiated by any other value. If this is
not possible, then the mapping between initiator values and generator states
should be a rapidly varying function of the initiator value.

47.a/2      Implementation Advice: Each value of Initiator passed to Reset for
            the random number packages should initiate a distinct sequence of
            random numbers, or, if that is not possible, be at least a rapidly
            varying function of the initiator value.

        NOTES

48      19  If two or more tasks are to share the same generator, then the
        tasks have to synchronize their access to the generator as for any
        shared variable (see 9.10).

49      20  Within a given implementation, a repeatable random number sequence
        can be obtained by relying on the implicit initialization of
        generators or by explicitly initializing a generator with a repeatable
        initiator value. Different sequences of random numbers can be obtained
        from a given generator in different program executions by explicitly
        initializing the generator to a time-dependent state.

50      21  A given implementation of the Random function in
        Numerics.Float_Random may or may not be capable of delivering the
        values 0.0 or 1.0. Portable applications should assume that these
        values, or values sufficiently close to them to behave
        indistinguishably from them, can occur. If a sequence of random
        integers from some fixed range is needed, the application should use
        the Random function in an appropriate instantiation of
        Numerics.Discrete_Random, rather than transforming the result of the
        Random function in Numerics.Float_Random. However, some applications
        with unusual requirements, such as for a sequence of random integers
        each drawn from a different range, will find it more convenient to
        transform the result of the floating point Random function. For M >=
        1, the expression

51             Integer(Float(M) * Random(G)) mod M

52      transforms the result of Random(G) to an integer uniformly distributed
        over the range 0 .. M-1; it is valid even if Random delivers 0.0 or
        1.0. Each value of the result range is possible, provided that M is
        not too large. Exponentially distributed (floating point) random
        numbers with mean and standard deviation 1.0 can be obtained by the
        transformation

53/2        {AI95-00434-01}    -Log(Random(G) + Float'Model_Small)

54      where Log comes from Numerics.Elementary_Functions (see A.5.1); in
        this expression, the addition of Float'Model_Small avoids the
        exception that would be raised were Log to be given the value zero,
        without affecting the result (in most implementations) when Random
        returns a nonzero value.


                                  Examples

55  Example of a program that plays a simulated dice game:

56      with Ada.Numerics.Discrete_Random;
        procedure Dice_Game is
           subtype Die is Integer range 1 .. 6;
           subtype Dice is Integer range 2*Die'First .. 2*Die'Last;
           package Random_Die is new Ada.Numerics.Discrete_Random (Die);
           use Random_Die;
           G : Generator;
           D : Dice;
        begin
           Reset (G);  -- Start the generator in a unique state in each run
           loop
              -- Roll a pair of dice; sum and process the results
              D := Random(G) + Random(G);
              ...
           end loop;
        end Dice_Game;

57  Example of a program that simulates coin tosses:

58      with Ada.Numerics.Discrete_Random;
        procedure Flip_A_Coin is
           type Coin is (Heads, Tails);
           package Random_Coin is new Ada.Numerics.Discrete_Random (Coin);
           use Random_Coin;
           G : Generator;
        begin
           Reset (G);  -- Start the generator in a unique state in each run
           loop
              -- Toss a coin and process the result
              case Random(G) is
                  when Heads =>
                     ...
                  when Tails =>
                     ...
              end case;
           ...
           end loop;
        end Flip_A_Coin;

59  Example of a parallel simulation of a physical system, with a separate
generator of event probabilities in each task:

60      with Ada.Numerics.Float_Random;
        procedure Parallel_Simulation is
           use Ada.Numerics.Float_Random;
           task type Worker is
              entry Initialize_Generator (Initiator : in Integer);
              ...
           end Worker;
           W : array (1 .. 10) of Worker;
           task body Worker is
              G : Generator;
              Probability_Of_Event : Uniformly_Distributed;
           begin
              accept Initialize_Generator (Initiator : in Integer) do
                 Reset (G, Initiator);
              end Initialize_Generator;
              loop
                 ...
                 Probability_Of_Event := Random(G);
                 ...
              end loop;
           end Worker;
        begin
           -- Initialize the generators in the Worker tasks to different states
           for I in W'Range loop
              W(I).Initialize_Generator (I);
           end loop;
           ... -- Wait for the Worker tasks to terminate
        end Parallel_Simulation;

        NOTES

61      22  Notes on the last example: Although each Worker task initializes
        its generator to a different state, those states will be the same in
        every execution of the program. The generator states can be
        initialized uniquely in each program execution by instantiating
        Ada.Numerics.Discrete_Random for the type Integer in the main
        procedure, resetting the generator obtained from that instance to a
        time-dependent state, and then using random integers obtained from
        that generator to initialize the generators in each Worker task.


                        Incompatibilities With Ada 95

61.a/2      {AI95-00360-01} Amendment Correction: Type Generator in
            Numerics.Float_Random and in an instance of
            Numerics.Discrete_Random is defined to need finalization. If the
            restriction No_Nested_Finalization (see D.7) applies to the
            partition, and Generator does not have a controlled part, it will
            not be allowed in local objects in Ada 2005 whereas it would be
            allowed in original Ada 95. Such code is not portable, as another
            Ada compiler may have a controlled part in Generator, and thus
            would be illegal.


                         Wording Changes from Ada 95

61.b/3      {8652/0050} {AI95-00089-01} {AI05-0005-1} Corrigendum: Made the
            passing of an incorrect Image of a generator a bounded error, as
            it might not be practical to check for problems (if a generator
            consists of several related values).


                        Wording Changes from Ada 2005

61.c/3      {AI05-0280-1} Correction: Specified the implicit initial value for
            (sub)type State. This was unspecified in Ada 95 and Ada 2005, so a
            program depending on some other initial value is very unlikely and
            certainly was not portable. An implementation can use default
            expressions, aspect Default_Value, or aspect
            Default_Component_Value to keep the representation of the type
            unchanged while meeting this new requirement.


A.5.3 Attributes of Floating Point Types



                              Static Semantics

1   The following representation-oriented attributes are defined for every
subtype S of a floating point type T.

2   S'Machine_Radix
                Yields the radix of the hardware representation of the type T.
                The value of this attribute is of the type universal_integer.

3   The values of other representation-oriented attributes of a floating point
subtype, and of the "primitive function" attributes of a floating point
subtype described later, are defined in terms of a particular representation
of nonzero values called the canonical form. The canonical form (for the type
T) is the form
    ± mantissa · T'Machine_Radix(exponent)
where

4     * mantissa is a fraction in the number base T'Machine_Radix, the first
        digit of which is nonzero, and

5     * exponent is an integer.

6   S'Machine_Mantissa
                Yields the largest value of p such that every value
                expressible in the canonical form (for the type T), having a
                p-digit mantissa and an exponent between T'Machine_Emin and
                T'Machine_Emax, is a machine number (see 3.5.7) of the type T.
                This attribute yields a value of the type universal_integer.

6.a         Ramification: Values of a type held in an extended register are,
            in general, not machine numbers of the type, since they cannot be
            expressed in the canonical form with a sufficiently short
            mantissa.

7   S'Machine_Emin
                Yields the smallest (most negative) value of exponent such
                that every value expressible in the canonical form (for the
                type T), having a mantissa of T'Machine_Mantissa digits, is a
                machine number (see 3.5.7) of the type T. This attribute
                yields a value of the type universal_integer.

8   S'Machine_Emax
                Yields the largest (most positive) value of exponent such that
                every value expressible in the canonical form (for the type
                T), having a mantissa of T'Machine_Mantissa digits, is a
                machine number (see 3.5.7) of the type T. This attribute
                yields a value of the type universal_integer.

8.a         Ramification: Note that the above definitions do not determine
            unique values for the representation-oriented attributes of
            floating point types. The implementation may choose any set of
            values that collectively satisfies the definitions.

9   S'Denorm    Yields the value True if every value expressible in the form
                    ± mantissa · T'Machine_Radix(T'Machine_Emin)
                where mantissa is a nonzero T'Machine_Mantissa-digit fraction
                in the number base T'Machine_Radix, the first digit of which
                is zero, is a machine number (see 3.5.7) of the type T; yields
                the value False otherwise. The value of this attribute is of
                the predefined type Boolean.

10  The values described by the formula in the definition of S'Denorm are
called denormalized numbers. A nonzero machine number that is not a
denormalized number is a normalized number. A normalized number x of a given
type T is said to be represented in canonical form when it is expressed in the
canonical form (for the type T) with a mantissa having T'Machine_Mantissa
digits; the resulting form is the canonical-form representation of x.

10.a        Discussion: The intent is that S'Denorm be True when such
            denormalized numbers exist and are generated in the circumstances
            defined by IEC 559:1989, though the latter requirement is not
            formalized here.

11  S'Machine_Rounds
                Yields the value True if rounding is performed on inexact
                results of every predefined operation that yields a result of
                the type T; yields the value False otherwise. The value of
                this attribute is of the predefined type Boolean.

11.a        Discussion: It is difficult to be more precise about what it means
            to round the result of a predefined operation. If the
            implementation does not use extended registers, so that every
            arithmetic result is necessarily a machine number, then rounding
            seems to imply two things:

11.b          * S'Model_Mantissa = S'Machine_Mantissa, so that operand
                preperturbation never occurs;

11.c          * when the exact mathematical result is not a machine number,
                the result of a predefined operation must be the nearer of the
                two adjacent machine numbers.

11.d        Technically, this attribute should yield False when extended
            registers are used, since a few computed results will cross over
            the half-way point as a result of double rounding, if and when a
            value held in an extended register has to be reduced in precision
            to that of the machine numbers. It does not seem desirable to
            preclude the use of extended registers when S'Machine_Rounds could
            otherwise be True.

12  S'Machine_Overflows
                Yields the value True if overflow and divide-by-zero are
                detected and reported by raising Constraint_Error for every
                predefined operation that yields a result of the type T;
                yields the value False otherwise. The value of this attribute
                is of the predefined type Boolean.

13  S'Signed_Zeros
                Yields the value True if the hardware representation for the
                type T has the capability of representing both positively and
                negatively signed zeros, these being generated and used by the
                predefined operations of the type T as specified in IEC
                559:1989; yields the value False otherwise. The value of this
                attribute is of the predefined type Boolean.

14  For every value x of a floating point type T, the normalized exponent of x
is defined as follows:

15    * the normalized exponent of zero is (by convention) zero;

16    * for nonzero x, the normalized exponent of x is the unique integer k
        such that T'Machine_Radix(k-1) <= |x| < T'Machine_Radix(k).

16.a        Ramification: The normalized exponent of a normalized number x is
            the value of exponent in the canonical-form representation of x.

16.b        The normalized exponent of a denormalized number is less than the
            value of T'Machine_Emin.

17  The following primitive function attributes are defined for any subtype S
of a floating point type T.

18  S'Exponent  S'Exponent denotes a function with the following
                specification:

19                  function S'Exponent (X : T)
                      return universal_integer

20              The function yields the normalized exponent of X.

21  S'Fraction  S'Fraction denotes a function with the following
                specification:

22                  function S'Fraction (X : T)
                      return T

23              The function yields the value X · T'Machine_Radix(-k), where k
                is the normalized exponent of X. A zero result[, which can
                only occur when X is zero,] has the sign of X.

23.a        Discussion: Informally, when X is a normalized number, the result
            is the value obtained by replacing the exponent by zero in the
            canonical-form representation of X.

23.b        Ramification: Except when X is zero, the magnitude of the result
            is greater than or equal to the reciprocal of T'Machine_Radix and
            less than one; consequently, the result is always a normalized
            number, even when X is a denormalized number.

23.c        Implementation Note: When X is a denormalized number, the result
            is the value obtained by replacing the exponent by zero in the
            canonical-form representation of the result of scaling X up
            sufficiently to normalize it.

24  S'Compose   S'Compose denotes a function with the following specification:

25                  function S'Compose (Fraction : T;
                                        Exponent : universal_integer)
                      return T

26              Let v be the value Fraction · T'Machine_Radix(Exponent-k),
                where k is the normalized exponent of Fraction. If v is a
                machine number of the type T, or if |v| >= T'Model_Small, the
                function yields v; otherwise, it yields either one of the
                machine numbers of the type T adjacent to v. Constraint_Error
                is optionally raised if v is outside the base range of S. A
                zero result has the sign of Fraction when S'Signed_Zeros is
                True.

26.a        Discussion: Informally, when Fraction and v are both normalized
            numbers, the result is the value obtained by replacing the
            exponent by Exponent in the canonical-form representation of
            Fraction.

26.b        Ramification: If Exponent is less than T'Machine_Emin and Fraction
            is nonzero, the result is either zero, T'Model_Small, or (if
            T'Denorm is True) a denormalized number.

27  S'Scaling   S'Scaling denotes a function with the following specification:

28                  function S'Scaling (X : T;
                                        Adjustment : universal_integer)
                      return T

29              Let v be the value X · T'Machine_Radix(Adjustment). If v is a
                machine number of the type T, or if |v| >= T'Model_Small, the
                function yields v; otherwise, it yields either one of the
                machine numbers of the type T adjacent to v. Constraint_Error
                is optionally raised if v is outside the base range of S. A
                zero result has the sign of X when S'Signed_Zeros is True.

29.a        Discussion: Informally, when X and v are both normalized numbers,
            the result is the value obtained by increasing the exponent by
            Adjustment in the canonical-form representation of X.

29.b        Ramification: If Adjustment is sufficiently small (i.e.,
            sufficiently negative), the result is either zero, T'Model_Small,
            or (if T'Denorm is True) a denormalized number.

30  S'Floor     S'Floor denotes a function with the following specification:

31                  function S'Floor (X : T)
                      return T

32              The function yields the value Floor(X), i.e., the largest
                (most positive) integral value less than or equal to X. When X
                is zero, the result has the sign of X; a zero result otherwise
                has a positive sign.

33  S'Ceiling   S'Ceiling denotes a function with the following specification:

34                  function S'Ceiling (X : T)
                      return T

35              The function yields the value Ceiling(X), i.e., the smallest
                (most negative) integral value greater than or equal to X.
                When X is zero, the result has the sign of X; a zero result
                otherwise has a negative sign when S'Signed_Zeros is True.

36  S'Rounding  S'Rounding denotes a function with the following
                specification:

37                  function S'Rounding (X : T)
                      return T

38              The function yields the integral value nearest to X, rounding
                away from zero if X lies exactly halfway between two integers.
                A zero result has the sign of X when S'Signed_Zeros is True.

39  S'Unbiased_Rounding
                S'Unbiased_Rounding denotes a function with the following
                specification:

40                  function S'Unbiased_Rounding (X : T)
                      return T

41              The function yields the integral value nearest to X, rounding
                toward the even integer if X lies exactly halfway between two
                integers. A zero result has the sign of X when S'Signed_Zeros
                is True.

41.1/2 S'Machine_Rounding
                {AI95-00267-01} S'Machine_Rounding denotes a function with the
                following specification:

41.2/2              function S'Machine_Rounding (X : T)
                      return T

41.3/2          The function yields the integral value nearest to X. If X lies
                exactly halfway between two integers, one of those integers is
                returned, but which of them is returned is unspecified. A zero
                result has the sign of X when S'Signed_Zeros is True. This
                function provides access to the rounding behavior which is
                most efficient on the target processor.

41.a.1/2    Discussion: We leave the rounding unspecified, so that users
            cannot depend on a particular rounding. This attribute is intended
            for use in cases where the particular rounding chosen is
            irrelevant. If there is a need to know which way values halfway
            between two integers are rounded, one of the other rounding
            attributes should be used.

42  S'Truncation
                S'Truncation denotes a function with the following
                specification:

43                  function S'Truncation (X : T)
                      return T

44              The function yields the value Ceiling(X) when X is negative,
                and Floor(X) otherwise. A zero result has the sign of X when
                S'Signed_Zeros is True.

45  S'Remainder S'Remainder denotes a function with the following
                specification:

46                  function S'Remainder (X, Y : T)
                      return T

47              For nonzero Y, let v be the value X - n · Y, where n is the
                integer nearest to the exact value of X/Y; if |n - X/Y| = 1/2,
                then n is chosen to be even. If v is a machine number of the
                type T, the function yields v; otherwise, it yields zero.
                Constraint_Error is raised if Y is zero. A zero result has the
                sign of X when S'Signed_Zeros is True.

47.a        Ramification: The magnitude of the result is less than or equal to
            one-half the magnitude of Y.

47.b        Discussion: Given machine numbers X and Y of the type T, v is
            necessarily a machine number of the type T, except when Y is in
            the neighborhood of zero, X is sufficiently close to a multiple of
            Y, and T'Denorm is False.

48  S'Adjacent  S'Adjacent denotes a function with the following
                specification:

49                  function S'Adjacent (X, Towards : T)
                      return T

50              If Towards = X, the function yields X; otherwise, it yields
                the machine number of the type T adjacent to X in the
                direction of Towards, if that machine number exists. If the
                result would be outside the base range of S, Constraint_Error
                is raised. When T'Signed_Zeros is True, a zero result has the
                sign of X. When Towards is zero, its sign has no bearing on
                the result.

50.a        Ramification: The value of S'Adjacent(0.0, 1.0) is the smallest
            normalized positive number of the type T when T'Denorm is False
            and the smallest denormalized positive number of the type T when
            T'Denorm is True.

51  S'Copy_Sign S'Copy_Sign denotes a function with the following
                specification:

52                  function S'Copy_Sign (Value, Sign : T)
                      return T

53              If the value of Value is nonzero, the function yields a result
                whose magnitude is that of Value and whose sign is that of
                Sign; otherwise, it yields the value zero. Constraint_Error is
                optionally raised if the result is outside the base range of
                S. A zero result has the sign of Sign when S'Signed_Zeros is
                True.

53.a        Discussion: S'Copy_Sign is provided for convenience in restoring
            the sign to a quantity from which it has been temporarily removed,
            or to a related quantity. When S'Signed_Zeros is True, it is also
            instrumental in determining the sign of a zero quantity, when
            required. (Because negative and positive zeros compare equal in
            systems conforming to IEC 559:1989, a negative zero does not
            appear to be negative when compared to zero.) The sign
            determination is accomplished by transferring the sign of the zero
            quantity to a nonzero quantity and then testing for a negative
            result.

54  S'Leading_Part
                S'Leading_Part denotes a function with the following
                specification:

55                  function S'Leading_Part (X : T;
                                             Radix_Digits : universal_integer)
                      return T

56              Let v be the value T'Machine_Radix(k-Radix_Digits), where k is
                the normalized exponent of X. The function yields the value

57                * Floor(X/v) · v, when X is nonnegative and Radix_Digits is
                    positive;

58                * Ceiling(X/v) · v, when X is negative and Radix_Digits is
                    positive.

59              Constraint_Error is raised when Radix_Digits is zero or
                negative. A zero result[, which can only occur when X is
                zero,] has the sign of X.

59.a        Discussion: Informally, if X is nonzero, the result is the value
            obtained by retaining only the specified number of (leading)
            significant digits of X (in the machine radix), setting all other
            digits to zero.

59.b        Implementation Note: The result can be obtained by first scaling X
            up, if necessary to normalize it, then masking the mantissa so as
            to retain only the specified number of leading digits, then
            scaling the result back down if X was scaled up.

60  S'Machine   S'Machine denotes a function with the following specification:

61                  function S'Machine (X : T)
                      return T

62              If X is a machine number of the type T, the function yields X;
                otherwise, it yields the value obtained by rounding or
                truncating X to either one of the adjacent machine numbers of
                the type T. Constraint_Error is raised if rounding or
                truncating X to the precision of the machine numbers results
                in a value outside the base range of S. A zero result has the
                sign of X when S'Signed_Zeros is True.

62.a/3      Discussion: {AI05-0005-1} All of the primitive function attributes
            except Rounding and Machine correspond to subprograms in the
            Generic_Primitive_Functions generic package that was proposed as a
            separate ISO standard (ISO/IEC DIS 11729) for Ada 83. The Scaling,
            Unbiased_Rounding, and Truncation attributes correspond to the
            Scale, Round, and Truncate functions, respectively, in
            Generic_Primitive_Functions. The Rounding attribute rounds away
            from zero; this functionality was not provided in
            Generic_Primitive_Functions. The name Round was not available for
            either of the primitive function attributes that perform rounding,
            since an attribute of that name is used for a different purpose
            for decimal fixed point types. Likewise, the name Scale was not
            available, since an attribute of that name is also used for a
            different purpose for decimal fixed point types. The functionality
            of the Machine attribute was also not provided in
            Generic_Primitive_Functions. The functionality of the Decompose
            procedure of Generic_Primitive_Functions is only provided in the
            form of the separate attributes Exponent and Fraction. The
            functionality of the Successor and Predecessor functions of
            Generic_Primitive_Functions is provided by the extension of the
            existing Succ and Pred attributes.

62.b        Implementation Note: The primitive function attributes may be
            implemented either with appropriate floating point arithmetic
            operations or with integer and logical operations that act on
            parts of the representation directly. The latter is strongly
            encouraged when it is more efficient than the former; it is
            mandatory when the former cannot deliver the required accuracy due
            to limitations of the implementation's arithmetic operations.

63  The following model-oriented attributes are defined for any subtype S of a
floating point type T.

64  S'Model_Mantissa
                If the Numerics Annex is not supported, this attribute yields
                an implementation defined value that is greater than or equal
                to Ceiling(d · log(10) / log(T'Machine_Radix)) + 1, where d is
                the requested decimal precision of T, and less than or equal
                to the value of T'Machine_Mantissa. See G.2.2 for further
                requirements that apply to implementations supporting the
                Numerics Annex. The value of this attribute is of the type
                universal_integer.

65  S'Model_Emin
                If the Numerics Annex is not supported, this attribute yields
                an implementation defined value that is greater than or equal
                to the value of T'Machine_Emin. See G.2.2 for further
                requirements that apply to implementations supporting the
                Numerics Annex. The value of this attribute is of the type
                universal_integer.

66  S'Model_Epsilon
                Yields the value T'Machine_Radix(1 - T'Model_Mantissa). The
                value of this attribute is of the type universal_real.

66.a        Discussion: In most implementations, this attribute yields the
            absolute value of the difference between one and the smallest
            machine number of the type T above one which, when added to one,
            yields a machine number different from one. Further discussion can
            be found in G.2.2.

67  S'Model_Small
                Yields the value T'Machine_Radix(T'Model_Emin - 1). The value
                of this attribute is of the type universal_real.

67.a        Discussion: In most implementations, this attribute yields the
            smallest positive normalized number of the type T, i.e. the number
            corresponding to the positive underflow threshold. In some
            implementations employing a radix-complement representation for
            the type T, the positive underflow threshold is closer to zero
            than is the negative underflow threshold, with the consequence
            that the smallest positive normalized number does not coincide
            with the positive underflow threshold (i.e., it exceeds the
            latter). Further discussion can be found in G.2.2.

68  S'Model     S'Model denotes a function with the following specification:

69                  function S'Model (X : T)
                      return T

70              If the Numerics Annex is not supported, the meaning of this
                attribute is implementation defined; see G.2.2 for the
                definition that applies to implementations supporting the
                Numerics Annex.

71  S'Safe_First
                Yields the lower bound of the safe range (see 3.5.7) of the
                type T. If the Numerics Annex is not supported, the value of
                this attribute is implementation defined; see G.2.2 for the
                definition that applies to implementations supporting the
                Numerics Annex. The value of this attribute is of the type
                universal_real.

72  S'Safe_Last Yields the upper bound of the safe range (see 3.5.7) of the
                type T. If the Numerics Annex is not supported, the value of
                this attribute is implementation defined; see G.2.2 for the
                definition that applies to implementations supporting the
                Numerics Annex. The value of this attribute is of the type
                universal_real.

72.a        Discussion: A predefined floating point arithmetic operation that
            yields a value in the safe range of its result type is guaranteed
            not to overflow.

72.b        To be honest: An exception is made for exponentiation by a
            negative exponent in 4.5.6.

72.c        Implementation defined: The values of the Model_Mantissa,
            Model_Emin, Model_Epsilon, Model, Safe_First, and Safe_Last
            attributes, if the Numerics Annex is not supported.


                        Incompatibilities With Ada 83

72.d        The Epsilon and Mantissa attributes of floating point types are
            removed from the language and replaced by Model_Epsilon and
            Model_Mantissa, which may have different values (as a result of
            changes in the definition of model numbers); the replacement of
            one set of attributes by another is intended to convert what would
            be an inconsistent change into an incompatible change.

72.e        The Emax, Small, Large, Safe_Emax, Safe_Small, and Safe_Large
            attributes of floating point types are removed from the language.
            Small and Safe_Small are collectively replaced by Model_Small,
            which is functionally equivalent to Safe_Small, though it may have
            a slightly different value. The others are collectively replaced
            by Safe_First and Safe_Last. Safe_Last is functionally equivalent
            to Safe_Large, though it may have a different value; Safe_First is
            comparable to the negation of Safe_Large but may differ slightly
            from it as well as from the negation of Safe_Last. Emax and
            Safe_Emax had relatively few uses in Ada 83; T'Safe_Emax can be
            computed in the revised language as
            Integer'Min(T'Exponent(T'Safe_First), T'Exponent(T'Safe_Last)).

72.f        Implementations are encouraged to eliminate the incompatibilities
            discussed here by retaining the old attributes, during a
            transition period, in the form of implementation-defined
            attributes with their former values.


                            Extensions to Ada 83

72.g        The Model_Emin attribute is new. It is conceptually similar to the
            negation of Safe_Emax attribute of Ada 83, adjusted for the fact
            that the model numbers now have the hardware radix. It is a
            fundamental determinant, along with Model_Mantissa, of the set of
            model numbers of a type (see G.2.1).

72.h        The Denorm and Signed_Zeros attributes are new, as are all of the
            primitive function attributes.


                            Extensions to Ada 95

72.i/2      {AI95-00388-01} The Machine_Rounding attribute is new.


A.5.4 Attributes of Fixed Point Types



                              Static Semantics

1   The following representation-oriented attributes are defined for every
subtype S of a fixed point type T.

2   S'Machine_Radix
                Yields the radix of the hardware representation of the type T.
                The value of this attribute is of the type universal_integer.

3   S'Machine_Rounds
                Yields the value True if rounding is performed on inexact
                results of every predefined operation that yields a result of
                the type T; yields the value False otherwise. The value of
                this attribute is of the predefined type Boolean.

4   S'Machine_Overflows
                Yields the value True if overflow and divide-by-zero are
                detected and reported by raising Constraint_Error for every
                predefined operation that yields a result of the type T;
                yields the value False otherwise. The value of this attribute
                is of the predefined type Boolean.


                        Incompatibilities With Ada 83

4.a         The Mantissa, Large, Safe_Small, and Safe_Large attributes of
            fixed point types are removed from the language.

4.b         Implementations are encouraged to eliminate the resulting
            incompatibility by retaining these attributes, during a transition
            period, in the form of implementation-defined attributes with
            their former values.


                            Extensions to Ada 83

4.c         The Machine_Radix attribute is now allowed for fixed point types.
            It is also specifiable in an attribute definition clause (see
            F.1).


A.6 Input-Output


1/2 {AI95-00285-01} [ Input-output is provided through language-defined
packages, each of which is a child of the root package Ada. The generic
packages Sequential_IO and Direct_IO define input-output operations applicable
to files containing elements of a given type. The generic package Storage_IO
supports reading from and writing to an in-memory buffer. Additional
operations for text input-output are supplied in the packages Text_IO,
Wide_Text_IO, and Wide_Wide_Text_IO. Heterogeneous input-output is provided
through the child packages Streams.Stream_IO and Text_IO.Text_Streams (see
also 13.13). The package IO_Exceptions defines the exceptions needed by the
predefined input-output packages.]


                         Inconsistencies With Ada 83

1.a         The introduction of Append_File as a new element of the
            enumeration type File_Mode in Sequential_IO and Text_IO, and the
            introduction of several new declarations in Text_IO, may result in
            name clashes in the presence of use clauses.


                            Extensions to Ada 83

1.b         Text_IO enhancements (Get_Immediate, Look_Ahead, Standard_Error,
            Modular_IO, Decimal_IO), Wide_Text_IO, and the stream input-output
            facilities are new in Ada 95.


                         Wording Changes from Ada 83

1.c         RM83-14.6, "Low Level Input-Output," is removed. This has no
            semantic effect, since the package was entirely implementation
            defined, nobody actually implemented it, and if they did, they can
            always provide it as a vendor-supplied package.


                         Wording Changes from Ada 95

1.d/2       {AI95-00285-01} Included package Wide_Wide_Text_IO in this
            description.


A.7 External Files and File Objects



                              Static Semantics

1   Values input from the external environment of the program, or output to
the external environment, are considered to occupy external files. An external
file can be anything external to the program that can produce a value to be
read or receive a value to be written. An external file is identified by a
string (the name). A second string (the form) gives further system-dependent
characteristics that may be associated with the file, such as the physical
organization or access rights. The conventions governing the interpretation of
such strings shall be documented.

2/3 {AI05-0299-1} Input and output operations are expressed as operations on
objects of some file type, rather than directly in terms of the external
files. In the remainder of this clause, the term file is always used to refer
to a file object; the term external file is used otherwise.

3   Input-output for sequential files of values of a single element type is
defined by means of the generic package Sequential_IO. In order to define
sequential input-output for a given element type, an instantiation of this
generic unit, with the given type as actual parameter, has to be declared. The
resulting package contains the declaration of a file type (called File_Type)
for files of such elements, as well as the operations applicable to these
files, such as the Open, Read, and Write procedures.

4/2 {AI95-00285-01} Input-output for direct access files is likewise defined
by a generic package called Direct_IO. Input-output in human-readable form is
defined by the (nongeneric) packages Text_IO for Character and String data,
Wide_Text_IO for Wide_Character and Wide_String data, and Wide_Wide_Text_IO
for Wide_Wide_Character and Wide_Wide_String data. Input-output for files
containing streams of elements representing values of possibly different types
is defined by means of the (nongeneric) package Streams.Stream_IO.

5   Before input or output operations can be performed on a file, the file
first has to be associated with an external file. While such an association is
in effect, the file is said to be open, and otherwise the file is said to be
closed.

6   The language does not define what happens to external files after the
completion of the main program and all the library tasks (in particular, if
corresponding files have not been closed). The effect of input-output for
access types is unspecified.

7   An open file has a current mode, which is a value of one of the following
enumeration types:

8       type File_Mode is (In_File, Inout_File, Out_File);  --  for Direct_IO

9           These values correspond respectively to the cases where only
            reading, both reading and writing, or only writing are to be
            performed.

10/2    {AI95-00285-01} type File_Mode is (In_File, Out_File, Append_File);
        --  for Sequential_IO, Text_IO, Wide_Text_IO, Wide_Wide_Text_IO, and Stream_IO

11          These values correspond respectively to the cases where only
            reading, only writing, or only appending are to be performed.

12          The mode of a file can be changed.

13/2 {AI95-00285-01} Several file management operations are common to
Sequential_IO, Direct_IO, Text_IO, Wide_Text_IO, and Wide_Wide_Text_IO. These
operations are described in subclause A.8.2 for sequential and direct files.
Any additional effects concerning text input-output are described in subclause
A.10.2.

14/3 {AI05-0299-1} The exceptions that can be propagated by the execution of
an input-output subprogram are defined in the package IO_Exceptions; the
situations in which they can be propagated are described following the
description of the subprogram (and in subclause A.13). The exceptions
Storage_Error and Program_Error may be propagated. (Program_Error can only be
propagated due to errors made by the caller of the subprogram.) Finally,
exceptions can be propagated in certain implementation-defined situations.

14.a/2      This paragraph was deleted.

14.b/2      Discussion: The last sentence here is referring to the
            documentation requirements in A.13, "Exceptions in Input-Output
            ", and the documentation summary item is provided there.

        NOTES

15/2    23  {AI95-00285-01} Each instantiation of the generic packages
        Sequential_IO and Direct_IO declares a different type File_Type. In
        the case of Text_IO, Wide_Text_IO, Wide_Wide_Text_IO, and
        Streams.Stream_IO, the corresponding type File_Type is unique.

16      24  A bidirectional device can often be modeled as two sequential
        files associated with the device, one of mode In_File, and one of mode
        Out_File. An implementation may restrict the number of files that may
        be associated with a given external file.


                         Wording Changes from Ada 95

16.a/2      {AI95-00285-01} Included package Wide_Wide_Text_IO in this
            description.


A.8 Sequential and Direct Files



                              Static Semantics

1/2 {AI95-00283-01} Two kinds of access to external files are defined in this
subclause: sequential access and direct access. The corresponding file types
and the associated operations are provided by the generic packages
Sequential_IO and Direct_IO. A file object to be used for sequential access is
called a sequential file, and one to be used for direct access is called a
direct file. Access to stream files is described in A.12.1.

2   For sequential access, the file is viewed as a sequence of values that are
transferred in the order of their appearance (as produced by the program or by
the external environment). When the file is opened with mode In_File or
Out_File, transfer starts respectively from or to the beginning of the file.
When the file is opened with mode Append_File, transfer to the file starts
after the last element of the file.

2.a         Discussion: Adding stream I/O necessitates a review of the
            terminology. In Ada 83, `sequential' implies both the access
            method (purely sequential - that is, no indexing or positional
            access) and homogeneity. Direct access includes purely sequential
            access and indexed access, as well as homogeneity. In Ada 95,
            streams allow purely sequential access but also positional access
            to an individual element, and are heterogeneous. We considered
            generalizing the notion of `sequential file' to include both
            Sequential_IO and Stream_IO files, but since streams allow
            positional access it seems misleading to call them sequential
            files. Or, looked at differently, if the criterion for calling
            something a sequential file is whether it permits (versus
            requires) purely sequential access, then one could just as soon
            regard a Direct_IO file as a sequential file.

2.b         It seems better to regard `sequential file' as meaning `only
            permitting purely sequential access'; hence we have decided to
            supplement `sequential access' and `direct access' with a third
            category, informally called `access to streams'. (We decided
            against the term `stream access' because of possible confusion
            with the Stream_Access type declared in one of the stream
            packages.)

3   For direct access, the file is viewed as a set of elements occupying
consecutive positions in linear order; a value can be transferred to or from
an element of the file at any selected position. The position of an element is
specified by its index, which is a number, greater than zero, of the
implementation-defined integer type Count. The first element, if any, has
index one; the index of the last element, if any, is called the current size;
the current size is zero if there are no elements. The current size is a
property of the external file.

4   An open direct file has a current index, which is the index that will be
used by the next read or write operation. When a direct file is opened, the
current index is set to one. The current index of a direct file is a property
of a file object, not of an external file.


                         Wording Changes from Ada 95

4.a/2       {AI95-00283-01} Italicized "stream file" to clarify that this is
            another kind of file.


A.8.1 The Generic Package Sequential_IO



                              Static Semantics

1   The generic library package Sequential_IO has the following declaration:

2       with Ada.IO_Exceptions;
        generic
           type Element_Type(<>) is private;
        package Ada.Sequential_IO is

3          type File_Type is limited private;

4          type File_Mode is (In_File, Out_File, Append_File);

5          -- File management

6          procedure Create(File : in out File_Type;
                            Mode : in File_Mode := Out_File;
                            Name : in String := "";
                            Form : in String := "");

7          procedure Open  (File : in out File_Type;
                            Mode : in File_Mode;
                            Name : in String;
                            Form : in String := "");

8          procedure Close (File : in out File_Type);
           procedure Delete(File : in out File_Type);
           procedure Reset (File : in out File_Type; Mode : in File_Mode);
           procedure Reset (File : in out File_Type);

9          function Mode   (File : in File_Type) return File_Mode;
           function Name   (File : in File_Type) return String;
           function Form   (File : in File_Type) return String;

10         function Is_Open(File : in File_Type) return Boolean;

10.1/4  {AI12-0130-1}    procedure Flush (File : in File_Type);

11         -- Input and output operations

12         procedure Read  (File : in File_Type; Item : out Element_Type);
           procedure Write (File : in File_Type; Item : in Element_Type);

13         function End_Of_File(File : in File_Type) return Boolean;

14         -- Exceptions

15         Status_Error : exception renames IO_Exceptions.Status_Error;
           Mode_Error   : exception renames IO_Exceptions.Mode_Error;
           Name_Error   : exception renames IO_Exceptions.Name_Error;
           Use_Error    : exception renames IO_Exceptions.Use_Error;
           Device_Error : exception renames IO_Exceptions.Device_Error;
           End_Error    : exception renames IO_Exceptions.End_Error;
           Data_Error   : exception renames IO_Exceptions.Data_Error;

16      private
           ... -- not specified by the language
        end Ada.Sequential_IO;

17/2 {AI95-00360-01} The type File_Type needs finalization (see 7.6) in every
instantiation of Sequential_IO.


                        Incompatibilities With Ada 83

17.a        The new enumeration element Append_File may introduce upward
            incompatibilities. It is possible that a program based on the
            assumption that File_Mode'Last = Out_File will be illegal (e.g.,
            case statement choice coverage) or execute with a different effect
            in Ada 95.

17.a.1/2    This paragraph was deleted.{8652/0097} {AI95-00115-01}
            {AI95-00344-01}


                        Incompatibilities With Ada 95

17.b/2      {AI95-00360-01} Amendment Correction: File_Type in an instance of
            Sequential_IO is defined to need finalization. If the restriction
            No_Nested_Finalization (see D.7) applies to the partition, and
            File_Type does not have a controlled part, it will not be allowed
            in local objects in Ada 2005 whereas it would be allowed in
            original Ada 95. Such code is not portable, as another Ada
            compiler may have a controlled part in File_Type, and thus would
            be illegal.


                       Incompatibilities With Ada 2012

17.c/4      {AI12-0130-1} Corrigendum: The Flush procedure is newly added to
            Ada.Sequential_IO. If an instance of Ada.Sequential_IO is
            referenced in a use_clause, and a procedure Flush is defined in
            some other package that is also referenced in a use_clause, the
            user-defined Flush may no longer be use-visible, resulting in
            errors. This should be rare and is easily fixed if it does occur.


A.8.2 File Management



                              Static Semantics

1   The procedures and functions described in this subclause provide for the
control of external files; their declarations are repeated in each of the
packages for sequential, direct, text, and stream input-output. For text
input-output, the procedures Create, Open, and Reset have additional effects
described in subclause A.10.2.

2       procedure Create(File : in out File_Type;
                         Mode : in File_Mode := default_mode;
                         Name : in String := "";
                         Form : in String := "");

3/2         {AI95-00283-01} Establishes a new external file, with the given
            name and form, and associates this external file with the given
            file. The given file is left open. The current mode of the given
            file is set to the given access mode. The default access mode is
            the mode Out_File for sequential, stream, and text input-output;
            it is the mode Inout_File for direct input-output. For direct
            access, the size of the created file is implementation defined.

3.a/4       Ramification: {AI12-0005-1} For a direct file, the initial value
            of current index is 1 (see A.8).

4           A null string for Name specifies an external file that is not
            accessible after the completion of the main program (a temporary
            file). A null string for Form specifies the use of the default
            options of the implementation for the external file.

5           The exception Status_Error is propagated if the given file is
            already open. The exception Name_Error is propagated if the string
            given as Name does not allow the identification of an external
            file. The exception Use_Error is propagated if, for the specified
            mode, the external environment does not support creation of an
            external file with the given name (in the absence of Name_Error)
            and form.

6       procedure Open(File : in out File_Type;
                       Mode : in File_Mode;
                       Name : in String;
                       Form : in String := "");

7           Associates the given file with an existing external file having
            the given name and form, and sets the current mode of the given
            file to the given mode. The given file is left open.

7.a/4       Ramification: {AI12-0005-1} For a direct file, the initial value
            of current index is 1 (see A.8).

8           The exception Status_Error is propagated if the given file is
            already open. The exception Name_Error is propagated if the string
            given as Name does not allow the identification of an external
            file; in particular, this exception is propagated if no external
            file with the given name exists. The exception Use_Error is
            propagated if, for the specified mode, the external environment
            does not support opening for an external file with the given name
            (in the absence of Name_Error) and form.

9       procedure Close(File : in out File_Type);

10          Severs the association between the given file and its associated
            external file. The given file is left closed. In addition, for
            sequential files, if the file being closed has mode Out_File or
            Append_File, then the last element written since the most recent
            open or reset is the last element that can be read from the file.
            If no elements have been written and the file mode is Out_File,
            then the closed file is empty. If no elements have been written
            and the file mode is Append_File, then the closed file is
            unchanged.

11          The exception Status_Error is propagated if the given file is not
            open.

12      procedure Delete(File : in out File_Type);

13          Deletes the external file associated with the given file. The
            given file is closed, and the external file ceases to exist.

14          The exception Status_Error is propagated if the given file is not
            open. The exception Use_Error is propagated if deletion of the
            external file is not supported by the external environment.

15      procedure Reset(File : in out File_Type; Mode : in File_Mode);
        procedure Reset(File : in out File_Type);

16/2        {AI95-00085-01} Resets the given file so that reading from its
            elements can be restarted from the beginning of the external file
            (for modes In_File and Inout_File), and so that writing to its
            elements can be restarted at the beginning of the external file
            (for modes Out_File and Inout_File) or after the last element of
            the external file (for mode Append_File). In particular, for
            direct access this means that the current index is set to one. If
            a Mode parameter is supplied, the current mode of the given file
            is set to the given mode. In addition, for sequential files, if
            the given file has mode Out_File or Append_File when Reset is
            called, the last element written since the most recent open or
            reset is the last element that can be read from the external file.
            If no elements have been written and the file mode is Out_File,
            the reset file is empty. If no elements have been written and the
            file mode is Append_File, then the reset file is unchanged.

17          The exception Status_Error is propagated if the file is not open.
            The exception Use_Error is propagated if the external environment
            does not support resetting for the external file and, also, if the
            external environment does not support resetting to the specified
            mode for the external file.

18      function Mode(File : in File_Type) return File_Mode;

19          Returns the current mode of the given file.

20          The exception Status_Error is propagated if the file is not open.

21      function Name(File : in File_Type) return String;

22/2        {AI95-00248-01} Returns a string which uniquely identifies the
            external file currently associated with the given file (and may
            thus be used in an Open operation).

22.a/2      Discussion: {AI95-00248-01} Retrieving the full path can be
            accomplished by passing the result of Name to
            Directories.Full_Name (see A.16). It is important to drop the
            requirement on Name, as the only way to accomplish this
            requirement given that the current directory can be changed with
            package Directories is to store the full path when the file is
            opened. That's expensive, and it's better for users that need the
            full path to explicitly request it.

23          The exception Status_Error is propagated if the given file is not
            open. The exception Use_Error is propagated if the associated
            external file is a temporary file that cannot be opened by any
            name.

24      function Form(File : in File_Type) return String;

25          Returns the form string for the external file currently associated
            with the given file. If an external environment allows alternative
            specifications of the form (for example, abbreviations using
            default options), the string returned by the function should
            correspond to a full specification (that is, it should indicate
            explicitly all options selected, including default options).

26          The exception Status_Error is propagated if the given file is not
            open.

27      function Is_Open(File : in File_Type) return Boolean;

28/3        {AI05-0264-1} Returns True if the file is open (that is, if it is
            associated with an external file); otherwise, returns False.

28.1/4  {AI12-0130-1} procedure Flush(File : in File_Type);

28.2/4      The Flush procedure synchronizes the external file with the
            internal file (by flushing any internal buffers) without closing
            the file. For a direct file, the current index is unchanged; for a
            stream file (see A.12.1), the current position is unchanged.

28.3/4      The exception Status_Error is propagated if the file is not open.
            The exception Mode_Error is propagated if the mode of the file is
            In_File.


                         Implementation Permissions

29  An implementation may propagate Name_Error or Use_Error if an attempt is
made to use an I/O feature that cannot be supported by the implementation due
to limitations in the external environment. Any such restriction should be
documented.


                         Wording Changes from Ada 95

29.a/2      {AI95-00085-01} Clarified that Reset affects and depends on the
            external file.

29.b/2      {AI95-00248-01} Removed the requirement for Name to return a full
            path; this is now accomplished by
            Directories.Full_Name(Name(File)) (see A.16). This is not
            documented as an inconsistency, because there is no requirement
            for implementations to change - the Ada 95 behavior is still
            allowed, it just is no longer required.

29.c/2      {AI95-00283-01} Added text to specify the default mode for a
            stream file.


                        Wording Changes from Ada 2012

29.d/4      {AI12-0130-1} Procedure Flush is now defined here, so it can be
            used for all of the I/O packages.


A.8.3 Sequential Input-Output Operations



                              Static Semantics

1   The operations available for sequential input and output are described in
this subclause. The exception Status_Error is propagated if any of these
operations is attempted for a file that is not open.

2       procedure Read(File : in File_Type; Item : out Element_Type);

3           Operates on a file of mode In_File. Reads an element from the
            given file, and returns the value of this element in the Item
            parameter.

3.a         Discussion: We considered basing Sequential_IO.Read on
            Element_Type'Read from an implicit stream associated with the
            sequential file. However, Element_Type'Read is a type-related
            attribute, whereas Sequential_IO should take advantage of the
            particular constraints of the actual subtype corresponding to
            Element_Type to minimize the size of the external file.
            Furthermore, forcing the implementation of Sequential_IO to be
            based on Element_Type'Read would create an upward incompatibility
            since existing data files written by an Ada 83 program using
            Sequential_IO might not be readable by the identical program built
            with an Ada 95 implementation of Sequential_IO.

3.b         An Ada 95 implementation might still use an implementation-defined
            attribute analogous to 'Read to implement the procedure Read, but
            that attribute will likely have to be subtype-specific rather than
            type-related, and it need not be user-specifiable. Such an
            attribute will presumably be needed to implement the generic
            package Storage_IO (see A.9).

4           The exception Mode_Error is propagated if the mode is not In_File.
            The exception End_Error is propagated if no more elements can be
            read from the given file. The exception Data_Error can be
            propagated if the element read cannot be interpreted as a value of
            the subtype Element_Type (see A.13, "Exceptions in Input-Output
            ").

4.a         Discussion: Data_Error need not be propagated if the check is too
            complex. See A.13, "Exceptions in Input-Output".

5       procedure Write(File : in File_Type; Item : in Element_Type);

6           Operates on a file of mode Out_File or Append_File. Writes the
            value of Item to the given file.

7           The exception Mode_Error is propagated if the mode is not Out_File
            or Append_File. The exception Use_Error is propagated if the
            capacity of the external file is exceeded.

8       function End_Of_File(File : in File_Type) return Boolean;

9/3         {AI05-0264-1} Operates on a file of mode In_File. Returns True if
            no more elements can be read from the given file; otherwise,
            returns False.

10          The exception Mode_Error is propagated if the mode is not In_File.


A.8.4 The Generic Package Direct_IO



                              Static Semantics

1   The generic library package Direct_IO has the following declaration:

2       with Ada.IO_Exceptions;
        generic
           type Element_Type is private;
        package Ada.Direct_IO is

3          type File_Type is limited private;

4          type File_Mode is (In_File, Inout_File, Out_File);
           type Count     is range 0 .. implementation-defined;
           subtype Positive_Count is Count range 1 .. Count'Last;

5          -- File management

6          procedure Create(File : in out File_Type;
                            Mode : in File_Mode := Inout_File;
                            Name : in String := "";
                            Form : in String := "");

7          procedure Open  (File : in out File_Type;
                            Mode : in File_Mode;
                            Name : in String;
                            Form : in String := "");

8          procedure Close (File : in out File_Type);
           procedure Delete(File : in out File_Type);
           procedure Reset (File : in out File_Type; Mode : in File_Mode);
           procedure Reset (File : in out File_Type);

9          function Mode   (File : in File_Type) return File_Mode;
           function Name   (File : in File_Type) return String;
           function Form   (File : in File_Type) return String;

10         function Is_Open(File : in File_Type) return Boolean;

10.1/4  {AI12-0130-1}    procedure Flush (File : in File_Type);

11         -- Input and output operations

12         procedure Read (File : in File_Type; Item : out Element_Type;
                                                From : in Positive_Count);
           procedure Read (File : in File_Type; Item : out Element_Type);

13         procedure Write(File : in File_Type; Item : in  Element_Type;
                                                To   : in Positive_Count);
           procedure Write(File : in File_Type; Item : in Element_Type);

14         procedure Set_Index(File : in File_Type; To : in Positive_Count);

15         function Index(File : in File_Type) return Positive_Count;
           function Size (File : in File_Type) return Count;

16         function End_Of_File(File : in File_Type) return Boolean;

17         -- Exceptions

18         Status_Error : exception renames IO_Exceptions.Status_Error;
           Mode_Error   : exception renames IO_Exceptions.Mode_Error;
           Name_Error   : exception renames IO_Exceptions.Name_Error;
           Use_Error    : exception renames IO_Exceptions.Use_Error;
           Device_Error : exception renames IO_Exceptions.Device_Error;
           End_Error    : exception renames IO_Exceptions.End_Error;
           Data_Error   : exception renames IO_Exceptions.Data_Error;

19      private
           ... -- not specified by the language
        end Ada.Direct_IO;

19.a        Reason: The Element_Type formal of Direct_IO does not have an
            unknown_discriminant_part (unlike Sequential_IO) so that the
            implementation can make use of the ability to declare
            uninitialized variables of the type.

20/2 {AI95-00360-01} The type File_Type needs finalization (see 7.6) in every
instantiation of Direct_IO.

20.a.1/2    This paragraph was deleted.{8652/0097} {AI95-00115-01}
            {AI95-00344-01}


                        Incompatibilities With Ada 95

20.a/2      {AI95-00360-01} Amendment Correction: File_Type in an instance of
            Direct_IO is defined to need finalization. If the restriction
            No_Nested_Finalization (see D.7) applies to the partition, and
            File_Type does not have a controlled part, it will not be allowed
            in local objects in Ada 2005 whereas it would be allowed in
            original Ada 95. Such code is not portable, as another Ada
            compiler may have a controlled part in File_Type, and thus would
            be illegal.


                       Incompatibilities With Ada 2012

20.b/4      {AI12-0130-1} Corrigendum: The Flush procedure is newly added to
            Ada.Direct_IO. If an instance of Ada.Direct_IO is referenced in a
            use_clause, and a procedure Flush is defined in some other package
            that is also referenced in a use_clause, the user-defined Flush
            may no longer be use-visible, resulting in errors. This should be
            rare and is easily fixed if it does occur.


A.8.5 Direct Input-Output Operations



                              Static Semantics

1   The operations available for direct input and output are described in this
subclause. The exception Status_Error is propagated if any of these operations
is attempted for a file that is not open.

2       procedure Read(File : in File_Type; Item : out Element_Type;
                                            From : in  Positive_Count);
        procedure Read(File : in File_Type; Item : out Element_Type);

3           Operates on a file of mode In_File or Inout_File. In the case of
            the first form, sets the current index of the given file to the
            index value given by the parameter From. Then (for both forms)
            returns, in the parameter Item, the value of the element whose
            position in the given file is specified by the current index of
            the file; finally, increases the current index by one.

4           The exception Mode_Error is propagated if the mode of the given
            file is Out_File. The exception End_Error is propagated if the
            index to be used exceeds the size of the external file. The
            exception Data_Error can be propagated if the element read cannot
            be interpreted as a value of the subtype Element_Type (see A.13).

5       procedure Write(File : in File_Type; Item : in Element_Type;
                                             To   : in Positive_Count);
        procedure Write(File : in File_Type; Item : in Element_Type);

6           Operates on a file of mode Inout_File or Out_File. In the case of
            the first form, sets the index of the given file to the index
            value given by the parameter To. Then (for both forms) gives the
            value of the parameter Item to the element whose position in the
            given file is specified by the current index of the file; finally,
            increases the current index by one.

7           The exception Mode_Error is propagated if the mode of the given
            file is In_File. The exception Use_Error is propagated if the
            capacity of the external file is exceeded.

8       procedure Set_Index(File : in File_Type; To : in Positive_Count);

9           Operates on a file of any mode. Sets the current index of the
            given file to the given index value (which may exceed the current
            size of the file).

10      function Index(File : in File_Type) return Positive_Count;

11          Operates on a file of any mode. Returns the current index of the
            given file.

12      function Size(File : in File_Type) return Count;

13          Operates on a file of any mode. Returns the current size of the
            external file that is associated with the given file.

14      function End_Of_File(File : in File_Type) return Boolean;

15/3        {AI05-0264-1} Operates on a file of mode In_File or Inout_File.
            Returns True if the current index exceeds the size of the external
            file; otherwise, returns False.

16          The exception Mode_Error is propagated if the mode of the given
            file is Out_File.

        NOTES

17      25  Append_File mode is not supported for the generic package
        Direct_IO.


A.9 The Generic Package Storage_IO


1   The generic package Storage_IO provides for reading from and writing to an
in-memory buffer. This generic package supports the construction of
user-defined input-output packages.

1.a         Reason: This package exists to allow the portable construction of
            user-defined direct-access-oriented input-output packages. The
            Write procedure writes a value of type Element_Type into a
            Storage_Array of size Buffer_Size, flattening out any implicit
            levels of indirection used in the representation of the type. The
            Read procedure reads a value of type Element_Type from the buffer,
            reconstructing any implicit levels of indirection used in the
            representation of the type. It also properly initializes any type
            tags that appear within the value, presuming that the buffer was
            written by a different program and that tag values for the"
            same" type might vary from one executable to another.


                              Static Semantics

2   The generic library package Storage_IO has the following declaration:

3       with Ada.IO_Exceptions;
        with System.Storage_Elements;
        generic
           type Element_Type is private;
        package Ada.Storage_IO is
           pragma Preelaborate(Storage_IO);

4          Buffer_Size : constant System.Storage_Elements.Storage_Count :=
              implementation-defined;
           subtype Buffer_Type is
              System.Storage_Elements.Storage_Array(1..Buffer_Size);

5          -- Input and output operations

6          procedure Read (Buffer : in  Buffer_Type; Item : out Element_Type);

7          procedure Write(Buffer : out Buffer_Type; Item : in  Element_Type);

8          -- Exceptions

9          Data_Error   : exception renames IO_Exceptions.Data_Error;
        end Ada.Storage_IO;

10  In each instance, the constant Buffer_Size has a value that is the size
(in storage elements) of the buffer required to represent the content of an
object of subtype Element_Type, including any implicit levels of indirection
used by the implementation. The Read and Write procedures of Storage_IO
correspond to the Read and Write procedures of Direct_IO (see A.8.4), but with
the content of the Item parameter being read from or written into the
specified Buffer, rather than an external file.

10.a        Reason: As with Direct_IO, the Element_Type formal of Storage_IO
            does not have an unknown_discriminant_part so that there is a
            well-defined upper bound on the size of the buffer needed to hold
            the content of an object of the formal subtype (i.e. Buffer_Size).
            If there are no implicit levels of indirection, Buffer_Size will
            typically equal:

10.b            (Element_Type'Size + System.Storage_Unit - 1) / System.Storage_Unit

10.c        Implementation defined: The value of Buffer_Size in Storage_IO.

        NOTES

11      26  A buffer used for Storage_IO holds only one element at a time; an
        external file used for Direct_IO holds a sequence of elements.


                            Extensions to Ada 83

11.a/3      {AI05-0005-1} Storage_IO is new in Ada 95.


A.10 Text Input-Output



                              Static Semantics

1/3 {AI05-0299-1} This subclause describes the package Text_IO, which provides
facilities for input and output in human-readable form. Each file is read or
written sequentially, as a sequence of characters grouped into lines, and as a
sequence of lines grouped into pages. The specification of the package is
given below in subclause A.10.1.

2/3 {AI05-0299-1} The facilities for file management given above, in
subclauses A.8.2 and A.8.3, are available for text input-output. In place of
Read and Write, however, there are procedures Get and Put that input values of
suitable types from text files, and output values to them. These values are
provided to the Put procedures, and returned by the Get procedures, in a
parameter Item. Several overloaded procedures of these names exist, for
different types of Item. These Get procedures analyze the input sequences of
characters based on lexical elements (see Clause 2) and return the
corresponding values; the Put procedures output the given values as
appropriate lexical elements. Procedures Get and Put are also available that
input and output individual characters treated as character values rather than
as lexical elements. Related to character input are procedures to look ahead
at the next character without reading it, and to read a character "
immediately" without waiting for an end-of-line to signal availability.

3   In addition to the procedures Get and Put for numeric and enumeration
types of Item that operate on text files, analogous procedures are provided
that read from and write to a parameter of type String. These procedures
perform the same analysis and composition of character sequences as their
counterparts which have a file parameter.

4   For all Get and Put procedures that operate on text files, and for many
other subprograms, there are forms with and without a file parameter. Each
such Get procedure operates on an input file, and each such Put procedure
operates on an output file. If no file is specified, a default input file or a
default output file is used.

5   At the beginning of program execution the default input and output files
are the so-called standard input file and standard output file. These files
are open, have respectively the current modes In_File and Out_File, and are
associated with two implementation-defined external files. Procedures are
provided to change the current default input file and the current default
output file.

5.a/2       Implementation defined: The external files associated with the
            standard input, standard output, and standard error files.

5.a.1/1     Implementation Note: {8652/0113} {AI95-00087-01} The default input
            file and default output file are not the names of distinct file
            objects, but rather the role played by one or more (other) file
            object(s). Thus, they generally will be implemented as accesses to
            another file object. An implementation that implements them by
            copying them is incorrect.

6   At the beginning of program execution a default file for program-dependent
error-related text output is the so-called standard error file. This file is
open, has the current mode Out_File, and is associated with an
implementation-defined external file. A procedure is provided to change the
current default error file.

7   From a logical point of view, a text file is a sequence of pages, a page
is a sequence of lines, and a line is a sequence of characters; the end of a
line is marked by a line terminator; the end of a page is marked by the
combination of a line terminator immediately followed by a page terminator;
and the end of a file is marked by the combination of a line terminator
immediately followed by a page terminator and then a file terminator.
Terminators are generated during output; either by calls of procedures
provided expressly for that purpose; or implicitly as part of other
operations, for example, when a bounded line length, a bounded page length, or
both, have been specified for a file.

8   The actual nature of terminators is not defined by the language and hence
depends on the implementation. Although terminators are recognized or
generated by certain of the procedures that follow, they are not necessarily
implemented as characters or as sequences of characters. Whether they are
characters (and if so which ones) in any particular implementation need not
concern a user who neither explicitly outputs nor explicitly inputs control
characters. The effect of input (Get) or output (Put) of control characters
(other than horizontal tabulation) is not specified by the language.

9   The characters of a line are numbered, starting from one; the number of a
character is called its column number. For a line terminator, a column number
is also defined: it is one more than the number of characters in the line. The
lines of a page, and the pages of a file, are similarly numbered. The current
column number is the column number of the next character or line terminator to
be transferred. The current line number is the number of the current line. The
current page number is the number of the current page. These numbers are
values of the subtype Positive_Count of the type Count (by convention, the
value zero of the type Count is used to indicate special conditions).

10      type Count is range 0 .. implementation-defined;
        subtype Positive_Count is Count range 1 .. Count'Last;

11  For an output file or an append file, a maximum line length can be
specified and a maximum page length can be specified. If a value to be output
cannot fit on the current line, for a specified maximum line length, then a
new line is automatically started before the value is output; if, further,
this new line cannot fit on the current page, for a specified maximum page
length, then a new page is automatically started before the value is output.
Functions are provided to determine the maximum line length and the maximum
page length. When a file is opened with mode Out_File or Append_File, both
values are zero: by convention, this means that the line lengths and page
lengths are unbounded. (Consequently, output consists of a single line if the
subprograms for explicit control of line and page structure are not used.) The
constant Unbounded is provided for this purpose.


                            Extensions to Ada 83

11.a        Append_File is new in Ada 95.


A.10.1 The Package Text_IO



                              Static Semantics

1   The library package Text_IO has the following declaration:

2       with Ada.IO_Exceptions;
        package Ada.Text_IO is

3          type File_Type is limited private;

4          type File_Mode is (In_File, Out_File, Append_File);

5          type Count is range 0 .. implementation-defined;
           subtype Positive_Count is Count range 1 .. Count'Last;
           Unbounded : constant Count := 0; -- line and page length

6          subtype Field       is Integer range 0 .. implementation-defined;
           subtype Number_Base is Integer range 2 .. 16;

7          type Type_Set is (Lower_Case, Upper_Case);

8          -- File Management

9          procedure Create (File : in out File_Type;
                             Mode : in File_Mode := Out_File;
                             Name : in String    := "";
                             Form : in String    := "");

10         procedure Open   (File : in out File_Type;
                             Mode : in File_Mode;
                             Name : in String;
                             Form : in String := "");

11         procedure Close  (File : in out File_Type);
           procedure Delete (File : in out File_Type);
           procedure Reset  (File : in out File_Type; Mode : in File_Mode);
           procedure Reset  (File : in out File_Type);

12         function  Mode   (File : in File_Type) return File_Mode;
           function  Name   (File : in File_Type) return String;
           function  Form   (File : in File_Type) return String;

13         function  Is_Open(File : in File_Type) return Boolean;

14         -- Control of default input and output files

15         procedure Set_Input (File : in File_Type);
           procedure Set_Output(File : in File_Type);
           procedure Set_Error (File : in File_Type);

16         function Standard_Input  return File_Type;
           function Standard_Output return File_Type;
           function Standard_Error  return File_Type;

17         function Current_Input   return File_Type;
           function Current_Output  return File_Type;
           function Current_Error   return File_Type;

18         type File_Access is access constant File_Type;

19         function Standard_Input  return File_Access;
           function Standard_Output return File_Access;
           function Standard_Error  return File_Access;

20         function Current_Input   return File_Access;
           function Current_Output  return File_Access;
           function Current_Error   return File_Access;

21/1    {8652/0051} {AI95-00057-01} --Buffer control
           procedure Flush (File : in File_Type);
           procedure Flush;

22         -- Specification of line and page lengths

23         procedure Set_Line_Length(File : in File_Type; To : in Count);
           procedure Set_Line_Length(To   : in Count);

24         procedure Set_Page_Length(File : in File_Type; To : in Count);
           procedure Set_Page_Length(To   : in Count);

25         function  Line_Length(File : in File_Type) return Count;
           function  Line_Length return Count;

26         function  Page_Length(File : in File_Type) return Count;
           function  Page_Length return Count;

27         -- Column, Line, and Page Control

28         procedure New_Line   (File    : in File_Type;
                                 Spacing : in Positive_Count := 1);
           procedure New_Line   (Spacing : in Positive_Count := 1);

29         procedure Skip_Line  (File    : in File_Type;
                                 Spacing : in Positive_Count := 1);
           procedure Skip_Line  (Spacing : in Positive_Count := 1);

30         function  End_Of_Line(File : in File_Type) return Boolean;
           function  End_Of_Line return Boolean;

31         procedure New_Page   (File : in File_Type);
           procedure New_Page;

32         procedure Skip_Page  (File : in File_Type);
           procedure Skip_Page;

33         function  End_Of_Page(File : in File_Type) return Boolean;
           function  End_Of_Page return Boolean;

34         function  End_Of_File(File : in File_Type) return Boolean;
           function  End_Of_File return Boolean;

35         procedure Set_Col (File : in File_Type; To : in Positive_Count);
           procedure Set_Col (To   : in Positive_Count);

36         procedure Set_Line(File : in File_Type; To : in Positive_Count);
           procedure Set_Line(To   : in Positive_Count);

37         function Col (File : in File_Type) return Positive_Count;
           function Col  return Positive_Count;

38         function Line(File : in File_Type) return Positive_Count;
           function Line return Positive_Count;

39         function Page(File : in File_Type) return Positive_Count;
           function Page return Positive_Count;

40         -- Character Input-Output

41         procedure Get(File : in  File_Type; Item : out Character);
           procedure Get(Item : out Character);

42         procedure Put(File : in  File_Type; Item : in Character);
           procedure Put(Item : in  Character);

43         procedure Look_Ahead (File        : in  File_Type;
                                 Item        : out Character;
                                 End_Of_Line : out Boolean);
           procedure Look_Ahead (Item        : out Character;
                                 End_Of_Line : out Boolean);

44         procedure Get_Immediate(File      : in  File_Type;
                                   Item      : out Character);
           procedure Get_Immediate(Item      : out Character);

45         procedure Get_Immediate(File      : in  File_Type;
                                   Item      : out Character;
                                   Available : out Boolean);
           procedure Get_Immediate(Item      : out Character;
                                   Available : out Boolean);

46         -- String Input-Output

47         procedure Get(File : in  File_Type; Item : out String);
           procedure Get(Item : out String);

48         procedure Put(File : in  File_Type; Item : in String);
           procedure Put(Item : in  String);

49         procedure Get_Line(File : in  File_Type;
                              Item : out String;
                              Last : out Natural);
           procedure Get_Line(Item : out String; Last : out Natural);

49.1/2  {AI95-00301-01}    function Get_Line
        (File : in  File_Type) return String;
           function Get_Line return String;

50         procedure Put_Line(File : in  File_Type; Item : in String);
           procedure Put_Line(Item : in  String);

51      -- Generic packages for Input-Output of Integer Types

52         generic
              type Num is range <>;
           package Integer_IO is

53            Default_Width : Field := Num'Width;
              Default_Base  : Number_Base := 10;

54            procedure Get(File  : in  File_Type;
                            Item  : out Num;
                            Width : in Field := 0);
              procedure Get(Item  : out Num;
                            Width : in  Field := 0);

55            procedure Put(File  : in File_Type;
                            Item  : in Num;
                            Width : in Field := Default_Width;
                            Base  : in Number_Base := Default_Base);
              procedure Put(Item  : in Num;
                            Width : in Field := Default_Width;
                            Base  : in Number_Base := Default_Base);
              procedure Get(From : in  String;
                            Item : out Num;
                            Last : out Positive);
              procedure Put(To   : out String;
                            Item : in Num;
                            Base : in Number_Base := Default_Base);

56         end Integer_IO;

57         generic
              type Num is mod <>;
           package Modular_IO is

58            Default_Width : Field := Num'Width;
              Default_Base  : Number_Base := 10;

59            procedure Get(File  : in  File_Type;
                            Item  : out Num;
                            Width : in Field := 0);
              procedure Get(Item  : out Num;
                            Width : in  Field := 0);

60            procedure Put(File  : in File_Type;
                            Item  : in Num;
                            Width : in Field := Default_Width;
                            Base  : in Number_Base := Default_Base);
              procedure Put(Item  : in Num;
                            Width : in Field := Default_Width;
                            Base  : in Number_Base := Default_Base);
              procedure Get(From : in  String;
                            Item : out Num;
                            Last : out Positive);
              procedure Put(To   : out String;
                            Item : in Num;
                            Base : in Number_Base := Default_Base);

61         end Modular_IO;

62         -- Generic packages for Input-Output of Real Types

63         generic
              type Num is digits <>;
           package Float_IO is

64            Default_Fore : Field := 2;
              Default_Aft  : Field := Num'Digits-1;
              Default_Exp  : Field := 3;

65            procedure Get(File  : in  File_Type;
                            Item  : out Num;
                            Width : in  Field := 0);
              procedure Get(Item  : out Num;
                            Width : in  Field := 0);

66            procedure Put(File : in File_Type;
                            Item : in Num;
                            Fore : in Field := Default_Fore;
                            Aft  : in Field := Default_Aft;
                            Exp  : in Field := Default_Exp);
              procedure Put(Item : in Num;
                            Fore : in Field := Default_Fore;
                            Aft  : in Field := Default_Aft;
                            Exp  : in Field := Default_Exp);

67            procedure Get(From : in String;
                            Item : out Num;
                            Last : out Positive);
              procedure Put(To   : out String;
                            Item : in Num;
                            Aft  : in Field := Default_Aft;
                            Exp  : in Field := Default_Exp);
           end Float_IO;

68         generic
              type Num is delta <>;
           package Fixed_IO is

69            Default_Fore : Field := Num'Fore;
              Default_Aft  : Field := Num'Aft;
              Default_Exp  : Field := 0;

70            procedure Get(File  : in  File_Type;
                            Item  : out Num;
                            Width : in  Field := 0);
              procedure Get(Item  : out Num;
                            Width : in  Field := 0);

71            procedure Put(File : in File_Type;
                            Item : in Num;
                            Fore : in Field := Default_Fore;
                            Aft  : in Field := Default_Aft;
                            Exp  : in Field := Default_Exp);
              procedure Put(Item : in Num;
                            Fore : in Field := Default_Fore;
                            Aft  : in Field := Default_Aft;
                            Exp  : in Field := Default_Exp);

72            procedure Get(From : in  String;
                            Item : out Num;
                            Last : out Positive);
              procedure Put(To   : out String;
                            Item : in Num;
                            Aft  : in Field := Default_Aft;
                            Exp  : in Field := Default_Exp);
           end Fixed_IO;

73         generic
              type Num is delta <> digits <>;
           package Decimal_IO is

74            Default_Fore : Field := Num'Fore;
              Default_Aft  : Field := Num'Aft;
              Default_Exp  : Field := 0;

75            procedure Get(File  : in  File_Type;
                            Item  : out Num;
                            Width : in  Field := 0);
              procedure Get(Item  : out Num;
                            Width : in  Field := 0);

76            procedure Put(File : in File_Type;
                            Item : in Num;
                            Fore : in Field := Default_Fore;
                            Aft  : in Field := Default_Aft;
                            Exp  : in Field := Default_Exp);
              procedure Put(Item : in Num;
                            Fore : in Field := Default_Fore;
                            Aft  : in Field := Default_Aft;
                            Exp  : in Field := Default_Exp);

77            procedure Get(From : in  String;
                            Item : out Num;
                            Last : out Positive);
              procedure Put(To   : out String;
                            Item : in Num;
                            Aft  : in Field := Default_Aft;
                            Exp  : in Field := Default_Exp);
           end Decimal_IO;

78         -- Generic package for Input-Output of Enumeration Types

79         generic
              type Enum is (<>);
           package Enumeration_IO is

80            Default_Width   : Field := 0;
              Default_Setting : Type_Set := Upper_Case;

81            procedure Get(File : in  File_Type;
                            Item : out Enum);
              procedure Get(Item : out Enum);

82            procedure Put(File  : in File_Type;
                            Item  : in Enum;
                            Width : in Field    := Default_Width;
                            Set   : in Type_Set := Default_Setting);
              procedure Put(Item  : in Enum;
                            Width : in Field    := Default_Width;
                            Set   : in Type_Set := Default_Setting);

83            procedure Get(From : in  String;
                            Item : out Enum;
                            Last : out Positive);
              procedure Put(To   : out String;
                            Item : in  Enum;
                            Set  : in  Type_Set := Default_Setting);
           end Enumeration_IO;

84      -- Exceptions

85         Status_Error : exception renames IO_Exceptions.Status_Error;
           Mode_Error   : exception renames IO_Exceptions.Mode_Error;
           Name_Error   : exception renames IO_Exceptions.Name_Error;
           Use_Error    : exception renames IO_Exceptions.Use_Error;
           Device_Error : exception renames IO_Exceptions.Device_Error;
           End_Error    : exception renames IO_Exceptions.End_Error;
           Data_Error   : exception renames IO_Exceptions.Data_Error;
           Layout_Error : exception renames IO_Exceptions.Layout_Error;
        private
           ... -- not specified by the language
        end Ada.Text_IO;

86/2 {AI95-00360-01} The type File_Type needs finalization (see 7.6).


                        Incompatibilities With Ada 83

86.a        Append_File is a new element of enumeration type File_Mode.


                            Extensions to Ada 83

86.b        Get_Immediate, Look_Ahead, the subprograms for dealing with
            standard error, the type File_Access and its associated
            subprograms, and the generic packages Modular_IO and Decimal_IO
            are new in Ada 95.


                        Incompatibilities With Ada 95

86.c/2      {AI95-00360-01} Amendment Correction: Text_IO.File_Type is defined
            to need finalization. If the restriction No_Nested_Finalization
            (see D.7) applies to the partition, and File_Type does not have a
            controlled part, it will not be allowed in local objects in Ada
            2005 whereas it would be allowed in original Ada 95. Such code is
            not portable, as another Ada compiler may have a controlled part
            in File_Type, and thus would be illegal.


                         Wording Changes from Ada 95

86.d/2      {8652/0051} {AI95-00057-01} Corrigendum: Corrected the parameter
            mode of Flush; otherwise it could not be used on Standard_Output.

86.e/2      {AI95-00301-01} The Text_IO.Get_Line functions are new; they are
            described in A.10.7, "Input-Output of Characters and Strings".


A.10.2 Text File Management



                              Static Semantics

1   The only allowed file modes for text files are the modes In_File,
Out_File, and Append_File. The subprograms given in subclause A.8.2 for the
control of external files, and the function End_Of_File given in subclause
A.8.3 for sequential input-output, are also available for text files. There is
also a version of End_Of_File that refers to the current default input file.
For text files, the procedures have the following additional effects:

2     * For the procedures Create and Open: After a file with mode Out_File or
        Append_File is opened, the page length and line length are unbounded
        (both have the conventional value zero). After a file (of any mode) is
        opened, the current column, current line, and current page numbers are
        set to one. If the mode is Append_File, it is implementation defined
        whether a page terminator will separate preexisting text in the file
        from the new text to be written.

2.a         Reason: For a file with mode Append_File, although it may seem
            more sensible for Open to set the current column, line, and page
            number based on the number of pages in the file, the number of
            lines on the last page, and the number of columns in the last
            line, we rejected this approach because of implementation costs;
            it would require the implementation to scan the file before doing
            the append, or to do processing that would be equivalent in effect.

2.b         For similar reasons, there is no requirement to erase the last
            page terminator of the file, nor to insert an explicit page
            terminator in the case when the final page terminator of a file is
            represented implicitly by the implementation.

3     * For the procedure Close: If the file has the current mode Out_File or
        Append_File, has the effect of calling New_Page, unless the current
        page is already terminated; then outputs a file terminator.

4     * For the procedure Reset: If the file has the current mode Out_File or
        Append_File, has the effect of calling New_Page, unless the current
        page is already terminated; then outputs a file terminator. The
        current column, line, and page numbers are set to one, and the line
        and page lengths to Unbounded. If the new mode is Append_File, it is
        implementation defined whether a page terminator will separate
        preexisting text in the file from the new text to be written.

4.a         Reason: The behavior of Reset should be similar to closing a file
            and reopening it with the given mode

5   The exception Mode_Error is propagated by the procedure Reset upon an
attempt to change the mode of a file that is the current default input file,
the current default output file, or the current default error file.

        NOTES

6       27  An implementation can define the Form parameter of Create and Open
        to control effects including the following:

7         * the interpretation of line and column numbers for an interactive
            file, and

8         * the interpretation of text formats in a file created by a foreign
            program.


A.10.3 Default Input, Output, and Error Files



                              Static Semantics

1   The following subprograms provide for the control of the particular
default files that are used when a file parameter is omitted from a Get, Put,
or other operation of text input-output described below, or when
application-dependent error-related text is to be output.

2       procedure Set_Input(File : in File_Type);

3           Operates on a file of mode In_File. Sets the current default input
            file to File.

4           The exception Status_Error is propagated if the given file is not
            open. The exception Mode_Error is propagated if the mode of the
            given file is not In_File.

5       procedure Set_Output(File : in File_Type);
        procedure Set_Error (File : in File_Type);

6           Each operates on a file of mode Out_File or Append_File.
            Set_Output sets the current default output file to File. Set_Error
            sets the current default error file to File. The exception
            Status_Error is propagated if the given file is not open. The
            exception Mode_Error is propagated if the mode of the given file
            is not Out_File or Append_File.

7       function Standard_Input return File_Type;
        function Standard_Input return File_Access;

8           Returns the standard input file (see A.10), or an access value
            designating the standard input file, respectively.

9       function Standard_Output return File_Type;
        function Standard_Output return File_Access;

10          Returns the standard output file (see A.10) or an access value
            designating the standard output file, respectively.

11      function Standard_Error return File_Type;
        function Standard_Error return File_Access;

12/1        {8652/0052} {AI95-00194-01} Returns the standard error file (see
            A.10), or an access value designating the standard error file,
            respectively.

13  The Form strings implicitly associated with the opening of Standard_Input,
Standard_Output, and Standard_Error at the start of program execution are
implementation defined.

14      function Current_Input return File_Type;
        function Current_Input return File_Access;

15          Returns the current default input file, or an access value
            designating the current default input file, respectively.

16      function Current_Output return File_Type;
        function Current_Output return File_Access;

17          Returns the current default output file, or an access value
            designating the current default output file, respectively.

18      function Current_Error return File_Type;
        function Current_Error return File_Access;

19          Returns the current default error file, or an access value
            designating the current default error file, respectively.

20/1    {8652/0051} {AI95-00057-01} procedure Flush (File : in File_Type);
        procedure Flush;

21/4        {AI12-0130-1} [The effect of Flush is the same as the
            corresponding subprogram in Sequential_IO (see A.8.2).] If File is
            not explicitly specified, Current_Output is used.

21.a/4      Discussion: {AI12-0052-1} For the purpose of determining whether
            concurrent calls on text input-output subprograms are required to
            perform as specified, subprograms that implicitly operate on one
            of the default input-output files are considered to have a
            parameter of Current_Input or Current_Output (as appropriate). The
            result of Current_Output is considered to be overlapping with the
            file given to the latest call of Set_Output (or Standard_Output if
            Set_Output hasn't been called); a corresponding consideration
            applies to the result of Current_Input. See the introduction of
            Annex A for details.


                             Erroneous Execution

22/1 {8652/0053} {AI95-00063-01} The execution of a program is erroneous if it
invokes an operation on a current default input, default output, or default
error file, and if the corresponding file object is closed or no longer
exists.

22.a.1/1    Ramification: {8652/0053} {AI95-00063-01} Closing a default file,
            then setting the default file to another open file before
            accessing it is not erroneous.

23/1 This paragraph was deleted.{8652/0053} {AI95-00063-01}

        NOTES

24      28  The standard input, standard output, and standard error files
        cannot be opened, closed, reset, or deleted, because the parameter
        File of the corresponding procedures has the mode in out.

25      29  The standard input, standard output, and standard error files are
        different file objects, but not necessarily different external files.


                         Wording Changes from Ada 95

25.a/2      {8652/0051} {AI95-00057-01} Corrigendum: Corrected the parameter
            mode of Flush; otherwise it could not be used on Standard_Output.

25.b/2      {8652/0052} {AI95-00194-01} Corrigendum: Corrected Standard_Error
            so it refers to the correct file.

25.c/2      {8652/0053} {AI95-00063-01} Corrigendum: Clarified that execution
            is erroneous only when a closed default file is accessed.


                        Wording Changes from Ada 2012

25.d/4      {AI12-0130-1} Corrigendum: Moved the definition of Flush to
            A.8.2, as all input-output packages now have it.


A.10.4 Specification of Line and Page Lengths



                              Static Semantics

1   The subprograms described in this subclause are concerned with the line
and page structure of a file of mode Out_File or Append_File. They operate
either on the file given as the first parameter, or, in the absence of such a
file parameter, on the current default output file. They provide for output of
text with a specified maximum line length or page length. In these cases, line
and page terminators are output implicitly and automatically when needed. When
line and page lengths are unbounded (that is, when they have the conventional
value zero), as in the case of a newly opened file, new lines and new pages
are only started when explicitly called for.

2   In all cases, the exception Status_Error is propagated if the file to be
used is not open; the exception Mode_Error is propagated if the mode of the
file is not Out_File or Append_File.

3       procedure Set_Line_Length(File : in File_Type; To : in Count);
        procedure Set_Line_Length(To   : in Count);

4           Sets the maximum line length of the specified output or append
            file to the number of characters specified by To. The value zero
            for To specifies an unbounded line length.

4.a         Ramification: The setting does not affect the lengths of lines in
            the existing file, rather it only influences subsequent output
            operations.

5           The exception Use_Error is propagated if the specified line length
            is inappropriate for the associated external file.

6       procedure Set_Page_Length(File : in File_Type; To : in Count);
        procedure Set_Page_Length(To   : in Count);

7           Sets the maximum page length of the specified output or append
            file to the number of lines specified by To. The value zero for To
            specifies an unbounded page length.

8           The exception Use_Error is propagated if the specified page length
            is inappropriate for the associated external file.

9       function Line_Length(File : in File_Type) return Count;
        function Line_Length return Count;

10          Returns the maximum line length currently set for the specified
            output or append file, or zero if the line length is unbounded.

11      function Page_Length(File : in File_Type) return Count;
        function Page_Length return Count;

12          Returns the maximum page length currently set for the specified
            output or append file, or zero if the page length is unbounded.


A.10.5 Operations on Columns, Lines, and Pages



                              Static Semantics

1   The subprograms described in this subclause provide for explicit control
of line and page structure; they operate either on the file given as the first
parameter, or, in the absence of such a file parameter, on the appropriate
(input or output) current default file. The exception Status_Error is
propagated by any of these subprograms if the file to be used is not open.

2       procedure New_Line(File : in File_Type; Spacing : in Positive_Count := 1);
        procedure New_Line(Spacing : in Positive_Count := 1);

3           Operates on a file of mode Out_File or Append_File.

4           For a Spacing of one: Outputs a line terminator and sets the
            current column number to one. Then increments the current line
            number by one, except in the case that the current line number is
            already greater than or equal to the maximum page length, for a
            bounded page length; in that case a page terminator is output, the
            current page number is incremented by one, and the current line
            number is set to one.

5           For a Spacing greater than one, the above actions are performed
            Spacing times.

6           The exception Mode_Error is propagated if the mode is not Out_File
            or Append_File.

7       procedure Skip_Line(File  : in File_Type; Spacing : in Positive_Count := 1);
        procedure Skip_Line(Spacing : in Positive_Count := 1);

8           Operates on a file of mode In_File.

9           For a Spacing of one: Reads and discards all characters until a
            line terminator has been read, and then sets the current column
            number to one. If the line terminator is not immediately followed
            by a page terminator, the current line number is incremented by
            one. Otherwise, if the line terminator is immediately followed by
            a page terminator, then the page terminator is skipped, the
            current page number is incremented by one, and the current line
            number is set to one.

10          For a Spacing greater than one, the above actions are performed
            Spacing times.

11          The exception Mode_Error is propagated if the mode is not In_File.
            The exception End_Error is propagated if an attempt is made to
            read a file terminator.

12      function End_Of_Line(File : in File_Type) return Boolean;
        function End_Of_Line return Boolean;

13/3        {AI05-0264-1} Operates on a file of mode In_File. Returns True if
            a line terminator or a file terminator is next; otherwise, returns
            False.

14          The exception Mode_Error is propagated if the mode is not In_File.

15      procedure New_Page(File : in File_Type);
        procedure New_Page;

16          Operates on a file of mode Out_File or Append_File. Outputs a line
            terminator if the current line is not terminated, or if the
            current page is empty (that is, if the current column and line
            numbers are both equal to one). Then outputs a page terminator,
            which terminates the current page. Adds one to the current page
            number and sets the current column and line numbers to one.

17          The exception Mode_Error is propagated if the mode is not Out_File
            or Append_File.

18      procedure Skip_Page(File : in File_Type);
        procedure Skip_Page;

19          Operates on a file of mode In_File. Reads and discards all
            characters and line terminators until a page terminator has been
            read. Then adds one to the current page number, and sets the
            current column and line numbers to one.

20          The exception Mode_Error is propagated if the mode is not In_File.
            The exception End_Error is propagated if an attempt is made to
            read a file terminator.

21      function End_Of_Page(File : in File_Type) return Boolean;
        function End_Of_Page return Boolean;

22/3        {AI05-0264-1} Operates on a file of mode In_File. Returns True if
            the combination of a line terminator and a page terminator is
            next, or if a file terminator is next; otherwise, returns False.

23          The exception Mode_Error is propagated if the mode is not In_File.

24      function End_Of_File(File : in File_Type) return Boolean;
        function End_Of_File return Boolean;

25/3        {AI05-0264-1} Operates on a file of mode In_File. Returns True if
            a file terminator is next, or if the combination of a line, a
            page, and a file terminator is next; otherwise, returns False.

26          The exception Mode_Error is propagated if the mode is not In_File.

27  The following subprograms provide for the control of the current position
of reading or writing in a file. In all cases, the default file is the current
output file.

28      procedure Set_Col(File : in File_Type; To : in Positive_Count);
        procedure Set_Col(To   : in Positive_Count);

29          If the file mode is Out_File or Append_File:

30            * If the value specified by To is greater than the current
                column number, outputs spaces, adding one to the current
                column number after each space, until the current column
                number equals the specified value. If the value specified by
                To is equal to the current column number, there is no effect.
                If the value specified by To is less than the current column
                number, has the effect of calling New_Line (with a spacing of
                one), then outputs (To - 1) spaces, and sets the current
                column number to the specified value.

31            * The exception Layout_Error is propagated if the value
                specified by To exceeds Line_Length when the line length is
                bounded (that is, when it does not have the conventional value
                zero).

32          If the file mode is In_File:

33            * Reads (and discards) individual characters, line terminators,
                and page terminators, until the next character to be read has
                a column number that equals the value specified by To; there
                is no effect if the current column number already equals this
                value. Each transfer of a character or terminator maintains
                the current column, line, and page numbers in the same way as
                a Get procedure (see A.10.6). (Short lines will be skipped
                until a line is reached that has a character at the specified
                column position.)

34            * The exception End_Error is propagated if an attempt is made to
                read a file terminator.

35      procedure Set_Line(File : in File_Type; To : in Positive_Count);
        procedure Set_Line(To   : in Positive_Count);

36          If the file mode is Out_File or Append_File:

37/3          * {AI05-0038-1} If the value specified by To is greater than the
                current line number, has the effect of repeatedly calling
                New_Line (with a spacing of one), until the current line
                number equals the specified value. If the value specified by
                To is equal to the current line number, there is no effect. If
                the value specified by To is less than the current line
                number, has the effect of calling New_Page followed, if To is
                greater than 1, by a call of New_Line with a spacing equal to
                (To - 1).

38            * The exception Layout_Error is propagated if the value
                specified by To exceeds Page_Length when the page length is
                bounded (that is, when it does not have the conventional value
                zero).

39          If the mode is In_File:

40            * Has the effect of repeatedly calling Skip_Line (with a spacing
                of one), until the current line number equals the value
                specified by To; there is no effect if the current line number
                already equals this value. (Short pages will be skipped until
                a page is reached that has a line at the specified line
                position.)

41            * The exception End_Error is propagated if an attempt is made to
                read a file terminator.

42      function Col(File : in File_Type) return Positive_Count;
        function Col return Positive_Count;

43          Returns the current column number.

44          The exception Layout_Error is propagated if this number exceeds
            Count'Last.

45      function Line(File : in File_Type) return Positive_Count;
        function Line return Positive_Count;

46          Returns the current line number.

47          The exception Layout_Error is propagated if this number exceeds
            Count'Last.

48      function Page(File : in File_Type) return Positive_Count;
        function Page return Positive_Count;

49          Returns the current page number.

50          The exception Layout_Error is propagated if this number exceeds
            Count'Last.

51  The column number, line number, or page number are allowed to exceed
Count'Last (as a consequence of the input or output of sufficiently many
characters, lines, or pages). These events do not cause any exception to be
propagated. However, a call of Col, Line, or Page propagates the exception
Layout_Error if the corresponding number exceeds Count'Last.

        NOTES

52      30  A page terminator is always skipped whenever the preceding line
        terminator is skipped. An implementation may represent the combination
        of these terminators by a single character, provided that it is
        properly recognized on input.


                        Inconsistencies With Ada 2005

52.a/3      {AI05-0038-1} Correction: Fixed a glitch in Set_Line such that we
            could have called New_Line(0), which would have to raise
            Constraint_Error. It's now defined to work. The bug occurred in
            Ada 95 and Ada 2005. It's very unlikely that any real programs
            depend on this exception being raised.


A.10.6 Get and Put Procedures



                              Static Semantics

1   The procedures Get and Put for items of the type Character, String,
numeric types, and enumeration types are described in subsequent subclauses.
Features of these procedures that are common to most of these types are
described in this subclause. The Get and Put procedures for items of type
Character and String deal with individual character values; the Get and Put
procedures for numeric and enumeration types treat the items as lexical
elements.

2   All procedures Get and Put have forms with a file parameter, written
first. Where this parameter is omitted, the appropriate (input or output)
current default file is understood to be specified. Each procedure Get
operates on a file of mode In_File. Each procedure Put operates on a file of
mode Out_File or Append_File.

3   All procedures Get and Put maintain the current column, line, and page
numbers of the specified file: the effect of each of these procedures upon
these numbers is the result of the effects of individual transfers of
characters and of individual output or skipping of terminators. Each transfer
of a character adds one to the current column number. Each output of a line
terminator sets the current column number to one and adds one to the current
line number. Each output of a page terminator sets the current column and line
numbers to one and adds one to the current page number. For input, each
skipping of a line terminator sets the current column number to one and adds
one to the current line number; each skipping of a page terminator sets the
current column and line numbers to one and adds one to the current page
number. Similar considerations apply to the procedures Get_Line, Put_Line, and
Set_Col.

4   Several Get and Put procedures, for numeric and enumeration types, have
format parameters which specify field lengths; these parameters are of the
nonnegative subtype Field of the type Integer.

5/2 {AI95-00223-01} Input-output of enumeration values uses the syntax of the
corresponding lexical elements. Any Get procedure for an enumeration type
begins by skipping any leading blanks, or line or page terminators. A blank is
defined as a space or a horizontal tabulation character. Next, characters are
input only so long as the sequence input is an initial sequence of an
identifier or of a character literal (in particular, input ceases when a line
terminator is encountered). The character or line terminator that causes input
to cease remains available for subsequent input.

6   For a numeric type, the Get procedures have a format parameter called
Width. If the value given for this parameter is zero, the Get procedure
proceeds in the same manner as for enumeration types, but using the syntax of
numeric literals instead of that of enumeration literals. If a nonzero value
is given, then exactly Width characters are input, or the characters up to a
line terminator, whichever comes first; any skipped leading blanks are
included in the count. The syntax used for numeric literals is an extended
syntax that allows a leading sign (but no intervening blanks, or line or page
terminators) and that also allows (for real types) an integer literal as well
as forms that have digits only before the point or only after the point.

7   Any Put procedure, for an item of a numeric or an enumeration type,
outputs the value of the item as a numeric literal, identifier, or character
literal, as appropriate. This is preceded by leading spaces if required by the
format parameters Width or Fore (as described in later subclauses), and then a
minus sign for a negative value; for an enumeration type, the spaces follow
instead of leading. The format given for a Put procedure is overridden if it
is insufficiently wide, by using the minimum needed width.

8   Two further cases arise for Put procedures for numeric and enumeration
types, if the line length of the specified output file is bounded (that is, if
it does not have the conventional value zero). If the number of characters to
be output does not exceed the maximum line length, but is such that they
cannot fit on the current line, starting from the current column, then (in
effect) New_Line is called (with a spacing of one) before output of the item.
Otherwise, if the number of characters exceeds the maximum line length, then
the exception Layout_Error is propagated and nothing is output.

9   The exception Status_Error is propagated by any of the procedures Get,
Get_Line, Put, and Put_Line if the file to be used is not open. The exception
Mode_Error is propagated by the procedures Get and Get_Line if the mode of the
file to be used is not In_File; and by the procedures Put and Put_Line, if the
mode is not Out_File or Append_File.

10  The exception End_Error is propagated by a Get procedure if an attempt is
made to skip a file terminator. The exception Data_Error is propagated by a
Get procedure if the sequence finally input is not a lexical element
corresponding to the type, in particular if no characters were input; for this
test, leading blanks are ignored; for an item of a numeric type, when a sign
is input, this rule applies to the succeeding numeric literal. The exception
Layout_Error is propagated by a Put procedure that outputs to a parameter of
type String, if the length of the actual string is insufficient for the output
of the item.


                                  Examples

11  In the examples, here and in subclauses A.10.8 and A.10.9, the string
quotes and the lower case letter b are not transferred: they are shown only to
reveal the layout and spaces.

12      N : Integer;
           ...
        Get(N);

13      --                        Characters at input  Sequence input  
        Value of N
        
        --                        bb-12535b           -12535  -12535
        --                        bb12_535e1b         12_535e1  125350
        --                        bb12_535e;          12_535e  
        (none) Data_Error raised

14  Example of overridden width parameter:

15      Put(Item => -23, Width => 2);  --  "-23"


                         Wording Changes from Ada 95

15.a/2      {AI95-00223-01} Removed conflicting text describing the skipping
            of blanks for a Get procedure.


A.10.7 Input-Output of Characters and Strings



                              Static Semantics

1   For an item of type Character the following procedures are provided:

2       procedure Get(File : in File_Type; Item : out Character);
        procedure Get(Item : out Character);

3           After skipping any line terminators and any page terminators,
            reads the next character from the specified input file and returns
            the value of this character in the out parameter Item.

4           The exception End_Error is propagated if an attempt is made to
            skip a file terminator.

5       procedure Put(File : in File_Type; Item : in Character);
        procedure Put(Item : in Character);

6           If the line length of the specified output file is bounded (that
            is, does not have the conventional value zero), and the current
            column number exceeds it, has the effect of calling New_Line with
            a spacing of one. Then, or otherwise, outputs the given character
            to the file.

7       procedure Look_Ahead (File        : in  File_Type;
                              Item        : out Character;
                              End_Of_Line : out Boolean);
        procedure Look_Ahead (Item        : out Character;
                              End_Of_Line : out Boolean);

8/3         {AI05-0038-1} {AI05-0264-1} Status_Error is propagated if the file
            is not open. Mode_Error is propagated if the mode of the file is
            not In_File. Sets End_Of_Line to True if at end of line, including
            if at end of page or at end of file; in each of these cases the
            value of Item is not specified. Otherwise, End_Of_Line is set to
            False and Item is set to the next character (without consuming it)
            from the file.

9       procedure Get_Immediate(File : in  File_Type;
                                Item : out Character);
        procedure Get_Immediate(Item : out Character);

10/3        {AI05-0038-1} Reads the next character, either control or graphic,
            from the specified File or the default input file. Status_Error is
            propagated if the file is not open. Mode_Error is propagated if
            the mode of the file is not In_File. End_Error is propagated if at
            the end of the file. The current column, line and page numbers for
            the file are not affected.

11      procedure Get_Immediate(File      : in  File_Type;
                                Item      : out Character;
                                Available : out Boolean);
        procedure Get_Immediate(Item      : out Character;
                                Available : out Boolean);

12/3        {AI05-0038-1} If a character, either control or graphic, is
            available from the specified File or the default input file, then
            the character is read; Available is True and Item contains the
            value of this character. If a character is not available, then
            Available is False and the value of Item is not specified.
            Status_Error is propagated if the file is not open. Mode_Error is
            propagated if the mode of the file is not In_File. End_Error is
            propagated if at the end of the file. The current column, line and
            page numbers for the file are not affected.

13/2 {AI95-00301-01} For an item of type String the following subprograms are
provided:

14      procedure Get(File : in File_Type; Item : out String);
        procedure Get(Item : out String);

15          Determines the length of the given string and attempts that number
            of Get operations for successive characters of the string (in
            particular, no operation is performed if the string is null).

16      procedure Put(File : in File_Type; Item : in String);
        procedure Put(Item : in String);

17          Determines the length of the given string and attempts that number
            of Put operations for successive characters of the string (in
            particular, no operation is performed if the string is null).

17.1/2  function Get_Line(File : in File_Type) return String;
        function Get_Line return String;

17.2/2      {AI95-00301-01} Returns a result string constructed by reading
            successive characters from the specified input file, and assigning
            them to successive characters of the result string. The result
            string has a lower bound of 1 and an upper bound of the number of
            characters read. Reading stops when the end of the line is met;
            Skip_Line is then (in effect) called with a spacing of 1.

17.3/2      {AI95-00301-01} Constraint_Error is raised if the length of the
            line exceeds Positive'Last; in this case, the line number and page
            number are unchanged, and the column number is unspecified but no
            less than it was before the call. The exception End_Error is
            propagated if an attempt is made to skip a file terminator.

17.a/2      Ramification: {AI95-00301-01} Precisely what is left in the file
            is unspecified if Constraint_Error is raised because the line
            doesn't fit in a String; it should be consistent with column
            number. This allows implementers to use whatever buffering scheme
            makes sense. But the line terminator is not skipped in this case.

18      procedure Get_Line(File : in File_Type;
                           Item : out String;
                           Last : out Natural);
        procedure Get_Line(Item : out String;
                           Last : out Natural);

19          Reads successive characters from the specified input file and
            assigns them to successive characters of the specified string.
            Reading stops if the end of the string is met. Reading also stops
            if the end of the line is met before meeting the end of the
            string; in this case Skip_Line is (in effect) called with a
            spacing of 1. The values of characters not assigned are not
            specified.

20          If characters are read, returns in Last the index value such that
            Item(Last) is the last character assigned (the index of the first
            character assigned is Item'First). If no characters are read,
            returns in Last an index value that is one less than Item'First.
            The exception End_Error is propagated if an attempt is made to
            skip a file terminator.

21      procedure Put_Line(File : in File_Type; Item : in String);
        procedure Put_Line(Item : in String);

22          Calls the procedure Put for the given string, and then the
            procedure New_Line with a spacing of one.


                            Implementation Advice

23  The Get_Immediate procedures should be implemented with unbuffered input.
For a device such as a keyboard, input should be "available" if a key has
already been typed, whereas for a disk file, input should always be available
except at end of file. For a file associated with a keyboard-like device, any
line-editing features of the underlying operating system should be disabled
during the execution of Get_Immediate.

23.a/2      Implementation Advice: Get_Immediate should be implemented with
            unbuffered input; input should be available immediately;
            line-editing should be disabled.

        NOTES

24      31  Get_Immediate can be used to read a single key from the keyboard
        "immediately"; that is, without waiting for an end of line. In a call
        of Get_Immediate without the parameter Available, the caller will wait
        until a character is available.

25      32  In a literal string parameter of Put, the enclosing string bracket
        characters are not output. Each doubled string bracket character in
        the enclosed string is output as a single string bracket character, as
        a consequence of the rule for string literals (see 2.6).

26      33  A string read by Get or written by Put can extend over several
        lines. An implementation is allowed to assume that certain external
        files do not contain page terminators, in which case Get_Line and
        Skip_Line can return as soon as a line terminator is read.


                        Incompatibilities With Ada 95

26.a/3      {AI95-00301-01} {AI05-0005-1} The Get_Line functions are added to
            Ada.Text_IO. If Ada.Text_IO is referenced in a use_clause, and a
            function Get_Line is defined in a package that is also referenced
            in a use_clause, the user-defined Get_Line may no longer be
            use-visible, resulting in errors. This should be rare and is
            easily fixed if it does occur.


                            Extensions to Ada 95

26.b/2      {AI95-00301-01} The Text_IO.Get_Line functions are new.


                        Wording Changes from Ada 2005

26.c/3      {AI05-0038-1} Correction: Added missing wording about raising
            Status_Error to Look_Ahead and Get_Immediate.


A.10.8 Input-Output for Integer Types



                              Static Semantics

1   The following procedures are defined in the generic packages Integer_IO
and Modular_IO, which have to be instantiated for the appropriate signed
integer or modular type respectively (indicated by Num in the specifications).

2   Values are output as decimal or based literals, without low line
characters or exponent, and, for Integer_IO, preceded by a minus sign if
negative. The format (which includes any leading spaces and minus sign) can be
specified by an optional field width parameter. Values of widths of fields in
output formats are of the nonnegative integer subtype Field. Values of bases
are of the integer subtype Number_Base.

3       subtype Number_Base is Integer range 2 .. 16;

4   The default field width and base to be used by output procedures are
defined by the following variables that are declared in the generic packages
Integer_IO and Modular_IO:

5       Default_Width : Field := Num'Width;
        Default_Base  : Number_Base := 10;

6   The following procedures are provided:

7       procedure Get(File : in File_Type; Item : out Num; Width : in Field := 0);
        procedure Get(Item : out Num; Width : in Field := 0);

8           If the value of the parameter Width is zero, skips any leading
            blanks, line terminators, or page terminators, then reads a plus
            sign if present or (for a signed type only) a minus sign if
            present, then reads the longest possible sequence of characters
            matching the syntax of a numeric literal without a point. If a
            nonzero value of Width is supplied, then exactly Width characters
            are input, or the characters (possibly none) up to a line
            terminator, whichever comes first; any skipped leading blanks are
            included in the count.

9           Returns, in the parameter Item, the value of type Num that
            corresponds to the sequence input.

10/3        {AI05-0038-1} The exception Data_Error is propagated if the
            sequence of characters read does not form a legal integer literal
            or if the value obtained is not of the subtype Num.

11      procedure Put(File  : in File_Type;
                      Item  : in Num;
                      Width : in Field := Default_Width;
                      Base  : in Number_Base := Default_Base);
        
        procedure Put(Item  : in Num;
                      Width : in Field := Default_Width;
                      Base  : in Number_Base := Default_Base);

12          Outputs the value of the parameter Item as an integer literal,
            with no low lines, no exponent, and no leading zeros (but a single
            zero for the value zero), and a preceding minus sign for a
            negative value.

13          If the resulting sequence of characters to be output has fewer
            than Width characters, then leading spaces are first output to
            make up the difference.

14          Uses the syntax for decimal literal if the parameter Base has the
            value ten (either explicitly or through Default_Base); otherwise,
            uses the syntax for based literal, with any letters in upper case.

15      procedure Get(From : in String; Item : out Num; Last : out Positive);

16          Reads an integer value from the beginning of the given string,
            following the same rules as the Get procedure that reads an
            integer value from a file, but treating the end of the string as a
            file terminator. Returns, in the parameter Item, the value of type
            Num that corresponds to the sequence input. Returns in Last the
            index value such that From(Last) is the last character read.

17          The exception Data_Error is propagated if the sequence input does
            not have the required syntax or if the value obtained is not of
            the subtype Num.

18      procedure Put(To   : out String;
                      Item : in Num;
                      Base : in Number_Base := Default_Base);

19          Outputs the value of the parameter Item to the given string,
            following the same rule as for output to a file, using the length
            of the given string as the value for Width.

20  Integer_Text_IO is a library package that is a nongeneric equivalent to
Text_IO.Integer_IO for the predefined type Integer:

21      with Ada.Text_IO;
        package Ada.Integer_Text_IO is new Ada.Text_IO.Integer_IO(Integer);

22  For each predefined signed integer type, a nongeneric equivalent to
Text_IO.Integer_IO is provided, with names such as Ada.Long_Integer_Text_IO.


                         Implementation Permissions

23  The nongeneric equivalent packages may, but need not, be actual
instantiations of the generic package for the appropriate predefined type.

Paragraphs 24 and 25 were deleted.


                                  Examples

26/3    {AI05-0298-1} subtype Byte_Int is Integer range -127 .. 127;
        package Int_IO is new Integer_IO(Byte_Int); use Int_IO;
        -- default format used at instantiation,
        -- Default_Width = 4, Default_Base = 10

27      Put(126);                            -- "b126"
        Put(-126, 7);                        -- "bbb-126"
        Put(126, Width => 13, Base => 2);    -- "bbb2#1111110#"


                        Inconsistencies With Ada 2005

27.a/3      {AI05-0038-1} Correction: Changed wording to make Integer_IO and
            Modular_IO raise Data_Error in the same way when the bounds of the
            subtype are exceeded. There is no value to different behavior, and
            all surveyed compilers already treat integer and modular values
            the same way. This could only cause a problem if a program was
            compiled with some unsurveyed compiler, and the Ada 95-defined
            behavior is expected for Modular_IO. But note that such code is
            not portable anyway, as most widely used compilers behave
            consistently with the new wording, so it is unlikely that such
            code exists.


A.10.9 Input-Output for Real Types



                              Static Semantics

1   The following procedures are defined in the generic packages Float_IO,
Fixed_IO, and Decimal_IO, which have to be instantiated for the appropriate
floating point, ordinary fixed point, or decimal fixed point type respectively
(indicated by Num in the specifications).

2   Values are output as decimal literals without low line characters. The
format of each value output consists of a Fore field, a decimal point, an Aft
field, and (if a nonzero Exp parameter is supplied) the letter E and an Exp
field. The two possible formats thus correspond to:

3       Fore  .  Aft

4   and to:

5       Fore  .  Aft  E  Exp

6   without any spaces between these fields. The Fore field may include
leading spaces, and a minus sign for negative values. The Aft field includes
only decimal digits (possibly with trailing zeros). The Exp field includes the
sign (plus or minus) and the exponent (possibly with leading zeros).

7   For floating point types, the default lengths of these fields are defined
by the following variables that are declared in the generic package Float_IO:

8       Default_Fore : Field := 2;
        Default_Aft  : Field := Num'Digits-1;
        Default_Exp  : Field := 3;

9   For ordinary or decimal fixed point types, the default lengths of these
fields are defined by the following variables that are declared in the generic
packages Fixed_IO and Decimal_IO, respectively:

10      Default_Fore : Field := Num'Fore;
        Default_Aft  : Field := Num'Aft;
        Default_Exp  : Field := 0;

11  The following procedures are provided:

12      procedure Get(File : in File_Type; Item : out Num; Width : in Field := 0);
        procedure Get(Item : out Num; Width : in Field := 0);

13          If the value of the parameter Width is zero, skips any leading
            blanks, line terminators, or page terminators, then reads the
            longest possible sequence of characters matching the syntax of any
            of the following (see 2.4):

14            * [+|-]numeric_literal

15            * [+|-]numeral.[exponent]

16            * [+|-].numeral[exponent]

17            * [+|-]base#based_numeral.#[exponent]

18            * [+|-]base#.based_numeral#[exponent]

19          If a nonzero value of Width is supplied, then exactly Width
            characters are input, or the characters (possibly none) up to a
            line terminator, whichever comes first; any skipped leading blanks
            are included in the count.

20          Returns in the parameter Item the value of type Num that
            corresponds to the sequence input, preserving the sign (positive
            if none has been specified) of a zero value if Num is a floating
            point type and Num'Signed_Zeros is True.

21          The exception Data_Error is propagated if the sequence input does
            not have the required syntax or if the value obtained is not of
            the subtype Num.

22      procedure Put(File : in File_Type;
                      Item : in Num;
                      Fore : in Field := Default_Fore;
                      Aft  : in Field := Default_Aft;
                      Exp  : in Field := Default_Exp);
        
        procedure Put(Item : in Num;
                      Fore : in Field := Default_Fore;
                      Aft  : in Field := Default_Aft;
                      Exp  : in Field := Default_Exp);

23          Outputs the value of the parameter Item as a decimal literal with
            the format defined by Fore, Aft and Exp. If the value is negative,
            or if Num is a floating point type where Num'Signed_Zeros is True
            and the value is a negatively signed zero, then a minus sign is
            included in the integer part. If Exp has the value zero, then the
            integer part to be output has as many digits as are needed to
            represent the integer part of the value of Item, overriding Fore
            if necessary, or consists of the digit zero if the value of Item
            has no integer part.

24          If Exp has a value greater than zero, then the integer part to be
            output has a single digit, which is nonzero except for the value
            0.0 of Item.

25          In both cases, however, if the integer part to be output has fewer
            than Fore characters, including any minus sign, then leading
            spaces are first output to make up the difference. The number of
            digits of the fractional part is given by Aft, or is one if Aft
            equals zero. The value is rounded; a value of exactly one half in
            the last place is rounded away from zero.

26          If Exp has the value zero, there is no exponent part. If Exp has a
            value greater than zero, then the exponent part to be output has
            as many digits as are needed to represent the exponent part of the
            value of Item (for which a single digit integer part is used), and
            includes an initial sign (plus or minus). If the exponent part to
            be output has fewer than Exp characters, including the sign, then
            leading zeros precede the digits, to make up the difference. For
            the value 0.0 of Item, the exponent has the value zero.

27      procedure Get(From : in String; Item : out Num; Last : out Positive);

28          Reads a real value from the beginning of the given string,
            following the same rule as the Get procedure that reads a real
            value from a file, but treating the end of the string as a file
            terminator. Returns, in the parameter Item, the value of type Num
            that corresponds to the sequence input. Returns in Last the index
            value such that From(Last) is the last character read.

29          The exception Data_Error is propagated if the sequence input does
            not have the required syntax, or if the value obtained is not of
            the subtype Num.

30      procedure Put(To   : out String;
                      Item : in Num;
                      Aft  : in Field := Default_Aft;
                      Exp  : in Field := Default_Exp);

31          Outputs the value of the parameter Item to the given string,
            following the same rule as for output to a file, using a value for
            Fore such that the sequence of characters output exactly fills the
            string, including any leading spaces.

32  Float_Text_IO is a library package that is a nongeneric equivalent to
Text_IO.Float_IO for the predefined type Float:

33      with Ada.Text_IO;
        package Ada.Float_Text_IO is new Ada.Text_IO.Float_IO(Float);

34  For each predefined floating point type, a nongeneric equivalent to
Text_IO.Float_IO is provided, with names such as Ada.Long_Float_Text_IO.


                         Implementation Permissions

35  An implementation may extend Get [and Put] for floating point types to
support special values such as infinities and NaNs.

35.a/3      Discussion: {AI05-0005-1} See also the similar permission for the
            Wide_Wide_Value, Wide_Value, and Value attributes in 3.5.

36  The implementation of Put need not produce an output value with greater
accuracy than is supported for the base subtype. The additional accuracy, if
any, of the value produced by Put when the number of requested digits in the
integer and fractional parts exceeds the required accuracy is implementation
defined.

36.a        Discussion: The required accuracy is thus Num'Base'Digits digits
            if Num is a floating point subtype. For a fixed point subtype the
            required accuracy is a function of the subtype's Fore, Aft, and
            Delta attributes.

36.b        Implementation defined: The accuracy of the value produced by Put.

37  The nongeneric equivalent packages may, but need not, be actual
instantiations of the generic package for the appropriate predefined type.

        NOTES

38      34  For an item with a positive value, if output to a string exactly
        fills the string without leading spaces, then output of the
        corresponding negative value will propagate Layout_Error.

39      35  The rules for the Value attribute (see 3.5) and the rules for Get
        are based on the same set of formats.


                                  Examples

40/1    This paragraph was deleted.

41      package Real_IO is new Float_IO(Real); use Real_IO;
        -- default format used at instantiation, Default_Exp = 3

42      X : Real := -123.4567;  --  digits 8      (see 3.5.7)

43      Put(X);  -- default format                                   "-
        1.2345670E+02"
        Put(X, Fore => 5, Aft => 3, Exp => 2);                       -- "bbb-
        1.235E+2"
        Put(X, 5, 3, 0);                                             -- "b-
        123.457"


A.10.10 Input-Output for Enumeration Types



                              Static Semantics

1   The following procedures are defined in the generic package
Enumeration_IO, which has to be instantiated for the appropriate enumeration
type (indicated by Enum in the specification).

2   Values are output using either upper or lower case letters for
identifiers. This is specified by the parameter Set, which is of the
enumeration type Type_Set.

3       type Type_Set is (Lower_Case, Upper_Case);

4   The format (which includes any trailing spaces) can be specified by an
optional field width parameter. The default field width and letter case are
defined by the following variables that are declared in the generic package
Enumeration_IO:

5       Default_Width   : Field := 0;
        Default_Setting : Type_Set := Upper_Case;

6   The following procedures are provided:

7       procedure Get(File : in File_Type; Item : out Enum);
        procedure Get(Item : out Enum);

8           After skipping any leading blanks, line terminators, or page
            terminators, reads an identifier according to the syntax of this
            lexical element (lower and upper case being considered
            equivalent), or a character literal according to the syntax of
            this lexical element (including the apostrophes). Returns, in the
            parameter Item, the value of type Enum that corresponds to the
            sequence input.

9           The exception Data_Error is propagated if the sequence input does
            not have the required syntax, or if the identifier or character
            literal does not correspond to a value of the subtype Enum.

10      procedure Put(File  : in File_Type;
                      Item  : in Enum;
                      Width : in Field := Default_Width;
                      Set   : in Type_Set := Default_Setting);
        
        procedure Put(Item  : in Enum;
                      Width : in Field := Default_Width;
                      Set   : in Type_Set := Default_Setting);

11          Outputs the value of the parameter Item as an enumeration literal
            (either an identifier or a character literal). The optional
            parameter Set indicates whether lower case or upper case is used
            for identifiers; it has no effect for character literals. If the
            sequence of characters produced has fewer than Width characters,
            then trailing spaces are finally output to make up the difference.
            If Enum is a character type, the sequence of characters produced
            is as for Enum'Image(Item), as modified by the Width and Set
            parameters.

11.a/3      Discussion: {AI05-0005-1} For a character type, the literal might
            be a Wide_Wide_Character, Wide_Character, or a control character.
            Whatever Image does for these things is appropriate here, too.

11.b/3      {AI05-0036-1} The "characters produced" defines the "characters to
            be output" in the sense of A.10.6, so a result that cannot fit on
            any bounded line will raise Layout_Error.

12      procedure Get(From : in String; Item : out Enum; Last : out Positive);

13          Reads an enumeration value from the beginning of the given string,
            following the same rule as the Get procedure that reads an
            enumeration value from a file, but treating the end of the string
            as a file terminator. Returns, in the parameter Item, the value of
            type Enum that corresponds to the sequence input. Returns in Last
            the index value such that From(Last) is the last character read.

14          The exception Data_Error is propagated if the sequence input does
            not have the required syntax, or if the identifier or character
            literal does not correspond to a value of the subtype Enum.

14.a/3      To be honest: {AI05-0005-1} For a character type, it is
            permissible for the implementation to make Get do the inverse of
            what Put does, in the case of wide and wide_wide
            character_literals and control characters.

15      procedure Put(To   : out String;
                      Item : in Enum;
                      Set  : in Type_Set := Default_Setting);

16          Outputs the value of the parameter Item to the given string,
            following the same rule as for output to a file, using the length
            of the given string as the value for Width.

17/1 {8652/0054} {AI95-00007-01} Although the specification of the generic
package Enumeration_IO would allow instantiation for an integer type, this is
not the intended purpose of this generic package, and the effect of such
instantiations is not defined by the language.

        NOTES

18      36  There is a difference between Put defined for characters, and for
        enumeration values. Thus

19             Ada.Text_IO.Put('A');  --  outputs the character A

20             package Char_IO is new Ada.Text_IO.Enumeration_IO(Character);
               Char_IO.Put('A');  --  outputs the character 'A', between apostrophes

21      37  The type Boolean is an enumeration type, hence Enumeration_IO can
        be instantiated for this type.


                         Wording Changes from Ada 95

21.a/2      {8652/0054} {AI95-00007-01} Corrigendum: Corrected the wording to
            say Enumeration_IO can be instantiated with an integer type, not a
            float type.


A.10.11 Input-Output for Bounded Strings


1/2 {AI95-00428-01} The package Text_IO.Bounded_IO provides input-output in
human-readable form for Bounded_Strings.


                              Static Semantics

2/2 {AI95-00428-01} The generic library package Text_IO.Bounded_IO has the
following declaration:

3/2     with Ada.Strings.Bounded;
        generic
           with package Bounded is
                             new Ada.Strings.Bounded.Generic_Bounded_Length (<>);
        package Ada.Text_IO.Bounded_IO is

4/2        procedure Put
              (File : in File_Type;
               Item : in Bounded.Bounded_String);

5/2        procedure Put
              (Item : in Bounded.Bounded_String);

6/2        procedure Put_Line
              (File : in File_Type;
               Item : in Bounded.Bounded_String);

7/2        procedure Put_Line
              (Item : in Bounded.Bounded_String);

8/2        function Get_Line
              (File : in File_Type)
              return Bounded.Bounded_String;

9/2        function Get_Line
              return Bounded.Bounded_String;

10/2       procedure Get_Line
              (File : in File_Type; Item : out Bounded.Bounded_String);

11/2       procedure Get_Line
              (Item : out Bounded.Bounded_String);

12/2    end Ada.Text_IO.Bounded_IO;

13/2 {AI95-00428-01} For an item of type Bounded_String, the following
subprograms are provided:

14/2    procedure Put
           (File : in File_Type;
            Item : in Bounded.Bounded_String);

15/2        {AI95-00428-01} Equivalent to Text_IO.Put (File,
            Bounded.To_String(Item));

16/2    procedure Put
           (Item : in Bounded.Bounded_String);

17/2        {AI95-00428-01} Equivalent to Text_IO.Put
            (Bounded.To_String(Item));

18/2    procedure Put_Line
           (File : in File_Type;
            Item : in Bounded.Bounded_String);

19/2        {AI95-00428-01} Equivalent to Text_IO.Put_Line (File,
            Bounded.To_String(Item));

20/2    procedure Put_Line
           (Item : in Bounded.Bounded_String);

21/2        {AI95-00428-01} Equivalent to Text_IO.Put_Line
            (Bounded.To_String(Item));

22/2    function Get_Line
           (File : in File_Type)
           return Bounded.Bounded_String;

23/2        {AI95-00428-01} Returns
            Bounded.To_Bounded_String(Text_IO.Get_Line(File));

24/2    function Get_Line
           return Bounded.Bounded_String;

25/2        {AI95-00428-01} Returns
            Bounded.To_Bounded_String(Text_IO.Get_Line);

26/2    procedure Get_Line
           (File : in File_Type; Item : out Bounded.Bounded_String);

27/2        {AI95-00428-01} Equivalent to Item := Get_Line (File);

28/2    procedure Get_Line
           (Item : out Bounded.Bounded_String);

29/2        {AI95-00428-01} Equivalent to Item := Get_Line;


                            Extensions to Ada 95

29.a/2      {AI95-00428-01} Package Text_IO.Bounded_IO is new.


A.10.12 Input-Output for Unbounded Strings


1/2 {AI95-00301-01} The package Text_IO.Unbounded_IO provides input-output in
human-readable form for Unbounded_Strings.


                              Static Semantics

2/2 {AI95-00301-01} The library package Text_IO.Unbounded_IO has the following
declaration:

3/2     with Ada.Strings.Unbounded;
        package Ada.Text_IO.Unbounded_IO is

4/2        procedure Put
              (File : in File_Type;
               Item : in Strings.Unbounded.Unbounded_String);

5/2        procedure Put
              (Item : in Strings.Unbounded.Unbounded_String);

6/2        procedure Put_Line
              (File : in File_Type;
               Item : in Strings.Unbounded.Unbounded_String);

7/2        procedure Put_Line
              (Item : in Strings.Unbounded.Unbounded_String);

8/2        function Get_Line
              (File : in File_Type)
              return Strings.Unbounded.Unbounded_String;

9/2        function Get_Line
              return Strings.Unbounded.Unbounded_String;

10/2       procedure Get_Line
              (File : in File_Type; Item : out Strings.Unbounded.Unbounded_String);

11/2       procedure Get_Line
              (Item : out Strings.Unbounded.Unbounded_String);

12/2    end Ada.Text_IO.Unbounded_IO;

13/2 {AI95-00301-01} For an item of type Unbounded_String, the following
subprograms are provided:

14/2    procedure Put
           (File : in File_Type;
            Item : in Strings.Unbounded.Unbounded_String);

15/2        {AI95-00301-01} Equivalent to Text_IO.Put (File,
            Strings.Unbounded.To_String(Item));

16/2    procedure Put
           (Item : in Strings.Unbounded.Unbounded_String);

17/2        {AI95-00301-01} Equivalent to Text_IO.Put
            (Strings.Unbounded.To_String(Item));

18/2    procedure Put_Line
           (File : in File_Type;
            Item : in Strings.Unbounded.Unbounded_String);

19/2        {AI95-00301-01} Equivalent to Text_IO.Put_Line (File,
            Strings.Unbounded.To_String(Item));

20/2    procedure Put_Line
           (Item : in Strings.Unbounded.Unbounded_String);

21/2        {AI95-00301-01} Equivalent to Text_IO.Put_Line
            (Strings.Unbounded.To_String(Item));

22/2    function Get_Line
           (File : in File_Type)
           return Strings.Unbounded.Unbounded_String;

23/2        {AI95-00301-01} Returns
            Strings.Unbounded.To_Unbounded_String(Text_IO.Get_Line(File));

24/2    function Get_Line
           return Strings.Unbounded.Unbounded_String;

25/2        {AI95-00301-01} Returns
            Strings.Unbounded.To_Unbounded_String(Text_IO.Get_Line);

26/2    procedure Get_Line
           (File : in File_Type; Item : out Strings.Unbounded.Unbounded_String);

27/2        {AI95-00301-01} Equivalent to Item := Get_Line (File);

28/2    procedure Get_Line
           (Item : out Strings.Unbounded.Unbounded_String);

29/2        {AI95-00301-01} Equivalent to Item := Get_Line;


                            Extensions to Ada 95

29.a/2      {AI95-00301-01} Package Text_IO.Unbounded_IO is new.


A.11 Wide Text Input-Output and Wide Wide Text Input-Output


1/2 {AI95-00285-01} The packages Wide_Text_IO and Wide_Wide_Text_IO provide
facilities for input and output in human-readable form. Each file is read or
written sequentially, as a sequence of wide characters (or wide wide
characters) grouped into lines, and as a sequence of lines grouped into pages.


                              Static Semantics

2/2 {AI95-00285-01} {AI95-00301-01} The specification of package Wide_Text_IO
is the same as that for Text_IO, except that in each Get, Look_Ahead,
Get_Immediate, Get_Line, Put, and Put_Line subprogram, any occurrence of
Character is replaced by Wide_Character, and any occurrence of String is
replaced by Wide_String. Nongeneric equivalents of Wide_Text_IO.Integer_IO and
Wide_Text_IO.Float_IO are provided (as for Text_IO) for each predefined
numeric type, with names such as Ada.Integer_Wide_Text_IO, Ada.Long_Integer_-
Wide_Text_IO, Ada.Float_Wide_Text_IO, Ada.Long_Float_Wide_Text_IO.

3/2 {AI95-00285-01} {AI95-00301-01} The specification of package
Wide_Wide_Text_IO is the same as that for Text_IO, except that in each Get,
Look_Ahead, Get_Immediate, Get_Line, Put, and Put_Line subprogram, any
occurrence of Character is replaced by Wide_Wide_Character, and any occurrence
of String is replaced by Wide_Wide_String. Nongeneric equivalents of
Wide_Wide_Text_IO.Integer_IO and Wide_Wide_Text_IO.Float_IO are provided (as
for Text_IO) for each predefined numeric type, with names such as Ada.Integer_-
Wide_Wide_Text_IO, Ada.Long_Integer_Wide_Wide_Text_IO, Ada.Float_Wide_Wide_-
Text_IO, Ada.Long_Float_Wide_Wide_Text_IO.

4/3 {AI95-00285-01} {AI95-00428-01} {AI05-0004-1} {AI05-0092-1} The
specification of package Wide_Text_IO.Wide_Bounded_IO is the same as that for
Text_IO.Bounded_IO, except that any occurrence of Bounded_String is replaced
by Bounded_Wide_String, and any occurrence of package Bounded is replaced by
Wide_Bounded. The specification of package Wide_Wide_Text_IO.Wide_Wide_-
Bounded_IO is the same as that for Text_IO.Bounded_IO, except that any
occurrence of Bounded_String is replaced by Bounded_Wide_Wide_String, and any
occurrence of package Bounded is replaced by Wide_Wide_Bounded.

4.a/3       To be honest: {AI05-0005-1} "package Bounded" refers to both the
            package Ada.Strings.Bounded and the formal package parameter named
            Bounded.

5/3 {AI95-00285-01} {AI95-00301-01} {AI05-0092-1} The specification of package
Wide_Text_IO.Wide_Unbounded_IO is the same as that for Text_IO.Unbounded_IO,
except that any occurrence of Unbounded_String is replaced by Unbounded_-
Wide_String, and any occurrence of package Unbounded is replaced by Wide_-
Unbounded. The specification of package
Wide_Wide_Text_IO.Wide_Wide_Unbounded_IO is the same as that for
Text_IO.Unbounded_IO, except that any occurrence of Unbounded_String is
replaced by Unbounded_Wide_Wide_String, and any occurrence of package
Unbounded is replaced by Wide_Wide_Unbounded.


                            Extensions to Ada 83

5.a         Support for Wide_Character and Wide_String I/O is new in Ada 95.


                            Extensions to Ada 95

5.b/2       {AI95-00285-01} Package Wide_Wide_Text_IO is new. Be glad it
            wasn't called Double_Wide_Text_IO (for use in trailer parks) or
            Really_Wide_Text_IO.

5.c/2       {AI95-00301-01} Packages Wide_Text_IO.Wide_Unbounded_IO and
            Wide_Wide_Text_IO.Wide_Wide_Unbounded_IO are also new.

5.d/2       {AI95-00428-01} Packages Wide_Text_IO.Wide_Bounded_IO and
            Wide_Wide_Text_IO.Wide_Wide_Bounded_IO are new as well.


                        Wording Changes from Ada 2005

5.e/3       {AI05-0092-1} Correction: Corrected the names of various entities
            in the above description. Since the previously named entities
            don't exist and the intent is obvious, this is just considered a
            presentation change.


A.12 Stream Input-Output


1/2 {AI95-00285-01} The packages Streams.Stream_IO, Text_IO.Text_Streams,
Wide_Text_IO.Text_Streams, and Wide_Wide_Text_IO.Text_Streams provide
stream-oriented operations on files.


                         Wording Changes from Ada 95

1.a/2       {AI95-00285-01} Included package Wide_Wide_Text_IO.Text_Streams in
            this description.


A.12.1 The Package Streams.Stream_IO


1   [The subprograms in the child package Streams.Stream_IO provide control
over stream files. Access to a stream file is either sequential, via a call on
Read or Write to transfer an array of stream elements, or positional (if
supported by the implementation for the given file), by specifying a relative
index for an element. Since a stream file can be converted to a Stream_Access
value, calling stream-oriented attribute subprograms of different element
types with the same Stream_Access value provides heterogeneous input-output.]
See 13.13 for a general discussion of streams.


                              Static Semantics

1.1/1 {8652/0055} {AI95-00026-01} The elements of a stream file are stream
elements. If positioning is supported for the specified external file, a
current index and current size are maintained for the file as described in
A.8. If positioning is not supported, a current index is not maintained, and
the current size is implementation defined.

1.a.1/1     Implementation defined: Current size for a stream file for which
            positioning is not supported.

2   The library package Streams.Stream_IO has the following declaration:

3/3     {AI05-0283-1} with Ada.IO_Exceptions;
        package Ada.Streams.Stream_IO is
            pragma Preelaborate(Stream_IO);

4           type Stream_Access is access all Root_Stream_Type'Class;

5/4     {AI12-0102-1}     type File_Type is limited private;
            pragma Preelaborable_Initialization(File_Type);

6           type File_Mode is (In_File, Out_File, Append_File);

7           type    Count          is range 0 .. implementation-defined;
            subtype Positive_Count is Count range 1 .. Count'Last;
              -- Index into file, in stream elements.

8           procedure Create (File : in out File_Type;
                              Mode : in File_Mode := Out_File;
                              Name : in String    := "";
                              Form : in String    := "");

9           procedure Open (File : in out File_Type;
                            Mode : in File_Mode;
                            Name : in String;
                            Form : in String := "");

10          procedure Close  (File : in out File_Type);
            procedure Delete (File : in out File_Type);
            procedure Reset  (File : in out File_Type; Mode : in File_Mode);
            procedure Reset  (File : in out File_Type);

11          function Mode (File : in File_Type) return File_Mode;
            function Name (File : in File_Type) return String;
            function Form (File : in File_Type) return String;

12          function Is_Open     (File : in File_Type) return Boolean;
            function End_Of_File (File : in File_Type) return Boolean;

13          function Stream (File : in File_Type) return Stream_Access;
                -- Return stream access for use with T'Input and T'Output

14/1    This paragraph was deleted.

15          -- Read array of stream elements from file
            procedure Read (File : in  File_Type;
                            Item : out Stream_Element_Array;
                            Last : out Stream_Element_Offset;
                            From : in  Positive_Count);

16          procedure Read (File : in  File_Type;
                            Item : out Stream_Element_Array;
                            Last : out Stream_Element_Offset);

17/1    This paragraph was deleted.

18          -- Write array of stream elements into file
            procedure Write (File : in File_Type;
                             Item : in Stream_Element_Array;
                             To   : in Positive_Count);

19          procedure Write (File : in File_Type;
                             Item : in Stream_Element_Array);

20/1    This paragraph was deleted.

21          -- Operations on position within file

22          procedure Set_Index(File : in File_Type; To : in Positive_Count);

23          function Index(File : in File_Type) return Positive_Count;
            function Size (File : in File_Type) return Count;

24          procedure Set_Mode(File : in out File_Type; Mode : in File_Mode);

25/1    {8652/0051} {AI95-00057-01}     procedure Flush(File : in File_Type);

26          -- exceptions
            Status_Error : exception renames IO_Exceptions.Status_Error;
            Mode_Error   : exception renames IO_Exceptions.Mode_Error;
            Name_Error   : exception renames IO_Exceptions.Name_Error;
            Use_Error    : exception renames IO_Exceptions.Use_Error;
            Device_Error : exception renames IO_Exceptions.Device_Error;
            End_Error    : exception renames IO_Exceptions.End_Error;
            Data_Error   : exception renames IO_Exceptions.Data_Error;

27      private
           ... -- not specified by the language
        end Ada.Streams.Stream_IO;

27.1/2 {AI95-00360-01} The type File_Type needs finalization (see 7.6).

28/4 {AI95-00283-01} {AI12-0130-1} The subprograms given in subclause A.8.2
for the control of external files (Create, Open, Close, Delete, Reset, Mode,
Name, Form, Is_Open, and Flush) are available for stream files.

28.1/2 {AI95-00283-01} The End_Of_File function:

28.2/2   * Propagates Mode_Error if the mode of the file is not In_File;

28.3/3   * {AI05-0264-1} If positioning is supported for the given external
        file, the function returns True if the current index exceeds the size
        of the external file; otherwise, it returns False;

28.4/3   * {AI05-0264-1} If positioning is not supported for the given
        external file, the function returns True if no more elements can be
        read from the given file; otherwise, it returns False.

28.5/2 {8652/0055} {AI95-00026-01} {AI95-00085-01} The Set_Mode procedure sets
the mode of the file. If the new mode is Append_File, the file is positioned
to its end; otherwise, the position in the file is unchanged.

28.6/4 This paragraph was deleted.{8652/0055} {AI95-00026-01} {AI12-0130-1}

29/1 {8652/0056} {AI95-00001-01} The Stream function returns a Stream_Access
result from a File_Type object, thus allowing the stream-oriented attributes
Read, Write, Input, and Output to be used on the same file for multiple types.
Stream propagates Status_Error if File is not open.

30/2 {AI95-00256-01} The procedures Read and Write are equivalent to the
corresponding operations in the package Streams. Read propagates Mode_Error if
the mode of File is not In_File. Write propagates Mode_Error if the mode of
File is not Out_File or Append_File. The Read procedure with a Positive_Count
parameter starts reading at the specified index. The Write procedure with a
Positive_Count parameter starts writing at the specified index. For a file
that supports positioning, Read without a Positive_Count parameter starts
reading at the current index, and Write without a Positive_Count parameter
starts writing at the current index.

30.1/1 {8652/0055} {AI95-00026-01} The Size function returns the current size
of the file.

31/1 {8652/0055} {AI95-00026-01} The Index function returns the current index.

31.a/1      This paragraph was deleted.

32  The Set_Index procedure sets the current index to the specified value.

32.1/1 {8652/0055} {AI95-00026-01} If positioning is supported for the
external file, the current index is maintained as follows:

32.2/1   * {8652/0055} {AI95-00026-01} For Open and Create, if the Mode
        parameter is Append_File, the current index is set to the current size
        of the file plus one; otherwise, the current index is set to one.

32.3/1   * {8652/0055} {AI95-00026-01} For Reset, if the Mode parameter is
        Append_File, or no Mode parameter is given and the current mode is
        Append_File, the current index is set to the current size of the file
        plus one; otherwise, the current index is set to one.

32.4/1   * {8652/0055} {AI95-00026-01} For Set_Mode, if the new mode is
        Append_File, the current index is set to current size plus one;
        otherwise, the current index is unchanged.

32.5/1   * {8652/0055} {AI95-00026-01} For Read and Write without a
        Positive_Count parameter, the current index is incremented by the
        number of stream elements read or written.

32.6/1   * {8652/0055} {AI95-00026-01} For Read and Write with a
        Positive_Count parameter, the value of the current index is set to the
        value of the Positive_Count parameter plus the number of stream
        elements read or written.

33  If positioning is not supported for the given file, then a call of Index
or Set_Index propagates Use_Error. Similarly, a call of Read or Write with a
Positive_Count parameter propagates Use_Error.

33.a/2      Implementation Note: {AI95-00085-01} It is permissible for an
            implementation to implement mode Append_File using the Unix append
            mode (the O_APPEND bit). Such an implementation does not support
            positioning when the mode is Append_File, and therefore the
            operations listed above must raise Use_Error. This is acceptable
            as there is no requirement that any particular file support
            positioning; therefore it is acceptable that a file support
            positioning when opened with mode Out_File, and the same file not
            support positioning when opened with mode Append_File. But it is
            not acceptable for a file to support positioning (by allowing the
            above operations), but to do something other than the defined
            semantics (that is, always write at the end, even when explicitly
            commanded to write somewhere else).

Paragraphs 34 through 36 were deleted.


                             Erroneous Execution

36.1/1 {8652/0056} {AI95-00001-01} If the File_Type object passed to the
Stream function is later closed or finalized, and the stream-oriented
attributes are subsequently called (explicitly or implicitly) on the
Stream_Access value returned by Stream, execution is erroneous. This rule
applies even if the File_Type object was opened again after it had been
closed.

36.a.1/1    Reason: These rules are analogous to the rule for the result of
            the Current_Input, Current_Output, and Current_Error functions.
            These rules make it possible to represent a value of (some
            descendant of) Root_Stream_Type which represents a file as an
            access value, with a null value corresponding to a closed file.


                         Inconsistencies With Ada 95

36.a/3      {AI95-00283-01} {AI05-0005-1} Amendment Correction: The
            description of the subprograms for managing files was corrected so
            that they do not require truncation of the external file - a
            stream file is not a sequential file. An Ada 95 program that
            expects truncation of the stream file might not work under Ada
            2005. Note that the Ada 95 standard was ambiguous on this point
            (the normative wording seemed to require truncation, but didn't
            explain where; the AARM notes seemed to expect behavior like
            Direct_IO), and implementations varied widely. Therefore, as a
            practical matter, code that depends on stream truncation might not
            work even in Ada 95; deleting the file before opening it provides
            truncation that works in both Ada 95 and Ada 2005.


                        Incompatibilities With Ada 95

36.b/2      {AI95-00360-01} Amendment Correction: Stream_IO.File_Type is
            defined to need finalization. If the restriction
            No_Nested_Finalization (see D.7) applies to the partition, and
            File_Type does not have a controlled part, it will not be allowed
            in local objects in Ada 2005 whereas it would be allowed in
            original Ada 95. Such code is not portable, as another Ada
            compiler may have a controlled part in File_Type, and thus would
            be illegal.


                         Wording Changes from Ada 95

36.c/2      {8652/0051} {AI95-00057-01} Corrigendum: Corrected the parameter
            mode of Flush; otherwise it could not be used on Standard_Output.

36.d/2      {8652/0055} {AI95-00026-01} {AI95-00256-01} Corrigendum: Added
            wording to describe the effects of the various operations on the
            current index. The Amendment adds an explanation of the use of
            current index for Read and Write.

36.e/2      {8652/0056} {AI95-00001-01} Corrigendum: Clarified that Stream can
            raise Status_Error, and clarified that using a Stream_Access whose
            file has been closed is erroneous.

36.f/2      {AI95-00085-01} Clarified that Set_Mode can be called with the
            current mode.


                           Extensions to Ada 2005

36.g/3      {AI05-0283-1} Package Ada.Streams.Stream_IO is now preelaborated,
            allowing it to be used in more contexts (including in distributed
            systems). Note that it is not a remote types package; File_Type
            objects cannot be passed between partitions.


                           Extensions to Ada 2012

36.h/4      {AI12-0102-1} Corrigendum: Type Ada.Streams.Stream_IO.File_Type
            now has preelaborable initialization. This allows declaring
            library-level file objects in preelaborable packages (an oversight
            from the change above).


                        Wording Changes from Ada 2012

36.i/4      {AI12-0130-1} Corrigendum: The definition of the Flush procedure
            was moved to A.8.2, so that it could be shared by all of the I/O
            packages.


A.12.2 The Package Text_IO.Text_Streams


1   The package Text_IO.Text_Streams provides a function for treating a text
file as a stream.


                              Static Semantics

2   The library package Text_IO.Text_Streams has the following declaration:

3       with Ada.Streams;
        package Ada.Text_IO.Text_Streams is
           type Stream_Access is access all Streams.Root_Stream_Type'Class;

4          function Stream (File : in File_Type) return Stream_Access;
        end Ada.Text_IO.Text_Streams;

5   The Stream function has the same effect as the corresponding function in
Streams.Stream_IO.

        NOTES

6       38  The ability to obtain a stream for a text file allows
        Current_Input, Current_Output, and Current_Error to be processed with
        the functionality of streams, including the mixing of text and binary
        input-output, and the mixing of binary input-output for different
        types.

7       39  Performing operations on the stream associated with a text file
        does not affect the column, line, or page counts.


A.12.3 The Package Wide_Text_IO.Text_Streams


1   The package Wide_Text_IO.Text_Streams provides a function for treating a
wide text file as a stream.


                              Static Semantics

2   The library package Wide_Text_IO.Text_Streams has the following
declaration:

3       with Ada.Streams;
        package Ada.Wide_Text_IO.Text_Streams is
           type Stream_Access is access all Streams.Root_Stream_Type'Class;

4          function Stream (File : in File_Type) return Stream_Access;
        end Ada.Wide_Text_IO.Text_Streams;

5   The Stream function has the same effect as the corresponding function in
Streams.Stream_IO.


A.12.4 The Package Wide_Wide_Text_IO.Text_Streams


1/2 {AI95-00285-01} The package Wide_Wide_Text_IO.Text_Streams provides a
function for treating a wide wide text file as a stream.


                              Static Semantics

2/2 {AI95-00285-01} The library package Wide_Wide_Text_IO.Text_Streams has the
following declaration:

3/2     with Ada.Streams;
        package Ada.Wide_Wide_Text_IO.Text_Streams is
           type Stream_Access is access all Streams.Root_Stream_Type'Class;

4/2        function Stream (File : in File_Type) return Stream_Access;
        end Ada.Wide_Wide_Text_IO.Text_Streams;

5/2 {AI95-00285-01} The Stream function has the same effect as the
corresponding function in Streams.Stream_IO.


                            Extensions to Ada 95

5.a/2       {AI95-00285-01} Package Wide_Wide_Text_IO.Text_Streams is new.


A.13 Exceptions in Input-Output


1   The package IO_Exceptions defines the exceptions needed by the predefined
input-output packages.


                              Static Semantics

2   The library package IO_Exceptions has the following declaration:

3       package Ada.IO_Exceptions is
           pragma Pure(IO_Exceptions);

4          Status_Error : exception;
           Mode_Error   : exception;
           Name_Error   : exception;
           Use_Error    : exception;
           Device_Error : exception;
           End_Error    : exception;
           Data_Error   : exception;
           Layout_Error : exception;

5       end Ada.IO_Exceptions;

6   If more than one error condition exists, the corresponding exception that
appears earliest in the following list is the one that is propagated.

7   The exception Status_Error is propagated by an attempt to operate upon a
file that is not open, and by an attempt to open a file that is already open.

8   The exception Mode_Error is propagated by an attempt to read from, or test
for the end of, a file whose current mode is Out_File or Append_File, and also
by an attempt to write to a file whose current mode is In_File. In the case of
Text_IO, the exception Mode_Error is also propagated by specifying a file
whose current mode is Out_File or Append_File in a call of Set_Input,
Skip_Line, End_Of_Line, Skip_Page, or End_Of_Page; and by specifying a file
whose current mode is In_File in a call of Set_Output, Set_Line_Length,
Set_Page_Length, Line_Length, Page_Length, New_Line, or New_Page.

9   The exception Name_Error is propagated by a call of Create or Open if the
string given for the parameter Name does not allow the identification of an
external file. For example, this exception is propagated if the string is
improper, or, alternatively, if either none or more than one external file
corresponds to the string.

10  The exception Use_Error is propagated if an operation is attempted that is
not possible for reasons that depend on characteristics of the external file.
For example, this exception is propagated by the procedure Create, among other
circumstances, if the given mode is Out_File but the form specifies an input
only device, if the parameter Form specifies invalid access rights, or if an
external file with the given name already exists and overwriting is not
allowed.

11  The exception Device_Error is propagated if an input-output operation
cannot be completed because of a malfunction of the underlying system.

12  The exception End_Error is propagated by an attempt to skip (read past)
the end of a file.

13  The exception Data_Error can be propagated by the procedure Read (or by
the Read attribute) if the element read cannot be interpreted as a value of
the required subtype. This exception is also propagated by a procedure Get
(defined in the package Text_IO) if the input character sequence fails to
satisfy the required syntax, or if the value input does not belong to the
range of the required subtype.

14  The exception Layout_Error is propagated (in text input-output) by Col,
Line, or Page if the value returned exceeds Count'Last. The exception
Layout_Error is also propagated on output by an attempt to set column or line
numbers in excess of specified maximum line or page lengths, respectively
(excluding the unbounded cases). It is also propagated by an attempt to Put
too many characters to a string.

14.1/3 {AI05-0262-1} These exceptions are also propagated by various other
language-defined packages and operations, see the definition of those entities
for other reasons that these exceptions are propagated.

14.a/3      Reason: {AI05-0299-1} This subclause is based in Ada 95. Later
            versions of Ada (starting with Technical Corrigendum 1) have added
            a number of additional places and reasons that cause these
            exceptions. In particular, TC1 says that stream attributes need to
            raise End_Error in some circumstances; Amendment 1 adds
            Ada.Directories and a number of new places and reasons that
            Name_Error and Use_Error are raised. There are more. We don't want
            to try to update this text (or even this note!) for every possible
            reason and place that might raise one of these exceptions, so we
            add this blanket statement.


                         Documentation Requirements

15  The implementation shall document the conditions under which Name_Error,
Use_Error and Device_Error are propagated.

15.a/2      Documentation Requirement: The conditions under which
            Io_Exceptions.Name_Error, Io_Exceptions.Use_Error, and
            Io_Exceptions.Device_Error are propagated.


                         Implementation Permissions

16  If the associated check is too complex, an implementation need not
propagate Data_Error as part of a procedure Read (or the Read attribute) if
the value read cannot be interpreted as a value of the required subtype.

16.a        Ramification: An example where the implementation may choose not
            to perform the check is an enumeration type with a representation
            clause with "holes" in the range of internal codes.


                             Erroneous Execution

17  [If the element read by the procedure Read (or by the Read attribute)
cannot be interpreted as a value of the required subtype, but this is not
detected and Data_Error is not propagated, then the resulting value can be
abnormal, and subsequent references to the value can lead to erroneous
execution, as explained in 13.9.1. ]


A.14 File Sharing



                              Dynamic Semantics

1   It is not specified by the language whether the same external file can be
associated with more than one file object. If such sharing is supported by the
implementation, the following effects are defined:

2     * Operations on one text file object do not affect the column, line, and
        page numbers of any other file object.

3/1   * This paragraph was deleted.{8652/0057} {AI95-00050-01}

4     * For direct and stream files, the current index is a property of each
        file object; an operation on one file object does not affect the
        current index of any other file object.

5     * For direct and stream files, the current size of the file is a
        property of the external file.

6   All other effects are identical.


                         Wording Changes from Ada 95

6.a/2       {8652/0057} {AI95-00050-01} Corrigendum: Removed the incorrect
            statement that the external files associated with the standard
            input, standard output, and standard error files are distinct.


A.15 The Package Command_Line


1   The package Command_Line allows a program to obtain the values of its
arguments and to set the exit status code to be returned on normal
termination.

1.a/2       Implementation defined: The meaning of Argument_Count, Argument,
            and Command_Name for package Command_Line. The bounds of type
            Command_Line.Exit_Status.


                              Static Semantics

2   The library package Ada.Command_Line has the following declaration:

3       package Ada.Command_Line is
          pragma Preelaborate(Command_Line);

4         function Argument_Count return Natural;

5         function Argument (Number : in Positive) return String;

6         function Command_Name return String;

7         type Exit_Status is implementation-defined integer type;

8         Success : constant Exit_Status;
          Failure : constant Exit_Status;

9         procedure Set_Exit_Status (Code : in Exit_Status);

10      private
          ... -- not specified by the language
        end Ada.Command_Line;
        

11      function Argument_Count return Natural;

12/3        {AI05-0264-1} If the external execution environment supports
            passing arguments to a program, then Argument_Count returns the
            number of arguments passed to the program invoking the function.
            Otherwise, it returns 0. The meaning of "number of arguments" is
            implementation defined.

13      function Argument (Number : in Positive) return String;

14          If the external execution environment supports passing arguments
            to a program, then Argument returns an implementation-defined
            value corresponding to the argument at relative position Number.
            If Number is outside the range 1..Argument_Count, then
            Constraint_Error is propagated.

14.a        Ramification: If the external execution environment does not
            support passing arguments to a program, then Argument(N) for any N
            will raise Constraint_Error, since Argument_Count is 0.

15      function Command_Name return String;

16/3        {AI05-0264-1} If the external execution environment supports
            passing arguments to a program, then Command_Name returns an
            implementation-defined value corresponding to the name of the
            command invoking the program; otherwise, Command_Name returns the
            null string.

16.1/1  type Exit_Status is implementation-defined integer type;

17          The type Exit_Status represents the range of exit status values
            supported by the external execution environment. The constants
            Success and Failure correspond to success and failure,
            respectively.

18      procedure Set_Exit_Status (Code : in Exit_Status);

19          If the external execution environment supports returning an exit
            status from a program, then Set_Exit_Status sets Code as the
            status. Normal termination of a program returns as the exit status
            the value most recently set by Set_Exit_Status, or, if no such
            value has been set, then the value Success. If a program
            terminates abnormally, the status set by Set_Exit_Status is
            ignored, and an implementation-defined exit status value is set.

20          If the external execution environment does not support returning
            an exit value from a program, then Set_Exit_Status does nothing.


                         Implementation Permissions

21  An alternative declaration is allowed for package Command_Line if
different functionality is appropriate for the external execution environment.

        NOTES

22      40  Argument_Count, Argument, and Command_Name correspond to the C
        language's argc, argv[n] (for n>0) and argv[0], respectively.

22.a        To be honest: The correspondence of Argument_Count to argc is not
            direct - argc would be one more than Argument_Count, since the
            argc count includes the command name, whereas Argument_Count does
            not.


                            Extensions to Ada 83

22.b/3      {AI05-0299-1} This subclause is new in Ada 95.


A.16 The Package Directories


1/2 {AI95-00248-01} The package Directories provides operations for
manipulating files and directories, and their names.

1.a/3       Discussion: {AI05-0299-1} The notes for this subclause contain the
            expected interpretations of some of the operations on various
            target systems. "Unix" refers to the UNIX® operating system, and
            in most cases also covers Unix-like systems such as Linux and
            POSIX. "Windows®" refers to the Microsoft® Windows® 2000 operating
            system and usually also covers most other versions that use the
            Win32 API.


                              Static Semantics

2/2 {AI95-00248-01} The library package Directories has the following
declaration:

3/2     with Ada.IO_Exceptions;
        with Ada.Calendar;
        package Ada.Directories is

4/2        -- Directory and file operations:

5/2        function Current_Directory return String;

6/2        procedure Set_Directory (Directory : in String);

7/2        procedure Create_Directory (New_Directory : in String;
                                       Form          : in String := "");

8/2        procedure Delete_Directory (Directory : in String);

9/2        procedure Create_Path (New_Directory : in String;
                                  Form          : in String := "");

10/2       procedure Delete_Tree (Directory : in String);

11/2       procedure Delete_File (Name : in String);

12/2       procedure Rename (Old_Name, New_Name : in String);

13/2       procedure Copy_File (Source_Name,
                                Target_Name : in String;
                                Form        : in String := "");

14/2       -- File and directory name operations:

15/2       function Full_Name (Name : in String) return String;

16/2       function Simple_Name (Name : in String) return String;

17/2       function Containing_Directory (Name : in String) return String;

18/2       function Extension (Name : in String) return String;

19/2       function Base_Name (Name : in String) return String;

20/2       function Compose (Containing_Directory : in String := "";
                             Name                 : in String;
                             Extension            : in String := "") return String;

20.1/3  {AI05-0049-1}    type Name_Case_Kind is
              (Unknown, Case_Sensitive, Case_Insensitive, Case_Preserving);

20.2/3  {AI05-0049-1}    function Name_Case_Equivalence
         (Name : in String) return Name_Case_Kind;

21/2       -- File and directory queries:

22/2       type File_Kind is (Directory, Ordinary_File, Special_File);

23/2       type File_Size is range 0 .. implementation-defined;

24/2       function Exists (Name : in String) return Boolean;

25/2       function Kind (Name : in String) return File_Kind;

26/2       function Size (Name : in String) return File_Size;

27/2       function Modification_Time
         (Name : in String) return Ada.Calendar.Time;

28/2       -- Directory searching:

29/2       type Directory_Entry_Type is limited private;

30/2       type Filter_Type is array (File_Kind) of Boolean;

31/2       type Search_Type is limited private;

32/2       procedure Start_Search (Search    : in out Search_Type;
                                   Directory : in String;
                                   Pattern   : in String;
                                   Filter    : in Filter_Type := (others => True));

33/2       procedure End_Search (Search : in out Search_Type);

34/2       function More_Entries (Search : in Search_Type) return Boolean;

35/2       procedure Get_Next_Entry (Search : in out Search_Type;
                                     Directory_Entry : out Directory_Entry_Type);

36/2       procedure Search (
              Directory : in String;
              Pattern   : in String;
              Filter    : in Filter_Type := (others => True);
              Process   : not null access procedure (
                  Directory_Entry : in Directory_Entry_Type));

37/2       -- Operations on Directory Entries:

38/2       function Simple_Name (Directory_Entry : in Directory_Entry_Type)
               return String;

39/2       function Full_Name (Directory_Entry : in Directory_Entry_Type)
               return String;

40/2       function Kind (Directory_Entry : in Directory_Entry_Type)
               return File_Kind;

41/2       function Size (Directory_Entry : in Directory_Entry_Type)
               return File_Size;

42/2       function Modification_Time
         (Directory_Entry : in Directory_Entry_Type)
               return Ada.Calendar.Time;

43/2       Status_Error : exception renames Ada.IO_Exceptions.Status_Error;
           Name_Error   : exception renames Ada.IO_Exceptions.Name_Error;
           Use_Error    : exception renames Ada.IO_Exceptions.Use_Error;
           Device_Error : exception renames Ada.IO_Exceptions.Device_Error;

44/3    {AI05-0092-1} private
            ... -- not specified by the language
        end Ada.Directories;

45/2 {AI95-00248-01} External files may be classified as directories, special
files, or ordinary files. A directory is an external file that is a container
for files on the target system. A special file is an external file that cannot
be created or read by a predefined Ada input-output package. External files
that are not special files or directories are called ordinary files.

45.a/2      Ramification: A directory is an external file, although it may not
            have a name on some targets. A directory is not a special file, as
            it can be created and read by Directories.

45.b/2      Discussion: Devices and soft links are examples of special files
            on Windows® and Unix.

45.c/2      Even if an implementation provides a package to create and read
            soft links, such links are still special files.

46/2 {AI95-00248-01} A file name is a string identifying an external file.
Similarly, a directory name is a string identifying a directory. The
interpretation of file names and directory names is implementation-defined.

46.a/2      Implementation defined: The interpretation of file names and
            directory names.

47/2 {AI95-00248-01} The full name of an external file is a full specification
of the name of the file. If the external environment allows alternative
specifications of the name (for example, abbreviations), the full name should
not use such alternatives. A full name typically will include the names of all
of the directories that contain the item. The simple name of an external file
is the name of the item, not including any containing directory names. Unless
otherwise specified, a file name or directory name parameter in a call to a
predefined Ada input-output subprogram can be a full name, a simple name, or
any other form of name supported by the implementation.

47.a/2      Discussion: The full name on Unix is a complete path to the root.
            For Windows®, the full name includes a complete path, as well as a
            disk name ("C:") or network share name. For both systems, the
            simple name is the part of the name following the last '/' (or '\'
            for Windows®). For example, in the name
            "/usr/randy/ada-directories.ads", "ada-directories.ads" is the
            simple name.

47.b/2      Ramification: It is possible for a file or directory name to be
            neither a full name nor a simple name. For instance, the Unix name
            "../parent/myfile" is neither a full name nor a simple name.

48/2 {AI95-00248-01} The default directory is the directory that is used if a
directory or file name is not a full name (that is, when the name does not
fully identify all of the containing directories).

48.a/2      Discussion: The default directory is the one maintained by the
            familiar "cd" command on Unix and Windows®. Note that Windows®
            maintains separate default directories for each disk drive;
            implementations should use the natural implementation.

49/2 {AI95-00248-01} A directory entry is a single item in a directory,
identifying a single external file (including directories and special files).

50/2 {AI95-00248-01} For each function that returns a string, the lower bound
of the returned value is 1.

51/2 {AI95-00248-01} The following file and directory operations are provided:

52/2    function Current_Directory return String;

53/2        Returns the full directory name for the current default directory.
            The name returned shall be suitable for a future call to
            Set_Directory. The exception Use_Error is propagated if a default
            directory is not supported by the external environment.

54/2    procedure Set_Directory (Directory : in String);

55/2        Sets the current default directory. The exception Name_Error is
            propagated if the string given as Directory does not identify an
            existing directory. The exception Use_Error is propagated if the
            external environment does not support making Directory (in the
            absence of Name_Error) a default directory.

56/2    procedure Create_Directory (New_Directory : in String;
                                    Form          : in String := "");

57/2        Creates a directory with name New_Directory. The Form parameter
            can be used to give system-dependent characteristics of the
            directory; the interpretation of the Form parameter is
            implementation-defined. A null string for Form specifies the use
            of the default options of the implementation of the new directory.
            The exception Name_Error is propagated if the string given as
            New_Directory does not allow the identification of a directory.
            The exception Use_Error is propagated if the external environment
            does not support the creation of a directory with the given name
            (in the absence of Name_Error) and form.

58/2    procedure Delete_Directory (Directory : in String);

59/3        {AI05-0231-1} Deletes an existing empty directory with name
            Directory. The exception Name_Error is propagated if the string
            given as Directory does not identify an existing directory. The
            exception Use_Error is propagated if the directory is not empty or
            the external environment does not support the deletion of the
            directory with the given name (in the absence of Name_Error).

60/2    procedure Create_Path (New_Directory : in String;
                               Form          : in String := "");

61/3        {AI05-0271-1} Creates zero or more directories with name
            New_Directory. Each nonexistent directory named by New_Directory
            is created.[ For example, on a typical Unix system, Create_Path
            ("/usr/me/my"); would create directory "me" in directory "usr",
            then create directory "my" in directory "me".] The Form parameter
            can be used to give system-dependent characteristics of the
            directory; the interpretation of the Form parameter is
            implementation-defined. A null string for Form specifies the use
            of the default options of the implementation of the new directory.
            The exception Name_Error is propagated if the string given as
            New_Directory does not allow the identification of any directory.
            The exception Use_Error is propagated if the external environment
            does not support the creation of any directories with the given
            name (in the absence of Name_Error) and form. If Use_Error is
            propagated, it is unspecified whether a portion of the directory
            path is created.

62/2    procedure Delete_Tree (Directory : in String);

63/2        Deletes an existing directory with name Directory. The directory
            and all of its contents (possibly including other directories) are
            deleted. The exception Name_Error is propagated if the string
            given as Directory does not identify an existing directory. The
            exception Use_Error is propagated if the external environment does
            not support the deletion of the directory or some portion of its
            contents with the given name (in the absence of Name_Error). If
            Use_Error is propagated, it is unspecified whether a portion of
            the contents of the directory is deleted.

64/2    procedure Delete_File (Name : in String);

65/2        Deletes an existing ordinary or special file with name Name. The
            exception Name_Error is propagated if the string given as Name
            does not identify an existing ordinary or special external file.
            The exception Use_Error is propagated if the external environment
            does not support the deletion of the file with the given name (in
            the absence of Name_Error).

66/2    procedure Rename (Old_Name, New_Name : in String);

67/3        {AI05-0231-1} Renames an existing external file (including
            directories) with name Old_Name to New_Name. The exception
            Name_Error is propagated if the string given as Old_Name does not
            identify an existing external file or if the string given as
            New_Name does not allow the identification of an external file.
            The exception Use_Error is propagated if the external environment
            does not support the renaming of the file with the given name (in
            the absence of Name_Error). In particular, Use_Error is propagated
            if a file or directory already exists with name New_Name.

67.a/2      Implementation Note: This operation is expected to work within a
            single directory, and implementers are encouraged to support it
            across directories on a single device. Copying files from one
            device to another is discouraged (that's what Copy_File is for).
            However, there is no requirement to detect file copying by the
            target system. If the target system has an API that gives that for
            "free", it can be used. For Windows®, for instance, MoveFile can
            be used to implement Rename.

68/3    {AI05-0092-1} procedure Copy_File (Source_Name,
                             Target_Name : in String;
                             Form        : in String := "");

69/3        {AI05-0271-1} Copies the contents of the existing external file
            with name Source_Name to an external file with name Target_Name.
            The resulting external file is a duplicate of the source external
            file. The Form parameter can be used to give system-dependent
            characteristics of the resulting external file; the interpretation
            of the Form parameter is implementation-defined. Exception
            Name_Error is propagated if the string given as Source_Name does
            not identify an existing external ordinary or special file, or if
            the string given as Target_Name does not allow the identification
            of an external file. The exception Use_Error is propagated if the
            external environment does not support creating the file with the
            name given by Target_Name and form given by Form, or copying of
            the file with the name given by Source_Name (in the absence of
            Name_Error). If Use_Error is propagated, it is unspecified whether
            a portion of the file is copied.

69.a/2      Ramification: Name_Error is always raised if Source_Name
            identifies a directory. It is up to the implementation whether
            special files can be copied, or if Use_Error will be raised.

70/2 {AI95-00248-01} The following file and directory name operations are
provided:

71/2    function Full_Name (Name : in String) return String;

72/2        Returns the full name corresponding to the file name specified by
            Name. The exception Name_Error is propagated if the string given
            as Name does not allow the identification of an external file
            (including directories and special files).

72.a/2      Discussion: Full name means that no abbreviations are used in the
            returned name, and that it is a full specification of the name.
            Thus, for Unix and Windows®, the result should be a full path that
            does not contain any "." or ".." directories. Typically, the
            default directory is used to fill in any missing information.

73/2    function Simple_Name (Name : in String) return String;

74/2        Returns the simple name portion of the file name specified by
            Name. The exception Name_Error is propagated if the string given
            as Name does not allow the identification of an external file
            (including directories and special files).

75/2    function Containing_Directory (Name : in String) return String;

76/2        Returns the name of the containing directory of the external file
            (including directories) identified by Name. (If more than one
            directory can contain Name, the directory name returned is
            implementation-defined.) The exception Name_Error is propagated if
            the string given as Name does not allow the identification of an
            external file. The exception Use_Error is propagated if the
            external file does not have a containing directory.

76.a/2      Discussion: This is purely a string manipulation function. If Name
            is not given as a full name, the containing directory probably
            won't be one, either. For example, if Containing_Directory
            ("..\AARM\RM-A-8") is called on Windows®, the result should be
            "..\AARM". If there is no path at all on the name, the result
            should be "." (which represents the current directory). Use
            Full_Name on the result of Containing_Directory if the full name
            is needed.

77/2    function Extension (Name : in String) return String;

78/2        Returns the extension name corresponding to Name. The extension
            name is a portion of a simple name (not including any separator
            characters), typically used to identify the file class. If the
            external environment does not have extension names, then the null
            string is returned. The exception Name_Error is propagated if the
            string given as Name does not allow the identification of an
            external file.

78.a/2      Discussion: For Unix and Windows®, the extension is the portion of
            the simple name following the rightmost period. For example, in
            the simple name "RM-A-8.html", the extension is "html".

79/2    function Base_Name (Name : in String) return String;

80/2        Returns the base name corresponding to Name. The base name is the
            remainder of a simple name after removing any extension and
            extension separators. The exception Name_Error is propagated if
            the string given as Name does not allow the identification of an
            external file (including directories and special files).

80.a/2      Discussion: For Unix and Windows®, the base name is the portion of
            the simple name preceding the rightmost period (except for the
            special directory names "." and "..", whose Base_Name is "." and
            ".."). For example, in the simple name "RM-A-8.html", the base
            name is "RM-A-8".

81/2    function Compose (Containing_Directory : in String := "";
                          Name                 : in String;
                          Extension            : in String := "") return String;

82/3        {AI05-0264-1} Returns the name of the external file with the
            specified Containing_Directory, Name, and Extension. If Extension
            is the null string, then Name is interpreted as a simple name;
            otherwise, Name is interpreted as a base name. The exception
            Name_Error is propagated if the string given as
            Containing_Directory is not null and does not allow the
            identification of a directory, or if the string given as Extension
            is not null and is not a possible extension, or if the string
            given as Name is not a possible simple name (if Extension is null)
            or base name (if Extension is nonnull).

82.a/2      Ramification: The above definition implies that if the Extension
            is null, for Unix and Windows® no '.' is added to Name.

82.b/2      Discussion: If Name is null, Name_Error should be raised, as
            nothing is not a possible simple name or base name.

82.c/2      Generally, Compose(Containing_Directory(F),
            Base_Name(F),Extension(F)) = F. However, this is not true on Unix
            or Windows® for file names that end with a '.';
            Compose(Base_Name("Fooey."),Extension("Fooey.")) = "Fooey". This
            is not a problem for Windows®, as the names have the same meaning
            with or without the '.', but these are different names for Unix.
            Thus, care needs to be taken on Unix; if Extension is null,
            Base_Name should be avoided. (That's not usually a problem with
            file names generated by a program.)

82.1/3  {AI05-0049-1}
        function Name_Case_Equivalence (Name : in String) return Name_Case_Kind;

82.2/3      {AI05-0049-1} {AI05-0248-1} Returns the file name equivalence rule
            for the directory containing Name. Raises Name_Error if Name is
            not a full name. Returns Case_Sensitive if file names that differ
            only in the case of letters are considered different names. If
            file names that differ only in the case of letters are considered
            the same name, then Case_Preserving is returned if names have the
            case of the file name used when a file is created; and
            Case_Insensitive is returned otherwise. Returns Unknown if the
            file name equivalence is not known.

82.c.1/3    Implementation Note: Unix, Linux, and their relatives are
            Case_Sensitive systems. Microsoft® Windows® is a Case_Preserving
            system (unless the rarely used POSIX mode is used). Ancient
            systems like CP/M and early MS-DOS were Case_Insensitive systems
            (file names were always in UPPER CASE). Unknown is provided in
            case it is impossible to tell (such as could be the case for
            network files).

83/2 {AI95-00248-01} The following file and directory queries and types are
provided:

84/2    type File_Kind is (Directory, Ordinary_File, Special_File);

85/2        The type File_Kind represents the kind of file represented by an
            external file or directory.

86/2    type File_Size is range 0 .. implementation-defined;

87/2        The type File_Size represents the size of an external file.

87.a/2      Implementation defined: The maximum value for a file size in
            Directories.

88/2    function Exists (Name : in String) return Boolean;

89/2        Returns True if an external file represented by Name exists, and
            False otherwise. The exception Name_Error is propagated if the
            string given as Name does not allow the identification of an
            external file (including directories and special files).

90/2    function Kind (Name : in String) return File_Kind;

91/2        Returns the kind of external file represented by Name. The
            exception Name_Error is propagated if the string given as Name
            does not allow the identification of an existing external file.

92/2    function Size (Name : in String) return File_Size;

93/2        Returns the size of the external file represented by Name. The
            size of an external file is the number of stream elements
            contained in the file. If the external file is not an ordinary
            file, the result is implementation-defined. The exception
            Name_Error is propagated if the string given as Name does not
            allow the identification of an existing external file. The
            exception Constraint_Error is propagated if the file size is not a
            value of type File_Size.

93.a/2      Implementation defined: The result for Directories.Size for a
            directory or special file

93.b/2      Discussion: We allow raising Constraint_Error, so that an
            implementation for a system with 64-bit file sizes does not need
            to support full numerics on 64-bit integers just to implement this
            package. Of course, if 64-bit integers are available on such a
            system, they should be used when defining type File_Size.

94/2    function Modification_Time (Name : in String) return Ada.Calendar.Time;

95/2        Returns the time that the external file represented by Name was
            most recently modified. If the external file is not an ordinary
            file, the result is implementation-defined. The exception
            Name_Error is propagated if the string given as Name does not
            allow the identification of an existing external file. The
            exception Use_Error is propagated if the external environment does
            not support reading the modification time of the file with the
            name given by Name (in the absence of Name_Error).

95.a/2      Implementation defined: The result for
            Directories.Modification_Time for a directory or special file.

96/2 {AI95-00248-01} The following directory searching operations and types
are provided:

97/2    type Directory_Entry_Type is limited private;

98/2        The type Directory_Entry_Type represents a single item in a
            directory. These items can only be created by the Get_Next_Entry
            procedure in this package. Information about the item can be
            obtained from the functions declared in this package. A
            default-initialized object of this type is invalid; objects
            returned from Get_Next_Entry are valid.

99/2    type Filter_Type is array (File_Kind) of Boolean;

100/2       The type Filter_Type specifies which directory entries are
            provided from a search operation. If the Directory component is
            True, directory entries representing directories are provided. If
            the Ordinary_File component is True, directory entries
            representing ordinary files are provided. If the Special_File
            component is True, directory entries representing special files
            are provided.

101/2   type Search_Type is limited private;

102/2       The type Search_Type contains the state of a directory search. A
            default-initialized Search_Type object has no entries available
            (function More_Entries returns False). Type Search_Type needs
            finalization (see 7.6).

103/2   procedure Start_Search (Search    : in out Search_Type;
                                Directory : in String;
                                Pattern   : in String;
                                Filter    : in Filter_Type := (others => True));

104/3       {AI05-0092-1} {AI05-0262-1} Starts a search in the directory named
            by Directory for entries matching Pattern and Filter. Pattern
            represents a pattern for matching file names. If Pattern is the
            null string, all items in the directory are matched; otherwise,
            the interpretation of Pattern is implementation-defined. Only
            items that match Filter will be returned. After a successful call
            on Start_Search, the object Search may have entries available, but
            it may have no entries available if no files or directories match
            Pattern and Filter. The exception Name_Error is propagated if the
            string given by Directory does not identify an existing directory,
            or if Pattern does not allow the identification of any possible
            external file or directory. The exception Use_Error is propagated
            if the external environment does not support the searching of the
            directory with the given name (in the absence of Name_Error). When
            Start_Search propagates Name_Error or Use_Error, the object Search
            will have no entries available.

104.a/2     Implementation defined: The interpretation of a nonnull search
            pattern in Directories.

105/2   procedure End_Search (Search : in out Search_Type);

106/2       Ends the search represented by Search. After a successful call on
            End_Search, the object Search will have no entries available.

106.a/2     Ramification: The only way that a call to End_Search could be
            unsuccessful if Device_Error (see A.13) is raised because of an
            underlying failure (or bug).

107/2   function More_Entries (Search : in Search_Type) return Boolean;

108/2       Returns True if more entries are available to be returned by a
            call to Get_Next_Entry for the specified search object, and False
            otherwise.

109/2   procedure Get_Next_Entry (Search : in out Search_Type;
                                  Directory_Entry : out Directory_Entry_Type);

110/3       {AI05-0262-1} Returns the next Directory_Entry for the search
            described by Search that matches the pattern and filter. If no
            further matches are available, Status_Error is raised. It is
            implementation-defined as to whether the results returned by this
            subprogram are altered if the contents of the directory are
            altered while the Search object is valid (for example, by another
            program). The exception Use_Error is propagated if the external
            environment does not support continued searching of the directory
            represented by Search.

110.a/2     Implementation defined: The results of a Directories search if the
            contents of the directory are altered while a search is in
            progress.

111/2   procedure Search (
            Directory : in String;
            Pattern   : in String;
            Filter    : in Filter_Type := (others => True);
            Process   : not null access procedure (
                Directory_Entry : in Directory_Entry_Type));

112/3       {AI05-0092-1} {AI05-0262-1} Searches in the directory named by
            Directory for entries matching Pattern and Filter. The subprogram
            designated by Process is called with each matching entry in turn.
            Pattern represents a pattern for matching file names. If Pattern
            is the null string, all items in the directory are matched;
            otherwise, the interpretation of Pattern is
            implementation-defined. Only items that match Filter will be
            returned. The exception Name_Error is propagated if the string
            given by Directory does not identify an existing directory, or if
            Pattern does not allow the identification of any possible external
            file or directory. The exception Use_Error is propagated if the
            external environment does not support the searching of the
            directory with the given name (in the absence of Name_Error).

112.a/2     Discussion: "In turn" means that the calls to the subprogram
            designated by Process are not made in parallel; they can be made
            in any order but must be in sequence.

113/2   function Simple_Name (Directory_Entry : in Directory_Entry_Type)
             return String;

114/2       Returns the simple external name of the external file (including
            directories) represented by Directory_Entry. The format of the
            name returned is implementation-defined. The exception
            Status_Error is propagated if Directory_Entry is invalid.

115/2   function Full_Name (Directory_Entry : in Directory_Entry_Type)
             return String;

116/2       Returns the full external name of the external file (including
            directories) represented by Directory_Entry. The format of the
            name returned is implementation-defined. The exception
            Status_Error is propagated if Directory_Entry is invalid.

117/2   function Kind (Directory_Entry : in Directory_Entry_Type)
             return File_Kind;

118/2       Returns the kind of external file represented by Directory_Entry.
            The exception Status_Error is propagated if Directory_Entry is
            invalid.

119/2   function Size (Directory_Entry : in Directory_Entry_Type)
             return File_Size;

120/2       Returns the size of the external file represented by
            Directory_Entry. The size of an external file is the number of
            stream elements contained in the file. If the external file
            represented by Directory_Entry is not an ordinary file, the result
            is implementation-defined. The exception Status_Error is
            propagated if Directory_Entry is invalid. The exception
            Constraint_Error is propagated if the file size is not a value of
            type File_Size.

121/2   function Modification_Time (Directory_Entry : in Directory_Entry_Type)
             return Ada.Calendar.Time;

122/2       Returns the time that the external file represented by
            Directory_Entry was most recently modified. If the external file
            represented by Directory_Entry is not an ordinary file, the result
            is implementation-defined. The exception Status_Error is
            propagated if Directory_Entry is invalid. The exception Use_Error
            is propagated if the external environment does not support reading
            the modification time of the file represented by Directory_Entry.


                         Implementation Requirements

123/2 For Copy_File, if Source_Name identifies an existing external ordinary
file created by a predefined Ada input-output package, and Target_Name and
Form can be used in the Create operation of that input-output package with
mode Out_File without raising an exception, then Copy_File shall not propagate
Use_Error.

123.a/2     Discussion: This means that Copy_File will copy any file that the
            Ada programmer could copy (by writing some possibly complicated
            Ada code).


                            Implementation Advice

124/2 If other information about a file (such as the owner or creation date)
is available in a directory entry, the implementation should provide functions
in a child package Directories.Information to retrieve it.

124.a/2     Implementation Advice: Package Directories.Information should be
            provided to retrieve other information about a file.

124.b/2     Implementation Note: For Windows®, Directories.Information should
            contain at least the following routines:

124.c/2         package Ada.Directories.Information is
                    -- System-specific directory information.
                    -- Version for the Microsoft® Windows® operating system.

124.d/2             function Creation_Time (Name : in String) return Ada.Calendar.Time;

124.e/2             function Last_Access_Time (Name : in String) return Ada.Calendar.Time;

124.f/2             function Is_Read_Only (Name : in String) return Boolean;

124.g/2             function Needs_Archiving (Name : in String) return Boolean;
                        -- This generally means that the file needs to be backed up.
                        -- The flag is only cleared by backup programs.

124.h/2             function Is_Compressed (Name : in String) return Boolean;

124.i/2             function Is_Encrypted (Name : in String) return Boolean;

124.j/2             function Is_Hidden (Name : in String) return Boolean;

124.k/2             function Is_System (Name : in String) return Boolean;

124.l/2             function Is_Offline (Name : in String) return Boolean;

124.m/2             function Is_Temporary (Name : in String) return Boolean;

124.n/2             function Is_Sparse (Name : in String) return Boolean;

124.o/2             function Is_Not_Indexed (Name : in String) return Boolean;

124.p/2             function Creation_Time (Directory_Entry : in Directory_Entry_Type)
                         return Ada.Calendar.Time;

124.q/2             function Last_Access_Time (Directory_Entry : in Directory_Entry_Type)
                         return Ada.Calendar.Time;

124.r/2             function Is_Read_Only (Directory_Entry : in Directory_Entry_Type) return Boolean;

124.s/2             function Needs_Archiving (Directory_Entry : in Directory_Entry_Type) return Boolean;
                        -- This generally means that the file needs to be backed up.
                        -- The flag is only cleared by backup programs.

124.t/2             function Is_Compressed (Directory_Entry : in Directory_Entry_Type) return Boolean;

124.u/2             function Is_Encrypted (Directory_Entry : in Directory_Entry_Type) return Boolean;

124.v/2             function Is_Hidden (Directory_Entry : in Directory_Entry_Type) return Boolean;

124.w/2             function Is_System (Directory_Entry : in Directory_Entry_Type) return Boolean;

124.x/2             function Is_Offline (Directory_Entry : in Directory_Entry_Type) return Boolean;

124.y/2             function Is_Temporary (Directory_Entry : in Directory_Entry_Type) return Boolean;

124.z/2             function Is_Sparse (Directory_Entry : in Directory_Entry_Type) return Boolean;

124.aa/2            function Is_Not_Indexed (Directory_Entry : in Directory_Entry_Type) return Boolean;

124.bb/2            -- Additional implementation-defined subprograms allowed here.
                end Ada.Directories.Information;

124.cc/2    For Unix-like systems (Unix, POSIX, Linux, etc.),
            Directories.Information should contain at least the following
            routines:

124.dd/2        package Ada.Directories.Information is
                    -- System-specific directory information.
                    -- Unix and similar systems version.

124.ee/2            function Last_Access_Time (Name : in String) return Ada.Calendar.Time;

124.ff/2            function Last_Status_Change_Time (Name : in String) return Ada.Calendar.Time;

124.gg/2            type Permission is
                      (Others_Execute, Others_Write, Others_Read,
                       Group_Execute,  Group_Write,  Group_Read,
                       Owner_Execute,  Owner_Write,  Owner_Read,
                       Set_Group_ID,   Set_User_ID);

124.hh/2            type Permission_Set_Type is array (Permission) of Boolean;

124.ii/2            function Permission_Set (Name : in String) return Permission_Set_Type;

124.jj/2            function Owner (Name : in String) return String;
                        -- Returns the image of the User_Id. If a definition of User_Id
                        -- is available, an implementation-defined version of Owner
                        -- returning User_Id should also be defined.

124.kk/3        {AI05-0005-1}
                    function Group (Name : in String) return String;
                        -- Returns the image of the Group_Id. If a definition of Group_Id
                        -- is available, an implementation-defined version of Group
                        -- returning Group_Id should also be defined.

124.ll/2            function Is_Block_Special_File (Name : in String) return Boolean;

124.mm/2            function Is_Character_Special_File (Name : in String) return Boolean;

124.nn/2            function Is_FIFO (Name : in String) return Boolean;

124.oo/2            function Is_Symbolic_Link (Name : in String) return Boolean;

124.pp/2            function Is_Socket (Name : in String) return Boolean;

124.qq/2            function Last_Access_Time (Directory_Entry : in Directory_Entry_Type)
                       return Ada.Calendar.Time;

124.rr/2            function Last_Status_Change_Time (Directory_Entry : in Directory_Entry_Type)
                       return Ada.Calendar.Time;

124.ss/2            function Permission_Set (Directory_Entry : in Directory_Entry_Type)
                       return Permission_Set_Type;

124.tt/2            function Owner (Directory_Entry : in Directory_Entry_Type) return String;
                       -- See Owner above.

124.uu/2            function Group (Directory_Entry : in Directory_Entry_Type) return String;
                       -- See Group above.

124.vv/2            function Is_Block_Special_File (Directory_Entry : in Directory_Entry_Type)
                       return Boolean;

124.ww/2            function Is_Character_Special_File (Directory_Entry : in Directory_Entry_Type)
                       return Boolean;

124.xx/2            function Is_FIFO (Directory_Entry : in Directory_Entry_Type) return Boolean;

124.yy/2            function Is_Symbolic_Link (Directory_Entry : in Directory_Entry_Type)
                       return Boolean;

124.zz/2            function Is_Socket (Directory_Entry : in Directory_Entry_Type) return Boolean;

124.aaa/2           -- Additional implementation-defined subprograms allowed here.
                end Ada.Directories.Information;

124.bbb/2   We give these definitions to give guidance so that every
            implementation for a given target is not unnecessarily different.
            Implementers are encouraged to make packages for other targets as
            similar to these as possible.

125/3 {AI05-0231-1} Start_Search and Search should raise Name_Error if Pattern
is malformed, but not if it could represent a file in the directory but does
not actually do so.

125.a/3     Implementation Advice: Directories.Start_Search and
            Directories.Search should raise Name_Error for malformed patterns.

126/2 Rename should be supported at least when both New_Name and Old_Name are
simple names and New_Name does not identify an existing external file.

126.a/2     Implementation Advice: Directories.Rename should be supported at
            least when both New_Name and Old_Name are simple names and
            New_Name does not identify an existing external file.

126.b/2     Discussion: "Supported" includes raising an exception if either
            name is malformed, the file to rename doesn't exist, insufficient
            permission for the operation exists, or similar problems. But this
            advice requires implementations to document what they do, and
            tells implementers that simply raising Use_Error isn't acceptable.

        NOTES

127/2   41  The operations Containing_Directory, Full_Name, Simple_Name,
        Base_Name, Extension, and Compose operate on file names, not external
        files. The files identified by these operations do not need to exist.
        Name_Error is raised only if the file name is malformed and cannot
        possibly identify a file. Of these operations, only the result of
        Full_Name depends on the current default directory; the result of the
        others depends only on their parameters.

128/2   42  Using access types, values of Search_Type and Directory_Entry_Type
        can be saved and queried later. However, another task or application
        can modify or delete the file represented by a Directory_Entry_Type
        value or the directory represented by a Search_Type value; such a
        value can only give the information valid at the time it is created.
        Therefore, long-term storage of these values is not recommended.

129/2   43  If the target system does not support directories inside of
        directories, then Kind will never return Directory and
        Containing_Directory will always raise Use_Error.

130/2   44  If the target system does not support creation or deletion of
        directories, then Create_Directory, Create_Path, Delete_Directory, and
        Delete_Tree will always propagate Use_Error.

131/2   45  To move a file or directory to a different location, use Rename.
        Most target systems will allow renaming of files from one directory to
        another. If the target file or directory might already exist, it
        should be deleted first.

131.a/2     Discussion: While Rename is only guaranteed to work for name
            changes within a single directory, its unlikely that implementers
            would purposely prevent functionality present in the underlying
            system from working. To move a file totally portably, it's
            necessary to handle failure of the Rename and fall back to
            Copy_File and Delete:

131.b           begin
                   Rename (Source, Target);
                exception
                   when Use_Error =>
                      Copy_File (Source, Target);
                      Delete (Source);
                end;


                            Extensions to Ada 95

131.c/2     {AI95-00248-01} Package Ada.Directories is new.


                        Inconsistencies With Ada 2005

131.d/3     {AI05-0231-1} Correction: Clarified when and which exceptions are
            raised for Start_Search, Search, Delete_Directory, and Rename. If
            an implementation followed the original incorrect wording, it
            might raise Use_Error instead of Name_Error for Start_Search and
            Search, Name_Error instead of Use_Error for Rename, and might have
            deleted a nonempty directory instead of raising Use_Error for
            Delete_Directory. The first two cases are very unlikely to matter
            in practice, and it unlikely that an implementation would have
            followed the latter implementation strategy, as it would be more
            work and would make Delete_Directory identical to Delete_Tree
            (which is obvious nonsense).


                       Incompatibilities With Ada 2005

131.e/3     {AI05-0049-1} A new enumeration type Name_Case_Kind and a new
            function Name_Case_Equivalence is added to Directories. If
            Directories is referenced in a use_clause, and an entity E with a
            defining_identifier of one of the new entities is defined in a
            package that is also referenced in a use_clause, the entity E may
            no longer be use-visible, resulting in errors. This should be rare
            and is easily fixed if it does occur.


                        Wording Changes from Ada 2005

131.f/3     {AI05-0271-1} Correction: We now explicitly say that the behavior
            of Create_Path and Copy_File is unspecified when Use_Error is
            raised. Nothing has changed here, as the behavior was (implicitly)
            unspecified in the 2007 Amendment.


A.16.1 The Package Directories.Hierarchical_File_Names


1/3 {AI05-0049-1} The library package Directories.Hierarchical_File_Names is
an optional package providing operations for file name construction and
decomposition for targets with hierarchical file naming.


                              Static Semantics

2/3 {AI05-0049-1} If provided, the library package
Directories.Hierarchical_File_Names has the following declaration:

3/3     package Ada.Directories.Hierarchical_File_Names is

4/3        function Is_Simple_Name (Name : in String) return Boolean;

5/3        function Is_Root_Directory_Name (Name : in String) return Boolean;

6/3        function Is_Parent_Directory_Name
         (Name : in String) return Boolean;

7/3        function Is_Current_Directory_Name
         (Name : in String) return Boolean;

8/3        function Is_Full_Name (Name : in String) return Boolean;

9/3        function Is_Relative_Name (Name : in String) return Boolean;

10/3       function Simple_Name (Name : in String) return String
              renames Ada.Directories.Simple_Name;

11/3       function Containing_Directory (Name : in String) return String
              renames Ada.Directories.Containing_Directory;

12/3       function Initial_Directory (Name : in String) return String;

13/3       function Relative_Name (Name : in String) return String;

14/3       function Compose (Directory      : in String := "";
                             Relative_Name  : in String;
                             Extension      : in String := "") return String;

15/3    end Ada.Directories.Hierarchical_File_Names;

16/3 {AI05-0049-1} {AI05-0269-1} In addition to the operations provided in
package Directories.Hierarchical_File_Names, the operations in package
Directories can be used with hierarchical file names. In particular, functions
Full_Name, Base_Name, and Extension provide additional capabilities for
hierarchical file names.

17/3    function Is_Simple_Name (Name : in String) return Boolean;

18/3        Returns True if Name is a simple name, and returns False otherwise.

19/3    function Is_Root_Directory_Name (Name : in String) return Boolean;

20/3        Returns True if Name is syntactically a root (a directory that
            cannot be decomposed further), and returns False otherwise.

20.a/3      Implementation Note: For Unix and Unix-like systems, "/" is the
            root. For Windows, "C:\" and "\\Computer\Share" are roots.

21/3    function Is_Parent_Directory_Name (Name : in String) return Boolean;

22/3        Returns True if Name can be used to indicate symbolically the
            parent directory of any directory, and returns False otherwise.

22.a/3      Implementation Note: Is_Parent_Directory_Name returns True if and
            only if Name is ".." for both Unix and Windows.

23/3    function Is_Current_Directory_Name (Name : in String) return Boolean;

24/3        Returns True if Name can be used to indicate symbolically the
            directory itself for any directory, and returns False otherwise.

24.a/3      Implementation Note: Is_Current_Directory_Name returns True if and
            only if Name is "." for both Unix and Windows.

25/3    function Is_Full_Name (Name : in String) return Boolean;

26/3        Returns True if the leftmost directory part of Name is a root, and
            returns False otherwise.

27/3    function Is_Relative_Name (Name : in String) return Boolean;

28/3        {AI05-0049-1} {AI05-0269-1} Returns True if Name allows the
            identification of an external file (including directories and
            special files) but is not a full name, and returns False otherwise.

28.a/3      Ramification: Relative names include simple names as a special
            case. This function returns False if the syntax of the name is
            incorrect.

29/3    function Initial_Directory (Name : in String) return String;

30/3        {AI05-0049-1} {AI05-0248-1} Returns the leftmost directory part in
            Name. [That is, it returns a root directory name (for a full
            name), or one of a parent directory name, a current directory
            name, or a simple name (for a relative name).] The exception
            Name_Error is propagated if the string given as Name does not
            allow the identification of an external file (including
            directories and special files).

31/3    function Relative_Name (Name : in String) return String;

32/3        Returns the entire file name except the Initial_Directory portion.
            The exception Name_Error is propagated if the string given as Name
            does not allow the identification of an external file (including
            directories and special files), or if Name has a single part (this
            includes if any of Is_Simple_Name, Is_Root_Directory_Name,
            Is_Parent_Directory_Name, or Is_Current_Directory_Name are True).

32.a/3      Ramification: The result might be a simple name.

33/3    function Compose (Directory      : in String := "";
                          Relative_Name  : in String;
                          Extension      : in String := "") return String;

34/3        Returns the name of the external file with the specified
            Directory, Relative_Name, and Extension. The exception Name_Error
            is propagated if the string given as Directory is not the null
            string and does not allow the identification of a directory, or if
            Is_Relative_Name (Relative_Name) is False, or if the string given
            as Extension is not the null string and is not a possible
            extension, or if Extension is not the null string and Simple_Name
            (Relative_Name) is not a base name.

35/3        The result of Compose is a full name if Is_Full_Name (Directory)
            is True; result is a relative name otherwise.

35.a/3      Ramification: Name_Error is raised by Compose if Directory is not
            the null string, and both Is_Full_Name and Is_Relative_Name return
            False.

35.b/3      Discussion: A common security problem is to include a parent
            directory name in the middle of a file name; this is often used to
            navigate outside of an intended root directory. We considered
            attempting to prevent that case by having Compose detect it and
            raise an exception. But the extra rules necessary were more
            confusing than helpful.

35.c/3      We can say more about the details of these operations by adopting
            the notation of a subscript to specify how many path fragments a
            particular result has. Then, we can abbreviate "Full Name" as
            "Full" and "Relative Name" as "Rel". In this notation, Unix file
            name "a/b" is a Rel(2), "../c/d" is a Rel(3), and "/a/b" is a
            Full(2). Rel(1) is equivalent to a simple name; thus we don't have
            to describe that separately.

35.d/3      In this notation,

35.e/3          For N>1,
                Containing_Directory(Rel(N)) = Leftmost Rel(N-1),
                Containing_Directory(Full(N)) = Leftmost Full(N-1),
                Else if N = 1, raise Name_Error.
                  

35.f/3      Similarly,

35.g/3          For N>1,
                Relative_Name(Rel(N)) = Rightmost Rel(N-1),
                Relative_Name(Full(N)) = Rightmost Full(N-1),
                Else if N = 1, raise Name_Error.
                  

35.h/3      Finally, for Compose (ignoring the extension here):

35.i/3          Compose (Directory => Full(N), Relative_Name => Rel(M)) => Full(N+M)
                Compose (Directory => Rel(N), Relative_Name => Rel(M)) => Rel(N+M)
                Name_Error if Relative_Name is a Full(M).
                  

35.j/3      We didn't try to write wording to reflect these details of these
            functions.


                            Implementation Advice

36/3 {AI05-0049-1} Directories.Hierarchical_File_Names should be provided for
systems with hierarchical file naming, and should not be provided on other
systems.

36.a/3      Implementation Advice: Directories.Hierarchical_File_Names should
            be provided for systems with hierarchical file naming, and should
            not be provided on other systems.

36.b/3      Implementation Note: This package should be provided when
            targeting Microsoft® Windows®, Unix, Linux, and most Unix-like
            systems.

        NOTES

37/3    46  {AI05-0049-1} These operations operate on file names, not external
        files. The files identified by these operations do not need to exist.
        Name_Error is raised only as specified or if the file name is
        malformed and cannot possibly identify a file. The result of these
        operations depends only on their parameters.

38/3    47  {AI05-0049-1} Containing_Directory raises Use_Error if Name does
        not have a containing directory, including when any of Is_Simple_Name,
        Is_Root_Directory_Name, Is_Parent_Directory_Name, or
        Is_Current_Directory_Name are True.

38.a/3      Ramification: In particular, the default directory is not used to
            find the containing directory either when Is_Parent_Directory_Name
            or Is_Current_Directory_Name is True. As noted above, these
            functions operate purely on the syntax of the file names and do
            not attempt to interpret them. If interpretation is needed,
            Directories.Full_Name can be to expand any shorthands used before
            calling Containing_Directory.


                           Extensions to Ada 2005

38.b/3      {AI05-0049-1} Package Ada.Directories.Hierarchical_File_Names is
            new.


A.17 The Package Environment_Variables


1/2 {AI95-00370-01} The package Environment_Variables allows a program to read
or modify environment variables. Environment variables are name-value pairs,
where both the name and value are strings. The definition of what constitutes
an environment variable, and the meaning of the name and value, are
implementation defined.

1.a/2       Implementation defined: The definition and meaning of an
            environment variable.


                              Static Semantics

2/2 {AI95-00370-01} The library package Environment_Variables has the
following declaration:

3/2     package Ada.Environment_Variables is
           pragma Preelaborate(Environment_Variables);

4/2        function Value (Name : in String) return String;

4.1/3   {AI05-0285-1}    function Value
         (Name : in String; Default : in String) return String;

5/2        function Exists (Name : in String) return Boolean;

6/2        procedure Set (Name : in String; Value : in String);

7/2        procedure Clear (Name : in String);
           procedure Clear;

8/3     {AI05-0248-1}    procedure Iterate
              (Process : not null access procedure (Name, Value : in String));

9/2     end Ada.Environment_Variables;

10/2    function Value (Name : in String) return String;

11/2        {AI95-00370-01} If the external execution environment supports
            environment variables, then Value returns the value of the
            environment variable with the given name. If no environment
            variable with the given name exists, then Constraint_Error is
            propagated. If the execution environment does not support
            environment variables, then Program_Error is propagated.

11.1/3  function Value (Name : in String; Default : in String) return String;

11.2/3      {AI05-0285-1} If the external execution environment supports
            environment variables and an environment variable with the given
            name currently exists, then Value returns its value; otherwise, it
            returns Default.

12/2    function Exists (Name : in String) return Boolean;

13/3        {AI95-00370-01} {AI05-0264-1} If the external execution
            environment supports environment variables and an environment
            variable with the given name currently exists, then Exists returns
            True; otherwise, it returns False.

14/2    procedure Set (Name : in String; Value : in String);

15/3        {AI95-00370-01} {AI05-0264-1} If the external execution
            environment supports environment variables, then Set first clears
            any existing environment variable with the given name, and then
            defines a single new environment variable with the given name and
            value. Otherwise, Program_Error is propagated.

16/2        If implementation-defined circumstances prohibit the definition of
            an environment variable with the given name and value, then
            Constraint_Error is propagated.

16.a/2      Implementation defined: The circumstances where an environment
            variable cannot be defined.

17/2        It is implementation defined whether there exist values for which
            the call Set(Name, Value) has the same effect as Clear (Name).

17.a/2      Implementation defined: Environment names for which Set has the
            effect of Clear.

18/2    procedure Clear (Name : in String);

19/3        {AI95-00370-01} {AI05-0264-1} {AI05-0269-1} If the external
            execution environment supports environment variables, then Clear
            deletes all existing environment variables with the given name.
            Otherwise, Program_Error is propagated.

20/2    procedure Clear;

21/3        {AI95-00370-01} {AI05-0264-1} If the external execution
            environment supports environment variables, then Clear deletes all
            existing environment variables. Otherwise, Program_Error is
            propagated.

22/3    {AI05-0248-1} procedure Iterate
           (Process : not null access procedure (Name, Value : in String));

23/3        {AI95-00370-01} {AI05-0264-1} If the external execution
            environment supports environment variables, then Iterate calls the
            subprogram designated by Process for each existing environment
            variable, passing the name and value of that environment variable.
            Otherwise, Program_Error is propagated.

24/2        If several environment variables exist that have the same name,
            Process is called once for each such variable.


                          Bounded (Run-Time) Errors

25/2 {AI95-00370-01} It is a bounded error to call Value if more than one
environment variable exists with the given name; the possible outcomes are
that:

26/2   * one of the values is returned, and that same value is returned in
        subsequent calls in the absence of changes to the environment; or

27/2   * Program_Error is propagated.


                             Erroneous Execution

28/2 {AI95-00370-01} Making calls to the procedures Set or Clear concurrently
with calls to any subprogram of package Environment_Variables, or to any
instantiation of Iterate, results in erroneous execution.

29/2 Making calls to the procedures Set or Clear in the actual subprogram
corresponding to the Process parameter of Iterate results in erroneous
execution.


                         Documentation Requirements

30/2 {AI95-00370-01} An implementation shall document how the operations of
this package behave if environment variables are changed by external
mechanisms (for instance, calling operating system services).

30.a/2      Documentation Requirement: The behavior of package
            Environment_Variables when environment variables are changed by
            external mechanisms.


                         Implementation Permissions

31/2 {AI95-00370-01} An implementation running on a system that does not
support environment variables is permitted to define the operations of package
Environment_Variables with the semantics corresponding to the case where the
external execution environment does support environment variables. In this
case, it shall provide a mechanism to initialize a nonempty set of environment
variables prior to the execution of a partition.


                            Implementation Advice

32/2 {AI95-00370-01} If the execution environment supports subprocesses, the
currently defined environment variables should be used to initialize the
environment variables of a subprocess.

32.a/2      Implementation Advice: If the execution environment supports
            subprocesses, the current environment variables should be used to
            initialize the environment variables of a subprocess.

33/2 Changes to the environment variables made outside the control of this
package should be reflected immediately in the effect of the operations of
this package. Changes to the environment variables made using this package
should be reflected immediately in the external execution environment. This
package should not perform any buffering of the environment variables.

33.a/2      Implementation Advice: Changes to the environment variables made
            outside the control of Environment_Variables should be reflected
            immediately.


                            Extensions to Ada 95

33.b/2      {AI95-00370-01} Package Environment_Variables is new.


                       Incompatibilities With Ada 2005

33.c/3      {AI05-0285-1} A new overloaded function Value is added to
            Environment_Variables. If Environment_Variables is referenced in a
            use_clause, and an entity E with the name Value is defined in a
            package that is also referenced in a use_clause, the entity E may
            no longer be use-visible, resulting in errors. This should be rare
            and is easily fixed if it does occur.


A.18 Containers


1/2 {AI95-00302-03} This clause presents the specifications of the package
Containers and several child packages, which provide facilities for storing
collections of elements.

1.a.1/3     Glossary entry: A container is an object that contain other
            objects all of the same type, which could be class-wide. Several
            predefined container types are provided by the children of package
            Ada.Containers (see A.18.1).

2/2 {AI95-00302-03} A variety of sequence and associative containers are
provided. Each container includes a cursor type. A cursor is a reference to an
element within a container. Many operations on cursors are common to all of
the containers. A cursor referencing an element in a container is considered
to be overlapping with the container object itself.

2.a/2       Reason: The last sentence is intended to clarify that operations
            that just use a cursor are on the same footing as operations that
            use a container in terms of the reentrancy rules of Annex A.

3/2 {AI95-00302-03} Within this clause we provide Implementation Advice for
the desired average or worst case time complexity of certain operations on a
container. This advice is expressed using the Landau symbol O(X). Presuming f
is some function of a length parameter N and t(N) is the time the operation
takes (on average or worst case, as specified) for the length N, a complexity
of O(f(N)) means that there exists a finite A such that for any N, t(N)/f(N) <
A.

3.a/2       Discussion: Of course, an implementation can do better than a
            specified O(f(N)): for example, O(1) meets the requirements for
            O(log N).

3.b/2       This concept seems to have as many names as there are authors. We
            used "Landau symbol" because that's what our reference does. But
            we'd also seen this referred as big-O notation (sometimes written
            as big-oh), and as Bachmann notation. Whatever the name, it always
            has the above definition.

4/2 If the advice suggests that the complexity should be less than O(f(N)),
then for any arbitrarily small positive real D, there should exist a positive
integer M such that for all N > M, t(N)/f(N) < D.

5/3 {AI05-0001-1} {AI05-0044-1} When a formal function is used to provide an
ordering for a container, it is generally required to define a strict weak
ordering. A function "<" defines a strict weak ordering if it is irreflexive,
asymmetric, transitive, and in addition, if x < y for any values x and y, then
for all other values z, (x < z) or (z < y).


                         Language Design Principles

5.a/3       {AI95-00302-03} {AI05-0299-1} This subclause provides a number of
            useful containers for Ada. Only the most useful containers are
            provided. Ones that are relatively easy to code, redundant, or
            rarely used are omitted from this set, even if they are generally
            included in containers libraries.

5.b/2       The containers packages are modeled on the Standard Template
            Library (STL), an algorithms and data structure library
            popularized by Alexander Stepanov, and included in the C++
            standard library. The structure and terminology differ from the
            STL where that better maps to common Ada usage. For instance, what
            the STL calls "iterators" are called "cursors" here.

5.c/2       The following major nonlimited containers are provided:

5.d/2         * (Expandable) Vectors of any nonlimited type;

5.e/2         * Doubly-linked Lists of any nonlimited type;

5.f/2         * Hashed Maps keyed by any nonlimited hashable type, and
                containing any nonlimited type;

5.g/2         * Ordered Maps keyed by any nonlimited ordered type, and
                containing any nonlimited type;

5.h/3         * {AI05-0136-1} Hashed Sets of any nonlimited hashable type;

5.i/3         * {AI05-0136-1} Ordered Sets of any nonlimited ordered type;

5.i.1/3       * {AI05-0136-1} Multiway Trees of any nonlimited type;

5.i.2/3       * {AI05-0069-1} Holders of any (indefinite) nonlimited type;

5.i.3/3       * {AI05-0159-1} Synchronized queues of any definite nonlimited
                type; and

5.i.4/3       * {AI05-0159-1} Priority queues of any definite nonlimited type.

5.j/3       {AI05-0001-1} Separate versions for definite and indefinite
            element types are provided, as those for definite types can be
            implemented more efficiently. Similarly, a separate bounded
            version is provided in order to give more predictable memory usage.

5.k/2       Each container includes a cursor, which is a reference to an
            element within a container. Cursors generally remain valid as long
            as the container exists and the element referenced is not deleted.
            Many operations on cursors are common to all of the containers.
            This makes it possible to write generic algorithms that work on
            any kind of container.

5.l/2       The containers packages are structured so that additional packages
            can be added in the future. Indeed, we hope that these packages
            provide the basis for a more extensive secondary standard for
            containers.

5.m/2       If containers with similar functionality (but different
            performance characteristics) are provided (by the implementation
            or by a secondary standard), we suggest that a prefix be used to
            identify the class of the functionality:
            "Ada.Containers.Bounded_Sets" (for a set with a maximum number of
            elements); "Ada.Containers.Protected_Maps" (for a map which can be
            accessed by multiple tasks at one time);
            "Ada.Containers.Persistent_Vectors" (for a persistent vector which
            continues to exist between executions of a program) and so on.

5.n/2       Note that the language already includes several requirements that
            are important to the use of containers. These include:

5.o/2         * Library packages must be reentrant - multiple tasks can use
                the packages as long as they operate on separate containers.
                Thus, it is only necessary for a user to protect a container
                if a single container needs to be used by multiple tasks.

5.p/2         * Language-defined types must stream "properly". That means that
                the stream attributes can be used to implement persistence of
                containers when necessary, and containers can be passed
                between partitions of a program.

5.q/2         * Equality of language-defined types must compose "properly".
                This means that the version of "=" directly used by users is
                the same one that will be used in generics and in predefined
                equality operators of types with components of the containers
                and/or cursors. This prevents the abstraction from breaking
                unexpectedly.

5.q.1/3       * {AI05-0048-1} Redispatching is not allowed (unless it is
                required). That means that overriding a container operation
                will not change the behavior of any other predefined container
                operation. This provides a stable base for extensions.

5.r/2       If a container's element type is controlled, the point at which
            the element is finalized will depend on the implementation of the
            container. We do not specify precisely where this will happen (it
            will happen no later than the finalization of the container, of
            course) in order to give implementation's flexibility to cache,
            block, or split the nodes of the container. In particular, Delete
            does not necessarily finalize the element; the implementation may
            (or may not) hold the space for reuse.

5.s/2       This is not likely to be a hardship, as the element type has to be
            nonlimited. Types used to manage scarce resources generally need
            to be limited. Otherwise, the amount of resources needed is hard
            to control, as the language allows a lot of variation in the
            number or order of adjusts/finalizations. For common uses of
            nonlimited controlled types such as managing storage, the types
            already have to manage arbitrary copies.

5.t/2       The use of controlled types also brings up the possibility of
            failure of finalization (and thus deallocation) of an element.
            This is a "serious bug", as AI95-179 puts it, so we don't try to
            specify what happens in that case. The implementation should
            propagate the exception.

5.u/2       Implementation Note: It is expected that exceptions propagated
            from these operations do not damage containers. That is, if
            Storage_Error is propagated because of an allocation failure, or
            Constraint_Error is propagated by the assignment of elements, the
            container can continue to be used without further exceptions. The
            intent is that it should be possible to recover from errors
            without losing data. We don't try to state this formally in most
            cases, because it is hard to define precisely what is and is not
            allowed behavior.

5.v/2       Implementation Note: When this clause says that the behavior of
            something is unspecified, we really mean that any result of
            executing Ada code short of erroneous execution is allowed. We do
            not mean that memory not belonging to the parameters of the
            operation can be trashed. When we mean to allow erroneous
            behavior, we specifically say that execution is erroneous. All
            this means if the containers are written in Ada is that checks
            should not be suppressed or removed assuming some behavior of
            other code, and that the implementation should take care to avoid
            creating internal dangling accesses by assuming behavior from
            generic formals that can't be guaranteed. We don't try to say this
            normatively because it would be fairly complex, and implementers
            are unlikely to increase their support costs by fielding
            implementations that are unstable if given buggy hash functions,
            et al.


                              Static Semantics

6/4 {AI12-0035-1} Certain subprograms declared within instances of some of the
generic packages presented in this clause are said to perform indefinite
insertion. These subprograms are those corresponding (in the sense of the
copying described in subclause 12.3) to subprograms that have formal
parameters of a generic formal indefinite type and that are identified as
performing indefinite insertion in the subclause defining the generic package.

7/4 {AI12-0035-1} If a subprogram performs indefinite insertion, then certain
run-time checks are performed as part of a call to the subprogram; if any of
these checks fail, then the resulting exception is propagated to the caller
and the container is not modified by the call. These checks are performed for
each parameter corresponding (in the sense of the copying described in 12.3)
to a parameter in the corresponding generic whose type is a generic formal
indefinite type. The checks performed for a given parameter are those checks
explicitly specified in subclause 4.8 that would be performed as part of the
evaluation of an initialized allocator whose access type is declared
immediately within the instance, where:

8/4   * the value of the qualified_expression is that of the parameter; and

9/4   * the designated subtype of the access type is the subtype of the
        parameter; and

10/4   * finalization of the collection of the access type has started if and
        only if the finalization of the instance has started.

10.a/4      Discussion: The phrase "explicitly specified" means those checks
            for which subclause 4.8 includes the phrase "<some exception> is
            raised if ...". It does not refer, for example, to any checks
            performed as part of any subtype conversion. In particular, this
            wording includes the checks described in subclause 4.8 to be
            performed in the case of a class-wide designated type, and of a
            designated subtype that has access discriminant parts. These
            checks are needed to prevent containers from outliving their
            contained (Element_Type or Key_Type) values.

10.b/4      Implementation Note: These rules have a dual purpose. Mainly, we
            are requiring checks needed to prevent dangling references. As a
            side effect, we are also allowing checks needed to permit an
            implementation of a container generic to make use of access types
            in a straightforward way. As an example of the second purpose,
            suppose that an implementation does declare such an access type
            and suppose further that the finalization of the collection of the
            access type has started. These rules allow Program_Error to be
            propagated in this case (as specified in 4.8); this is necessary
            to allow an all-Ada implementation of these packages.


                            Extensions to Ada 95

10.c/3      {AI95-00302-03} {AI05-0299-1} This subclause is new. It just
            provides an introduction to the following subclauses.


                        Wording Changes from Ada 2005

10.d/3      {AI05-0044-1} Correction: Added a definition of strict weak
            ordering.


                        Wording Changes from Ada 2012

10.e/4      {AI05-0035-1} Corrigendum: Added a definition of "performs
            indefinite insertion". This is used in other subclauses and any
            resulting inconsistencies are documented there.


A.18.1 The Package Containers


1/2 {AI95-00302-03} The package Containers is the root of the containers
subsystem.


                              Static Semantics

2/2 {AI95-00302-03} The library package Containers has the following
declaration:

3/2     package Ada.Containers is
           pragma Pure(Containers);

4/2        type Hash_Type is mod implementation-defined;

5/2        type Count_Type is range 0 .. implementation-defined;

5.1/3   {AI05-0001-1}    Capacity_Error : exception;

6/2     end Ada.Containers;

7/2 {AI95-00302-03} Hash_Type represents the range of the result of a hash
function. Count_Type represents the (potential or actual) number of elements
of a container.

7.a/2       Implementation defined: The value of Containers.Hash_Type'Modulus.
            The value of Containers.Count_Type'Last.

7.1/3 {AI05-0262-1} Capacity_Error is raised when the capacity of a container
is exceeded.


                            Implementation Advice

8/2 {AI95-00302-03} Hash_Type'Modulus should be at least 2**32.
Count_Type'Last should be at least 2**31-1.

8.a/2       Implementation Advice: Containers.Hash_Type'Modulus should be at
            least 2**32. Containers.Count_Type'Last should be at least 2**31-1.

8.b/2       Discussion: This is not a requirement so that these types can be
            declared properly on machines with native sizes that are not 32
            bits. For instance, a 24-bit target could use 2**24 for
            Hash_Type'Modulus.


                            Extensions to Ada 95

8.c/2       {AI95-00302-03} The package Containers is new.


                       Incompatibilities With Ada 2005

8.d/3       {AI05-0001-1} Exception Capacity_Error is added to Containers. If
            Containers is referenced in a use_clause, and an entity with the
            name Capacity_Error is defined in a package that is also
            referenced in a use_clause, the entity Capacity_Error may no
            longer be use-visible, resulting in errors. This should be rare
            and is easily fixed if it does occur.


A.18.2 The Generic Package Containers.Vectors


1/2 The language-defined generic package Containers.Vectors provides private
types Vector and Cursor, and a set of operations for each type. A vector
container allows insertion and deletion at any position, but it is
specifically optimized for insertion and deletion at the high end (the end
with the higher index) of the container. A vector container also provides
random access to its elements.

2/2 A vector container behaves conceptually as an array that expands as
necessary as items are inserted. The length of a vector is the number of
elements that the vector contains. The capacity of a vector is the maximum
number of elements that can be inserted into the vector prior to it being
automatically expanded.

3/2 Elements in a vector container can be referred to by an index value of a
generic formal type. The first element of a vector always has its index value
equal to the lower bound of the formal type.

4/2 A vector container may contain empty elements. Empty elements do not have
a specified value.

4.a/2       Implementation Note: Vectors are not intended to be sparse (that
            is, there are elements at all defined positions). Users are
            expected to use other containers (like a Map) when they need
            sparse structures (there is a Note to this effect at the end of
            this subclause).

4.b/2       The internal array is a conceptual model of a vector. There is no
            requirement for an implementation to be a single contiguous array.


                              Static Semantics

5/2 {AI95-00302-03} The generic library package Containers.Vectors has the
following declaration:

6/3     {AI05-0084-1} {AI05-0212-1} with Ada.Iterator_Interfaces;
        generic
           type Index_Type is range <>;
           type Element_Type is private;
           with function "=" (Left, Right : Element_Type)
              return Boolean is <>;
        package Ada.Containers.Vectors is
           pragma Preelaborate(Vectors);
           pragma Remote_Types(Vectors);

7/2        subtype Extended_Index is
              Index_Type'Base range
                 Index_Type'First-1 ..
                 Index_Type'Min (Index_Type'Base'Last - 1, Index_Type'Last) + 1;
           No_Index : constant Extended_Index := Extended_Index'First;

8/3     {AI05-0212-1}    type Vector is tagged private
              with Constant_Indexing => Constant_Reference,
                   Variable_Indexing => Reference,
                   Default_Iterator  => Iterate,
                   Iterator_Element  => Element_Type;
           pragma Preelaborable_Initialization(Vector);

9/2        type Cursor is private;
           pragma Preelaborable_Initialization(Cursor);

10/2       Empty_Vector : constant Vector;

11/2       No_Element : constant Cursor;

11.1/3  {AI05-0212-1}    function Has_Element
         (Position : Cursor) return Boolean;

11.2/3  {AI05-0212-1}    package Vector_Iterator_Interfaces is new
               Ada.Iterator_Interfaces (Cursor, Has_Element);

12/2       function "=" (Left, Right : Vector) return Boolean;

13/2       function To_Vector (Length : Count_Type) return Vector;

14/2       function To_Vector
             (New_Item : Element_Type;
              Length   : Count_Type) return Vector;

15/2       function "&" (Left, Right : Vector) return Vector;

16/2       function "&" (Left  : Vector;
                         Right : Element_Type) return Vector;

17/2       function "&" (Left  : Element_Type;
                         Right : Vector) return Vector;

18/2       function "&" (Left, Right  : Element_Type) return Vector;

19/2       function Capacity (Container : Vector) return Count_Type;

20/2       procedure Reserve_Capacity (Container : in out Vector;
                                       Capacity  : in     Count_Type);

21/2       function Length (Container : Vector) return Count_Type;

22/2       procedure Set_Length (Container : in out Vector;
                                 Length    : in     Count_Type);

23/2       function Is_Empty (Container : Vector) return Boolean;

24/2       procedure Clear (Container : in out Vector);

25/2       function To_Cursor (Container : Vector;
                               Index     : Extended_Index) return Cursor;

26/2       function To_Index (Position  : Cursor) return Extended_Index;

27/2       function Element (Container : Vector;
                             Index     : Index_Type)
              return Element_Type;

28/2       function Element (Position : Cursor) return Element_Type;

29/2       procedure Replace_Element (Container : in out Vector;
                                      Index     : in     Index_Type;
                                      New_Item  : in     Element_Type);

30/2       procedure Replace_Element (Container : in out Vector;
                                      Position  : in     Cursor;
                                      New_item  : in     Element_Type);

31/2       procedure Query_Element
             (Container : in Vector;
              Index     : in Index_Type;
              Process   : not null access procedure (Element : in Element_Type));

32/2       procedure Query_Element
             (Position : in Cursor;
              Process  : not null access procedure (Element : in Element_Type));

33/2       procedure Update_Element
             (Container : in out Vector;
              Index     : in     Index_Type;
              Process   : not null access procedure
                              (Element : in out Element_Type));

34/2       procedure Update_Element
             (Container : in out Vector;
              Position  : in     Cursor;
              Process   : not null access procedure
                              (Element : in out Element_Type));

34.1/3  {AI05-0212-1}    type Constant_Reference_Type
                 (Element : not null access constant Element_Type) is private
              with Implicit_Dereference => Element;

34.2/3  {AI05-0212-1}    type Reference_Type
         (Element : not null access Element_Type) is private
              with Implicit_Dereference => Element;

34.3/3  {AI05-0212-1}    function Constant_Reference
         (Container : aliased in Vector;
                                        Index     : in Index_Type)
              return Constant_Reference_Type;

34.4/3  {AI05-0212-1}    function Reference
         (Container : aliased in out Vector;
                               Index     : in Index_Type)
              return Reference_Type;

34.5/3  {AI05-0212-1}    function Constant_Reference
         (Container : aliased in Vector;
                                        Position  : in Cursor)
              return Constant_Reference_Type;

34.6/3  {AI05-0212-1}    function Reference
         (Container : aliased in out Vector;
                               Position  : in Cursor)
              return Reference_Type;

34.7/3  {AI05-0001-1}    procedure Assign
         (Target : in out Vector; Source : in Vector);

34.8/3  {AI05-0001-1}    function Copy
         (Source : Vector; Capacity : Count_Type := 0)
              return Vector;

35/2       procedure Move (Target : in out Vector;
                           Source : in out Vector);

36/2       procedure Insert (Container : in out Vector;
                             Before    : in     Extended_Index;
                             New_Item  : in     Vector);

37/2       procedure Insert (Container : in out Vector;
                             Before    : in     Cursor;
                             New_Item  : in     Vector);

38/2       procedure Insert (Container : in out Vector;
                             Before    : in     Cursor;
                             New_Item  : in     Vector;
                             Position  :    out Cursor);

39/2       procedure Insert (Container : in out Vector;
                             Before    : in     Extended_Index;
                             New_Item  : in     Element_Type;
                             Count     : in     Count_Type := 1);

40/2       procedure Insert (Container : in out Vector;
                             Before    : in     Cursor;
                             New_Item  : in     Element_Type;
                             Count     : in     Count_Type := 1);

41/2       procedure Insert (Container : in out Vector;
                             Before    : in     Cursor;
                             New_Item  : in     Element_Type;
                             Position  :    out Cursor;
                             Count     : in     Count_Type := 1);

42/2       procedure Insert (Container : in out Vector;
                             Before    : in     Extended_Index;
                             Count     : in     Count_Type := 1);

43/2       procedure Insert (Container : in out Vector;
                             Before    : in     Cursor;
                             Position  :    out Cursor;
                             Count     : in     Count_Type := 1);

44/2       procedure Prepend (Container : in out Vector;
                              New_Item  : in     Vector);

45/2       procedure Prepend (Container : in out Vector;
                              New_Item  : in     Element_Type;
                              Count     : in     Count_Type := 1);

46/2       procedure Append (Container : in out Vector;
                             New_Item  : in     Vector);

47/2       procedure Append (Container : in out Vector;
                             New_Item  : in     Element_Type;
                             Count     : in     Count_Type := 1);

48/2       procedure Insert_Space (Container : in out Vector;
                                   Before    : in     Extended_Index;
                                   Count     : in     Count_Type := 1);

49/2       procedure Insert_Space (Container : in out Vector;
                                   Before    : in     Cursor;
                                   Position  :    out Cursor;
                                   Count     : in     Count_Type := 1);

50/2       procedure Delete (Container : in out Vector;
                             Index     : in     Extended_Index;
                             Count     : in     Count_Type := 1);

51/2       procedure Delete (Container : in out Vector;
                             Position  : in out Cursor;
                             Count     : in     Count_Type := 1);

52/2       procedure Delete_First (Container : in out Vector;
                                   Count     : in     Count_Type := 1);

53/2       procedure Delete_Last (Container : in out Vector;
                                  Count     : in     Count_Type := 1);

54/2       procedure Reverse_Elements (Container : in out Vector);

55/2       procedure Swap (Container : in out Vector;
                           I, J      : in     Index_Type);

56/2       procedure Swap (Container : in out Vector;
                           I, J      : in     Cursor);

57/2       function First_Index (Container : Vector) return Index_Type;

58/2       function First (Container : Vector) return Cursor;

59/2       function First_Element (Container : Vector)
              return Element_Type;

60/2       function Last_Index (Container : Vector) return Extended_Index;

61/2       function Last (Container : Vector) return Cursor;

62/2       function Last_Element (Container : Vector)
              return Element_Type;

63/2       function Next (Position : Cursor) return Cursor;

64/2       procedure Next (Position : in out Cursor);

65/2       function Previous (Position : Cursor) return Cursor;

66/2       procedure Previous (Position : in out Cursor);

67/2       function Find_Index (Container : Vector;
                                Item      : Element_Type;
                                Index     : Index_Type := Index_Type'First)
              return Extended_Index;

68/2       function Find (Container : Vector;
                          Item      : Element_Type;
                          Position  : Cursor := No_Element)
              return Cursor;

69/2       function Reverse_Find_Index (Container : Vector;
                                        Item      : Element_Type;
                                        Index     : Index_Type := Index_Type'Last)
              return Extended_Index;

70/2       function Reverse_Find (Container : Vector;
                                  Item      : Element_Type;
                                  Position  : Cursor := No_Element)
              return Cursor;

71/2       function Contains (Container : Vector;
                              Item      : Element_Type) return Boolean;

72/3    This paragraph was deleted.{AI05-0212-1}

73/2       procedure  Iterate
             (Container : in Vector;
              Process   : not null access procedure (Position : in Cursor));

74/2       procedure Reverse_Iterate
             (Container : in Vector;
              Process   : not null access procedure (Position : in Cursor));

74.1/3  {AI05-0212-1}    function Iterate (Container : in Vector)
              return Vector_Iterator_Interfaces.Reversible_Iterator'Class;

74.2/3  {AI05-0212-1}
           function Iterate (Container : in Vector; Start : in Cursor)
              return Vector_Iterator_Interfaces.Reversible_Iterator'Class;

75/2       generic
              with function "<" (Left, Right : Element_Type)
                 return Boolean is <>;
           package Generic_Sorting is

76/2          function Is_Sorted (Container : Vector) return Boolean;

77/2          procedure Sort (Container : in out Vector);

78/2          procedure Merge (Target  : in out Vector;
                               Source  : in out Vector);

79/2       end Generic_Sorting;

80/2    private

81/2       ... -- not specified by the language

82/2    end Ada.Containers.Vectors;

83/2 {AI95-00302-03} The actual function for the generic formal function "="
on Element_Type values is expected to define a reflexive and symmetric
relationship and return the same result value each time it is called with a
particular pair of values. If it behaves in some other manner, the functions
defined to use it return an unspecified value. The exact arguments and number
of calls of this generic formal function by the functions defined to use it
are unspecified.

83.a/2      Ramification: The "functions defined to use it" are Find,
            Find_Index, Reverse_Find, Reverse_Find_Index, and "=" for Vectors.
            This list is a bit too long to give explicitly.

83.b/2      If the actual function for "=" is not symmetric and consistent,
            the result returned by any of the functions defined to use "="
            cannot be predicted. The implementation is not required to protect
            against "=" raising an exception, or returning random results, or
            any other "bad" behavior. And it can call "=" in whatever manner
            makes sense. But note that only the results of the functions
            defined to use "=" are unspecified; other subprograms are not
            allowed to break if "=" is bad.

84/2 {AI95-00302-03} The type Vector is used to represent vectors. The type
Vector needs finalization (see 7.6).

85/2 {AI95-00302-03} Empty_Vector represents the empty vector object. It has a
length of 0. If an object of type Vector is not otherwise initialized, it is
initialized to the same value as Empty_Vector.

86/2 {AI95-00302-03} No_Element represents a cursor that designates no
element. If an object of type Cursor is not otherwise initialized, it is
initialized to the same value as No_Element.

87/2 {AI95-00302-03} The predefined "=" operator for type Cursor returns True
if both cursors are No_Element, or designate the same element in the same
container.

88/2 {AI95-00302-03} Execution of the default implementation of the Input,
Output, Read, or Write attribute of type Cursor raises Program_Error.

88.a/2      Reason: A cursor will probably be implemented in terms of one or
            more access values, and the effects of streaming access values is
            unspecified. Rather than letting the user stream junk by accident,
            we mandate that streaming of cursors raise Program_Error by
            default. The attributes can always be specified if there is a need
            to support streaming.

88.1/3 {AI05-0001-1} {AI05-0262-1} Vector'Write for a Vector object V writes
Length(V) elements of the vector to the stream. It also may write additional
information about the vector.

88.2/3 {AI05-0001-1} {AI05-0262-1} Vector'Read reads the representation of a
vector from the stream, and assigns to Item a vector with the same length and
elements as was written by Vector'Write.

88.b/3      Implementation Note: The Standard requires streaming of all
            language-defined nonlimited types (including containers) to "work"
            (see 13.13.2). In addition, we do not want all of the elements
            that make up the capacity of the vector streamed, as those beyond
            the length of the container have undefined contents (and might
            cause bad things when read back in). This will require a custom
            stream attribute implementation; the language-defined default
            implementation will not work (even for a bounded form, as that
            would most likely stream the entire capacity of the vector). There
            is a separate requirement that the unbounded and Bounded form use
            the same streaming representation for the same element type, see
            A.18.19.

89/2 {AI95-00302-03} No_Index represents a position that does not correspond
to any element. The subtype Extended_Index includes the indices covered by
Index_Type plus the value No_Index and, if it exists, the successor to the
Index_Type'Last.

89.a/2      Discussion: We require the existence of Index_Type'First - 1, so
            that No_Index and Last_Index of an empty vector is well-defined.
            We don't require the existence of Index_Type'Last + 1, as it is
            only used as the position of insertions (and needs to be allowed
            only when inserting an empty vector).

89.1/3 {AI05-0001-1} If an operation attempts to modify the vector such that
the position of the last element would be greater than Index_Type'Last, then
the operation propagates Constraint_Error.

89.b/3      Reason: We don't want to require an implementation to go to heroic
            efforts to handle index values larger than the base type of the
            index subtype.

90/2 {AI95-00302-03} [Some operations of this generic package have
access-to-subprogram parameters. To ensure such operations are well-defined,
they guard against certain actions by the designated subprogram. In
particular, some operations check for "tampering with cursors" of a container
because they depend on the set of elements of the container remaining
constant, and others check for "tampering with elements" of a container
because they depend on elements of the container not being replaced.]

91/2 {AI95-00302-03} A subprogram is said to tamper with cursors of a vector
object V if:

92/2   * it inserts or deletes elements of V, that is, it calls the Insert,
        Insert_Space, Clear, Delete, or Set_Length procedures with V as a
        parameter; or

92.a/2      To be honest: Operations which are defined to be equivalent to a
            call on one of these operations also are included. Similarly,
            operations which call one of these as part of their definition are
            included.

93/2   * it finalizes V; or

93.1/3   * {AI05-0001-1} it calls the Assign procedure with V as the Target
        parameter; or

93.a.1/3    Ramification: We don't need to explicitly mention
            assignment_statement, because that finalizes the target object as
            part of the operation, and finalization of an object is already
            defined as tampering with cursors.

94/2   * it calls the Move procedure with V as a parameter.

94.a/2      Discussion: Swap, Sort, and Merge copy elements rather than
            reordering them, so they don't tamper with cursors.

95/2 {AI95-00302-03} A subprogram is said to tamper with elements of a vector
object V if:

96/2   * it tampers with cursors of V; or

97/2   * it replaces one or more elements of V, that is, it calls the
        Replace_Element, Reverse_Elements, or Swap procedures or the Sort or
        Merge procedures of an instance of Generic_Sorting with V as a
        parameter.

97.a/2      Reason: Complete replacement of an element can cause its memory to
            be deallocated while another operation is holding onto a reference
            to it. That can't be allowed. However, a simple modification of
            (part of) an element is not a problem, so Update_Element does not
            cause a problem.

97.1/4 {AI05-0265-1} {AI12-0110-1} When tampering with cursors is prohibited
for a particular vector object V, Program_Error is propagated by a call of any
language-defined subprogram that is defined to tamper with the cursors of V,
leaving V unmodified. Similarly, when tampering with elements is prohibited
for a particular vector object V, Program_Error is propagated by a call of any
language-defined subprogram that is defined to tamper with the elements of V
[(or tamper with the cursors of V)], leaving V unmodified. These checks are
made before any other defined behavior of the body of the language-defined
subprogram.

97.b/3      Proof: Tampering with elements includes tampering with cursors, so
            we mention it only from completeness in the second sentence.

97.2/3  function Has_Element (Position : Cursor) return Boolean;

97.3/3      {AI05-0212-1} Returns True if Position designates an element, and
            returns False otherwise.

97.c/3      To be honest: {AI05-0005-1} {AI05-0212-1} This function might not
            detect cursors that designate deleted elements; such cursors are
            invalid (see below) and the result of calling Has_Element with an
            invalid cursor is unspecified (but not erroneous).

98/2    function "=" (Left, Right : Vector) return Boolean;

99/3        {AI95-00302-03} {AI05-0264-1} If Left and Right denote the same
            vector object, then the function returns True. If Left and Right
            have different lengths, then the function returns False.
            Otherwise, it compares each element in Left to the corresponding
            element in Right using the generic formal equality operator. If
            any such comparison returns False, the function returns False;
            otherwise, it returns True. Any exception raised during evaluation
            of element equality is propagated.

99.a/2      Implementation Note: This wording describes the canonical
            semantics. However, the order and number of calls on the formal
            equality function is unspecified for all of the operations that
            use it in this package, so an implementation can call it as many
            or as few times as it needs to get the correct answer.
            Specifically, there is no requirement to call the formal equality
            additional times once the answer has been determined.

100/2   function To_Vector (Length : Count_Type) return Vector;

101/2       {AI95-00302-03} Returns a vector with a length of Length, filled
            with empty elements.

102/2   function To_Vector
          (New_Item : Element_Type;
           Length   : Count_Type) return Vector;

103/2       {AI95-00302-03} Returns a vector with a length of Length, filled
            with elements initialized to the value New_Item.

104/2   function "&" (Left, Right : Vector) return Vector;

105/2       {AI95-00302-03} Returns a vector comprising the elements of Left
            followed by the elements of Right.

106/2   function "&" (Left  : Vector;
                      Right : Element_Type) return Vector;

107/2       {AI95-00302-03} Returns a vector comprising the elements of Left
            followed by the element Right.

108/2   function "&" (Left  : Element_Type;
                      Right : Vector) return Vector;

109/2       {AI95-00302-03} Returns a vector comprising the element Left
            followed by the elements of Right.

110/2   function "&" (Left, Right  : Element_Type) return Vector;

111/2       {AI95-00302-03} Returns a vector comprising the element Left
            followed by the element Right.

112/2   function Capacity (Container : Vector) return Count_Type;

113/2       {AI95-00302-03} Returns the capacity of Container.

114/2   procedure Reserve_Capacity (Container : in out Vector;
                                    Capacity  : in     Count_Type);

115/3       {AI95-00302-03} {AI05-0001-1} {AI05-0264-1} If the capacity of
            Container is already greater than or equal to Capacity, then
            Reserve_Capacity has no effect. Otherwise, Reserve_Capacity
            allocates additional storage as necessary to ensure that the
            length of the resulting vector can become at least the value
            Capacity without requiring an additional call to Reserve_Capacity,
            and is large enough to hold the current length of Container.
            Reserve_Capacity then, as necessary, moves elements into the new
            storage and deallocates any storage no longer needed. Any
            exception raised during allocation is propagated and Container is
            not modified.

115.a/2     Discussion: Expanding the internal array can be done by allocating
            a new, longer array, copying the elements, and deallocating the
            original array. This may raise Storage_Error, or cause an
            exception from a controlled subprogram. We require that a failed
            Reserve_Capacity does not lose any elements if an exception
            occurs, but we do not require a specific order of evaluations or
            copying.

115.b/2     This routine is used to preallocate the internal array to the
            specified capacity such that future Inserts do not require memory
            allocation overhead. Therefore, the implementation should allocate
            the needed memory to make that true at this point, even though the
            visible semantics could be preserved by waiting until the memory
            is needed. This doesn't apply to the indefinite element container,
            because elements will have to be allocated individually.

115.c/2     The implementation does not have to contract the internal array if
            the capacity is reduced, as any capacity greater than or equal to
            the specified capacity is allowed.

116/2   function Length (Container : Vector) return Count_Type;

117/2       {AI95-00302-03} Returns the number of elements in Container.

118/2   procedure Set_Length (Container : in out Vector;
                              Length    : in     Count_Type);

119/3       {AI95-00302-03} {AI05-0264-1} If Length is larger than the
            capacity of Container, Set_Length calls Reserve_Capacity
            (Container, Length), then sets the length of the Container to
            Length. If Length is greater than the original length of
            Container, empty elements are added to Container; otherwise,
            elements are removed from Container.

119.a/2     Ramification: No elements are moved by this operation; any new
            empty elements are added at the end. This follows from the rules
            that a cursor continues to designate the same element unless the
            routine is defined to make the cursor ambiguous or invalid; this
            operation does not do that.

120/2   function Is_Empty (Container : Vector) return Boolean;

121/2       {AI95-00302-03} Equivalent to Length (Container) = 0.

122/2   procedure Clear (Container : in out Vector);

123/2       {AI95-00302-03} Removes all the elements from Container. The
            capacity of Container does not change.

124/2   function To_Cursor (Container : Vector;
                            Index     : Extended_Index) return Cursor;

125/2       {AI95-00302-03} If Index is not in the range First_Index
            (Container) .. Last_Index (Container), then No_Element is
            returned. Otherwise, a cursor designating the element at position
            Index in Container is returned.

126/2   function To_Index (Position  : Cursor) return Extended_Index;

127/2       {AI95-00302-03} If Position is No_Element, No_Index is returned.
            Otherwise, the index (within its containing vector) of the element
            designated by Position is returned.

127.a/2     Ramification: This implies that the index is determinable from a
            bare cursor alone. The basic model is that a vector cursor is
            implemented as a record containing an access to the vector
            container and an index value. This does constrain implementations,
            but it also allows all of the cursor operations to be defined in
            terms of the corresponding index operation (which should be
            primary for a vector).

128/2   function Element (Container : Vector;
                          Index     : Index_Type)
           return Element_Type;

129/2       {AI95-00302-03} If Index is not in the range First_Index
            (Container) .. Last_Index (Container), then Constraint_Error is
            propagated. Otherwise, Element returns the element at position
            Index.

130/2   function Element (Position  : Cursor) return Element_Type;

131/2       {AI95-00302-03} If Position equals No_Element, then
            Constraint_Error is propagated. Otherwise, Element returns the
            element designated by Position.

132/2   procedure Replace_Element (Container : in out Vector;
                                   Index     : in     Index_Type;
                                   New_Item  : in     Element_Type);

133/3       {AI95-00302-03} {AI05-0264-1} If Index is not in the range
            First_Index (Container) .. Last_Index (Container), then
            Constraint_Error is propagated. Otherwise, Replace_Element assigns
            the value New_Item to the element at position Index. Any exception
            raised during the assignment is propagated. The element at
            position Index is not an empty element after successful call to
            Replace_Element.

134/2   procedure Replace_Element (Container : in out Vector;
                                   Position  : in     Cursor;
                                   New_Item  : in     Element_Type);

135/3       {AI95-00302-03} {AI05-0264-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Replace_Element assigns New_Item to the element designated by
            Position. Any exception raised during the assignment is
            propagated. The element at Position is not an empty element after
            successful call to Replace_Element.

135.a/3     Ramification: {AI05-0212-1} Replace_Element, Update_Element, and
            Reference are the only ways that an element can change from empty
            to nonempty. Also see the note following Update_Element.

136/2   procedure Query_Element
          (Container : in Vector;
           Index     : in Index_Type;
           Process   : not null access procedure (Element : in Element_Type));

137/3       {AI95-00302-03} {AI05-0265-1} If Index is not in the range
            First_Index (Container) .. Last_Index (Container), then
            Constraint_Error is propagated. Otherwise, Query_Element calls
            Process.all with the element at position Index as the argument.
            Tampering with the elements of Container is prohibited during the
            execution of the call on Process.all. Any exception raised by
            Process.all is propagated.

137.a/2     Reason: {AI05-0005-1} The "tamper with the elements" check is
            intended to prevent the Element parameter of Process from being
            replaced or deleted outside of Process. The check prevents data
            loss (if Element_Type is passed by copy) or erroneous execution
            (if Element_Type is an unconstrained type in an indefinite
            container).

138/2   procedure Query_Element
          (Position : in Cursor;
           Process  : not null access procedure (Element : in Element_Type));

139/3       {AI95-00302-03} {AI05-0021-1} {AI05-0265-1} If Position equals
            No_Element, then Constraint_Error is propagated. Otherwise,
            Query_Element calls Process.all with the element designated by
            Position as the argument. Tampering with the elements of the
            vector that contains the element designated by Position is
            prohibited during the execution of the call on Process.all. Any
            exception raised by Process.all is propagated.

140/2   procedure Update_Element
          (Container : in out Vector;
           Index     : in     Index_Type;
           Process   : not null access procedure (Element : in out Element_Type));

141/3       {AI95-00302-03} {AI05-0265-1} If Index is not in the range
            First_Index (Container) .. Last_Index (Container), then
            Constraint_Error is propagated. Otherwise, Update_Element calls
            Process.all with the element at position Index as the argument.
            Tampering with the elements of Container is prohibited during the
            execution of the call on Process.all. Any exception raised by
            Process.all is propagated.

142/2       If Element_Type is unconstrained and definite, then the actual
            Element parameter of Process.all shall be unconstrained.

142.a/2     Ramification: This means that the elements cannot be directly
            allocated from the heap; it must be possible to change the
            discriminants of the element in place.

143/2       The element at position Index is not an empty element after
            successful completion of this operation.

143.a/2     Ramification: Since reading an empty element is a bounded error,
            attempting to use this procedure to replace empty elements may
            fail. Use Replace_Element to do that reliably.

144/2   procedure Update_Element
          (Container : in out Vector;
           Position  : in     Cursor;
           Process   : not null access procedure (Element : in out Element_Type));

145/3       {AI95-00302-03} {AI05-0264-1} {AI05-0265-1} If Position equals
            No_Element, then Constraint_Error is propagated; if Position does
            not designate an element in Container, then Program_Error is
            propagated. Otherwise, Update_Element calls Process.all with the
            element designated by Position as the argument. Tampering with the
            elements of Container is prohibited during the execution of the
            call on Process.all. Any exception raised by Process.all is
            propagated.

146/2       If Element_Type is unconstrained and definite, then the actual
            Element parameter of Process.all shall be unconstrained.

147/2       The element designated by Position is not an empty element after
            successful completion of this operation.

147.1/3 type Constant_Reference_Type
              (Element : not null access constant Element_Type) is private
           with Implicit_Dereference => Element;

147.2/3 type Reference_Type (Element : not null access Element_Type) is private
           with Implicit_Dereference => Element;

147.3/3     {AI05-0212-1} The types Constant_Reference_Type and Reference_Type
            need finalization.

147.4/3     The default initialization of an object of type
            Constant_Reference_Type or Reference_Type propagates Program_Error.

147.a/3     Reason: It is expected that Reference_Type (and
            Constant_Reference_Type) will be a controlled type, for which
            finalization will have some action to terminate the tampering
            check for the associated container. If the object is created by
            default, however, there is no associated container. Since this is
            useless, and supporting this case would take extra work, we define
            it to raise an exception.

147.5/3 function Constant_Reference (Container : aliased in Vector;
                                     Index     : in Index_Type)
           return Constant_Reference_Type;

147.6/3     {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Constant_Indexing and Implicit_Dereference aspects) provides a
            convenient way to gain read access to an individual element of a
            vector given an index value.

147.7/3     {AI05-0212-1} {AI05-0265-1} If Index is not in the range
            First_Index (Container) .. Last_Index (Container), then
            Constraint_Error is propagated. Otherwise, Constant_Reference
            returns an object whose discriminant is an access value that
            designates the element at position Index. Tampering with the
            elements of Container is prohibited while the object returned by
            Constant_Reference exists and has not been finalized.

147.8/3 function Reference (Container : aliased in out Vector;
                            Index     : in Index_Type)
           return Reference_Type;

147.9/3     {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Variable_Indexing and Implicit_Dereference aspects) provides a
            convenient way to gain read and write access to an individual
            element of a vector given an index value.

147.10/3    {AI05-0212-1} {AI05-0265-1} If Index is not in the range
            First_Index (Container) .. Last_Index (Container), then
            Constraint_Error is propagated. Otherwise, Reference returns an
            object whose discriminant is an access value that designates the
            element at position Index. Tampering with the elements of
            Container is prohibited while the object returned by Reference
            exists and has not been finalized.

147.11/3    The element at position Index is not an empty element after
            successful completion of this operation.

147.12/3 function Constant_Reference (Container : aliased in Vector;
                                     Position  : in Cursor)
           return Constant_Reference_Type;

147.13/3    {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Constant_Indexing and Implicit_Dereference aspects) provides a
            convenient way to gain read access to an individual element of a
            vector given a cursor.

147.14/3    {AI05-0212-1} {AI05-0265-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Constant_Reference returns an object whose discriminant is an
            access value that designates the element designated by Position.
            Tampering with the elements of Container is prohibited while the
            object returned by Constant_Reference exists and has not been
            finalized.

147.15/3 function Reference (Container : aliased in out Vector;
                            Position  : in Cursor)
           return Reference_Type;

147.16/3    {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Variable_Indexing and Implicit_Dereference aspects) provides a
            convenient way to gain read and write access to an individual
            element of a vector given a cursor.

147.17/3    {AI05-0212-1} {AI05-0265-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Reference returns an object whose discriminant is an access value
            that designates the element designated by Position. Tampering with
            the elements of Container is prohibited while the object returned
            by Reference exists and has not been finalized.

147.18/3    The element designated by Position is not an empty element after
            successful completion of this operation.

147.19/3 procedure Assign (Target : in out Vector; Source : in Vector);

147.20/3    {AI05-0001-1} {AI05-0248-1} {AI05-0262-1} If Target denotes the
            same object as Source, the operation has no effect. If the length
            of Source is greater than the capacity of Target, Reserve_Capacity
            (Target, Length (Source)) is called. The elements of Source are
            then copied to Target as for an assignment_statement assigning
            Source to Target (this includes setting the length of Target to be
            that of Source).

147.b/3     Discussion: {AI05-0005-1} This routine exists for compatibility
            with the bounded vector container. For an unbounded vector,
            Assign(A, B) and A := B behave identically. For a bounded vector,
            := will raise an exception if the container capacities are
            different, while Assign will not raise an exception if there is
            enough room in the target.

147.21/3 function Copy (Source : Vector; Capacity : Count_Type := 0)
           return Vector;

147.22/3    {AI05-0001-1} Returns a vector whose elements are initialized from
            the corresponding elements of Source. If Capacity is 0, then the
            vector capacity is the length of Source; if Capacity is equal to
            or greater than the length of Source, the vector capacity is at
            least the specified value. Otherwise, the operation propagates
            Capacity_Error.

148/2   procedure Move (Target : in out Vector;
                        Source : in out Vector);

149/3       {AI95-00302-03} {AI05-0001-1} {AI05-0248-1} If Target denotes the
            same object as Source, then the operation has no effect.
            Otherwise, Move first calls Reserve_Capacity (Target, Length
            (Source)) and then Clear (Target); then, each element from Source
            is removed from Source and inserted into Target in the original
            order. The length of Source is 0 after a successful call to Move.

149.a/2     Discussion: The idea is that the internal array is removed from
            Source and moved to Target. (See the Implementation Advice for
            Move). If Capacity (Target) /= 0, the previous internal array may
            need to be deallocated. We don't mention this explicitly, because
            it is covered by the "no memory loss" Implementation Requirement.

150/2   procedure Insert (Container : in out Vector;
                          Before    : in     Extended_Index;
                          New_Item  : in     Vector);

151/3       {AI95-00302-03} {AI05-0264-1} If Before is not in the range
            First_Index (Container) .. Last_Index (Container) + 1, then
            Constraint_Error is propagated. If Length(New_Item) is 0, then
            Insert does nothing. Otherwise, it computes the new length NL as
            the sum of the current length and Length (New_Item); if the value
            of Last appropriate for length NL would be greater than
            Index_Type'Last, then Constraint_Error is propagated.

152/2       If the current vector capacity is less than NL, Reserve_Capacity
            (Container, NL) is called to increase the vector capacity. Then
            Insert slides the elements in the range Before .. Last_Index
            (Container) up by Length(New_Item) positions, and then copies the
            elements of New_Item to the positions starting at Before. Any
            exception raised during the copying is propagated.

152.a/2     Ramification: Moving the elements does not necessarily involve
            copying. Similarly, since Reserve_Capacity does not require the
            copying of elements, it does not need to be explicitly called (the
            implementation can combine the operations if it wishes to).

153/2   procedure Insert (Container : in out Vector;
                          Before    : in     Cursor;
                          New_Item  : in     Vector);

154/3       {AI95-00302-03} {AI05-0264-1} If Before is not No_Element, and
            does not designate an element in Container, then Program_Error is
            propagated. Otherwise, if Length(New_Item) is 0, then Insert does
            nothing. If Before is No_Element, then the call is equivalent to
            Insert (Container, Last_Index (Container) + 1, New_Item);
            otherwise, the call is equivalent to Insert (Container, To_Index
            (Before), New_Item);

154.a/2     Ramification: The check on Before checks that the cursor does not
            belong to some other Container. This check implies that a
            reference to the container is included in the cursor value. This
            wording is not meant to require detection of dangling cursors;
            such cursors are defined to be invalid, which means that execution
            is erroneous, and any result is allowed (including not raising an
            exception).

155/2   procedure Insert (Container : in out Vector;
                          Before    : in     Cursor;
                          New_Item  : in     Vector;
                          Position  :    out Cursor);

156/2       {AI95-00302-03} If Before is not No_Element, and does not
            designate an element in Container, then Program_Error is
            propagated. If Before equals No_Element, then let T be Last_Index
            (Container) + 1; otherwise, let T be To_Index (Before). Insert
            (Container, T, New_Item) is called, and then Position is set to
            To_Cursor (Container, T).

156.a/2     Discussion: The messy wording is needed because Before is
            invalidated by Insert, and we don't want Position to be invalid
            after this call. An implementation probably only needs to copy
            Before to Position.

157/2   procedure Insert (Container : in out Vector;
                          Before    : in     Extended_Index;
                          New_Item  : in     Element_Type;
                          Count     : in     Count_Type := 1);

158/2       {AI95-00302-03} Equivalent to Insert (Container, Before, To_Vector
            (New_Item, Count));

159/2   procedure Insert (Container : in out Vector;
                          Before    : in     Cursor;
                          New_Item  : in     Element_Type;
                          Count     : in     Count_Type := 1);

160/2       {AI95-00302-03} Equivalent to Insert (Container, Before, To_Vector
            (New_Item, Count));

161/2   procedure Insert (Container : in out Vector;
                          Before    : in     Cursor;
                          New_Item  : in     Element_Type;
                          Position  :    out Cursor;
                          Count     : in     Count_Type := 1);

162/2       {AI95-00302-03} Equivalent to Insert (Container, Before, To_Vector
            (New_Item, Count), Position);

162.a/3     Ramification: {AI05-0257-1} If Count equals 0, Position will
            designate the element designated by Before, rather than a newly
            inserted element. Otherwise, Position will designate the first
            newly inserted element.

163/2   procedure Insert (Container : in out Vector;
                          Before    : in     Extended_Index;
                          Count     : in     Count_Type := 1);

164/3       {AI95-00302-03} {AI05-0264-1} If Before is not in the range
            First_Index (Container) .. Last_Index (Container) + 1, then
            Constraint_Error is propagated. If Count is 0, then Insert does
            nothing. Otherwise, it computes the new length NL as the sum of
            the current length and Count; if the value of Last appropriate for
            length NL would be greater than Index_Type'Last, then
            Constraint_Error is propagated.

165/2       If the current vector capacity is less than NL, Reserve_Capacity
            (Container, NL) is called to increase the vector capacity. Then
            Insert slides the elements in the range Before .. Last_Index
            (Container) up by Count positions, and then inserts elements that
            are initialized by default (see 3.3.1) in the positions starting
            at Before.

166/2   procedure Insert (Container : in out Vector;
                          Before    : in     Cursor;
                          Position  :    out Cursor;
                          Count     : in     Count_Type := 1);

167/2       {AI95-00302-03} If Before is not No_Element, and does not
            designate an element in Container, then Program_Error is
            propagated. If Before equals No_Element, then let T be Last_Index
            (Container) + 1; otherwise, let T be To_Index (Before). Insert
            (Container, T, Count) is called, and then Position is set to
            To_Cursor (Container, T).

167.a/2     Reason: This routine exists mainly to ease conversion between
            Vector and List containers. Unlike Insert_Space, this routine
            default initializes the elements it inserts, which can be more
            expensive for some element types.

168/4   {AI12-0080-1} procedure Prepend (Container : in out Vector;
                           New_Item  : in     Vector);

169/2       {AI95-00302-03} Equivalent to Insert (Container, First_Index
            (Container), New_Item).

170/2   procedure Prepend (Container : in out Vector;
                           New_Item  : in     Element_Type;
                           Count     : in     Count_Type := 1);

171/2       {AI95-00302-03} Equivalent to Insert (Container, First_Index
            (Container), New_Item, Count).

172/2   procedure Append (Container : in out Vector;
                          New_Item  : in     Vector);

173/2       {AI95-00302-03} Equivalent to Insert (Container, Last_Index
            (Container) + 1, New_Item).

174/2   procedure Append (Container : in out Vector;
                          New_Item  : in     Element_Type;
                          Count     : in     Count_Type := 1);

175/2       {AI95-00302-03} Equivalent to Insert (Container, Last_Index
            (Container) + 1, New_Item, Count).

176/2   procedure Insert_Space (Container : in out Vector;
                                Before    : in     Extended_Index;
                                Count     : in     Count_Type := 1);

177/3       {AI95-00302-03} {AI05-0264-1} If Before is not in the range
            First_Index (Container) .. Last_Index (Container) + 1, then
            Constraint_Error is propagated. If Count is 0, then Insert_Space
            does nothing. Otherwise, it computes the new length NL as the sum
            of the current length and Count; if the value of Last appropriate
            for length NL would be greater than Index_Type'Last, then
            Constraint_Error is propagated.

178/2       If the current vector capacity is less than NL, Reserve_Capacity
            (Container, NL) is called to increase the vector capacity. Then
            Insert_Space slides the elements in the range Before .. Last_Index
            (Container) up by Count positions, and then inserts empty elements
            in the positions starting at Before.

179/2   procedure Insert_Space (Container : in out Vector;
                                Before    : in     Cursor;
                                Position  :    out Cursor;
                                Count     : in     Count_Type := 1);

180/2       {AI95-00302-03} If Before is not No_Element, and does not
            designate an element in Container, then Program_Error is
            propagated. If Before equals No_Element, then let T be Last_Index
            (Container) + 1; otherwise, let T be To_Index (Before).
            Insert_Space (Container, T, Count) is called, and then Position is
            set to To_Cursor (Container, T).

181/2   procedure Delete (Container : in out Vector;
                          Index     : in     Extended_Index;
                          Count     : in     Count_Type := 1);

182/3       {AI95-00302-03} {AI05-0264-1} If Index is not in the range
            First_Index (Container) .. Last_Index (Container) + 1, then
            Constraint_Error is propagated. If Count is 0, Delete has no
            effect. Otherwise, Delete slides the elements (if any) starting at
            position Index + Count down to Index. Any exception raised during
            element assignment is propagated.

182.a/2     Ramification: If Index + Count >= Last_Index(Container), this
            effectively truncates the vector (setting Last_Index to Index - 1
            and consequently sets Length to Index - Index_Type'First).

183/2   procedure Delete (Container : in out Vector;
                          Position  : in out Cursor;
                          Count     : in     Count_Type := 1);

184/2       {AI95-00302-03} If Position equals No_Element, then
            Constraint_Error is propagated. If Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Delete (Container, To_Index (Position), Count) is called, and then
            Position is set to No_Element.

185/2   procedure Delete_First (Container : in out Vector;
                                Count     : in     Count_Type := 1);

186/2       {AI95-00302-03} Equivalent to Delete (Container, First_Index
            (Container), Count).

187/2   procedure Delete_Last (Container : in out Vector;
                               Count     : in     Count_Type := 1);

188/3       {AI95-00302-03} {AI05-0264-1} If Length (Container) <= Count, then
            Delete_Last is equivalent to Clear (Container). Otherwise, it is
            equivalent to Delete (Container,
            Index_Type'Val(Index_Type'Pos(Last_Index (Container)) - Count +
            1), Count).

189/2   {AI05-0092-1} procedure Reverse_Elements (Container : in out Vector);

190/2       {AI95-00302-03} Reorders the elements of Container in reverse
            order.

190.a/2     Discussion: This can copy the elements of the vector - all cursors
            referencing the vector are ambiguous afterwards and may designate
            different elements afterwards.

191/2   procedure Swap (Container : in out Vector;
                        I, J      : in     Index_Type);

192/2       {AI95-00302-03} If either I or J is not in the range First_Index
            (Container) .. Last_Index (Container), then Constraint_Error is
            propagated. Otherwise, Swap exchanges the values of the elements
            at positions I and J.

192.a/2     To be honest: The implementation is not required to actually copy
            the elements if it can do the swap some other way. But it is
            allowed to copy the elements if needed.

193/2   procedure Swap (Container : in out Vector;
                        I, J      : in     Cursor);

194/2       {AI95-00302-03} If either I or J is No_Element, then
            Constraint_Error is propagated. If either I or J do not designate
            an element in Container, then Program_Error is propagated.
            Otherwise, Swap exchanges the values of the elements designated by
            I and J.

194.a/2     Ramification: After a call to Swap, I designates the element value
            previously designated by J, and J designates the element value
            previously designated by I. The cursors do not become ambiguous
            from this operation.

194.b/2     To be honest: The implementation is not required to actually copy
            the elements if it can do the swap some other way. But it is
            allowed to copy the elements if needed.

195/2   function First_Index (Container : Vector) return Index_Type;

196/2       {AI95-00302-03} Returns the value Index_Type'First.

196.a/2     Discussion: We'd rather call this "First", but then calling most
            routines in here with First (Some_Vect) would be ambiguous.

197/2   function First (Container : Vector) return Cursor;

198/2       {AI95-00302-03} If Container is empty, First returns No_Element.
            Otherwise, it returns a cursor that designates the first element
            in Container.

199/2   function First_Element (Container : Vector) return Element_Type;

200/2       {AI95-00302-03} Equivalent to Element (Container, First_Index
            (Container)).

201/2   function Last_Index (Container : Vector) return Extended_Index;

202/2       {AI95-00302-03} If Container is empty, Last_Index returns
            No_Index. Otherwise, it returns the position of the last element
            in Container.

203/2   function Last (Container : Vector) return Cursor;

204/2       {AI95-00302-03} If Container is empty, Last returns No_Element.
            Otherwise, it returns a cursor that designates the last element in
            Container.

205/2   function Last_Element (Container : Vector) return Element_Type;

206/2       {AI95-00302-03} Equivalent to Element (Container, Last_Index
            (Container)).

207/2   function Next (Position : Cursor) return Cursor;

208/2       {AI95-00302-03} If Position equals No_Element or designates the
            last element of the container, then Next returns the value
            No_Element. Otherwise, it returns a cursor that designates the
            element with index To_Index (Position) + 1 in the same vector as
            Position.

209/2   procedure Next (Position : in out Cursor);

210/2       {AI95-00302-03} Equivalent to Position := Next (Position).

211/2   function Previous (Position : Cursor) return Cursor;

212/2       {AI95-00302-03} If Position equals No_Element or designates the
            first element of the container, then Previous returns the value
            No_Element. Otherwise, it returns a cursor that designates the
            element with index To_Index (Position) - 1 in the same vector as
            Position.

213/2   procedure Previous (Position : in out Cursor);

214/2       {AI95-00302-03} Equivalent to Position := Previous (Position).

215/2   function Find_Index (Container : Vector;
                             Item      : Element_Type;
                             Index     : Index_Type := Index_Type'First)
           return Extended_Index;

216/2       {AI95-00302-03} Searches the elements of Container for an element
            equal to Item (using the generic formal equality operator). The
            search starts at position Index and proceeds towards Last_Index
            (Container). If no equal element is found, then Find_Index returns
            No_Index. Otherwise, it returns the index of the first equal
            element encountered.

217/2   function Find (Container : Vector;
                       Item      : Element_Type;
                       Position  : Cursor := No_Element)
           return Cursor;

218/3       {AI95-00302-03} {AI05-0264-1} If Position is not No_Element, and
            does not designate an element in Container, then Program_Error is
            propagated. Otherwise, Find searches the elements of Container for
            an element equal to Item (using the generic formal equality
            operator). The search starts at the first element if Position
            equals No_Element, and at the element designated by Position
            otherwise. It proceeds towards the last element of Container. If
            no equal element is found, then Find returns No_Element.
            Otherwise, it returns a cursor designating the first equal element
            encountered.

219/2   function Reverse_Find_Index (Container : Vector;
                                     Item      : Element_Type;
                                     Index     : Index_Type := Index_Type'Last)
           return Extended_Index;

220/2       {AI95-00302-03} Searches the elements of Container for an element
            equal to Item (using the generic formal equality operator). The
            search starts at position Index or, if Index is greater than
            Last_Index (Container), at position Last_Index (Container). It
            proceeds towards First_Index (Container). If no equal element is
            found, then Reverse_Find_Index returns No_Index. Otherwise, it
            returns the index of the first equal element encountered.

221/2   function Reverse_Find (Container : Vector;
                               Item      : Element_Type;
                               Position  : Cursor := No_Element)
           return Cursor;

222/3       {AI95-00302-03} {AI05-0264-1} If Position is not No_Element, and
            does not designate an element in Container, then Program_Error is
            propagated. Otherwise, Reverse_Find searches the elements of
            Container for an element equal to Item (using the generic formal
            equality operator). The search starts at the last element if
            Position equals No_Element, and at the element designated by
            Position otherwise. It proceeds towards the first element of
            Container. If no equal element is found, then Reverse_Find returns
            No_Element. Otherwise, it returns a cursor designating the first
            equal element encountered.

223/2   function Contains (Container : Vector;
                           Item      : Element_Type) return Boolean;

224/2       {AI95-00302-03} Equivalent to Has_Element (Find (Container, Item)).

            Paragraphs 225 and 226 were moved above.

227/2   procedure Iterate
          (Container : in Vector;
           Process   : not null access procedure (Position : in Cursor));

228/3       {AI95-00302-03} {AI05-0265-1} Invokes Process.all with a cursor
            that designates each element in Container, in index order.
            Tampering with the cursors of Container is prohibited during the
            execution of a call on Process.all. Any exception raised by
            Process.all is propagated.

228.a/2     Discussion: The purpose of the "tamper with the cursors" check is
            to prevent erroneous execution from the Position parameter of
            Process.all becoming invalid. This check takes place when the
            operations that tamper with the cursors of the container are
            called. The check cannot be made later (say in the body of
            Iterate), because that could cause the Position cursor to be
            invalid and potentially cause execution to become erroneous --
            defeating the purpose of the check.

228.b/2     There is no check needed if an attempt is made to insert or delete
            nothing (that is, Count = 0 or Length(Item) = 0).

228.c/2     The check is easy to implement: each container needs a counter.
            The counter is incremented when Iterate is called, and decremented
            when Iterate completes. If the counter is nonzero when an
            operation that inserts or deletes is called, Finalize is called,
            or one of the other operations in the list occurs, Program_Error
            is raised.

229/2   procedure Reverse_Iterate
          (Container : in Vector;
           Process   : not null access procedure (Position : in Cursor));

230/3       {AI95-00302-03} {AI05-0212-1} Iterates over the elements in
            Container as per procedure Iterate, except that elements are
            traversed in reverse index order.

230.1/3 function Iterate (Container : in Vector)
           return Vector_Iterator_Interfaces.Reversible_Iterator'Class;

230.2/3     {AI05-0212-1} {AI05-0265-1} {AI05-0269-1} Iterate returns a
            reversible iterator object (see 5.5.1) that will generate a value
            for a loop parameter (see 5.5.2) designating each node in
            Container, starting with the first node and moving the cursor as
            per the Next function when used as a forward iterator, and
            starting with the last node and moving the cursor as per the
            Previous function when used as a reverse iterator. Tampering with
            the cursors of Container is prohibited while the iterator object
            exists (in particular, in the sequence_of_statements of the
            loop_statement whose iterator_specification denotes this object).
            The iterator object needs finalization.

230.3/3 function Iterate (Container : in Vector; Start : in Cursor)
           return Vector_Iterator_Interfaces.Reversible_Iterator'Class;

230.4/3     {AI05-0212-1} {AI05-0262-1} {AI05-0265-1} {AI05-0269-1} If Start
            is not No_Element and does not designate an item in Container,
            then Program_Error is propagated. If Start is No_Element, then
            Constraint_Error is propagated. Otherwise, Iterate returns a
            reversible iterator object (see 5.5.1) that will generate a value
            for a loop parameter (see 5.5.2) designating each node in
            Container, starting with the node designated by Start and moving
            the cursor as per the Next function when used as a forward
            iterator, or moving the cursor as per the Previous function when
            used as a reverse iterator. Tampering with the cursors of
            Container is prohibited while the iterator object exists (in
            particular, in the sequence_of_statements of the loop_statement
            whose iterator_specification denotes this object). The iterator
            object needs finalization.

230.a/3     Discussion: Exits are allowed from the loops created using the
            iterator objects. In particular, to stop the iteration at a
            particular cursor, just add

230.b/3         exit when Cur = Stop;

230.c/3     in the body of the loop (assuming that Cur is the loop parameter
            and Stop is the cursor that you want to stop at).

231/3 {AI05-0044-1} {AI05-0262-1} The actual function for the generic formal
function "<" of Generic_Sorting is expected to return the same value each time
it is called with a particular pair of element values. It should define a
strict weak ordering relationship (see A.18); it should not modify Container.
If the actual for "<" behaves in some other manner, the behavior of the
subprograms of Generic_Sorting are unspecified. The number of times the
subprograms of Generic_Sorting call "<" is unspecified.

232/2   function Is_Sorted (Container : Vector) return Boolean;

233/2       {AI95-00302-03} Returns True if the elements are sorted smallest
            first as determined by the generic formal "<" operator; otherwise,
            Is_Sorted returns False. Any exception raised during evaluation of
            "<" is propagated.

234/2   procedure Sort (Container : in out Vector);

235/2       {AI95-00302-03} Reorders the elements of Container such that the
            elements are sorted smallest first as determined by the generic
            formal "<" operator provided. Any exception raised during
            evaluation of "<" is propagated.

235.a/2     Ramification: This implies swapping the elements, usually
            including an intermediate copy. This means that the elements will
            usually be copied. (As with Swap, if the implementation can do
            this some other way, it is allowed to.) Since the elements are
            nonlimited, this usually will not be a problem. Note that there is
            Implementation Advice below that the implementation should use a
            sort that minimizes copying of elements.

235.b/2     The sort is not required to be stable (and the fast algorithm
            required will not be stable). If a stable sort is needed, the user
            can include the original location of the element as an extra "sort
            key". We considered requiring the implementation to do that, but
            it is mostly extra overhead -- usually there is something already
            in the element that provides the needed stability.

236/2   procedure Merge (Target  : in out Vector;
                         Source  : in out Vector);

237/3       {AI95-00302-03} {AI05-0021-1} If Source is empty, then Merge does
            nothing. If Source and Target are the same nonempty container
            object, then Program_Error is propagated. Otherwise, Merge removes
            elements from Source and inserts them into Target; afterwards,
            Target contains the union of the elements that were initially in
            Source and Target; Source is left empty. If Target and Source are
            initially sorted smallest first, then Target is ordered smallest
            first as determined by the generic formal "<" operator; otherwise,
            the order of elements in Target is unspecified. Any exception
            raised during evaluation of "<" is propagated.

237.a/2     Discussion: It is a bounded error if either of the vectors is
            unsorted, see below. The bounded error can be recovered by sorting
            Target after the merge call, or the vectors can be pretested with
            Is_Sorted.

237.b/2     Implementation Note: The Merge operation will usually require
            copying almost all of the elements. One implementation strategy
            would be to extend Target to the appropriate length, then copying
            elements from the back of the vectors working towards the front.
            An alternative approach would be to allocate a new internal data
            array of the appropriate length, copy the elements into it in an
            appropriate order, and then replacing the data array in Target
            with the temporary.


                          Bounded (Run-Time) Errors

238/3 {AI95-00302-03} {AI05-0212-1} Reading the value of an empty element by
calling Element, Query_Element, Update_Element, Constant_Reference, Reference,
Swap, Is_Sorted, Sort, Merge, "=", Find, or Reverse_Find is a bounded error.
The implementation may treat the element as having any normal value (see
13.9.1) of the element type, or raise Constraint_Error or Program_Error before
modifying the vector.

238.a/2     Ramification: For instance, a default initialized element could be
            returned. Or some previous value of an element. But returning
            random junk is not allowed if the type has default initial
            value(s).

238.b/2     Assignment and streaming of empty elements are not bounded errors.
            This is consistent with regular composite types, for which
            assignment and streaming of uninitialized components do not cause
            a bounded error, but reading the uninitialized component does
            cause a bounded error.

238.c/2     There are other operations which are defined in terms of the
            operations listed above.

239/2 {AI95-00302-03} Calling Merge in an instance of Generic_Sorting with
either Source or Target not ordered smallest first using the provided generic
formal "<" operator is a bounded error. Either Program_Error is raised after
Target is updated as described for Merge, or the operation works as defined.

239.1/3 {AI05-0022-1} {AI05-0248-1} It is a bounded error for the actual
function associated with a generic formal subprogram, when called as part of
an operation of this package, to tamper with elements of any Vector parameter
of the operation. Either Program_Error is raised, or the operation works as
defined on the value of the Vector either prior to, or subsequent to, some or
all of the modifications to the Vector.

239.2/3 {AI05-0027-1} It is a bounded error to call any subprogram declared in
the visible part of Containers.Vectors when the associated container has been
finalized. If the operation takes Container as an in out parameter, then it
raises Constraint_Error or Program_Error. Otherwise, the operation either
proceeds as it would for an empty container, or it raises Constraint_Error or
Program_Error.

240/2 {AI95-00302-03} A Cursor value is ambiguous if any of the following have
occurred since it was created:

241/2   * Insert, Insert_Space, or Delete has been called on the vector that
        contains the element the cursor designates with an index value (or a
        cursor designating an element at such an index value) less than or
        equal to the index value of the element designated by the cursor; or

242/2   * The vector that contains the element it designates has been passed
        to the Sort or Merge procedures of an instance of Generic_Sorting, or
        to the Reverse_Elements procedure.

243/2 {AI95-00302-03} It is a bounded error to call any subprogram other than
"=" or Has_Element declared in Containers.Vectors with an ambiguous (but not
invalid, see below) cursor parameter. Possible results are:

244/2   * The cursor may be treated as if it were No_Element;

245/2   * The cursor may designate some element in the vector (but not
        necessarily the element that it originally designated);

246/2   * Constraint_Error may be raised; or

247/2   * Program_Error may be raised.

247.a/2     Reason: Cursors are made ambiguous if an Insert or Delete occurs
            that moves the elements in the internal array including the
            designated ones. After such an operation, the cursor probably
            still designates an element (although it might not after a
            deletion), but it is a different element. That violates the
            definition of cursor - it designates a particular element.

247.b/2     For "=" or Has_Element, the cursor works normally (it would not be
            No_Element). We don't want to trigger an exception simply for
            comparing a bad cursor.

247.c/2     While it is possible to check for these cases or ensure that
            cursors survive such operations, in many cases the overhead
            necessary to make the check (or ensure cursors continue to
            designate the same element) is substantial in time or space.


                             Erroneous Execution

248/2 {AI95-00302-03} A Cursor value is invalid if any of the following have
occurred since it was created:

249/2   * The vector that contains the element it designates has been
        finalized;

249.1/3   * {AI05-0160-1} The vector that contains the element it designates
        has been used as the Target of a call to Assign, or as the target of
        an assignment_statement;

250/2   * [The vector that contains the element it designates has been used as
        the Source or Target of a call to Move;] or

250.a/3     Proof: {AI05-0001-1} Move has been reworded in terms of Assign and
            Clear, which are covered by other bullets, so this text is
            redundant.

251/3   * {AI05-0160-1} {AI05-0262-1} The element it designates has been
        deleted or removed from the vector that previously contained the
        element.

251.a/3     Ramification: {AI05-0160-1} An element can be removed via calls to
            Set_Length, Clear, and Merge; and indirectly via calls to Assign
            and Move.

252/2 {AI95-00302-03} The result of "=" or Has_Element is unspecified if it is
called with an invalid cursor parameter. Execution is erroneous if any other
subprogram declared in Containers.Vectors is called with an invalid cursor
parameter.

252.a/2     Discussion: The list above (combined with the bounded error cases)
            is intended to be exhaustive. In other cases, a cursor value
            continues to designate its original element. For instance, cursor
            values survive the appending of new elements.

252.1/3 {AI05-0212-1} Execution is erroneous if the vector associated with the
result of a call to Reference or Constant_Reference is finalized before the
result object returned by the call to Reference or Constant_Reference is
finalized.

252.b/3     Reason: Each object of Reference_Type and Constant_Reference_Type
            probably contains some reference to the originating container. If
            that container is prematurely finalized (which is only possible
            via Unchecked_Deallocation, as accessibility checks prevent
            passing a container to Reference that will not live as long as the
            result), the finalization of the object of Reference_Type will try
            to access a nonexistent object. This is a normal case of a
            dangling pointer created by Unchecked_Deallocation; we have to
            explicitly mention it here as the pointer in question is not
            visible in the specification of the type. (This is the same reason
            we have to say this for invalid cursors.)


                         Implementation Requirements

253/2 {AI95-00302-03} No storage associated with a vector object shall be lost
upon assignment or scope exit.

254/3 {AI95-00302-03} {AI05-0262-1} The execution of an assignment_statement
for a vector shall have the effect of copying the elements from the source
vector object to the target vector object and changing the length of the
target object to that of the source object.

254.a/3     Implementation Note: {AI05-0298-1} An assignment of a Vector is a
            "deep" copy; that is the elements are copied as well as the data
            structures. We say "effect of" in order to allow the
            implementation to avoid copying elements immediately if it wishes.
            For instance, an implementation that avoided copying until one of
            the containers is modified would be allowed. (Note that such an
            implementation would be require care, as Query_Element and
            Constant_Reference both could be used to access an element which
            later needs to be reallocated while the parameter or reference
            still exists, potentially leaving the parameter or reference
            pointing at the wrong element.)


                            Implementation Advice

255/2 {AI95-00302-03} Containers.Vectors should be implemented similarly to an
array. In particular, if the length of a vector is N, then

256/2   * the worst-case time complexity of Element should be O(log N);

256.a/2     Implementation Advice: The worst-case time complexity of Element
            for Containers.Vector should be O(log N).

257/2   * the worst-case time complexity of Append with Count=1 when N is less
        than the capacity of the vector should be O(log N); and

257.a/2     Implementation Advice: The worst-case time complexity of Append
            with Count = 1 when N is less than the capacity for
            Containers.Vector should be O(log N).

258/2   * the worst-case time complexity of Prepend with Count=1 and
        Delete_First with Count=1 should be O(N log N).

258.a/2     Implementation Advice: The worst-case time complexity of Prepend
            with Count = 1 and Delete_First with Count=1 for
            Containers.Vectors should be O(N log N).

258.b/2     Reason: We do not mean to overly constrain implementation
            strategies here. However, it is important for portability that the
            performance of large containers has roughly the same factors on
            different implementations. If a program is moved to an
            implementation that takes O(N) time to access elements, that
            program could be unusable when the vectors are large. We allow
            O(log N) access because the proportionality constant and caching
            effects are likely to be larger than the log factor, and we don't
            want to discourage innovative implementations.

259/2 {AI95-00302-03} The worst-case time complexity of a call on procedure
Sort of an instance of Containers.Vectors.Generic_Sorting should be O(N**2),
and the average time complexity should be better than O(N**2).

259.a/2     Implementation Advice: The worst-case time complexity of a call on
            procedure Sort of an instance of
            Containers.Vectors.Generic_Sorting should be O(N**2), and the
            average time complexity should be better than O(N**2).

259.b/2     Ramification: In other words, we're requiring the use of a better
            than O(N**2) sorting algorithm, such as Quicksort. No bubble sorts
            allowed!

260/2 {AI95-00302-03} Containers.Vectors.Generic_Sorting.Sort and
Containers.Vectors.Generic_Sorting.Merge should minimize copying of elements.

260.a/2     Implementation Advice: Containers.Vectors.Generic_Sorting.Sort and
            Containers.Vectors.Generic_Sorting.Merge should minimize copying
            of elements.

260.b/2     To be honest: We do not mean "absolutely minimize" here; we're not
            intending to require a single copy for each element. Rather, we
            want to suggest that the sorting algorithm chosen is one that does
            not copy items unnecessarily. Bubble sort would not meet this
            advice, for instance.

261/2 {AI95-00302-03} Move should not copy elements, and should minimize
copying of internal data structures.

261.a/2     Implementation Advice: Containers.Vectors.Move should not copy
            elements, and should minimize copying of internal data structures.

261.b/2     Implementation Note: Usually that can be accomplished simply by
            moving the pointer(s) to the internal data structures from the
            Source vector to the Target vector.

262/2 {AI95-00302-03} If an exception is propagated from a vector operation,
no storage should be lost, nor any elements removed from a vector unless
specified by the operation.

262.a/2     Implementation Advice: If an exception is propagated from a vector
            operation, no storage should be lost, nor any elements removed
            from a vector unless specified by the operation.

262.b/2     Reason: This is important so that programs can recover from
            errors. But we don't want to require heroic efforts, so we just
            require documentation of cases where this can't be accomplished.

        NOTES

263/2   48  All elements of a vector occupy locations in the internal array.
        If a sparse container is required, a Hashed_Map should be used rather
        than a vector.

264/2   49  If Index_Type'Base'First = Index_Type'First an instance of
        Ada.Containers.Vectors will raise Constraint_Error. A value below
        Index_Type'First is required so that an empty vector has a meaningful
        value of Last_Index.

264.a/2     Discussion: This property is the main reason why only integer
            types (as opposed to any discrete type) are allowed as the index
            type of a vector. An enumeration or modular type would require a
            subtype in order to meet this requirement.


                            Extensions to Ada 95

264.b/2     {AI95-00302-03} The package Containers.Vectors is new.


                       Incompatibilities With Ada 2005

264.c/3     {AI05-0001-1} Subprograms Assign and Copy are added to
            Containers.Vectors. If an instance of Containers.Vectors is
            referenced in a use_clause, and an entity E with the same
            defining_identifier as a new entity in Containers.Vectors is
            defined in a package that is also referenced in a use_clause, the
            entity E may no longer be use-visible, resulting in errors. This
            should be rare and is easily fixed if it does occur.


                           Extensions to Ada 2005

264.d/3     {AI05-0212-1} Added iterator, reference, and indexing support to
            make vector containers more convenient to use.


                        Wording Changes from Ada 2005

264.e/3     {AI05-0001-1} Generalized the definition of Reserve_Capacity and
            Move. Specified which elements are read/written by stream
            attributes.

264.f/3     {AI05-0022-1} Correction: Added a Bounded (Run-Time) Error to
            cover tampering by generic actual subprograms.

264.g/3     {AI05-0027-1} Correction: Added a Bounded (Run-Time) Error to
            cover access to finalized vector containers.

264.h/3     {AI05-0044-1} Correction: Redefined "<" actuals to require a
            strict weak ordering; the old definition allowed indeterminant
            comparisons that would not have worked in a container.

264.i/3     {AI05-0084-1} Correction: Added a pragma Remote_Types so that
            containers can be used in distributed programs.

264.j/3     {AI05-0160-1} Correction: Revised the definition of invalid
            cursors to cover missing (and new) cases.

264.k/3     {AI05-0265-1} Correction: Defined when a container prohibits
            tampering in order to more clearly define where the check is made
            and the exception raised.


                        Wording Changes from Ada 2012

264.l/4     {AI12-0110-1} Corrigendum: Clarified that tampering checks precede
            all other checks made by a subprogram (but come after those
            associated with the call).


A.18.3 The Generic Package Containers.Doubly_Linked_Lists


1/2 {AI95-00302-03} The language-defined generic package
Containers.Doubly_Linked_Lists provides private types List and Cursor, and a
set of operations for each type. A list container is optimized for insertion
and deletion at any position.

2/2 {AI95-00302-03} A doubly-linked list container object manages a linked
list of internal nodes, each of which contains an element and pointers to the
next (successor) and previous (predecessor) internal nodes. A cursor
designates a particular node within a list (and by extension the element
contained in that node). A cursor keeps designating the same node (and
element) as long as the node is part of the container, even if the node is
moved in the container.

3/2 {AI95-00302-03} The length of a list is the number of elements it contains.


                              Static Semantics

4/2 {AI95-00302-03} The generic library package Containers.Doubly_Linked_Lists
has the following declaration:

5/3     {AI05-0084-1} {AI05-0212-1} with Ada.Iterator_Interfaces;
        generic
           type Element_Type is private;
           with function "=" (Left, Right : Element_Type)
              return Boolean is <>;
        package Ada.Containers.Doubly_Linked_Lists is
           pragma Preelaborate(Doubly_Linked_Lists);
           pragma Remote_Types(Doubly_Linked_Lists);

6/3     {AI05-0212-1}    type List is tagged private
              with Constant_Indexing => Constant_Reference,
                   Variable_Indexing => Reference,
                   Default_Iterator  => Iterate,
                   Iterator_Element  => Element_Type;
           pragma Preelaborable_Initialization(List);

7/2        type Cursor is private;
           pragma Preelaborable_Initialization(Cursor);

8/2        Empty_List : constant List;

9/2        No_Element : constant Cursor;

9.1/3   {AI05-0212-1}    function Has_Element
         (Position : Cursor) return Boolean;

9.2/3   {AI05-0212-1}    package List_Iterator_Interfaces is new
               Ada.Iterator_Interfaces (Cursor, Has_Element);

10/2       function "=" (Left, Right : List) return Boolean;

11/2       function Length (Container : List) return Count_Type;

12/2       function Is_Empty (Container : List) return Boolean;

13/2       procedure Clear (Container : in out List);

14/2       function Element (Position : Cursor)
              return Element_Type;

15/2       procedure Replace_Element (Container : in out List;
                                      Position  : in     Cursor;
                                      New_Item  : in     Element_Type);

16/2       procedure Query_Element
             (Position : in Cursor;
              Process  : not null access procedure (Element : in Element_Type));

17/2       procedure Update_Element
             (Container : in out List;
              Position  : in     Cursor;
              Process   : not null access procedure
                              (Element : in out Element_Type));

17.1/3  {AI05-0212-1}    type Constant_Reference_Type
                 (Element : not null access constant Element_Type) is private
              with Implicit_Dereference => Element;

17.2/3  {AI05-0212-1}    type Reference_Type
         (Element : not null access Element_Type) is private
              with Implicit_Dereference => Element;

17.3/3  {AI05-0212-1}    function Constant_Reference
         (Container : aliased in List;
                                        Position  : in Cursor)
              return Constant_Reference_Type;

17.4/3  {AI05-0212-1}    function Reference (Container : aliased in out List;
                               Position  : in Cursor)
              return Reference_Type;

17.5/3  {AI05-0001-1}    procedure Assign
         (Target : in out List; Source : in List);

17.6/3  {AI05-0001-1}    function Copy (Source : List) return List;

18/2       procedure Move (Target : in out List;
                           Source : in out List);

19/2       procedure Insert (Container : in out List;
                             Before    : in     Cursor;
                             New_Item  : in     Element_Type;
                             Count     : in     Count_Type := 1);

20/2       procedure Insert (Container : in out List;
                             Before    : in     Cursor;
                             New_Item  : in     Element_Type;
                             Position  :    out Cursor;
                             Count     : in     Count_Type := 1);

21/2       procedure Insert (Container : in out List;
                             Before    : in     Cursor;
                             Position  :    out Cursor;
                             Count     : in     Count_Type := 1);

22/2       procedure Prepend (Container : in out List;
                              New_Item  : in     Element_Type;
                              Count     : in     Count_Type := 1);

23/2       procedure Append (Container : in out List;
                             New_Item  : in     Element_Type;
                             Count     : in     Count_Type := 1);

24/2       procedure Delete (Container : in out List;
                             Position  : in out Cursor;
                             Count     : in     Count_Type := 1);

25/2       procedure Delete_First (Container : in out List;
                                   Count     : in     Count_Type := 1);

26/2       procedure Delete_Last (Container : in out List;
                                  Count     : in     Count_Type := 1);

27/2       procedure Reverse_Elements (Container : in out List);

28/2       procedure Swap (Container : in out List;
                           I, J      : in     Cursor);

29/2       procedure Swap_Links (Container : in out List;
                                 I, J      : in     Cursor);

30/2       procedure Splice (Target   : in out List;
                             Before   : in     Cursor;
                             Source   : in out List);

31/2       procedure Splice (Target   : in out List;
                             Before   : in     Cursor;
                             Source   : in out List;
                             Position : in out Cursor);

32/2       procedure Splice (Container: in out List;
                             Before   : in     Cursor;
                             Position : in     Cursor);

33/2       function First (Container : List) return Cursor;

34/2       function First_Element (Container : List)
              return Element_Type;

35/2       function Last (Container : List) return Cursor;

36/2       function Last_Element (Container : List)
              return Element_Type;

37/2       function Next (Position : Cursor) return Cursor;

38/2       function Previous (Position : Cursor) return Cursor;

39/2       procedure Next (Position : in out Cursor);

40/2       procedure Previous (Position : in out Cursor);

41/2       function Find (Container : List;
                          Item      : Element_Type;
                          Position  : Cursor := No_Element)
              return Cursor;

42/2       function Reverse_Find (Container : List;
                                  Item      : Element_Type;
                                  Position  : Cursor := No_Element)
              return Cursor;

43/2       function Contains (Container : List;
                              Item      : Element_Type) return Boolean;

44/3    This paragraph was deleted.{AI05-0212-1}

45/2       procedure Iterate
             (Container : in List;
              Process   : not null access procedure (Position : in Cursor));

46/2       procedure Reverse_Iterate
             (Container : in List;
              Process   : not null access procedure (Position : in Cursor));

46.1/3  {AI05-0212-1}    function Iterate (Container : in List)
              return List_Iterator_Interfaces.Reversible_Iterator'Class;

46.2/3  {AI05-0212-1}
           function Iterate (Container : in List; Start : in Cursor)
              return List_Iterator_Interfaces.Reversible_Iterator'Class;

47/2       generic
              with function "<" (Left, Right : Element_Type)
                 return Boolean is <>;
           package Generic_Sorting is

48/2          function Is_Sorted (Container : List) return Boolean;

49/2          procedure Sort (Container : in out List);

50/2          procedure Merge (Target  : in out List;
                               Source  : in out List);

51/2       end Generic_Sorting;

52/2    private

53/2       ... -- not specified by the language

54/2    end Ada.Containers.Doubly_Linked_Lists;

55/2 {AI95-00302-03} The actual function for the generic formal function "="
on Element_Type values is expected to define a reflexive and symmetric
relationship and return the same result value each time it is called with a
particular pair of values. If it behaves in some other manner, the functions
Find, Reverse_Find, and "=" on list values return an unspecified value. The
exact arguments and number of calls of this generic formal function by the
functions Find, Reverse_Find, and "=" on list values are unspecified.

55.a/2      Ramification: If the actual function for "=" is not symmetric and
            consistent, the result returned by the listed functions cannot be
            predicted. The implementation is not required to protect against
            "=" raising an exception, or returning random results, or any
            other "bad" behavior. And it can call "=" in whatever manner makes
            sense. But note that only the results of Find, Reverse_Find, and
            List "=" are unspecified; other subprograms are not allowed to
            break if "=" is bad (they aren't expected to use "=").

56/2 {AI95-00302-03} The type List is used to represent lists. The type List
needs finalization (see 7.6).

57/2 {AI95-00302-03} Empty_List represents the empty List object. It has a
length of 0. If an object of type List is not otherwise initialized, it is
initialized to the same value as Empty_List.

58/2 {AI95-00302-03} No_Element represents a cursor that designates no
element. If an object of type Cursor is not otherwise initialized, it is
initialized to the same value as No_Element.

59/2 {AI95-00302-03} The predefined "=" operator for type Cursor returns True
if both cursors are No_Element, or designate the same element in the same
container.

60/2 {AI95-00302-03} Execution of the default implementation of the Input,
Output, Read, or Write attribute of type Cursor raises Program_Error.

60.a/2      Reason: A cursor will probably be implemented in terms of one or
            more access values, and the effects of streaming access values is
            unspecified. Rather than letting the user stream junk by accident,
            we mandate that streaming of cursors raise Program_Error by
            default. The attributes can always be specified if there is a need
            to support streaming.

60.1/3 {AI05-0001-1} {AI05-0262-1} List'Write for a List object L writes
Length(L) elements of the list to the stream. It also may write additional
information about the list.

60.2/3 {AI05-0001-1} {AI05-0262-1} List'Read reads the representation of a
list from the stream, and assigns to Item a list with the same length and
elements as was written by List'Write.

60.b/3      Ramification: Streaming more elements than the container length is
            wrong. For implementation implications of this rule, see the
            Implementation Note in A.18.2.

61/2 {AI95-00302-03} [Some operations of this generic package have
access-to-subprogram parameters. To ensure such operations are well-defined,
they guard against certain actions by the designated subprogram. In
particular, some operations check for "tampering with cursors" of a container
because they depend on the set of elements of the container remaining
constant, and others check for "tampering with elements" of a container
because they depend on elements of the container not being replaced.]

62/2 {AI95-00302-03} A subprogram is said to tamper with cursors of a list
object L if:

63/2   * it inserts or deletes elements of L, that is, it calls the Insert,
        Clear, Delete, or Delete_Last procedures with L as a parameter; or

63.a/2      To be honest: Operations which are defined to be equivalent to a
            call on one of these operations also are included. Similarly,
            operations which call one of these as part of their definition are
            included.

64/2   * it reorders the elements of L, that is, it calls the Splice,
        Swap_Links, or Reverse_Elements procedures or the Sort or Merge
        procedures of an instance of Generic_Sorting with L as a parameter; or

65/2   * it finalizes L; or

65.1/3   * {AI05-0001-1} it calls the Assign procedure with L as the Target
        parameter; or

65.a.1/3    Ramification: We don't need to explicitly mention
            assignment_statement, because that finalizes the target object as
            part of the operation, and finalization of an object is already
            defined as tampering with cursors.

66/2   * it calls the Move procedure with L as a parameter.

66.a/2      Reason: Swap copies elements rather than reordering them, so it
            doesn't tamper with cursors.

67/2 {AI95-00302-03} A subprogram is said to tamper with elements of a list
object L if:

68/2   * it tampers with cursors of L; or

69/2   * it replaces one or more elements of L, that is, it calls the
        Replace_Element or Swap procedures with L as a parameter.

69.a/2      Reason: Complete replacement of an element can cause its memory to
            be deallocated while another operation is holding onto a reference
            to it. That can't be allowed. However, a simple modification of
            (part of) an element is not a problem, so Update_Element does not
            cause a problem.

69.1/4 {AI05-0265-1} {AI12-0110-1} When tampering with cursors is prohibited
for a particular list object L, Program_Error is propagated by a call of any
language-defined subprogram that is defined to tamper with the cursors of L,
leaving L unmodified. Similarly, when tampering with elements is prohibited
for a particular list object L, Program_Error is propagated by a call of any
language-defined subprogram that is defined to tamper with the elements of L
[(or tamper with the cursors of L)], leaving L unmodified. These checks are
made before any other defined behavior of the body of the language-defined
subprogram.

69.b/3      Proof: Tampering with elements includes tampering with cursors, so
            we mention it only from completeness in the second sentence.

69.2/3  function Has_Element (Position : Cursor) return Boolean;

69.3/3      {AI05-0212-1} Returns True if Position designates an element, and
            returns False otherwise.

69.c/3      To be honest: {AI05-0005-1} {AI05-0212-1} This function might not
            detect cursors that designate deleted elements; such cursors are
            invalid (see below) and the result of calling Has_Element with an
            invalid cursor is unspecified (but not erroneous).

70/2    function "=" (Left, Right : List) return Boolean;

71/3        {AI95-00302-03} {AI05-0264-1} If Left and Right denote the same
            list object, then the function returns True. If Left and Right
            have different lengths, then the function returns False.
            Otherwise, it compares each element in Left to the corresponding
            element in Right using the generic formal equality operator. If
            any such comparison returns False, the function returns False;
            otherwise, it returns True. Any exception raised during evaluation
            of element equality is propagated.

71.a/2      Implementation Note: This wording describes the canonical
            semantics. However, the order and number of calls on the formal
            equality function is unspecified for all of the operations that
            use it in this package, so an implementation can call it as many
            or as few times as it needs to get the correct answer.
            Specifically, there is no requirement to call the formal equality
            additional times once the answer has been determined.

72/2    function Length (Container : List) return Count_Type;

73/2        {AI95-00302-03} Returns the number of elements in Container.

74/2    function Is_Empty (Container : List) return Boolean;

75/2        {AI95-00302-03} Equivalent to Length (Container) = 0.

76/2    procedure Clear (Container : in out List);

77/2        {AI95-00302-03} Removes all the elements from Container.

78/2    function Element (Position : Cursor) return Element_Type;

79/2        {AI95-00302-03} If Position equals No_Element, then
            Constraint_Error is propagated. Otherwise, Element returns the
            element designated by Position.

80/2    procedure Replace_Element (Container : in out List;
                                   Position  : in     Cursor;
                                   New_Item  : in     Element_Type);

81/3        {AI95-00302-03} {AI05-0264-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Replace_Element assigns the value New_Item to the element
            designated by Position.

82/2    procedure Query_Element
          (Position : in Cursor;
           Process  : not null access procedure (Element : in Element_Type));

83/3        {AI95-00302-03} {AI05-0021-1} {AI05-0265-1} If Position equals
            No_Element, then Constraint_Error is propagated. Otherwise,
            Query_Element calls Process.all with the element designated by
            Position as the argument. Tampering with the elements of the list
            that contains the element designated by Position is prohibited
            during the execution of the call on Process.all. Any exception
            raised by Process.all is propagated.

84/2    procedure Update_Element
          (Container : in out List;
           Position  : in     Cursor;
           Process   : not null access procedure (Element : in out Element_Type));

85/3        {AI95-00302-03} {AI05-0264-1} {AI05-0265-1} If Position equals
            No_Element, then Constraint_Error is propagated; if Position does
            not designate an element in Container, then Program_Error is
            propagated. Otherwise, Update_Element calls Process.all with the
            element designated by Position as the argument. Tampering with the
            elements of Container is prohibited during the execution of the
            call on Process.all. Any exception raised by Process.all is
            propagated.

86/2        If Element_Type is unconstrained and definite, then the actual
            Element parameter of Process.all shall be unconstrained.

86.a/2      Ramification: This means that the elements cannot be directly
            allocated from the heap; it must be possible to change the
            discriminants of the element in place.

86.1/3  type Constant_Reference_Type
              (Element : not null access constant Element_Type) is private
           with Implicit_Dereference => Element;

86.2/3  type Reference_Type (Element : not null access Element_Type) is private
           with Implicit_Dereference => Element;

86.3/3      {AI05-0212-1} The types Constant_Reference_Type and Reference_Type
            need finalization.

86.4/3      The default initialization of an object of type
            Constant_Reference_Type or Reference_Type propagates Program_Error.

86.b/3      Reason: It is expected that Reference_Type (and
            Constant_Reference_Type) will be a controlled type, for which
            finalization will have some action to terminate the tampering
            check for the associated container. If the object is created by
            default, however, there is no associated container. Since this is
            useless, and supporting this case would take extra work, we define
            it to raise an exception.

86.5/3  function Constant_Reference (Container : aliased in List;
                                     Position  : in Cursor)
           return Constant_Reference_Type;

86.6/3      {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Constant_Indexing and Implicit_Dereference aspects) provides a
            convenient way to gain read access to an individual element of a
            list given a cursor.

86.7/3      {AI05-0212-1} {AI05-0265-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Constant_Reference returns an object whose discriminant is an
            access value that designates the element designated by Position.
            Tampering with the elements of Container is prohibited while the
            object returned by Constant_Reference exists and has not been
            finalized.

86.8/3  function Reference (Container : aliased in out List;
                            Position  : in Cursor)
           return Reference_Type;

86.9/3      {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Variable_Indexing and Implicit_Dereference aspects) provides a
            convenient way to gain read and write access to an individual
            element of a list given a cursor.

86.10/3     {AI05-0212-1} {AI05-0265-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Reference returns an object whose discriminant is an access value
            that designates the element designated by Position. Tampering with
            the elements of Container is prohibited while the object returned
            by Reference exists and has not been finalized.

86.11/3 procedure Assign (Target : in out List; Source : in List);

86.12/3     {AI05-0001-1} {AI05-0248-1} If Target denotes the same object as
            Source, the operation has no effect. Otherwise, the elements of
            Source are copied to Target as for an assignment_statement
            assigning Source to Target.

86.c/3      Discussion: {AI05-0005-1} This routine exists for compatibility
            with the bounded list container. For an unbounded list, Assign(A,
            B) and A := B behave identically. For a bounded list, := will
            raise an exception if the container capacities are different,
            while Assign will not raise an exception if there is enough room
            in the target.

86.13/3 function Copy (Source : List) return List;

86.14/3     {AI05-0001-1} Returns a list whose elements match the elements of
            Source.

87/2    procedure Move (Target : in out List;
                        Source : in out List);

88/3        {AI95-00302-03} {AI05-0001-1} {AI05-0248-1} {AI05-0262-1} If
            Target denotes the same object as Source, then the operation has
            no effect. Otherwise, the operation is equivalent to Assign
            (Target, Source) followed by Clear (Source).

89/2    procedure Insert (Container : in out List;
                          Before    : in     Cursor;
                          New_Item  : in     Element_Type;
                          Count     : in     Count_Type := 1);

90/2        {AI95-00302-03} If Before is not No_Element, and does not
            designate an element in Container, then Program_Error is
            propagated. Otherwise, Insert inserts Count copies of New_Item
            prior to the element designated by Before. If Before equals
            No_Element, the new elements are inserted after the last node (if
            any). Any exception raised during allocation of internal storage
            is propagated, and Container is not modified.

90.a/2      Ramification: The check on Before checks that the cursor does not
            belong to some other Container. This check implies that a
            reference to the container is included in the cursor value. This
            wording is not meant to require detection of dangling cursors;
            such cursors are defined to be invalid, which means that execution
            is erroneous, and any result is allowed (including not raising an
            exception).

91/2    procedure Insert (Container : in out List;
                          Before    : in     Cursor;
                          New_Item  : in     Element_Type;
                          Position  :    out Cursor;
                          Count     : in     Count_Type := 1);

92/3        {AI95-00302-03} {AI05-0257-1} If Before is not No_Element, and
            does not designate an element in Container, then Program_Error is
            propagated. Otherwise, Insert allocates Count copies of New_Item,
            and inserts them prior to the element designated by Before. If
            Before equals No_Element, the new elements are inserted after the
            last element (if any). Position designates the first
            newly-inserted element, or if Count equals 0, then Position is
            assigned the value of Before. Any exception raised during
            allocation of internal storage is propagated, and Container is not
            modified.

93/2    procedure Insert (Container : in out List;
                          Before    : in     Cursor;
                          Position  :    out Cursor;
                          Count     : in     Count_Type := 1);

94/3        {AI95-00302-03} {AI05-0257-1} If Before is not No_Element, and
            does not designate an element in Container, then Program_Error is
            propagated. Otherwise, Insert inserts Count new elements prior to
            the element designated by Before. If Before equals No_Element, the
            new elements are inserted after the last node (if any). The new
            elements are initialized by default (see 3.3.1). Position
            designates the first newly-inserted element, or if Count equals 0,
            then Position is assigned the value of Before. Any exception
            raised during allocation of internal storage is propagated, and
            Container is not modified.

95/2    procedure Prepend (Container : in out List;
                           New_Item  : in     Element_Type;
                           Count     : in     Count_Type := 1);

96/2        {AI95-00302-03} Equivalent to Insert (Container, First
            (Container), New_Item, Count).

97/2    procedure Append (Container : in out List;
                          New_Item  : in     Element_Type;
                          Count     : in     Count_Type := 1);

98/2        {AI95-00302-03} Equivalent to Insert (Container, No_Element,
            New_Item, Count).

99/2    procedure Delete (Container : in out List;
                          Position  : in out Cursor;
                          Count     : in     Count_Type := 1);

100/3       {AI95-00302-03} {AI05-0264-1} If Position equals No_Element, then
            Constraint_Error is propagated. If Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Delete removes (from Container) Count elements starting at the
            element designated by Position (or all of the elements starting at
            Position if there are fewer than Count elements starting at
            Position). Finally, Position is set to No_Element.

101/2   procedure Delete_First (Container : in out List;
                                Count     : in     Count_Type := 1);

102/3       {AI95-00302-03} {AI05-0021-1} If Length (Container) <= Count, then
            Delete_First is equivalent to Clear (Container). Otherwise, it
            removes the first Count nodes from Container.

103/2   procedure Delete_Last (Container : in out List;
                               Count     : in     Count_Type := 1);

104/3       {AI95-00302-03} {AI05-0264-1} If Length (Container) <= Count, then
            Delete_Last is equivalent to Clear (Container). Otherwise, it
            removes the last Count nodes from Container.

105/2   procedure Reverse_Elements (Container : in out List);

106/2       {AI95-00302-03} Reorders the elements of Container in reverse
            order.

106.a/2     Discussion: Unlike the similar routine for a vector, elements
            should not be copied; rather, the nodes should be exchanged.
            Cursors are expected to reference the same elements afterwards.

107/2   procedure Swap (Container : in out List;
                        I, J      : in     Cursor);

108/2       {AI95-00302-03} If either I or J is No_Element, then
            Constraint_Error is propagated. If either I or J do not designate
            an element in Container, then Program_Error is propagated.
            Otherwise, Swap exchanges the values of the elements designated by
            I and J.

108.a/2     Ramification: After a call to Swap, I designates the element value
            previously designated by J, and J designates the element value
            previously designated by I. The cursors do not become ambiguous
            from this operation.

108.b/2     To be honest: The implementation is not required to actually copy
            the elements if it can do the swap some other way. But it is
            allowed to copy the elements if needed.

109/2   procedure Swap_Links (Container : in out List;
                              I, J      : in     Cursor);

110/2       {AI95-00302-03} If either I or J is No_Element, then
            Constraint_Error is propagated. If either I or J do not designate
            an element in Container, then Program_Error is propagated.
            Otherwise, Swap_Links exchanges the nodes designated by I and J.

110.a/2     Ramification: Unlike Swap, this exchanges the nodes, not the
            elements. No copying is performed. I and J designate the same
            elements after this call as they did before it. This operation can
            provide better performance than Swap if the element size is large.

111/2   procedure Splice (Target   : in out List;
                          Before   : in     Cursor;
                          Source   : in out List);

112/2       {AI95-00302-03} If Before is not No_Element, and does not
            designate an element in Target, then Program_Error is propagated.
            Otherwise, if Source denotes the same object as Target, the
            operation has no effect. Otherwise, Splice reorders elements such
            that they are removed from Source and moved to Target, immediately
            prior to Before. If Before equals No_Element, the nodes of Source
            are spliced after the last node of Target. The length of Target is
            incremented by the number of nodes in Source, and the length of
            Source is set to 0.

113/2   procedure Splice (Target   : in out List;
                          Before   : in     Cursor;
                          Source   : in out List;
                          Position : in out Cursor);

114/3       {AI95-00302-03} {AI05-0264-1} If Position is No_Element, then
            Constraint_Error is propagated. If Before does not equal
            No_Element, and does not designate an element in Target, then
            Program_Error is propagated. If Position does not equal
            No_Element, and does not designate a node in Source, then
            Program_Error is propagated. If Source denotes the same object as
            Target, then there is no effect if Position equals Before, else
            the element designated by Position is moved immediately prior to
            Before, or, if Before equals No_Element, after the last element.
            In both cases, Position and the length of Target are unchanged.
            Otherwise, the element designated by Position is removed from
            Source and moved to Target, immediately prior to Before, or, if
            Before equals No_Element, after the last element of Target. The
            length of Target is incremented, the length of Source is
            decremented, and Position is updated to represent an element in
            Target.

114.a/2     Ramification: If Source is the same as Target, and Position =
            Before, or Next(Position) = Before, Splice has no effect, as the
            element does not have to move to meet the postcondition.

115/2   procedure Splice (Container: in out List;
                          Before   : in     Cursor;
                          Position : in     Cursor);

116/3       {AI95-00302-03} {AI05-0264-1} If Position is No_Element, then
            Constraint_Error is propagated. If Before does not equal
            No_Element, and does not designate an element in Container, then
            Program_Error is propagated. If Position does not equal
            No_Element, and does not designate a node in Container, then
            Program_Error is propagated. If Position equals Before there is no
            effect. Otherwise, the element designated by Position is moved
            immediately prior to Before, or, if Before equals No_Element,
            after the last element. The length of Container is unchanged.

117/2   function First (Container : List) return Cursor;

118/3       {AI95-00302-03} {AI05-0264-1} If Container is empty, First returns
            the value No_Element. Otherwise, it returns a cursor that
            designates the first node in Container.

119/2   function First_Element (Container : List) return Element_Type;

120/2       {AI95-00302-03} Equivalent to Element (First (Container)).

121/2   function Last (Container : List) return Cursor;

122/3       {AI95-00302-03} {AI05-0264-1} If Container is empty, Last returns
            the value No_Element. Otherwise, it returns a cursor that
            designates the last node in Container.

123/2   function Last_Element (Container : List) return Element_Type;

124/2       {AI95-00302-03} Equivalent to Element (Last (Container)).

125/2   function Next (Position : Cursor) return Cursor;

126/2       {AI95-00302-03} If Position equals No_Element or designates the
            last element of the container, then Next returns the value
            No_Element. Otherwise, it returns a cursor that designates the
            successor of the element designated by Position.

127/2   function Previous (Position : Cursor) return Cursor;

128/2       {AI95-00302-03} If Position equals No_Element or designates the
            first element of the container, then Previous returns the value
            No_Element. Otherwise, it returns a cursor that designates the
            predecessor of the element designated by Position.

129/2   procedure Next (Position : in out Cursor);

130/2       {AI95-00302-03} Equivalent to Position := Next (Position).

131/2   procedure Previous (Position : in out Cursor);

132/2       {AI95-00302-03} Equivalent to Position := Previous (Position).

133/2   function Find (Container : List;
                       Item      : Element_Type;
                       Position  : Cursor := No_Element)
          return Cursor;

134/2       {AI95-00302-03} If Position is not No_Element, and does not
            designate an element in Container, then Program_Error is
            propagated. Find searches the elements of Container for an element
            equal to Item (using the generic formal equality operator). The
            search starts at the element designated by Position, or at the
            first element if Position equals No_Element. It proceeds towards
            Last (Container). If no equal element is found, then Find returns
            No_Element. Otherwise, it returns a cursor designating the first
            equal element encountered.

135/2   function Reverse_Find (Container : List;
                               Item      : Element_Type;
                               Position  : Cursor := No_Element)
           return Cursor;

136/2       {AI95-00302-03} If Position is not No_Element, and does not
            designate an element in Container, then Program_Error is
            propagated. Find searches the elements of Container for an element
            equal to Item (using the generic formal equality operator). The
            search starts at the element designated by Position, or at the
            last element if Position equals No_Element. It proceeds towards
            First (Container). If no equal element is found, then Reverse_Find
            returns No_Element. Otherwise, it returns a cursor designating the
            first equal element encountered.

137/2   function Contains (Container : List;
                           Item      : Element_Type) return Boolean;

138/2       {AI95-00302-03} Equivalent to Find (Container, Item) /= No_Element.

            Paragraphs 139 and 140 were moved above.

141/2   procedure Iterate
          (Container : in List;
           Process   : not null access procedure (Position : in Cursor));

142/3       {AI95-00302-03} {AI05-0265-1} Iterate calls Process.all with a
            cursor that designates each node in Container, starting with the
            first node and moving the cursor as per the Next function.
            Tampering with the cursors of Container is prohibited during the
            execution of a call on Process.all. Any exception raised by
            Process.all is propagated.

142.a/2     Implementation Note: The purpose of the tamper with cursors check
            is to prevent erroneous execution from the Position parameter of
            Process.all becoming invalid. This check takes place when the
            operations that tamper with the cursors of the container are
            called. The check cannot be made later (say in the body of
            Iterate), because that could cause the Position cursor to be
            invalid and potentially cause execution to become erroneous --
            defeating the purpose of the check.

142.b/2     See Iterate for vectors (A.18.2) for a suggested implementation of
            the check.

143/2   procedure Reverse_Iterate
          (Container : in List;
           Process   : not null access procedure (Position : in Cursor));

144/3       {AI95-00302-03} {AI05-0212-1} Iterates over the nodes in Container
            as per procedure Iterate, except that elements are traversed in
            reverse order, starting with the last node and moving the cursor
            as per the Previous function.

144.1/3 function Iterate (Container : in List)
           return List_Iterator_Interfaces.Reversible_Iterator'Class;

144.2/3     {AI05-0212-1} {AI05-0265-1} {AI05-0269-1} Iterate returns a
            reversible iterator object (see 5.5.1) that will generate a value
            for a loop parameter (see 5.5.2) designating each node in
            Container, starting with the first node and moving the cursor as
            per the Next function when used as a forward iterator, and
            starting with the last node and moving the cursor as per the
            Previous function when used as a reverse iterator. Tampering with
            the cursors of Container is prohibited while the iterator object
            exists (in particular, in the sequence_of_statements of the
            loop_statement whose iterator_specification denotes this object).
            The iterator object needs finalization.

144.3/3 function Iterate (Container : in List; Start : in Cursor)
           return List_Iterator_Interfaces.Reversible_Iterator'Class;

144.4/3     {AI05-0212-1} {AI05-0262-1} {AI05-0265-1} {AI05-0269-1} If Start
            is not No_Element and does not designate an item in Container,
            then Program_Error is propagated. If Start is No_Element, then
            Constraint_Error is propagated. Otherwise, Iterate returns a
            reversible iterator object (see 5.5.1) that will generate a value
            for a loop parameter (see 5.5.2) designating each node in
            Container, starting with the node designated by Start and moving
            the cursor as per the Next function when used as a forward
            iterator, or moving the cursor as per the Previous function when
            used as a reverse iterator. Tampering with the cursors of
            Container is prohibited while the iterator object exists (in
            particular, in the sequence_of_statements of the loop_statement
            whose iterator_specification denotes this object). The iterator
            object needs finalization.

144.a/3     Discussion: Exits are allowed from the loops created using the
            iterator objects. In particular, to stop the iteration at a
            particular cursor, just add

144.b/3         exit when Cur = Stop;

144.c/3     in the body of the loop (assuming that Cur is the loop parameter
            and Stop is the cursor that you want to stop at).

145/3 {AI05-0044-1} {AI05-0262-1} The actual function for the generic formal
function "<" of Generic_Sorting is expected to return the same value each time
it is called with a particular pair of element values. It should define a
strict weak ordering relationship (see A.18); it should not modify Container.
If the actual for "<" behaves in some other manner, the behavior of the
subprograms of Generic_Sorting are unspecified. The number of times the
subprograms of Generic_Sorting call "<" is unspecified.

146/2   function Is_Sorted (Container : List) return Boolean;

147/2       {AI95-00302-03} Returns True if the elements are sorted smallest
            first as determined by the generic formal "<" operator; otherwise,
            Is_Sorted returns False. Any exception raised during evaluation of
            "<" is propagated.

148/2   procedure Sort (Container : in out List);

149/2       {AI95-00302-03} Reorders the nodes of Container such that the
            elements are sorted smallest first as determined by the generic
            formal "<" operator provided. The sort is stable. Any exception
            raised during evaluation of "<" is propagated.

149.a/2     Ramification: Unlike array sorts, we do require stable sorts here.
            That's because algorithms in the merge sort family (as described
            by Knuth) can be both fast and stable. Such sorts use the extra
            memory as offered by the links to provide better performance.

149.b/2     Note that list sorts never copy elements; it is the nodes, not the
            elements, that are reordered.

150/2   procedure Merge (Target  : in out List;
                         Source  : in out List);

151/3       {AI95-00302-03} {AI05-0021-1} If Source is empty, then Merge does
            nothing. If Source and Target are the same nonempty container
            object, then Program_Error is propagated. Otherwise, Merge removes
            elements from Source and inserts them into Target; afterwards,
            Target contains the union of the elements that were initially in
            Source and Target; Source is left empty. If Target and Source are
            initially sorted smallest first, then Target is ordered smallest
            first as determined by the generic formal "<" operator; otherwise,
            the order of elements in Target is unspecified. Any exception
            raised during evaluation of "<" is propagated.

151.a/2     Ramification: It is a bounded error if either of the lists is
            unsorted, see below. The bounded error can be recovered by sorting
            Target after the merge call, or the lists can be pretested with
            Is_Sorted.


                          Bounded (Run-Time) Errors

152/2 {AI95-00302-03} Calling Merge in an instance of Generic_Sorting with
either Source or Target not ordered smallest first using the provided generic
formal "<" operator is a bounded error. Either Program_Error is raised after
Target is updated as described for Merge, or the operation works as defined.

152.1/3 {AI05-0022-1} {AI05-0248-1} It is a bounded error for the actual
function associated with a generic formal subprogram, when called as part of
an operation of this package, to tamper with elements of any List parameter of
the operation. Either Program_Error is raised, or the operation works as
defined on the value of the List either prior to, or subsequent to, some or
all of the modifications to the List.

152.2/3 {AI05-0027-1} It is a bounded error to call any subprogram declared in
the visible part of Containers.Doubly_Linked_Lists when the associated
container has been finalized. If the operation takes Container as an in out
parameter, then it raises Constraint_Error or Program_Error. Otherwise, the
operation either proceeds as it would for an empty container, or it raises
Constraint_Error or Program_Error.


                             Erroneous Execution

153/2 {AI95-00302-03} A Cursor value is invalid if any of the following have
occurred since it was created:

154/2   * The list that contains the element it designates has been finalized;

154.1/3   * {AI05-0160-1} The list that contains the element it designates has
        been used as the Target of a call to Assign, or as the target of an
        assignment_statement;

155/2   * [The list that contains the element it designates has been used as
        the Source or Target of a call to Move;] or

155.a/3     Proof: {AI05-0001-1} Move has been reworded in terms of Assign and
            Clear, which are covered by other bullets, so this text is
            redundant.

156/3   * {AI05-0160-1} {AI05-0262-1} The element it designates has been
        removed from the list that previously contained the element.

156.a/3     To be honest: {AI05-0160-1} The cursor modified by the four
            parameter Splice is not invalid, even though the element it
            designates has been removed from the source list, because that
            cursor has been modified to designate that element in the target
            list - the cursor no longer designates an element in the source
            list.

156.b/3     Ramification: {AI05-0160-1} This can happen directly via calls to
            Delete, Delete_Last, Clear, Splice with a Source parameter, and
            Merge; and indirectly via calls to Delete_First, Assign, and Move.

157/2 {AI95-00302-03} The result of "=" or Has_Element is unspecified if it is
called with an invalid cursor parameter. Execution is erroneous if any other
subprogram declared in Containers.Doubly_Linked_Lists is called with an
invalid cursor parameter.

157.a/2     Discussion: The list above is intended to be exhaustive. In other
            cases, a cursor value continues to designate its original element.
            For instance, cursor values survive the insertion and deletion of
            other nodes.

157.b/2     While it is possible to check for these cases, in many cases the
            overhead necessary to make the check is substantial in time or
            space. Implementations are encouraged to check for as many of
            these cases as possible and raise Program_Error if detected.

157.1/3 {AI05-0212-1} Execution is erroneous if the list associated with the
result of a call to Reference or Constant_Reference is finalized before the
result object returned by the call to Reference or Constant_Reference is
finalized.

157.c/3     Reason: Each object of Reference_Type and Constant_Reference_Type
            probably contains some reference to the originating container. If
            that container is prematurely finalized (which is only possible
            via Unchecked_Deallocation, as accessibility checks prevent
            passing a container to Reference that will not live as long as the
            result), the finalization of the object of Reference_Type will try
            to access a nonexistent object. This is a normal case of a
            dangling pointer created by Unchecked_Deallocation; we have to
            explicitly mention it here as the pointer in question is not
            visible in the specification of the type. (This is the same reason
            we have to say this for invalid cursors.)


                         Implementation Requirements

158/2 {AI95-00302-03} No storage associated with a doubly-linked List object
shall be lost upon assignment or scope exit.

159/3 {AI95-00302-03} {AI05-0262-1} The execution of an assignment_statement
for a list shall have the effect of copying the elements from the source list
object to the target list object and changing the length of the target object
to that of the source object.

159.a/3     Implementation Note: {AI05-0298-1} An assignment of a List is a
            "deep" copy; that is the elements are copied as well as the data
            structures. We say "effect of" in order to allow the
            implementation to avoid copying elements immediately if it wishes.
            For instance, an implementation that avoided copying until one of
            the containers is modified would be allowed. (Note that this
            implementation would require care, see A.18.2 for more.)


                            Implementation Advice

160/2 {AI95-00302-03} Containers.Doubly_Linked_Lists should be implemented
similarly to a linked list. In particular, if N is the length of a list, then
the worst-case time complexity of Element, Insert with Count=1, and Delete
with Count=1 should be O(log N).

160.a/2     Implementation Advice: The worst-case time complexity of Element,
            Insert with Count=1, and Delete with Count=1 for
            Containers.Doubly_Linked_Lists should be O(log N).

160.b/2     Reason: We do not mean to overly constrain implementation
            strategies here. However, it is important for portability that the
            performance of large containers has roughly the same factors on
            different implementations. If a program is moved to an
            implementation that takes O(N) time to access elements, that
            program could be unusable when the lists are large. We allow O(log
            N) access because the proportionality constant and caching effects
            are likely to be larger than the log factor, and we don't want to
            discourage innovative implementations.

161/2 {AI95-00302-03} The worst-case time complexity of a call on procedure
Sort of an instance of Containers.Doubly_Linked_Lists.Generic_Sorting should
be O(N**2), and the average time complexity should be better than O(N**2).

161.a/2     Implementation Advice: A call on procedure Sort of an instance of
            Containers.Doubly_Linked_Lists.Generic_Sorting should have an
            average time complexity better than O(N**2) and worst case no
            worse than O(N**2).

161.b/2     Ramification: In other words, we're requiring the use of a better
            than O(N**2) sorting algorithm, such as Quicksort. No bubble sorts
            allowed!

162/2 {AI95-00302-03} Move should not copy elements, and should minimize
copying of internal data structures.

162.a/2     Implementation Advice: Containers.Doubly_Linked_Lists.Move should
            not copy elements, and should minimize copying of internal data
            structures.

162.b/2     Implementation Note: Usually that can be accomplished simply by
            moving the pointer(s) to the internal data structures from the
            Source container to the Target container.

163/2 {AI95-00302-03} If an exception is propagated from a list operation, no
storage should be lost, nor any elements removed from a list unless specified
by the operation.

163.a/2     Implementation Advice: If an exception is propagated from a list
            operation, no storage should be lost, nor any elements removed
            from a list unless specified by the operation.

163.b/2     Reason: This is important so that programs can recover from
            errors. But we don't want to require heroic efforts, so we just
            require documentation of cases where this can't be accomplished.

        NOTES

164/2   50  {AI95-00302-03} Sorting a list never copies elements, and is a
        stable sort (equal elements remain in the original order). This is
        different than sorting an array or vector, which may need to copy
        elements, and is probably not a stable sort.


                            Extensions to Ada 95

164.a/2     {AI95-00302-03} The generic package Containers.Doubly_Linked_Lists
            is new.


                        Inconsistencies With Ada 2005

164.b/3     {AI05-0248-1} {AI05-0257-1} Correction: The Insert versions that
            return a Position parameter are now defined to return Position =
            Before if Count = 0. This was unspecified for Ada 2005; so this
            will only be inconsistent if an implementation did something else
            and a program depended on that something else - this should be
            very rare.


                       Incompatibilities With Ada 2005

164.c/3     {AI05-0001-1} Subprograms Assign and Copy are added to
            Containers.Doubly_Linked_Lists. If an instance of
            Containers.Doubly_Linked_Lists is referenced in a use_clause, and
            an entity E with the same defining_identifier as a new entity in
            Containers.Doubly_Linked_Lists is defined in a package that is
            also referenced in a use_clause, the entity E may no longer be
            use-visible, resulting in errors. This should be rare and is
            easily fixed if it does occur.


                           Extensions to Ada 2005

164.d/3     {AI05-0212-1} Added iterator, reference, and indexing support to
            make list containers more convenient to use.


                        Wording Changes from Ada 2005

164.e/3     {AI05-0001-1} Generalized the definition of Move. Specified which
            elements are read/written by stream attributes.

164.f/3     {AI05-0022-1} Correction: Added a Bounded (Run-Time) Error to
            cover tampering by generic actual subprograms.

164.g/3     {AI05-0027-1} Correction: Added a Bounded (Run-Time) Error to
            cover access to finalized list containers.

164.h/3     {AI05-0044-1} Correction: Redefined "<" actuals to require a
            strict weak ordering; the old definition allowed indeterminant
            comparisons that would not have worked in a container.

164.i/3     {AI05-0084-1} Correction: Added a pragma Remote_Types so that
            containers can be used in distributed programs.

164.j/3     {AI05-0160-1} Correction: Revised the definition of invalid
            cursors to cover missing (and new) cases.

164.k/3     {AI05-0257-1} Correction: Added missing wording to describe the
            Position after Inserting 0 elements.

164.l/3     {AI05-0265-1} Correction: Defined when a container prohibits
            tampering in order to more clearly define where the check is made
            and the exception raised.


                        Wording Changes from Ada 2012

164.m/4     {AI12-0110-1} Corrigendum: Clarified that tampering checks precede
            all other checks made by a subprogram (but come after those
            associated with the call).


A.18.4 Maps


1/2 {AI95-00302-03} The language-defined generic packages
Containers.Hashed_Maps and Containers.Ordered_Maps provide private types Map
and Cursor, and a set of operations for each type. A map container allows an
arbitrary type to be used as a key to find the element associated with that
key. A hashed map uses a hash function to organize the keys, while an ordered
map orders the keys per a specified relation.

2/3 {AI95-00302-03} {AI05-0299-1} This subclause describes the declarations
that are common to both kinds of maps. See A.18.5 for a description of the
semantics specific to Containers.Hashed_Maps and A.18.6 for a description of
the semantics specific to Containers.Ordered_Maps.


                              Static Semantics

3/2 {AI95-00302-03} The actual function for the generic formal function "=" on
Element_Type values is expected to define a reflexive and symmetric
relationship and return the same result value each time it is called with a
particular pair of values. If it behaves in some other manner, the function
"=" on map values returns an unspecified value. The exact arguments and number
of calls of this generic formal function by the function "=" on map values are
unspecified.

3.a/2       Ramification: If the actual function for "=" is not symmetric and
            consistent, the result returned by "=" for Map objects cannot be
            predicted. The implementation is not required to protect against
            "=" raising an exception, or returning random results, or any
            other "bad" behavior. And it can call "=" in whatever manner makes
            sense. But note that only the result of "=" for Map objects is
            unspecified; other subprograms are not allowed to break if "=" is
            bad (they aren't expected to use "=").

4/2 {AI95-00302-03} The type Map is used to represent maps. The type Map needs
finalization (see 7.6).

5/2 {AI95-00302-03} A map contains pairs of keys and elements, called nodes.
Map cursors designate nodes, but also can be thought of as designating an
element (the element contained in the node) for consistency with the other
containers. There exists an equivalence relation on keys, whose definition is
different for hashed maps and ordered maps. A map never contains two or more
nodes with equivalent keys. The length of a map is the number of nodes it
contains.

6/2 {AI95-00302-03} Each nonempty map has two particular nodes called the
first node and the last node (which may be the same). Each node except for the
last node has a successor node. If there are no other intervening operations,
starting with the first node and repeatedly going to the successor node will
visit each node in the map exactly once until the last node is reached. The
exact definition of these terms is different for hashed maps and ordered maps.

7/2 {AI95-00302-03} [Some operations of these generic packages have
access-to-subprogram parameters. To ensure such operations are well-defined,
they guard against certain actions by the designated subprogram. In
particular, some operations check for "tampering with cursors" of a container
because they depend on the set of elements of the container remaining
constant, and others check for "tampering with elements" of a container
because they depend on elements of the container not being replaced.]

8/2 {AI95-00302-03} A subprogram is said to tamper with cursors of a map
object M if:

9/2   * it inserts or deletes elements of M, that is, it calls the Insert,
        Include, Clear, Delete, or Exclude procedures with M as a parameter; or

9.a/2       To be honest: Operations which are defined to be equivalent to a
            call on one of these operations also are included. Similarly,
            operations which call one of these as part of their definition are
            included.

10/2   * it finalizes M; or

10.1/3   * {AI05-0001-1} it calls the Assign procedure with M as the Target
        parameter; or

10.a/3      Ramification: We don't need to explicitly mention
            assignment_statement, because that finalizes the target object as
            part of the operation, and finalization of an object is already
            defined as tampering with cursors.

11/2   * it calls the Move procedure with M as a parameter; or

12/2   * it calls one of the operations defined to tamper with the cursors of
        M.

12.a/2      Ramification: Replace only modifies a key and element rather than
            rehashing, so it does not tamper with cursors.

13/2 {AI95-00302-03} A subprogram is said to tamper with elements of a map
object M if:

14/2   * it tampers with cursors of M; or

15/2   * it replaces one or more elements of M, that is, it calls the Replace
        or Replace_Element procedures with M as a parameter.

15.a/2      Reason: Complete replacement of an element can cause its memory to
            be deallocated while another operation is holding onto a reference
            to it. That can't be allowed. However, a simple modification of
            (part of) an element is not a problem, so Update_Element does not
            cause a problem.

15.1/4 {AI05-0265-1} {AI12-0110-1} When tampering with cursors is prohibited
for a particular map object M, Program_Error is propagated by a call of any
language-defined subprogram that is defined to tamper with the cursors of M,
leaving M unmodified. Similarly, when tampering with elements is prohibited
for a particular map object M, Program_Error is propagated by a call of any
language-defined subprogram that is defined to tamper with the elements of M
[(or tamper with the cursors of M)], leaving M unmodified. These checks are
made before any other defined behavior of the body of the language-defined
subprogram.

15.b/3      Proof: Tampering with elements includes tampering with cursors, so
            we mention it only from completeness in the second sentence.

16/2 {AI95-00302-03} Empty_Map represents the empty Map object. It has a
length of 0. If an object of type Map is not otherwise initialized, it is
initialized to the same value as Empty_Map.

17/2 {AI95-00302-03} No_Element represents a cursor that designates no node.
If an object of type Cursor is not otherwise initialized, it is initialized to
the same value as No_Element.

18/2 {AI95-00302-03} The predefined "=" operator for type Cursor returns True
if both cursors are No_Element, or designate the same element in the same
container.

19/2 {AI95-00302-03} Execution of the default implementation of the Input,
Output, Read, or Write attribute of type Cursor raises Program_Error.

19.a/2      Reason: A cursor will probably be implemented in terms of one or
            more access values, and the effects of streaming access values is
            unspecified. Rather than letting the user stream junk by accident,
            we mandate that streaming of cursors raise Program_Error by
            default. The attributes can always be specified if there is a need
            to support streaming.

19.1/3 {AI05-0001-1} {AI05-0262-1} Map'Write for a Map object M writes
Length(M) elements of the map to the stream. It also may write additional
information about the map.

19.2/3 {AI05-0001-1} {AI05-0262-1} Map'Read reads the representation of a map
from the stream, and assigns to Item a map with the same length and elements
as was written by Map'Write.

19.b/3      Ramification: Streaming more elements than the container length is
            wrong. For implementation implications of this rule, see the
            Implementation Note in A.18.2.

19.3/3  function Has_Element (Position : Cursor) return Boolean;

19.4/3      {AI05-0212-1} Returns True if Position designates an element, and
            returns False otherwise.

19.c/3      To be honest: {AI05-0005-1} {AI05-0212-1} This function might not
            detect cursors that designate deleted elements; such cursors are
            invalid (see below) and the result of calling Has_Element with an
            invalid cursor is unspecified (but not erroneous).

20/2    function "=" (Left, Right : Map) return Boolean;

21/2        {AI95-00302-03} If Left and Right denote the same map object, then
            the function returns True. If Left and Right have different
            lengths, then the function returns False. Otherwise, for each key
            K in Left, the function returns False if:

22/2          * a key equivalent to K is not present in Right; or

23/2          * the element associated with K in Left is not equal to the
                element associated with K in Right (using the generic formal
                equality operator for elements).

24/2        If the function has not returned a result after checking all of
            the keys, it returns True. Any exception raised during evaluation
            of key equivalence or element equality is propagated.

24.a/2      Implementation Note: This wording describes the canonical
            semantics. However, the order and number of calls on the formal
            equality function is unspecified for all of the operations that
            use it in this package, so an implementation can call it as many
            or as few times as it needs to get the correct answer.
            Specifically, there is no requirement to call the formal equality
            additional times once the answer has been determined.

25/2    function Length (Container : Map) return Count_Type;

26/2        {AI95-00302-03} Returns the number of nodes in Container.

27/2    function Is_Empty (Container : Map) return Boolean;

28/2        {AI95-00302-03} Equivalent to Length (Container) = 0.

29/2    procedure Clear (Container : in out Map);

30/2        {AI95-00302-03} Removes all the nodes from Container.

31/2    function Key (Position : Cursor) return Key_Type;

32/2        {AI95-00302-03} If Position equals No_Element, then
            Constraint_Error is propagated. Otherwise, Key returns the key
            component of the node designated by Position.

33/2    function Element (Position : Cursor) return Element_Type;

34/2        {AI95-00302-03} If Position equals No_Element, then
            Constraint_Error is propagated. Otherwise, Element returns the
            element component of the node designated by Position.

35/2    procedure Replace_Element (Container : in out Map;
                                   Position  : in     Cursor;
                                   New_Item  : in     Element_Type);

36/3        {AI95-00302-03} {AI05-0264-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Replace_Element assigns New_Item to the element of the node
            designated by Position.

37/2    procedure Query_Element
          (Position : in Cursor;
           Process  : not null access procedure (Key     : in Key_Type;
                                                 Element : in Element_Type));

38/3        {AI95-00302-03} {AI05-0021-1} {AI05-0265-1} If Position equals
            No_Element, then Constraint_Error is propagated. Otherwise,
            Query_Element calls Process.all with the key and element from the
            node designated by Position as the arguments. Tampering with the
            elements of the map that contains the element designated by
            Position is prohibited during the execution of the call on
            Process.all. Any exception raised by Process.all is propagated.

39/2    procedure Update_Element
          (Container : in out Map;
           Position  : in     Cursor;
           Process   : not null access procedure (Key     : in     Key_Type;
                                                  Element : in out Element_Type));

40/3        {AI95-00302-03} {AI05-0264-1} {AI05-0265-1} If Position equals
            No_Element, then Constraint_Error is propagated; if Position does
            not designate an element in Container, then Program_Error is
            propagated. Otherwise, Update_Element calls Process.all with the
            key and element from the node designated by Position as the
            arguments. Tampering with the elements of Container is prohibited
            during the execution of the call on Process.all. Any exception
            raised by Process.all is propagated.

41/2        If Element_Type is unconstrained and definite, then the actual
            Element parameter of Process.all shall be unconstrained.

41.a/2      Ramification: This means that the elements cannot be directly
            allocated from the heap; it must be possible to change the
            discriminants of the element in place.

41.1/3  type Constant_Reference_Type
              (Element : not null access constant Element_Type) is private
           with Implicit_Dereference => Element;

41.2/3  type Reference_Type (Element : not null access Element_Type) is private
           with Implicit_Dereference => Element;

41.3/3      {AI05-0212-1} The types Constant_Reference_Type and Reference_Type
            need finalization.

41.4/3      The default initialization of an object of type
            Constant_Reference_Type or Reference_Type propagates Program_Error.

41.b/3      Reason: It is expected that Reference_Type (and
            Constant_Reference_Type) will be a controlled type, for which
            finalization will have some action to terminate the tampering
            check for the associated container. If the object is created by
            default, however, there is no associated container. Since this is
            useless, and supporting this case would take extra work, we define
            it to raise an exception.

41.5/3  function Constant_Reference (Container : aliased in Map;
                                     Position  : in Cursor)
           return Constant_Reference_Type;

41.6/3      {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Constant_Indexing and Implicit_Dereference aspects) provides a
            convenient way to gain read access to an individual element of a
            map given a cursor.

41.7/3      {AI05-0212-1} {AI05-0265-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Constant_Reference returns an object whose discriminant is an
            access value that designates the element designated by Position.
            Tampering with the elements of Container is prohibited while the
            object returned by Constant_Reference exists and has not been
            finalized.

41.8/3  function Reference (Container : aliased in out Map;
                            Position  : in Cursor)
           return Reference_Type;

41.9/3      {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Variable_Indexing and Implicit_Dereference aspects) provides a
            convenient way to gain read and write access to an individual
            element of a map given a cursor.

41.10/3     {AI05-0212-1} {AI05-0265-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Reference returns an object whose discriminant is an access value
            that designates the element designated by Position. Tampering with
            the elements of Container is prohibited while the object returned
            by Reference exists and has not been finalized.

41.11/3 function Constant_Reference (Container : aliased in Map;
                                     Key       : in Key_Type)
           return Constant_Reference_Type;

41.12/3     {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Constant_Indexing and Implicit_Dereference aspects) provides a
            convenient way to gain read access to an individual element of a
            map given a key value.

41.13/3     Equivalent to Constant_Reference (Container, Find (Container,
            Key)).

41.14/3 function Reference (Container : aliased in out Map;
                            Key       : in Key_Type)
           return Reference_Type;

41.15/3     {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Variable_Indexing and Implicit_Dereference aspects) provides a
            convenient way to gain read and write access to an individual
            element of a map given a key value.

41.16/3     Equivalent to Reference (Container, Find (Container, Key)).

41.17/3 procedure Assign (Target : in out Map; Source : in Map);

41.18/3     {AI05-0001-1} {AI05-0248-1} If Target denotes the same object as
            Source, the operation has no effect. Otherwise, the key/element
            pairs of Source are copied to Target as for an
            assignment_statement assigning Source to Target.

41.c/3      Discussion: {AI05-0005-1} This routine exists for compatibility
            with the bounded map containers. For an unbounded map, Assign(A,
            B) and A := B behave identically. For a bounded map, := will raise
            an exception if the container capacities are different, while
            Assign will not raise an exception if there is enough room in the
            target.

42/2    procedure Move (Target : in out Map;
                        Source : in out Map);

43/3        {AI95-00302-03} {AI05-0001-1} {AI05-0248-1} {AI05-0262-1} If
            Target denotes the same object as Source, then the operation has
            no effect. Otherwise, the operation is equivalent to Assign
            (Target, Source) followed by Clear (Source).

44/2    procedure Insert (Container : in out Map;
                          Key       : in     Key_Type;
                          New_Item  : in     Element_Type;
                          Position  :    out Cursor;
                          Inserted  :    out Boolean);

45/2        {AI95-00302-03} Insert checks if a node with a key equivalent to
            Key is already present in Container. If a match is found, Inserted
            is set to False and Position designates the element with the
            matching key. Otherwise, Insert allocates a new node, initializes
            it to Key and New_Item, and adds it to Container; Inserted is set
            to True and Position designates the newly-inserted node. Any
            exception raised during allocation is propagated and Container is
            not modified.

46/2    procedure Insert (Container : in out Map;
                          Key       : in     Key_Type;
                          Position  :    out Cursor;
                          Inserted  :    out Boolean);

47/2        {AI95-00302-03} Insert inserts Key into Container as per the
            five-parameter Insert, with the difference that an element
            initialized by default (see 3.3.1) is inserted.

48/2    procedure Insert (Container : in out Map;
                          Key       : in     Key_Type;
                          New_Item  : in     Element_Type);

49/2        {AI95-00302-03} Insert inserts Key and New_Item into Container as
            per the five-parameter Insert, with the difference that if a node
            with a key equivalent to Key is already in the map, then
            Constraint_Error is propagated.

49.a/2      Ramification: This is equivalent to:

49.b/2          declare
                  Inserted : Boolean; C : Cursor;
                begin
                  Insert (Container, Key, New_Item, C, Inserted);
                  if not Inserted then
                     raise Constraint_Error;
                  end if;
                end;

49.c/2      but doesn't require the hassle of out parameters.

50/2    procedure Include (Container : in out Map;
                           Key       : in     Key_Type;
                           New_Item  : in     Element_Type);

51/2        {AI95-00302-03} Include inserts Key and New_Item into Container as
            per the five-parameter Insert, with the difference that if a node
            with a key equivalent to Key is already in the map, then this
            operation assigns Key and New_Item to the matching node. Any
            exception raised during assignment is propagated.

51.a/2      Ramification: This is equivalent to:

51.b/2          declare
                  C : Cursor := Find (Container, Key);
                begin
                  if C = No_Element then
                     Insert (Container, Key, New_Item);
                  else
                     Replace (Container, Key, New_Item);
                  end if;
                end;

51.c/2      but this avoids doing the search twice.

52/2    procedure Replace (Container : in out Map;
                           Key       : in     Key_Type;
                           New_Item  : in     Element_Type);

53/2        {AI95-00302-03} Replace checks if a node with a key equivalent to
            Key is present in Container. If a match is found, Replace assigns
            Key and New_Item to the matching node; otherwise, Constraint_Error
            is propagated.

53.a/2      Discussion: We update the key as well as the element, as the key
            might include additional information that does not participate in
            equivalence. If only the element needs to be updated, use
            Replace_Element (Find (Container, Key), New_Element).

54/2    procedure Exclude (Container : in out Map;
                           Key       : in     Key_Type);

55/2        {AI95-00302-03} Exclude checks if a node with a key equivalent to
            Key is present in Container. If a match is found, Exclude removes
            the node from the map.

55.a/2      Ramification: Exclude should work on an empty map; nothing happens
            in that case.

56/2    procedure Delete (Container : in out Map;
                          Key       : in     Key_Type);

57/2        {AI95-00302-03} Delete checks if a node with a key equivalent to
            Key is present in Container. If a match is found, Delete removes
            the node from the map; otherwise, Constraint_Error is propagated.

58/2    procedure Delete (Container : in out Map;
                          Position  : in out Cursor);

59/2        {AI95-00302-03} If Position equals No_Element, then
            Constraint_Error is propagated. If Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Delete removes the node designated by Position from the map.
            Position is set to No_Element on return.

59.a/2      Ramification: The check on Position checks that the cursor does
            not belong to some other map. This check implies that a reference
            to the map is included in the cursor value. This wording is not
            meant to require detection of dangling cursors; such cursors are
            defined to be invalid, which means that execution is erroneous,
            and any result is allowed (including not raising an exception).

60/2    function First (Container : Map) return Cursor;

61/2        {AI95-00302-03} If Length (Container) = 0, then First returns
            No_Element. Otherwise, First returns a cursor that designates the
            first node in Container.

62/2    function Next (Position  : Cursor) return Cursor;

63/2        {AI95-00302-03} Returns a cursor that designates the successor of
            the node designated by Position. If Position designates the last
            node, then No_Element is returned. If Position equals No_Element,
            then No_Element is returned.

64/2    procedure Next (Position  : in out Cursor);

65/2        {AI95-00302-03} Equivalent to Position := Next (Position).

66/2    function Find (Container : Map;
                       Key       : Key_Type) return Cursor;

67/2        {AI95-00302-03} If Length (Container) equals 0, then Find returns
            No_Element. Otherwise, Find checks if a node with a key equivalent
            to Key is present in Container. If a match is found, a cursor
            designating the matching node is returned; otherwise, No_Element
            is returned.

68/2    function Element (Container : Map;
                          Key       : Key_Type) return Element_Type;

69/2        {AI95-00302-03} Equivalent to Element (Find (Container, Key)).

70/2    function Contains (Container : Map;
                           Key       : Key_Type) return Boolean;

71/2        {AI95-00302-03} Equivalent to Find (Container, Key) /= No_Element.

            Paragraphs 72 and 73 were moved above.

74/2    procedure Iterate
          (Container : in Map;
           Process   : not null access procedure (Position : in Cursor));

75/3        {AI95-00302-03} {AI05-0265-1} Iterate calls Process.all with a
            cursor that designates each node in Container, starting with the
            first node and moving the cursor according to the successor
            relation. Tampering with the cursors of Container is prohibited
            during the execution of a call on Process.all. Any exception
            raised by Process.all is propagated.

75.a/2      Implementation Note: The "tamper with cursors" check takes place
            when the operations that insert or delete elements, and so on, are
            called.

75.b/2      See Iterate for vectors (A.18.2) for a suggested implementation of
            the check.


                          Bounded (Run-Time) Errors

75.1/3 {AI05-0022-1} {AI05-0248-1} It is a bounded error for the actual
function associated with a generic formal subprogram, when called as part of
an operation of a map package, to tamper with elements of any map parameter of
the operation. Either Program_Error is raised, or the operation works as
defined on the value of the map either prior to, or subsequent to, some or all
of the modifications to the map.

75.2/3 {AI05-0027-1} It is a bounded error to call any subprogram declared in
the visible part of a map package when the associated container has been
finalized. If the operation takes Container as an in out parameter, then it
raises Constraint_Error or Program_Error. Otherwise, the operation either
proceeds as it would for an empty container, or it raises Constraint_Error or
Program_Error.


                             Erroneous Execution

76/2 {AI95-00302-03} A Cursor value is invalid if any of the following have
occurred since it was created:

77/2   * The map that contains the node it designates has been finalized;

77.1/3   * {AI05-0160-1} The map that contains the node it designates has been
        used as the Target of a call to Assign, or as the target of an
        assignment_statement;

78/2   * The map that contains the node it designates has been used as the
        Source or Target of a call to Move; or

79/3   * {AI05-0160-1} {AI05-0262-1} The node it designates has been removed
        from the map that previously contained the node.

79.a/3      Ramification: {AI05-0160-1} This can happen directly via calls to
            Clear, Exclude, and Delete.

80/2 The result of "=" or Has_Element is unspecified if these functions are
called with an invalid cursor parameter. Execution is erroneous if any other
subprogram declared in Containers.Hashed_Maps or Containers.Ordered_Maps is
called with an invalid cursor parameter.

80.a/2      Discussion: The list above is intended to be exhaustive. In other
            cases, a cursor value continues to designate its original element.
            For instance, cursor values survive the insertion and deletion of
            other nodes.

80.b/2      While it is possible to check for these cases, in many cases the
            overhead necessary to make the check is substantial in time or
            space. Implementations are encouraged to check for as many of
            these cases as possible and raise Program_Error if detected.

80.1/3 {AI05-0212-1} Execution is erroneous if the map associated with the
result of a call to Reference or Constant_Reference is finalized before the
result object returned by the call to Reference or Constant_Reference is
finalized.

80.c/3      Reason: Each object of Reference_Type and Constant_Reference_Type
            probably contains some reference to the originating container. If
            that container is prematurely finalized (which is only possible
            via Unchecked_Deallocation, as accessibility checks prevent
            passing a container to Reference that will not live as long as the
            result), the finalization of the object of Reference_Type will try
            to access a nonexistent object. This is a normal case of a
            dangling pointer created by Unchecked_Deallocation; we have to
            explicitly mention it here as the pointer in question is not
            visible in the specification of the type. (This is the same reason
            we have to say this for invalid cursors.)


                         Implementation Requirements

81/2 {AI95-00302-03} No storage associated with a Map object shall be lost
upon assignment or scope exit.

82/3 {AI95-00302-03} {AI05-0262-1} The execution of an assignment_statement
for a map shall have the effect of copying the elements from the source map
object to the target map object and changing the length of the target object
to that of the source object.

82.a/3      Implementation Note: {AI05-0298-1} An assignment of a Map is a "
            deep" copy; that is the elements are copied as well as the data
            structures. We say "effect of" in order to allow the
            implementation to avoid copying elements immediately if it wishes.
            For instance, an implementation that avoided copying until one of
            the containers is modified would be allowed. (Note that this
            implementation would require care, see A.18.2 for more.)


                            Implementation Advice

83/2 {AI95-00302-03} Move should not copy elements, and should minimize
copying of internal data structures.

83.a/2      Implementation Advice: Move for a map should not copy elements,
            and should minimize copying of internal data structures.

83.b/2      Implementation Note: Usually that can be accomplished simply by
            moving the pointer(s) to the internal data structures from the
            Source container to the Target container.

84/2 {AI95-00302-03} If an exception is propagated from a map operation, no
storage should be lost, nor any elements removed from a map unless specified
by the operation.

84.a/2      Implementation Advice: If an exception is propagated from a map
            operation, no storage should be lost, nor any elements removed
            from a map unless specified by the operation.

84.b/2      Reason: This is important so that programs can recover from
            errors. But we don't want to require heroic efforts, so we just
            require documentation of cases where this can't be accomplished.


                         Wording Changes from Ada 95

84.c/2      {AI95-00302-03} This description of maps is new; the extensions
            are documented with the specific packages.


                           Extensions to Ada 2005

84.d/3      {AI05-0212-1} Added reference support to make map containers more
            convenient to use.


                        Wording Changes from Ada 2005

84.e/3      {AI05-0001-1} Added procedure Assign; the extension and
            incompatibility is documented with the specific packages.

84.f/3      {AI05-0001-1} Generalized the definition of Move. Specified which
            elements are read/written by stream attributes.

84.g/3      {AI05-0022-1} Correction: Added a Bounded (Run-Time) Error to
            cover tampering by generic actual subprograms.

84.h/3      {AI05-0027-1} Correction: Added a Bounded (Run-Time) Error to
            cover access to finalized map containers.

84.i/3      {AI05-0160-1} Correction: Revised the definition of invalid
            cursors to cover missing (and new) cases.

84.j/3      {AI05-0265-1} Correction: Defined when a container prohibits
            tampering in order to more clearly define where the check is made
            and the exception raised.


                        Wording Changes from Ada 2012

84.k/4      {AI12-0110-1} Corrigendum: Clarified that tampering checks precede
            all other checks made by a subprogram (but come after those
            associated with the call).


A.18.5 The Generic Package Containers.Hashed_Maps



                              Static Semantics

1/2 {AI95-00302-03} The generic library package Containers.Hashed_Maps has the
following declaration:

2/3     {AI05-0084-1} {AI05-0212-1} with Ada.Iterator_Interfaces;
        generic
           type Key_Type is private;
           type Element_Type is private;
           with function Hash (Key : Key_Type) return Hash_Type;
           with function Equivalent_Keys (Left, Right : Key_Type)
              return Boolean;
           with function "=" (Left, Right : Element_Type)
              return Boolean is <>;
        package Ada.Containers.Hashed_Maps is
           pragma Preelaborate(Hashed_Maps);
           pragma Remote_Types(Hashed_Maps);

3/3     {AI05-0212-1}    type Map is tagged private
              with Constant_Indexing => Constant_Reference,
                   Variable_Indexing => Reference,
                   Default_Iterator  => Iterate,
                   Iterator_Element  => Element_Type;
           pragma Preelaborable_Initialization(Map);

4/2        type Cursor is private;
           pragma Preelaborable_Initialization(Cursor);

5/2        Empty_Map : constant Map;

6/2        No_Element : constant Cursor;

6.1/3   {AI05-0212-1}    function Has_Element
         (Position : Cursor) return Boolean;

6.2/3   {AI05-0212-1}    package Map_Iterator_Interfaces is new
               Ada.Iterator_Interfaces (Cursor, Has_Element);

7/2        function "=" (Left, Right : Map) return Boolean;

8/2        function Capacity (Container : Map) return Count_Type;

9/2        procedure Reserve_Capacity (Container : in out Map;
                                       Capacity  : in     Count_Type);

10/2       function Length (Container : Map) return Count_Type;

11/2       function Is_Empty (Container : Map) return Boolean;

12/2       procedure Clear (Container : in out Map);

13/2       function Key (Position : Cursor) return Key_Type;

14/2       function Element (Position : Cursor) return Element_Type;

15/2       procedure Replace_Element (Container : in out Map;
                                      Position  : in     Cursor;
                                      New_Item  : in     Element_Type);

16/2       procedure Query_Element
             (Position : in Cursor;
              Process  : not null access procedure (Key     : in Key_Type;
                                                    Element : in Element_Type));

17/2       procedure Update_Element
             (Container : in out Map;
              Position  : in     Cursor;
              Process   : not null access procedure
                              (Key     : in     Key_Type;
                               Element : in out Element_Type));

17.1/3  {AI05-0212-1}    type Constant_Reference_Type
                 (Element : not null access constant Element_Type) is private
              with Implicit_Dereference => Element;

17.2/3  {AI05-0212-1}    type Reference_Type
         (Element : not null access Element_Type) is private
              with Implicit_Dereference => Element;

17.3/3  {AI05-0212-1}    function Constant_Reference
         (Container : aliased in Map;
                                        Position  : in Cursor)
              return Constant_Reference_Type;

17.4/3  {AI05-0212-1}    function Reference (Container : aliased in out Map;
                               Position  : in Cursor)
              return Reference_Type;

17.5/3  {AI05-0212-1}    function Constant_Reference
         (Container : aliased in Map;
                                        Key       : in Key_Type)
              return Constant_Reference_Type;

17.6/3  {AI05-0212-1}    function Reference (Container : aliased in out Map;
                               Key       : in Key_Type)
              return Reference_Type;

17.7/3  {AI05-0001-1}    procedure Assign
         (Target : in out Map; Source : in Map);

17.8/3  {AI05-0001-1}    function Copy
         (Source : Map; Capacity : Count_Type := 0) return Map;

18/2       procedure Move (Target : in out Map;
                           Source : in out Map);

19/2       procedure Insert (Container : in out Map;
                             Key       : in     Key_Type;
                             New_Item  : in     Element_Type;
                             Position  :    out Cursor;
                             Inserted  :    out Boolean);

20/2       procedure Insert (Container : in out Map;
                             Key       : in     Key_Type;
                             Position  :    out Cursor;
                             Inserted  :    out Boolean);

21/2       procedure Insert (Container : in out Map;
                             Key       : in     Key_Type;
                             New_Item  : in     Element_Type);

22/2       procedure Include (Container : in out Map;
                              Key       : in     Key_Type;
                              New_Item  : in     Element_Type);

23/2       procedure Replace (Container : in out Map;
                              Key       : in     Key_Type;
                              New_Item  : in     Element_Type);

24/2       procedure Exclude (Container : in out Map;
                              Key       : in     Key_Type);

25/2       procedure Delete (Container : in out Map;
                             Key       : in     Key_Type);

26/2       procedure Delete (Container : in out Map;
                             Position  : in out Cursor);

27/2       function First (Container : Map)
              return Cursor;

28/2       function Next (Position  : Cursor) return Cursor;

29/2       procedure Next (Position  : in out Cursor);

30/2       function Find (Container : Map;
                          Key       : Key_Type)
              return Cursor;

31/2       function Element (Container : Map;
                             Key       : Key_Type)
              return Element_Type;

32/2       function Contains (Container : Map;
                              Key       : Key_Type) return Boolean;

33/3    This paragraph was deleted.{AI05-0212-1}

34/2       function Equivalent_Keys (Left, Right : Cursor)
              return Boolean;

35/2       function Equivalent_Keys (Left  : Cursor;
                                     Right : Key_Type)
              return Boolean;

36/2       function Equivalent_Keys (Left  : Key_Type;
                                     Right : Cursor)
              return Boolean;

37/2       procedure Iterate
             (Container : in Map;
              Process   : not null access procedure (Position : in Cursor));

37.1/3  {AI05-0212-1}    function Iterate (Container : in Map)
              return Map_Iterator_Interfaces.Forward_Iterator'Class;

38/2    private

39/2       ... -- not specified by the language

40/2    end Ada.Containers.Hashed_Maps;

41/2 {AI95-00302-03} An object of type Map contains an expandable hash table,
which is used to provide direct access to nodes. The capacity of an object of
type Map is the maximum number of nodes that can be inserted into the hash
table prior to it being automatically expanded.

41.a/2      Implementation Note: The expected implementation for a Map uses a
            hash table which is grown when it is too small, with linked lists
            hanging off of each bucket. Note that in that implementation a
            cursor needs a back pointer to the Map object to implement
            iteration; that could either be in the nodes, or in the cursor
            object. To provide an average O(1) access time, capacity would
            typically equal the number of buckets in such an implementation,
            so that the average bucket linked list length would be no more
            than 1.0.

41.b/2      There is no defined relationship between elements in a hashed map.
            Typically, iteration will return elements in the order that they
            are hashed in.

42/2 {AI95-00302-03} Two keys K1 and K2 are defined to be equivalent if
Equivalent_Keys (K1, K2) returns True.

43/2 {AI95-00302-03} The actual function for the generic formal function Hash
is expected to return the same value each time it is called with a particular
key value. For any two equivalent key values, the actual for Hash is expected
to return the same value. If the actual for Hash behaves in some other manner,
the behavior of this package is unspecified. Which subprograms of this package
call Hash, and how many times they call it, is unspecified.

43.a/2      Implementation Note: The implementation is not required to protect
            against Hash raising an exception, or returning random numbers, or
            any other "bad" behavior. It's not practical to do so, and a
            broken Hash function makes the container unusable.

43.b/2      The implementation can call Hash whenever it is needed; we don't
            want to specify how often that happens. The result must remain the
            same (this is logically a pure function), or the behavior is
            unspecified.

44/2 {AI95-00302-03} The actual function for the generic formal function
Equivalent_Keys on Key_Type values is expected to return the same value each
time it is called with a particular pair of key values. It should define an
equivalence relationship, that is, be reflexive, symmetric, and transitive. If
the actual for Equivalent_Keys behaves in some other manner, the behavior of
this package is unspecified. Which subprograms of this package call
Equivalent_Keys, and how many times they call it, is unspecified.

44.a/2      Implementation Note: As with Hash, the implementation is not
            required to protect against Equivalent_Keys raising an exception
            or returning random results. Similarly, the implementation can
            call this operation whenever it is needed. The result must remain
            the same (this is a logically pure function), or the behavior is
            unspecified.

45/2 {AI95-00302-03} If the value of a key stored in a node of a map is
changed other than by an operation in this package such that at least one of
Hash or Equivalent_Keys give different results, the behavior of this package
is unspecified.

45.a/2      Implementation Note: The implementation is not required to protect
            against changes to key values other than via the operations
            declared in the Hashed_Maps package.

45.b/2      To see how this could happen, imagine an instance of Hashed_Maps
            where the key type is an access-to-variable type and Hash returns
            a value derived from the components of the designated object.
            Then, any operation that has a key value could modify those
            components and change the hash value:

45.c/2          Key (Map).Some_Component := New_Value;

45.d/2      This is really a design error on the part of the user of the map;
            it shouldn't be possible to modify keys stored in a map. But we
            can't prevent this error anymore than we can prevent someone
            passing as Hash a random number generator.

46/2 {AI95-00302-03} Which nodes are the first node and the last node of a
map, and which node is the successor of a given node, are unspecified, other
than the general semantics described in A.18.4.

46.a/2      Implementation Note: Typically the first node will be the first
            node in the first bucket, the last node will be the last node in
            the last bucket, and the successor will be obtained by following
            the collision list, and going to the next bucket at the end of
            each bucket.

47/2    function Capacity (Container : Map) return Count_Type;

48/2        {AI95-00302-03} Returns the capacity of Container.

49/2    procedure Reserve_Capacity (Container : in out Map;
                                    Capacity  : in     Count_Type);

50/2        {AI95-00302-03} Reserve_Capacity allocates a new hash table such
            that the length of the resulting map can become at least the value
            Capacity without requiring an additional call to Reserve_Capacity,
            and is large enough to hold the current length of Container.
            Reserve_Capacity then rehashes the nodes in Container onto the new
            hash table. It replaces the old hash table with the new hash
            table, and then deallocates the old hash table. Any exception
            raised during allocation is propagated and Container is not
            modified.

51/2        Reserve_Capacity tampers with the cursors of Container.

51.a/2      Implementation Note: This routine is used to preallocate the
            internal hash table to the specified capacity such that future
            Inserts do not require expansion of the hash table. Therefore, the
            implementation should allocate the needed memory to make that true
            at this point, even though the visible semantics could be
            preserved by waiting until enough elements are inserted.

51.b/3      {AI05-0005-1} While Reserve_Capacity can be used to reduce the
            capacity of a map, we do not specify whether an implementation
            actually supports reduction of the capacity. Since the actual
            capacity can be anything greater than or equal to Capacity, an
            implementation never has to reduce the capacity.

51.c/2      Reserve_Capacity tampers with the cursors, as rehashing probably
            will change the order that elements are stored in the map.

52/2    procedure Clear (Container : in out Map);

53/2        {AI95-00302-03} In addition to the semantics described in A.18.4,
            Clear does not affect the capacity of Container.

53.1/3  procedure Assign (Target : in out Map; Source : in Map);

53.2/3      {AI05-0001-1} {AI05-0248-1} In addition to the semantics described
            in A.18.4, if the length of Source is greater than the capacity of
            Target, Reserve_Capacity (Target, Length (Source)) is called
            before assigning any elements.

53.3/3  function Copy (Source : Map; Capacity : Count_Type := 0) return Map;

53.4/3      {AI05-0001-1} Returns a map whose keys and elements are
            initialized from the keys and elements of Source. If Capacity is
            0, then the map capacity is the length of Source; if Capacity is
            equal to or greater than the length of Source, the map capacity is
            at least the specified value. Otherwise, the operation propagates
            Capacity_Error.

53.a/2      Implementation Note: In:

53.b/2          procedure Move (Target : in out Map;
                                Source : in out Map);

53.c/2      The intended implementation is that the internal hash table of
            Target is first deallocated; then the internal hash table is
            removed from Source and moved to Target.

54/2    procedure Insert (Container : in out Map;
                          Key       : in     Key_Type;
                          New_Item  : in     Element_Type;
                          Position  :    out Cursor;
                          Inserted  :    out Boolean);

55/2        {AI95-00302-03} In addition to the semantics described in A.18.4,
            if Length (Container) equals Capacity (Container), then Insert
            first calls Reserve_Capacity to increase the capacity of Container
            to some larger value.

55.a/2      Implementation Note: Insert should only compare keys that hash to
            the same bucket in the hash table.

55.b/2      We specify when Reserve_Capacity is called to bound the overhead
            of capacity expansion operations (which are potentially
            expensive). Moreover, expansion can be predicted by comparing
            Capacity(Map) to Length(Map). Since we don't specify by how much
            the hash table is expanded, this only can be used to predict the
            next expansion, not later ones.

55.c/2      Implementation Note: In:

55.d/2          procedure Exclude (Container : in out Map;
                                   Key       : in     Key_Type);

55.e/2      Exclude should only compare keys that hash to the same bucket in
            the hash table.

55.f/2      Implementation Note: In:

55.g/2          procedure Delete (Container : in out Map;
                                  Key       : in     Key_Type);

55.h/2      Delete should only compare keys that hash to the same bucket in
            the hash table. The node containing the element may be deallocated
            now, or it may be saved and reused later.

55.i/2      Implementation Note: In:

55.j/2          function First (Container : Map) return Cursor;

55.k/2      In a typical implementation, this will be the first node in the
            lowest numbered hash bucket that contains a node.

55.l/2      Implementation Note: In:

55.m/2          function Next (Position  : Cursor) return Cursor;

55.n/2      In a typical implementation, this will return the next node in a
            bucket; if Position is the last node in a bucket, this will return
            the first node in the next nonempty bucket.

55.o/2      A typical implementation will need to a keep a pointer at the map
            container in the cursor in order to implement this function.

55.p/2      Implementation Note: In:

55.q/2          function Find (Container : Map;
                               Key       : Key_Type) return Cursor;

55.r/2      Find should only compare keys that hash to the same bucket in the
            hash table.

56/2    function Equivalent_Keys (Left, Right : Cursor)
              return Boolean;

57/2        {AI95-00302-03} Equivalent to Equivalent_Keys (Key (Left), Key
            (Right)).

58/2    function Equivalent_Keys (Left  : Cursor;
                                  Right : Key_Type) return Boolean;

59/2        {AI95-00302-03} Equivalent to Equivalent_Keys (Key (Left), Right).

60/2    function Equivalent_Keys (Left  : Key_Type;
                                  Right : Cursor) return Boolean;

61/2        {AI95-00302-03} Equivalent to Equivalent_Keys (Left, Key (Right)).

61.1/3  function Iterate (Container : in Map)
           return Map_Iterator_Interfaces.Forward_Iterator'Class;

61.2/3      {AI05-0212-1} {AI05-0265-1} {AI05-0269-1} Iterate returns an
            iterator object (see 5.5.1) that will generate a value for a loop
            parameter (see 5.5.2) designating each node in Container, starting
            with the first node and moving the cursor according to the
            successor relation. Tampering with the cursors of Container is
            prohibited while the iterator object exists (in particular, in the
            sequence_of_statements of the loop_statement whose
            iterator_specification denotes this object). The iterator object
            needs finalization.


                            Implementation Advice

62/2 {AI95-00302-03} If N is the length of a map, the average time complexity
of the subprograms Element, Insert, Include, Replace, Delete, Exclude and Find
that take a key parameter should be O(log N). The average time complexity of
the subprograms that take a cursor parameter should be O(1). The average time
complexity of Reserve_Capacity should be O(N).

62.a/2      Implementation Advice: The average time complexity of Element,
            Insert, Include, Replace, Delete, Exclude and Find operations that
            take a key parameter for Containers.Hashed_Maps should be O(log
            N). The average time complexity of the subprograms of
            Containers.Hashed_Maps that take a cursor parameter should be
            O(1). The average time complexity of
            Containers.Hashed_Maps.Reserve_Capacity should be O(N).

62.b/2      Reason: We do not mean to overly constrain implementation
            strategies here. However, it is important for portability that the
            performance of large containers has roughly the same factors on
            different implementations. If a program is moved to an
            implementation for which Find is O(N), that program could be
            unusable when the maps are large. We allow O(log N) access because
            the proportionality constant and caching effects are likely to be
            larger than the log factor, and we don't want to discourage
            innovative implementations.


                            Extensions to Ada 95

62.c/2      {AI95-00302-03} The generic package Containers.Hashed_Maps is new.


                       Incompatibilities With Ada 2005

62.d/3      {AI05-0001-1} Subprograms Assign and Copy are added to
            Containers.Hashed_Maps. If an instance of Containers.Hashed_Maps
            is referenced in a use_clause, and an entity E with the same
            defining_identifier as a new entity in Containers.Hashed_Maps is
            defined in a package that is also referenced in a use_clause, the
            entity E may no longer be use-visible, resulting in errors. This
            should be rare and is easily fixed if it does occur.


                           Extensions to Ada 2005

62.e/3      {AI05-0212-1} Added iterator and indexing support to make hashed
            map containers more convenient to use.


                        Wording Changes from Ada 2005

62.f/3      {AI05-0084-1} Correction: Added a pragma Remote_Types so that
            containers can be used in distributed programs.


A.18.6 The Generic Package Containers.Ordered_Maps



                              Static Semantics

1/2 {AI95-00302-03} The generic library package Containers.Ordered_Maps has
the following declaration:

2/3     {AI05-0084-1} {AI05-0212-1} with Ada.Iterator_Interfaces;
        generic
           type Key_Type is private;
           type Element_Type is private;
           with function "<" (Left, Right : Key_Type) return Boolean is <>;
           with function "=" (Left, Right : Element_Type) return Boolean is <>;
        package Ada.Containers.Ordered_Maps is
           pragma Preelaborate(Ordered_Maps);
           pragma Remote_Types(Ordered_Maps);

3/2        function Equivalent_Keys (Left, Right : Key_Type) return Boolean;

4/3     {AI05-0212-1}    type Map is tagged private
              with Constant_Indexing => Constant_Reference,
                   Variable_Indexing => Reference,
                   Default_Iterator  => Iterate,
                   Iterator_Element  => Element_Type;
           pragma Preelaborable_Initialization(Map);

5/2        type Cursor is private;
           pragma Preelaborable_Initialization(Cursor);

6/2        Empty_Map : constant Map;

7/2        No_Element : constant Cursor;

7.1/3   {AI05-0212-1}    function Has_Element
         (Position : Cursor) return Boolean;

7.2/3   {AI05-0212-1}    package Map_Iterator_Interfaces is new
               Ada.Iterator_Interfaces (Cursor, Has_Element);

8/2        function "=" (Left, Right : Map) return Boolean;

9/2        function Length (Container : Map) return Count_Type;

10/2       function Is_Empty (Container : Map) return Boolean;

11/2       procedure Clear (Container : in out Map);

12/2       function Key (Position : Cursor) return Key_Type;

13/2       function Element (Position : Cursor) return Element_Type;

14/2       procedure Replace_Element (Container : in out Map;
                                      Position  : in     Cursor;
                                      New_Item  : in     Element_Type);

15/2       procedure Query_Element
             (Position : in Cursor;
              Process  : not null access procedure (Key     : in Key_Type;
                                                    Element : in Element_Type));

16/2       procedure Update_Element
             (Container : in out Map;
              Position  : in     Cursor;
              Process   : not null access procedure
                              (Key     : in     Key_Type;
                               Element : in out Element_Type));

16.1/3  {AI05-0212-1}    type Constant_Reference_Type
                 (Element : not null access constant Element_Type) is private
              with Implicit_Dereference => Element;

16.2/3  {AI05-0212-1}    type Reference_Type
         (Element : not null access Element_Type) is private
              with Implicit_Dereference => Element;

16.3/3  {AI05-0212-1}    function Constant_Reference
         (Container : aliased in Map;
                                        Position  : in Cursor)
              return Constant_Reference_Type;

16.4/3  {AI05-0212-1}    function Reference (Container : aliased in out Map;
                               Position  : in Cursor)
              return Reference_Type;

16.5/3  {AI05-0212-1}    function Constant_Reference
         (Container : aliased in Map;
                                        Key       : in Key_Type)
              return Constant_Reference_Type;

16.6/3  {AI05-0212-1}    function Reference (Container : aliased in out Map;
                               Key       : in Key_Type)
              return Reference_Type;

16.7/3  {AI05-0001-1}    procedure Assign
         (Target : in out Map; Source : in Map);

16.8/3  {AI05-0001-1}    function Copy (Source : Map) return Map;

17/2       procedure Move (Target : in out Map;
                           Source : in out Map);

18/2       procedure Insert (Container : in out Map;
                             Key       : in     Key_Type;
                             New_Item  : in     Element_Type;
                             Position  :    out Cursor;
                             Inserted  :    out Boolean);

19/2       procedure Insert (Container : in out Map;
                             Key       : in     Key_Type;
                             Position  :    out Cursor;
                             Inserted  :    out Boolean);

20/2       procedure Insert (Container : in out Map;
                             Key       : in     Key_Type;
                             New_Item  : in     Element_Type);

21/2       procedure Include (Container : in out Map;
                              Key       : in     Key_Type;
                              New_Item  : in     Element_Type);

22/2       procedure Replace (Container : in out Map;
                              Key       : in     Key_Type;
                              New_Item  : in     Element_Type);

23/2       procedure Exclude (Container : in out Map;
                              Key       : in     Key_Type);

24/2       procedure Delete (Container : in out Map;
                             Key       : in     Key_Type);

25/2       procedure Delete (Container : in out Map;
                             Position  : in out Cursor);

26/2       procedure Delete_First (Container : in out Map);

27/2       procedure Delete_Last (Container : in out Map);

28/2       function First (Container : Map) return Cursor;

29/2       function First_Element (Container : Map) return Element_Type;

30/2       function First_Key (Container : Map) return Key_Type;

31/2       function Last (Container : Map) return Cursor;

32/2       function Last_Element (Container : Map) return Element_Type;

33/2       function Last_Key (Container : Map) return Key_Type;

34/2       function Next (Position : Cursor) return Cursor;

35/2       procedure Next (Position : in out Cursor);

36/2       function Previous (Position : Cursor) return Cursor;

37/2       procedure Previous (Position : in out Cursor);

38/2       function Find (Container : Map;
                          Key       : Key_Type) return Cursor;

39/2       function Element (Container : Map;
                             Key       : Key_Type) return Element_Type;

40/2       function Floor (Container : Map;
                           Key       : Key_Type) return Cursor;

41/2       function Ceiling (Container : Map;
                             Key       : Key_Type) return Cursor;

42/2       function Contains (Container : Map;
                              Key       : Key_Type) return Boolean;

43/3    This paragraph was deleted.{AI05-0212-1}

44/2       function "<" (Left, Right : Cursor) return Boolean;

45/2       function ">" (Left, Right : Cursor) return Boolean;

46/2       function "<" (Left : Cursor; Right : Key_Type) return Boolean;

47/2       function ">" (Left : Cursor; Right : Key_Type) return Boolean;

48/2       function "<" (Left : Key_Type; Right : Cursor) return Boolean;

49/2       function ">" (Left : Key_Type; Right : Cursor) return Boolean;

50/2       procedure Iterate
             (Container : in Map;
              Process   : not null access procedure (Position : in Cursor));

51/2       procedure Reverse_Iterate
             (Container : in Map;
              Process   : not null access procedure (Position : in Cursor));

51.1/3  {AI05-0212-1}    function Iterate (Container : in Map)
              return Map_Iterator_Interfaces.Reversible_Iterator'Class;

51.2/3  {AI05-0262-1}
           function Iterate (Container : in Map; Start : in Cursor)
              return Map_Iterator_Interfaces.Reversible_Iterator'Class;

52/2    private

53/2       ... -- not specified by the language

54/2    end Ada.Containers.Ordered_Maps;

55/2 {AI95-00302-03} Two keys K1 and K2 are equivalent if both K1 < K2 and K2
< K1 return False, using the generic formal "<" operator for keys. Function
Equivalent_Keys returns True if Left and Right are equivalent, and False
otherwise.

56/3 {AI95-00302-03} {AI05-0044-1} The actual function for the generic formal
function "<" on Key_Type values is expected to return the same value each time
it is called with a particular pair of key values. It should define a strict
weak ordering relationship (see A.18). If the actual for "<" behaves in some
other manner, the behavior of this package is unspecified. Which subprograms
of this package call "<" and how many times they call it, is unspecified.

56.a/2      Implementation Note: The implementation is not required to protect
            against "<" raising an exception, or returning random results, or
            any other "bad" behavior. It's not practical to do so, and a
            broken "<" function makes the container unusable.

56.b/2      The implementation can call "<" whenever it is needed; we don't
            want to specify how often that happens. The result must remain the
            same (this is a logically pure function), or the behavior is
            unspecified.

57/2 {AI95-00302-03} If the value of a key stored in a map is changed other
than by an operation in this package such that at least one of "<" or "=" give
different results, the behavior of this package is unspecified.

57.a/2      Implementation Note: The implementation is not required to protect
            against changes to key values other than via the operations
            declared in the Ordered_Maps package.

57.b/2      To see how this could happen, imagine an instance of Ordered_Maps
            package where the key type is an access-to-variable type and "<"
            returns a value derived from comparing the components of the
            designated objects. Then, any operation that has a key value (even
            if the key value is constant) could modify those components and
            change the result of "<":

57.c/2          Key (Map).Some_Component := New_Value;

57.d/2      This is really a design error on the part of the user of the map;
            it shouldn't be possible to modify keys stored in a map such that
            "<" changes. But we can't prevent this error anymore than we can
            prevent someone passing as "<" a routine that produces random
            answers.

58/3 {AI95-00302-03} {AI05-0262-1} The first node of a nonempty map is the one
whose key is less than the key of all the other nodes in the map. The last
node of a nonempty map is the one whose key is greater than the key of all the
other elements in the map. The successor of a node is the node with the
smallest key that is larger than the key of the given node. The predecessor of
a node is the node with the largest key that is smaller than the key of the
given node. All comparisons are done using the generic formal "<" operator for
keys.

58.1/3  function Copy (Source : Map) return Map;

58.2/3      {AI05-0001-1} Returns a map whose keys and elements are
            initialized from the corresponding keys and elements of Source.

59/2    procedure Delete_First (Container : in out Map);

60/3        {AI95-00302-03} {AI05-0264-1} If Container is empty, Delete_First
            has no effect. Otherwise, the node designated by First (Container)
            is removed from Container. Delete_First tampers with the cursors
            of Container.

61/2    procedure Delete_Last (Container : in out Map);

62/3        {AI95-00302-03} {AI05-0264-1} If Container is empty, Delete_Last
            has no effect. Otherwise, the node designated by Last (Container)
            is removed from Container. Delete_Last tampers with the cursors of
            Container.

63/2    function First_Element (Container : Map) return Element_Type;

64/2        {AI95-00302-03} Equivalent to Element (First (Container)).

65/2    function First_Key (Container : Map) return Key_Type;

66/2        {AI95-00302-03} Equivalent to Key (First (Container)).

67/2    function Last (Container : Map) return Cursor;

68/2        {AI95-00302-03} Returns a cursor that designates the last node in
            Container. If Container is empty, returns No_Element.

69/2    function Last_Element (Container : Map) return Element_Type;

70/2        {AI95-00302-03} Equivalent to Element (Last (Container)).

71/2    function Last_Key (Container : Map) return Key_Type;

72/2        {AI95-00302-03} Equivalent to Key (Last (Container)).

73/2    function Previous (Position : Cursor) return Cursor;

74/3        {AI95-00302-03} {AI05-0262-1} If Position equals No_Element, then
            Previous returns No_Element. Otherwise, Previous returns a cursor
            designating the predecessor node of the one designated by
            Position. If Position designates the first element, then Previous
            returns No_Element.

75/2    procedure Previous (Position : in out Cursor);

76/2        {AI95-00302-03} Equivalent to Position := Previous (Position).

77/2    function Floor (Container : Map;
                        Key       : Key_Type) return Cursor;

78/3        {AI95-00302-03} {AI05-0264-1} Floor searches for the last node
            whose key is not greater than Key, using the generic formal "<"
            operator for keys. If such a node is found, a cursor that
            designates it is returned. Otherwise, No_Element is returned.

79/2    function Ceiling (Container : Map;
                          Key       : Key_Type) return Cursor;

80/3        {AI95-00302-03} {AI05-0264-1} Ceiling searches for the first node
            whose key is not less than Key, using the generic formal "<"
            operator for keys. If such a node is found, a cursor that
            designates it is returned. Otherwise, No_Element is returned.

81/2    function "<" (Left, Right : Cursor) return Boolean;

82/2        {AI95-00302-03} Equivalent to Key (Left) < Key (Right).

83/2    function ">" (Left, Right : Cursor) return Boolean;

84/2        {AI95-00302-03} Equivalent to Key (Right) < Key (Left).

85/2    function "<" (Left : Cursor; Right : Key_Type) return Boolean;

86/2        {AI95-00302-03} Equivalent to Key (Left) < Right.

87/2    function ">" (Left : Cursor; Right : Key_Type) return Boolean;

88/2        {AI95-00302-03} Equivalent to Right < Key (Left).

89/2    function "<" (Left : Key_Type; Right : Cursor) return Boolean;

90/2        {AI95-00302-03} Equivalent to Left < Key (Right).

91/2    function ">" (Left : Key_Type; Right : Cursor) return Boolean;

92/2        {AI95-00302-03} Equivalent to Key (Right) < Left.

93/2    procedure Reverse_Iterate
          (Container : in Map;
           Process   : not null access procedure (Position : in Cursor));

94/3        {AI95-00302-03} {AI05-0212-1} Iterates over the nodes in Container
            as per procedure Iterate, with the difference that the nodes are
            traversed in predecessor order, starting with the last node.

94.1/3  function Iterate (Container : in Map)
           return Map_Iterator_Interfaces.Reversible_Iterator'Class;

94.2/3      {AI05-0212-1} {AI05-0265-1} {AI05-0269-1} Iterate returns a
            reversible iterator object (see 5.5.1) that will generate a value
            for a loop parameter (see 5.5.2) designating each node in
            Container, starting with the first node and moving the cursor
            according to the successor relation when used as a forward
            iterator, and starting with the last node and moving the cursor
            according to the predecessor relation when used as a reverse
            iterator. Tampering with the cursors of Container is prohibited
            while the iterator object exists (in particular, in the
            sequence_of_statements of the loop_statement whose
            iterator_specification denotes this object). The iterator object
            needs finalization.

94.3/3  function Iterate (Container : in Map; Start : in Cursor)
           return Map_Iterator_Interfaces.Reversible_Iterator'Class;

94.4/3      {AI05-0262-1} {AI05-0265-1} {AI05-0269-1} If Start is not
            No_Element and does not designate an item in Container, then
            Program_Error is propagated. If Start is No_Element, then
            Constraint_Error is propagated. Otherwise, Iterate returns a
            reversible iterator object (see 5.5.1) that will generate a value
            for a loop parameter (see 5.5.2) designating each node in
            Container, starting with the node designated by Start and moving
            the cursor according to the successor relation when used as a
            forward iterator, or moving the cursor according to the
            predecessor relation when used as a reverse iterator. Tampering
            with the cursors of Container is prohibited while the iterator
            object exists (in particular, in the sequence_of_statements of the
            loop_statement whose iterator_specification denotes this object).
            The iterator object needs finalization.

94.a/3      Discussion: Exits are allowed from the loops created using the
            iterator objects. In particular, to stop the iteration at a
            particular cursor, just add

94.b/3          exit when Cur = Stop;

94.c/3      in the body of the loop (assuming that Cur is the loop parameter
            and Stop is the cursor that you want to stop at).


                            Implementation Advice

95/2 {AI95-00302-03} If N is the length of a map, then the worst-case time
complexity of the Element, Insert, Include, Replace, Delete, Exclude and Find
operations that take a key parameter should be O((log N)**2) or better. The
worst-case time complexity of the subprograms that take a cursor parameter
should be O(1).

95.a/2      Implementation Advice: The worst-case time complexity of Element,
            Insert, Include, Replace, Delete, Exclude and Find operations that
            take a key parameter for Containers.Ordered_Maps should be O((log
            N)**2) or better. The worst-case time complexity of the
            subprograms of Containers.Ordered_Maps that take a cursor
            parameter should be O(1).

95.b/2      Implementation Note: A balanced (red-black) tree for keys has
            O(log N) worst-case performance. Note that a O(N) worst-case
            implementation (like a list) would be wrong.

95.c/2      Reason: We do not mean to overly constrain implementation
            strategies here. However, it is important for portability that the
            performance of large containers has roughly the same factors on
            different implementations. If a program is moved to an
            implementation that takes O(N) to find elements, that program
            could be unusable when the maps are large. We allow the extra log
            N factors because the proportionality constant and caching effects
            are likely to be larger than the log factor, and we don't want to
            discourage innovative implementations.


                            Extensions to Ada 95

95.d/2      {AI95-00302-03} The generic package Containers.Ordered_Maps is
            new.


                       Incompatibilities With Ada 2005

95.e/3      {AI05-0001-1} Subprograms Assign and Copy are added to
            Containers.Ordered_Maps. If an instance of Containers.Ordered_Maps
            is referenced in a use_clause, and an entity E with the same
            defining_identifier as a new entity in Containers.Ordered_Maps is
            defined in a package that is also referenced in a use_clause, the
            entity E may no longer be use-visible, resulting in errors. This
            should be rare and is easily fixed if it does occur.


                           Extensions to Ada 2005

95.f/3      {AI05-0212-1} Added iterator and indexing support to make ordered
            map containers more convenient to use.


                        Wording Changes from Ada 2005

95.g/3      {AI05-0044-1} Correction: Redefined "<" actuals to require a
            strict weak ordering; the old definition allowed indeterminant
            comparisons that would not have worked in a container.

95.h/3      {AI05-0084-1} Correction: Added a pragma Remote_Types so that
            containers can be used in distributed programs.


A.18.7 Sets


1/2 {AI95-00302-03} The language-defined generic packages
Containers.Hashed_Sets and Containers.Ordered_Sets provide private types Set
and Cursor, and a set of operations for each type. A set container allows
elements of an arbitrary type to be stored without duplication. A hashed set
uses a hash function to organize elements, while an ordered set orders its
element per a specified relation.

2/3 {AI95-00302-03} {AI05-0299-1} This subclause describes the declarations
that are common to both kinds of sets. See A.18.8 for a description of the
semantics specific to Containers.Hashed_Sets and A.18.9 for a description of
the semantics specific to Containers.Ordered_Sets.


                              Static Semantics

3/2 {AI95-00302-03} The actual function for the generic formal function "=" on
Element_Type values is expected to define a reflexive and symmetric
relationship and return the same result value each time it is called with a
particular pair of values. If it behaves in some other manner, the function
"=" on set values returns an unspecified value. The exact arguments and number
of calls of this generic formal function by the function "=" on set values are
unspecified.

3.a/2       Ramification: If the actual function for "=" is not symmetric and
            consistent, the result returned by the "=" for Set objects cannot
            be predicted. The implementation is not required to protect
            against "=" raising an exception, or returning random results, or
            any other "bad" behavior. And it can call "=" in whatever manner
            makes sense. But note that only the result of "=" for Set objects
            is unspecified; other subprograms are not allowed to break if "="
            is bad (they aren't expected to use "=").

4/2 {AI95-00302-03} The type Set is used to represent sets. The type Set needs
finalization (see 7.6).

5/2 {AI95-00302-03} A set contains elements. Set cursors designate elements.
There exists an equivalence relation on elements, whose definition is
different for hashed sets and ordered sets. A set never contains two or more
equivalent elements. The length of a set is the number of elements it contains.

6/2 {AI95-00302-03} Each nonempty set has two particular elements called the
first element and the last element (which may be the same). Each element
except for the last element has a successor element. If there are no other
intervening operations, starting with the first element and repeatedly going
to the successor element will visit each element in the set exactly once until
the last element is reached. The exact definition of these terms is different
for hashed sets and ordered sets.

7/2 {AI95-00302-03} [Some operations of these generic packages have
access-to-subprogram parameters. To ensure such operations are well-defined,
they guard against certain actions by the designated subprogram. In
particular, some operations check for "tampering with cursors" of a container
because they depend on the set of elements of the container remaining
constant, and others check for "tampering with elements" of a container
because they depend on elements of the container not being replaced.]

8/2 {AI95-00302-03} A subprogram is said to tamper with cursors of a set
object S if:

9/2   * it inserts or deletes elements of S, that is, it calls the Insert,
        Include, Clear, Delete, Exclude, or Replace_Element procedures with S
        as a parameter; or

9.a/2       To be honest: Operations which are defined to be equivalent to a
            call on one of these operations also are included. Similarly,
            operations which call one of these as part of their definition are
            included.

9.b/2       Discussion: We have to include Replace_Element here because it
            might delete and reinsert the element if it moves in the set. That
            could change the order of iteration, which is what this check is
            designed to prevent. Replace is also included, as it is defined in
            terms of Replace_Element.

10/2   * it finalizes S; or

10.1/3   * {AI05-0001-1} it calls the Assign procedure with S as the Target
        parameter; or

10.a/3      Ramification: We don't need to explicitly mention
            assignment_statement, because that finalizes the target object as
            part of the operation, and finalization of an object is already
            defined as tampering with cursors.

11/2   * it calls the Move procedure with S as a parameter; or

12/2   * it calls one of the operations defined to tamper with cursors of S.

13/2 {AI95-00302-03} A subprogram is said to tamper with elements of a set
object S if:

14/2   * it tampers with cursors of S.

14.a/2      Reason: Complete replacement of an element can cause its memory to
            be deallocated while another operation is holding onto a reference
            to it. That can't be allowed. However, a simple modification of
            (part of) an element is not a problem, so
            Update_Element_Preserving_Key does not cause a problem.

14.b/2      We don't need to list Replace and Replace_Element here because
            they are covered by "tamper with cursors". For Set, "tamper with
            cursors" and "tamper with elements" are the same. We leave both
            terms so that the rules for routines like Iterate and
            Query_Element are consistent across all containers.

14.1/4 {AI05-0265-1} {AI12-0110-1} When tampering with cursors is prohibited
for a particular set object S, Program_Error is propagated by a call of any
language-defined subprogram that is defined to tamper with the cursors of S,
leaving S unmodified. Similarly, when tampering with elements is prohibited
for a particular set object S, Program_Error is propagated by a call of any
language-defined subprogram that is defined to tamper with the elements of S
[(or tamper with the cursors of S)], leaving S unmodified. These checks are
made before any other defined behavior of the body of the language-defined
subprogram.

14.c/3      Proof: Tampering with elements includes tampering with cursors, so
            we mention it only from completeness in the second sentence.

15/2 {AI95-00302-03} Empty_Set represents the empty Set object. It has a
length of 0. If an object of type Set is not otherwise initialized, it is
initialized to the same value as Empty_Set.

16/2 {AI95-00302-03} No_Element represents a cursor that designates no
element. If an object of type Cursor is not otherwise initialized, it is
initialized to the same value as No_Element.

17/2 {AI95-00302-03} The predefined "=" operator for type Cursor returns True
if both cursors are No_Element, or designate the same element in the same
container.

18/2 {AI95-00302-03} Execution of the default implementation of the Input,
Output, Read, or Write attribute of type Cursor raises Program_Error.

18.a/2      Reason: A cursor will probably be implemented in terms of one or
            more access values, and the effects of streaming access values is
            unspecified. Rather than letting the user stream junk by accident,
            we mandate that streaming of cursors raise Program_Error by
            default. The attributes can always be specified if there is a need
            to support streaming.

18.1/3 {AI05-0001-1} {AI05-0262-1} Set'Write for a Set object S writes
Length(S) elements of the set to the stream. It also may write additional
information about the set.

18.2/3 {AI05-0001-1} {AI05-0262-1} Set'Read reads the representation of a set
from the stream, and assigns to Item a set with the same length and elements
as was written by Set'Write.

18.b/3      Ramification: Streaming more elements than the container length is
            wrong. For implementation implications of this rule, see the
            Implementation Note in A.18.2.

18.3/3  function Has_Element (Position : Cursor) return Boolean;

18.4/3      {AI05-0212-1} Returns True if Position designates an element, and
            returns False otherwise.

18.c/3      To be honest: {AI05-0005-1} {AI05-0212-1} This function might not
            detect cursors that designate deleted elements; such cursors are
            invalid (see below) and the result of calling Has_Element with an
            invalid cursor is unspecified (but not erroneous).

19/2    function "=" (Left, Right : Set) return Boolean;

20/2        {AI95-00302-03} If Left and Right denote the same set object, then
            the function returns True. If Left and Right have different
            lengths, then the function returns False. Otherwise, for each
            element E in Left, the function returns False if an element equal
            to E (using the generic formal equality operator) is not present
            in Right. If the function has not returned a result after checking
            all of the elements, it returns True. Any exception raised during
            evaluation of element equality is propagated.

20.a/2      Implementation Note: This wording describes the canonical
            semantics. However, the order and number of calls on the formal
            equality function is unspecified for all of the operations that
            use it in this package, so an implementation can call it as many
            or as few times as it needs to get the correct answer.
            Specifically, there is no requirement to call the formal equality
            additional times once the answer has been determined.

21/2    function Equivalent_Sets (Left, Right : Set) return Boolean;

22/2        {AI95-00302-03} If Left and Right denote the same set object, then
            the function returns True. If Left and Right have different
            lengths, then the function returns False. Otherwise, for each
            element E in Left, the function returns False if an element
            equivalent to E is not present in Right. If the function has not
            returned a result after checking all of the elements, it returns
            True. Any exception raised during evaluation of element
            equivalence is propagated.

23/2    function To_Set (New_Item : Element_Type) return Set;

24/2        {AI95-00302-03} Returns a set containing the single element
            New_Item.

25/2    function Length (Container : Set) return Count_Type;

26/2        {AI95-00302-03} Returns the number of elements in Container.

27/2    function Is_Empty (Container : Set) return Boolean;

28/2        {AI95-00302-03} Equivalent to Length (Container) = 0.

29/2    procedure Clear (Container : in out Set);

30/2        {AI95-00302-03} Removes all the elements from Container.

31/2    function Element (Position : Cursor) return Element_Type;

32/2        {AI95-00302-03} If Position equals No_Element, then
            Constraint_Error is propagated. Otherwise, Element returns the
            element designated by Position.

33/2    procedure Replace_Element (Container : in out Set;
                                   Position  : in     Cursor;
                                   New_Item  : in     Element_Type);

34/2        {AI95-00302-03} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. If an
            element equivalent to New_Item is already present in Container at
            a position other than Position, Program_Error is propagated.
            Otherwise, Replace_Element assigns New_Item to the element
            designated by Position. Any exception raised by the assignment is
            propagated.

34.a/2      Implementation Note: The final assignment may require that the
            node of the element be moved in the Set's data structures. That
            could mean that implementing this operation exactly as worded
            above could require the overhead of searching twice.
            Implementations are encouraged to avoid this extra overhead when
            possible, by prechecking if the old element is equivalent to the
            new one, by inserting a placeholder node while checking for an
            equivalent element, and similar optimizations.

34.b/2      The cursor still designates the same element after this operation;
            only the value of that element has changed. Cursors cannot include
            information about the relative position of an element in a Set (as
            they must survive insertions and deletions of other elements), so
            this should not pose an implementation hardship.

35/2    procedure Query_Element
          (Position : in Cursor;
           Process  : not null access procedure (Element : in Element_Type));

36/3        {AI95-00302-03} {AI05-0021-1} {AI05-0265-1} If Position equals
            No_Element, then Constraint_Error is propagated. Otherwise,
            Query_Element calls Process.all with the element designated by
            Position as the argument. Tampering with the elements of the set
            that contains the element designated by Position is prohibited
            during the execution of the call on Process.all. Any exception
            raised by Process.all is propagated.

36.1/3  type Constant_Reference_Type
              (Element : not null access constant Element_Type) is private
           with Implicit_Dereference => Element;

36.2/3      {AI05-0212-1} The type Constant_Reference_Type needs finalization.

36.3/3      The default initialization of an object of type
            Constant_Reference_Type propagates Program_Error.

36.a/3      Reason: It is expected that Constant_Reference_Type will be a
            controlled type, for which finalization will have some action to
            terminate the tampering check for the associated container. If the
            object is created by default, however, there is no associated
            container. Since this is useless, and supporting this case would
            take extra work, we define it to raise an exception.

36.4/3  function Constant_Reference (Container : aliased in Set;
                                     Position  : in Cursor)
           return Constant_Reference_Type;

36.5/3      {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Constant_Indexing and Implicit_Dereference aspects) provides a
            convenient way to gain read access to an individual element of a
            set given a cursor.

36.6/3      {AI05-0212-1} {AI05-0265-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Constant_Reference returns an object whose discriminant is an
            access value that designates the element designated by Position.
            Tampering with the elements of Container is prohibited while the
            object returned by Constant_Reference exists and has not been
            finalized.

36.7/3  procedure Assign (Target : in out Set; Source : in Set);

36.8/3      {AI05-0001-1} {AI05-0248-1} If Target denotes the same object as
            Source, the operation has no effect. Otherwise, the elements of
            Source are copied to Target as for an assignment_statement
            assigning Source to Target.

36.b/3      Discussion: {AI05-0005-1} This routine exists for compatibility
            with the bounded set containers. For an unbounded set, Assign(A,
            B) and A := B behave identically. For a bounded set, := will raise
            an exception if the container capacities are different, while
            Assign will not raise an exception if there is enough room in the
            target.

37/2    procedure Move (Target : in out Set;
                        Source : in out Set);

38/3        {AI95-00302-03} {AI05-0001-1} {AI05-0248-1} {AI05-0262-1} If
            Target denotes the same object as Source, then the operation has
            no effect. Otherwise, the operation is equivalent to Assign
            (Target, Source) followed by Clear (Source).

39/2    procedure Insert (Container : in out Set;
                          New_Item  : in     Element_Type;
                          Position  :    out Cursor;
                          Inserted  :    out Boolean);

40/2        {AI95-00302-03} Insert checks if an element equivalent to New_Item
            is already present in Container. If a match is found, Inserted is
            set to False and Position designates the matching element.
            Otherwise, Insert adds New_Item to Container; Inserted is set to
            True and Position designates the newly-inserted element. Any
            exception raised during allocation is propagated and Container is
            not modified.

41/2    procedure Insert (Container : in out Set;
                          New_Item  : in     Element_Type);

42/2        {AI95-00302-03} Insert inserts New_Item into Container as per the
            four-parameter Insert, with the difference that if an element
            equivalent to New_Item is already in the set, then
            Constraint_Error is propagated.

42.a/2      Discussion: This is equivalent to:

42.b/2          declare
                  Inserted : Boolean; C : Cursor;
                begin
                  Insert (Container, New_Item, C, Inserted);
                  if not Inserted then
                     raise Constraint_Error;
                  end if;
                end;

42.c/2      but doesn't require the hassle of out parameters.

43/2    procedure Include (Container : in out Set;
                           New_Item  : in     Element_Type);

44/2        {AI95-00302-03} Include inserts New_Item into Container as per the
            four-parameter Insert, with the difference that if an element
            equivalent to New_Item is already in the set, then it is replaced.
            Any exception raised during assignment is propagated.

45/2    procedure Replace (Container : in out Set;
                           New_Item  : in     Element_Type);

46/2        {AI95-00302-03} Replace checks if an element equivalent to
            New_Item is already in the set. If a match is found, that element
            is replaced with New_Item; otherwise, Constraint_Error is
            propagated.

47/2    procedure Exclude (Container : in out Set;
                           Item      : in     Element_Type);

48/2        {AI95-00302-03} Exclude checks if an element equivalent to Item is
            present in Container. If a match is found, Exclude removes the
            element from the set.

49/2    procedure Delete (Container : in out Set;
                          Item      : in     Element_Type);

50/2        {AI95-00302-03} Delete checks if an element equivalent to Item is
            present in Container. If a match is found, Delete removes the
            element from the set; otherwise, Constraint_Error is propagated.

51/2    procedure Delete (Container : in out Set;
                          Position  : in out Cursor);

52/2        {AI95-00302-03} If Position equals No_Element, then
            Constraint_Error is propagated. If Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Delete removes the element designated by Position from the set.
            Position is set to No_Element on return.

52.a/2      Ramification: The check on Position checks that the cursor does
            not belong to some other set. This check implies that a reference
            to the set is included in the cursor value. This wording is not
            meant to require detection of dangling cursors; such cursors are
            defined to be invalid, which means that execution is erroneous,
            and any result is allowed (including not raising an exception).

53/2    procedure Union (Target : in out Set;
                         Source : in     Set);

54/2        {AI95-00302-03} Union inserts into Target the elements of Source
            that are not equivalent to some element already in Target.

54.a/2      Implementation Note: If the objects are the same, the result is
            the same as the original object. The implementation needs to take
            care so that aliasing effects do not make the result trash; Union
            (S, S); must work.

55/2    function Union (Left, Right : Set) return Set;

56/2        {AI95-00302-03} Returns a set comprising all of the elements of
            Left, and the elements of Right that are not equivalent to some
            element of Left.

57/2    procedure Intersection (Target : in out Set;
                                Source : in     Set);

58/3        {AI95-00302-03} {AI05-0004-1} Intersection deletes from Target the
            elements of Target that are not equivalent to some element of
            Source.

58.a/2      Implementation Note: If the objects are the same, the result is
            the same as the original object. The implementation needs to take
            care so that aliasing effects do not make the result trash;
            Intersection (S, S); must work.

59/2    function Intersection (Left, Right : Set) return Set;

60/2        {AI95-00302-03} Returns a set comprising all the elements of Left
            that are equivalent to the some element of Right.

61/2    procedure Difference (Target : in out Set;
                              Source : in     Set);

62/2        {AI95-00302-03} If Target denotes the same object as Source, then
            Difference clears Target. Otherwise, it deletes from Target the
            elements that are equivalent to some element of Source.

63/2    function Difference (Left, Right : Set) return Set;

64/2        {AI95-00302-03} Returns a set comprising the elements of Left that
            are not equivalent to some element of Right.

65/2    procedure Symmetric_Difference (Target : in out Set;
                                        Source : in     Set);

66/2        {AI95-00302-03} If Target denotes the same object as Source, then
            Symmetric_Difference clears Target. Otherwise, it deletes from
            Target the elements that are equivalent to some element of Source,
            and inserts into Target the elements of Source that are not
            equivalent to some element of Target.

67/2    function Symmetric_Difference (Left, Right : Set) return Set;

68/2        {AI95-00302-03} Returns a set comprising the elements of Left that
            are not equivalent to some element of Right, and the elements of
            Right that are not equivalent to some element of Left.

69/2    function Overlap (Left, Right : Set) return Boolean;

70/3        {AI95-00302-03} {AI05-0264-1} If an element of Left is equivalent
            to some element of Right, then Overlap returns True. Otherwise, it
            returns False.

70.a/2      Discussion: This operation is commutative. If Overlap returns
            False, the two sets are disjoint.

71/2    function Is_Subset (Subset : Set;
                            Of_Set : Set) return Boolean;

72/3        {AI95-00302-03} {AI05-0264-1} If an element of Subset is not
            equivalent to some element of Of_Set, then Is_Subset returns
            False. Otherwise, it returns True.

72.a/2      Discussion: This operation is not commutative, so we use parameter
            names that make it clear in named notation which set is which.

73/2    function First (Container : Set) return Cursor;

74/2        {AI95-00302-03} If Length (Container) = 0, then First returns
            No_Element. Otherwise, First returns a cursor that designates the
            first element in Container.

75/2    function Next (Position  : Cursor) return Cursor;

76/2        {AI95-00302-03} Returns a cursor that designates the successor of
            the element designated by Position. If Position designates the
            last element, then No_Element is returned. If Position equals
            No_Element, then No_Element is returned.

77/2    procedure Next (Position  : in out Cursor);

78/2        {AI95-00302-03} Equivalent to Position := Next (Position).

79/3        This paragraph was deleted.{AI95-00302-03} {AI05-0004-1}

80/2    function Find (Container : Set;
                       Item      : Element_Type) return Cursor;

81/2        {AI95-00302-03} If Length (Container) equals 0, then Find returns
            No_Element. Otherwise, Find checks if an element equivalent to
            Item is present in Container. If a match is found, a cursor
            designating the matching element is returned; otherwise,
            No_Element is returned.

82/2    function Contains (Container : Set;
                           Item      : Element_Type) return Boolean;

82.1/3      {AI05-0004-1} Equivalent to Find (Container, Item) /= No_Element.

            Paragraphs 83 and 84 were moved above.

85/2    procedure Iterate
          (Container : in Set;
           Process   : not null access procedure (Position : in Cursor));

86/3        {AI95-00302-03} {AI05-0265-1} Iterate calls Process.all with a
            cursor that designates each element in Container, starting with
            the first element and moving the cursor according to the successor
            relation. Tampering with the cursors of Container is prohibited
            during the execution of a call on Process.all. Any exception
            raised by Process.all is propagated.

86.a/2      Implementation Note: The "tamper with cursors" check takes place
            when the operations that insert or delete elements, and so on are
            called.

86.b/2      See Iterate for vectors (A.18.2) for a suggested implementation of
            the check.

87/2 {AI95-00302-03} Both Containers.Hashed_Set and Containers.Ordered_Set
declare a nested generic package Generic_Keys, which provides operations that
allow set manipulation in terms of a key (typically, a portion of an element)
instead of a complete element. The formal function Key of Generic_Keys
extracts a key value from an element. It is expected to return the same value
each time it is called with a particular element. The behavior of Generic_Keys
is unspecified if Key behaves in some other manner.

88/2 {AI95-00302-03} A key is expected to unambiguously determine a single
equivalence class for elements. The behavior of Generic_Keys is unspecified if
the formal parameters of this package behave in some other manner.

89/2    function Key (Position : Cursor) return Key_Type;

90/2        {AI95-00302-03} Equivalent to Key (Element (Position)).

91/2 {AI95-00302-03} The subprograms in package Generic_Keys named Contains,
Find, Element, Delete, and Exclude, are equivalent to the corresponding
subprograms in the parent package, with the difference that the Key parameter
is used to locate an element in the set.

92/2    procedure Replace (Container : in out Set;
                           Key       : in     Key_Type;
                           New_Item  : in     Element_Type);

93/2        {AI95-00302-03} Equivalent to Replace_Element (Container, Find
            (Container, Key), New_Item).

94/2    procedure Update_Element_Preserving_Key
          (Container : in out Set;
           Position  : in     Cursor;
           Process   : not null access procedure
                                         (Element : in out Element_Type));

95/3        {AI95-00302-03} {AI05-0265-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Update_Element_Preserving_Key uses Key to save the key value K of
            the element designated by Position. Update_Element_Preserving_Key
            then calls Process.all with that element as the argument.
            Tampering with the elements of Container is prohibited during the
            execution of the call on Process.all. Any exception raised by
            Process.all is propagated. After Process.all returns, Update_-
            Element_Preserving_Key checks if K determines the same equivalence
            class as that for the new element; if not, the element is removed
            from the set and Program_Error is propagated.

95.a/2      Reason: The key check ensures that the invariants of the set are
            preserved by the modification. The "tampers with the elements"
            check prevents data loss (if Element_Type is by-copy) or erroneous
            execution (if element type is unconstrained and indefinite).

96/2        If Element_Type is unconstrained and definite, then the actual
            Element parameter of Process.all shall be unconstrained.

96.a/2      Ramification: This means that the elements cannot be directly
            allocated from the heap; it must be possible to change the
            discriminants of the element in place.

96.1/3  type Reference_Type (Element : not null access Element_Type) is private
           with Implicit_Dereference => Element;

96.2/3      {AI05-0212-1} The type Reference_Type needs finalization.

96.3/3      The default initialization of an object of type Reference_Type
            propagates Program_Error.

96.4/3  function Reference_Preserving_Key (Container : aliased in out Set;
                                           Position  : in Cursor)
           return Reference_Type;

96.5/3      {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Implicit_Dereference aspect) provides a convenient way to gain
            read and write access to an individual element of a set given a
            cursor.

96.6/3      {AI05-0212-1} {AI05-0265-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Reference_Preserving_Key uses Key to save the key value K; then
            returns an object whose discriminant is an access value that
            designates the element designated by Position. Tampering with the
            elements of Container is prohibited while the object returned by
            Reference_Preserving_Key exists and has not been finalized. When
            the object returned by Reference_Preserving_Key is finalized, a
            check is made if K determines the same equivalence class as that
            for the new element; if not, the element is removed from the set
            and Program_Error is propagated.

96.7/3  function Constant_Reference (Container : aliased in Set;
                                     Key       : in Key_Type)
           return Constant_Reference_Type;

96.8/3      {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Implicit_Dereference aspect) provides a convenient way to gain
            read access to an individual element of a set given a key value.

96.9/3      Equivalent to Constant_Reference (Container, Find (Container,
            Key)).

96.10/3 function Reference_Preserving_Key (Container : aliased in out Set;
                                           Key       : in Key_Type)
           return Reference_Type;

96.11/3     {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Implicit_Dereference aspect) provides a convenient way to gain
            read and write access to an individual element of a set given a
            key value.

96.12/3     Equivalent to Reference_Preserving_Key (Container, Find
            (Container, Key)).


                          Bounded (Run-Time) Errors

96.13/3 {AI05-0022-1} {AI05-0248-1} It is a bounded error for the actual
function associated with a generic formal subprogram, when called as part of
an operation of a set package, to tamper with elements of any set parameter of
the operation. Either Program_Error is raised, or the operation works as
defined on the value of the set either prior to, or subsequent to, some or all
of the modifications to the set.

96.14/3 {AI05-0027-1} It is a bounded error to call any subprogram declared in
the visible part of a set package when the associated container has been
finalized. If the operation takes Container as an in out parameter, then it
raises Constraint_Error or Program_Error. Otherwise, the operation either
proceeds as it would for an empty container, or it raises Constraint_Error or
Program_Error.


                             Erroneous Execution

97/2 {AI95-00302-03} A Cursor value is invalid if any of the following have
occurred since it was created:

98/2   * The set that contains the element it designates has been finalized;

98.1/3   * {AI05-0160-1} The set that contains the element it designates has
        been used as the Target of a call to Assign, or as the target of an
        assignment_statement;

99/2   * The set that contains the element it designates has been used as the
        Source or Target of a call to Move; or

100/3   * {AI05-0160-1} {AI05-0262-1} The element it designates has been
        removed from the set that previously contained the element.

100.a/3     Ramification: {AI05-0160-1} This can happen directly via calls to
            Clear, Exclude, Delete, and Update_Element_Preserving_Key, and
            indirectly via calls to procedures Intersection, Difference, and
            Symmetric_Difference.

101/2 {AI95-00302-03} The result of "=" or Has_Element is unspecified if these
functions are called with an invalid cursor parameter. Execution is erroneous
if any other subprogram declared in Containers.Hashed_Sets or
Containers.Ordered_Sets is called with an invalid cursor parameter.

101.a/2     Discussion: The list above is intended to be exhaustive. In other
            cases, a cursor value continues to designate its original element.
            For instance, cursor values survive the insertion and deletion of
            other elements.

101.b/2     While it is possible to check for these cases, in many cases the
            overhead necessary to make the check is substantial in time or
            space. Implementations are encouraged to check for as many of
            these cases as possible and raise Program_Error if detected.

101.1/3 {AI05-0212-1} Execution is erroneous if the set associated with the
result of a call to Reference or Constant_Reference is finalized before the
result object returned by the call to Reference or Constant_Reference is
finalized.

101.c/3     Reason: Each object of Reference_Type and Constant_Reference_Type
            probably contains some reference to the originating container. If
            that container is prematurely finalized (which is only possible
            via Unchecked_Deallocation, as accessibility checks prevent
            passing a container to Reference that will not live as long as the
            result), the finalization of the object of Reference_Type will try
            to access a nonexistent object. This is a normal case of a
            dangling pointer created by Unchecked_Deallocation; we have to
            explicitly mention it here as the pointer in question is not
            visible in the specification of the type. (This is the same reason
            we have to say this for invalid cursors.)


                         Implementation Requirements

102/2 {AI95-00302-03} No storage associated with a Set object shall be lost
upon assignment or scope exit.

103/3 {AI95-00302-03} {AI05-0262-1} The execution of an assignment_statement
for a set shall have the effect of copying the elements from the source set
object to the target set object and changing the length of the target object
to that of the source object.

103.a/3     Implementation Note: {AI05-0298-1} An assignment of a Set is a "
            deep" copy; that is the elements are copied as well as the data
            structures. We say "effect of" in order to allow the
            implementation to avoid copying elements immediately if it wishes.
            For instance, an implementation that avoided copying until one of
            the containers is modified would be allowed. (Note that this
            implementation would require care, see A.18.2 for more.)


                            Implementation Advice

104/2 {AI95-00302-03} Move should not copy elements, and should minimize
copying of internal data structures.

104.a/2     Implementation Advice: Move for sets should not copy elements, and
            should minimize copying of internal data structures.

104.b/2     Implementation Note: Usually that can be accomplished simply by
            moving the pointer(s) to the internal data structures from the
            Source container to the Target container.

105/2 {AI95-00302-03} If an exception is propagated from a set operation, no
storage should be lost, nor any elements removed from a set unless specified
by the operation.

105.a/2     Implementation Advice: If an exception is propagated from a set
            operation, no storage should be lost, nor any elements removed
            from a set unless specified by the operation.

105.b/2     Reason: This is important so that programs can recover from
            errors. But we don't want to require heroic efforts, so we just
            require documentation of cases where this can't be accomplished.


                         Wording Changes from Ada 95

105.c/2     {AI95-00302-03} This description of sets is new; the extensions
            are documented with the specific packages.


                           Extensions to Ada 2005

105.d/3     {AI05-0212-1} Added reference support to make set containers more
            convenient to use.


                        Wording Changes from Ada 2005

105.e/3     {AI05-0001-1} Added procedure Assign; the extension and
            incompatibility is documented with the specific packages.

105.f/3     {AI05-0001-1} Generalized the definition of Move. Specified which
            elements are read/written by stream attributes.

105.g/3     {AI05-0022-1} Correction: Added a Bounded (Run-Time) Error to
            cover tampering by generic actual subprograms.

105.h/3     {AI05-0027-1} Correction: Added a Bounded (Run-Time) Error to
            cover access to finalized set containers.

105.i/3     {AI05-0160-1} Correction: Revised the definition of invalid
            cursors to cover missing (and new) cases.

105.j/3     {AI05-0265-1} Correction: Defined when a container prohibits
            tampering in order to more clearly define where the check is made
            and the exception raised.


                        Wording Changes from Ada 2012

105.k/4     {AI12-0110-1} Corrigendum: Clarified that tampering checks precede
            all other checks made by a subprogram (but come after those
            associated with the call).


A.18.8 The Generic Package Containers.Hashed_Sets



                              Static Semantics

1/2 {AI95-00302-03} The generic library package Containers.Hashed_Sets has the
following declaration:

2/3     {AI05-0084-1} {AI05-0212-1} with Ada.Iterator_Interfaces;
        generic
           type Element_Type is private;
           with function Hash (Element : Element_Type) return Hash_Type;
           with function Equivalent_Elements (Left, Right : Element_Type)
                         return Boolean;
           with function "=" (Left, Right : Element_Type) return Boolean is <>;
        package Ada.Containers.Hashed_Sets is
           pragma Preelaborate(Hashed_Sets);
           pragma Remote_Types(Hashed_Sets);

3/3     {AI05-0212-1}    type Set is tagged private
              with Constant_Indexing => Constant_Reference,
                   Default_Iterator  => Iterate,
                   Iterator_Element  => Element_Type;
           pragma Preelaborable_Initialization(Set);

4/2        type Cursor is private;
           pragma Preelaborable_Initialization(Cursor);

5/2        Empty_Set : constant Set;

6/2        No_Element : constant Cursor;

6.1/3   {AI05-0212-1}    function Has_Element
         (Position : Cursor) return Boolean;

6.2/3   {AI05-0212-1}    package Set_Iterator_Interfaces is new
               Ada.Iterator_Interfaces (Cursor, Has_Element);

7/2        function "=" (Left, Right : Set) return Boolean;

8/2        function Equivalent_Sets (Left, Right : Set) return Boolean;

9/2        function To_Set (New_Item : Element_Type) return Set;

10/2       function Capacity (Container : Set) return Count_Type;

11/2       procedure Reserve_Capacity (Container : in out Set;
                                       Capacity  : in     Count_Type);

12/2       function Length (Container : Set) return Count_Type;

13/2       function Is_Empty (Container : Set) return Boolean;

14/2       procedure Clear (Container : in out Set);

15/2       function Element (Position : Cursor) return Element_Type;

16/2       procedure Replace_Element (Container : in out Set;
                                      Position  : in     Cursor;
                                      New_Item  : in     Element_Type);

17/2       procedure Query_Element
             (Position : in Cursor;
              Process  : not null access procedure (Element : in Element_Type));

17.1/3  {AI05-0212-1}    type Constant_Reference_Type
                 (Element : not null access constant Element_Type) is private
              with Implicit_Dereference => Element;

17.2/3  {AI05-0212-1}    function Constant_Reference
         (Container : aliased in Set;
                                        Position  : in Cursor)
              return Constant_Reference_Type;

17.3/3  {AI05-0001-1}    procedure Assign
         (Target : in out Set; Source : in Set);

17.4/3  {AI05-0001-1}    function Copy
         (Source : Set; Capacity : Count_Type := 0) return Set;

18/2       procedure Move (Target : in out Set;
                           Source : in out Set);

19/2       procedure Insert (Container : in out Set;
                             New_Item  : in     Element_Type;
                             Position  :    out Cursor;
                             Inserted  :    out Boolean);

20/2       procedure Insert (Container : in out Set;
                             New_Item  : in     Element_Type);

21/2       procedure Include (Container : in out Set;
                              New_Item  : in     Element_Type);

22/2       procedure Replace (Container : in out Set;
                              New_Item  : in     Element_Type);

23/2       procedure Exclude (Container : in out Set;
                              Item      : in     Element_Type);

24/2       procedure Delete (Container : in out Set;
                             Item      : in     Element_Type);

25/2       procedure Delete (Container : in out Set;
                             Position  : in out Cursor);

26/2       procedure Union (Target : in out Set;
                            Source : in     Set);

27/2       function Union (Left, Right : Set) return Set;

28/2       function "or" (Left, Right : Set) return Set renames Union;

29/2       procedure Intersection (Target : in out Set;
                                   Source : in     Set);

30/2       function Intersection (Left, Right : Set) return Set;

31/2       function "and" (Left, Right : Set) return Set renames Intersection;

32/2       procedure Difference (Target : in out Set;
                                 Source : in     Set);

33/2       function Difference (Left, Right : Set) return Set;

34/2       function "-" (Left, Right : Set) return Set renames Difference;

35/2       procedure Symmetric_Difference (Target : in out Set;
                                           Source : in     Set);

36/2       function Symmetric_Difference (Left, Right : Set) return Set;

37/2       function "xor" (Left, Right : Set) return Set
             renames Symmetric_Difference;

38/2       function Overlap (Left, Right : Set) return Boolean;

39/2       function Is_Subset (Subset : Set;
                               Of_Set : Set) return Boolean;

40/2       function First (Container : Set) return Cursor;

41/2       function Next (Position : Cursor) return Cursor;

42/2       procedure Next (Position : in out Cursor);

43/2       function Find (Container : Set;
                          Item      : Element_Type) return Cursor;

44/2       function Contains (Container : Set;
                              Item      : Element_Type) return Boolean;

45/3    This paragraph was deleted.{AI05-0212-1}

46/2       function Equivalent_Elements (Left, Right : Cursor)
             return Boolean;

47/2       function Equivalent_Elements (Left  : Cursor;
                                         Right : Element_Type)
             return Boolean;

48/2       function Equivalent_Elements (Left  : Element_Type;
                                         Right : Cursor)
             return Boolean;

49/2       procedure Iterate
             (Container : in Set;
              Process   : not null access procedure (Position : in Cursor));

49.1/3  {AI05-0212-1}    function Iterate (Container : in Set)
              return Set_Iterator_Interfaces.Forward_Iterator'Class;

50/2       generic
              type Key_Type (<>) is private;
              with function Key (Element : Element_Type) return Key_Type;
              with function Hash (Key : Key_Type) return Hash_Type;
              with function Equivalent_Keys (Left, Right : Key_Type)
                                             return Boolean;
           package Generic_Keys is

51/2          function Key (Position : Cursor) return Key_Type;

52/2          function Element (Container : Set;
                                Key       : Key_Type)
                return Element_Type;

53/2          procedure Replace (Container : in out Set;
                                 Key       : in     Key_Type;
                                 New_Item  : in     Element_Type);

54/2          procedure Exclude (Container : in out Set;
                                 Key       : in     Key_Type);

55/2          procedure Delete (Container : in out Set;
                                Key       : in     Key_Type);

56/2          function Find (Container : Set;
                             Key       : Key_Type)
                 return Cursor;

57/2          function Contains (Container : Set;
                                 Key       : Key_Type)
                 return Boolean;

58/2          procedure Update_Element_Preserving_Key
                (Container : in out Set;
                 Position  : in     Cursor;
                 Process   : not null access procedure
                                 (Element : in out Element_Type));

58.1/3  {AI05-0212-1}       type Reference_Type
                    (Element : not null access Element_Type) is private
                 with Implicit_Dereference => Element;

58.2/3  {AI05-0212-1}       function Reference_Preserving_Key
         (Container : aliased in out Set;
                                                 Position  : in Cursor)
                 return Reference_Type;

58.3/3  {AI05-0212-1}       function Constant_Reference
         (Container : aliased in Set;
                                           Key       : in Key_Type)
                 return Constant_Reference_Type;

58.4/3  {AI05-0212-1}       function Reference_Preserving_Key
         (Container : aliased in out Set;
                                                 Key       : in Key_Type)
                 return Reference_Type;

59/2       end Generic_Keys;

60/2    private

61/2       ... -- not specified by the language

62/2    end Ada.Containers.Hashed_Sets;

63/2 {AI95-00302-03} An object of type Set contains an expandable hash table,
which is used to provide direct access to elements. The capacity of an object
of type Set is the maximum number of elements that can be inserted into the
hash table prior to it being automatically expanded.

64/2 {AI95-00302-03} Two elements E1 and E2 are defined to be equivalent if
Equivalent_Elements (E1, E2) returns True.

65/2 {AI95-00302-03} The actual function for the generic formal function Hash
is expected to return the same value each time it is called with a particular
element value. For any two equivalent elements, the actual for Hash is
expected to return the same value. If the actual for Hash behaves in some
other manner, the behavior of this package is unspecified. Which subprograms
of this package call Hash, and how many times they call it, is unspecified.

66/2 {AI95-00302-03} The actual function for the generic formal function
Equivalent_Elements is expected to return the same value each time it is
called with a particular pair of Element values. It should define an
equivalence relationship, that is, be reflexive, symmetric, and transitive. If
the actual for Equivalent_Elements behaves in some other manner, the behavior
of this package is unspecified. Which subprograms of this package call
Equivalent_Elements, and how many times they call it, is unspecified.

66.1/3 {AI05-0044-1} If the actual function for the generic formal function
"=" returns True for any pair of nonequivalent elements, then the behavior of
the container function "=" is unspecified.

67/2 {AI95-00302-03} If the value of an element stored in a set is changed
other than by an operation in this package such that at least one of Hash or
Equivalent_Elements give different results, the behavior of this package is
unspecified.

67.a/2      Discussion: See A.18.5, "
            The Generic Package Containers.Hashed_Maps" for a suggested
            implementation, and for justification of the restrictions
            regarding Hash and Equivalent_Elements. Note that sets only need
            to store elements, not key/element pairs.

68/2 {AI95-00302-03} Which elements are the first element and the last element
of a set, and which element is the successor of a given element, are
unspecified, other than the general semantics described in A.18.7.

69/2    function Capacity (Container : Set) return Count_Type;

70/2        {AI95-00302-03} Returns the capacity of Container.

71/2    procedure Reserve_Capacity (Container : in out Set;
                                    Capacity  : in     Count_Type);

72/2        {AI95-00302-03} Reserve_Capacity allocates a new hash table such
            that the length of the resulting set can become at least the value
            Capacity without requiring an additional call to Reserve_Capacity,
            and is large enough to hold the current length of Container.
            Reserve_Capacity then rehashes the elements in Container onto the
            new hash table. It replaces the old hash table with the new hash
            table, and then deallocates the old hash table. Any exception
            raised during allocation is propagated and Container is not
            modified.

73/2        Reserve_Capacity tampers with the cursors of Container.

73.a/2      Reason: Reserve_Capacity tampers with the cursors, as rehashing
            probably will change the relationships of the elements in
            Container.

74/2    procedure Clear (Container : in out Set);

75/2        {AI95-00302-03} In addition to the semantics described in A.18.7,
            Clear does not affect the capacity of Container.

75.1/3  procedure Assign (Target : in out Set; Source : in Set);

75.2/3      {AI05-0001-1} {AI05-0248-1} In addition to the semantics described
            in A.18.7, if the length of Source is greater than the capacity of
            Target, Reserve_Capacity (Target, Length (Source)) is called
            before assigning any elements.

75.3/3  function Copy (Source : Set; Capacity : Count_Type := 0) return Set;

75.4/3      {AI05-0001-1} Returns a set whose elements are initialized from
            the elements of Source. If Capacity is 0, then the set capacity is
            the length of Source; if Capacity is equal to or greater than the
            length of Source, the set capacity is at least the specified
            value. Otherwise, the operation propagates Capacity_Error.

76/2    procedure Insert (Container : in out Set;
                          New_Item  : in     Element_Type;
                          Position  :    out Cursor;
                          Inserted  :    out Boolean);

77/2        {AI95-00302-03} In addition to the semantics described in A.18.7,
            if Length (Container) equals Capacity (Container), then Insert
            first calls Reserve_Capacity to increase the capacity of Container
            to some larger value.

78/2    function First (Container : Set) return Cursor;

79/2        {AI95-00302-03} If Length (Container) = 0, then First returns
            No_Element. Otherwise, First returns a cursor that designates the
            first hashed element in Container.

80/2    function Equivalent_Elements (Left, Right : Cursor)
              return Boolean;

81/2        {AI95-00302-03} Equivalent to Equivalent_Elements (Element (Left),
            Element (Right)).

82/2    function Equivalent_Elements (Left  : Cursor;
                                      Right : Element_Type) return Boolean;

83/2        {AI95-00302-03} Equivalent to Equivalent_Elements (Element (Left),
            Right).

84/2    function Equivalent_Elements (Left  : Element_Type;
                                      Right : Cursor) return Boolean;

85/2        {AI95-00302-03} Equivalent to Equivalent_Elements (Left, Element
            (Right)).

85.1/3  function Iterate (Container : in Set)
           return Set_Iterator_Interfaces.Forward_Iterator'Class;

85.2/3      {AI05-0212-1} {AI05-0265-1} {AI05-0269-1} Iterate returns an
            iterator object (see 5.5.1) that will generate a value for a loop
            parameter (see 5.5.2) designating each element in Container,
            starting with the first element and moving the cursor according to
            the successor relation. Tampering with the cursors of Container is
            prohibited while the iterator object exists (in particular, in the
            sequence_of_statements of the loop_statement whose
            iterator_specification denotes this object). The iterator object
            needs finalization.

86/2 {AI95-00302-03} For any element E, the actual function for the generic
formal function Generic_Keys.Hash is expected to be such that Hash (E) =
Generic_Keys.Hash (Key (E)). If the actuals for Key or Generic_Keys.Hash
behave in some other manner, the behavior of Generic_Keys is unspecified.
Which subprograms of Generic_Keys call Generic_Keys.Hash, and how many times
they call it, is unspecified.

87/2 {AI95-00302-03} For any two elements E1 and E2, the boolean values
Equivalent_Elements (E1, E2) and Equivalent_Keys (Key (E1), Key (E2)) are
expected to be equal. If the actuals for Key or Equivalent_Keys behave in some
other manner, the behavior of Generic_Keys is unspecified. Which subprograms
of Generic_Keys call Equivalent_Keys, and how many times they call it, is
unspecified.


                            Implementation Advice

88/2 {AI95-00302-03} If N is the length of a set, the average time complexity
of the subprograms Insert, Include, Replace, Delete, Exclude and Find that
take an element parameter should be O(log N). The average time complexity of
the subprograms that take a cursor parameter should be O(1). The average time
complexity of Reserve_Capacity should be O(N).

88.a/2      Implementation Advice: The average time complexity of the Insert,
            Include, Replace, Delete, Exclude and Find operations of
            Containers.Hashed_Sets that take an element parameter should be
            O(log N). The average time complexity of the subprograms of
            Containers.Hashed_Sets that take a cursor parameter should be
            O(1). The average time complexity of Containers.Hashed_Sets.-
            Reserve_Capacity should be O(N).

88.b/2      Implementation Note: {AI95-00302-03} See A.18.5, "
            The Generic Package Containers.Hashed_Maps" for implementation
            notes regarding some of the operations of this package.


                            Extensions to Ada 95

88.c/2      {AI95-00302-03} The generic package Containers.Hashed_Sets is new.


                       Incompatibilities With Ada 2005

88.d/3      {AI05-0001-1} Subprograms Assign and Copy are added to
            Containers.Hashed_Sets. If an instance of Containers.Hashed_Sets
            is referenced in a use_clause, and an entity E with the same
            defining_identifier as a new entity in Containers.Hashed_Sets is
            defined in a package that is also referenced in a use_clause, the
            entity E may no longer be use-visible, resulting in errors. This
            should be rare and is easily fixed if it does occur.


                           Extensions to Ada 2005

88.e/3      {AI05-0212-1} Added iterator and indexing support to make hashed
            set containers more convenient to use.


                        Wording Changes from Ada 2005

88.f/3      {AI05-0044-1} Correction: Added wording to require the formal
            function be such that equal elements are also equivalent.

88.g/3      {AI05-0084-1} Correction: Added a pragma Remote_Types so that
            containers can be used in distributed programs.


A.18.9 The Generic Package Containers.Ordered_Sets



                              Static Semantics

1/2 {AI95-00302-03} The generic library package Containers.Ordered_Sets has
the following declaration:

2/3     {AI05-0084-1} {AI05-0212-1} with Ada.Iterator_Interfaces;
        generic
           type Element_Type is private;
           with function "<" (Left, Right : Element_Type) return Boolean is <>;
           with function "=" (Left, Right : Element_Type) return Boolean is <>;
        package Ada.Containers.Ordered_Sets is
           pragma Preelaborate(Ordered_Sets);
           pragma Remote_Types(Ordered_Sets);

3/2        function Equivalent_Elements
         (Left, Right : Element_Type) return Boolean;

4/3     {AI05-0212-1}    type Set is tagged private
              with Constant_Indexing => Constant_Reference,
                   Default_Iterator  => Iterate,
                   Iterator_Element  => Element_Type;
           pragma Preelaborable_Initialization(Set);

5/2        type Cursor is private;
           pragma Preelaborable_Initialization(Cursor);

6/2        Empty_Set : constant Set;

7/2        No_Element : constant Cursor;

7.1/3   {AI05-0212-1}    function Has_Element
         (Position : Cursor) return Boolean;

7.2/3   {AI05-0212-1}    package Set_Iterator_Interfaces is new
               Ada.Iterator_Interfaces (Cursor, Has_Element);

8/2        function "=" (Left, Right : Set) return Boolean;

9/2        function Equivalent_Sets (Left, Right : Set) return Boolean;

10/2       function To_Set (New_Item : Element_Type) return Set;

11/2       function Length (Container : Set) return Count_Type;

12/2       function Is_Empty (Container : Set) return Boolean;

13/2       procedure Clear (Container : in out Set);

14/2       function Element (Position : Cursor) return Element_Type;

15/2       procedure Replace_Element (Container : in out Set;
                                      Position  : in     Cursor;
                                      New_Item  : in     Element_Type);

16/2       procedure Query_Element
             (Position : in Cursor;
              Process  : not null access procedure (Element : in Element_Type));

16.1/3  {AI05-0212-1}    type Constant_Reference_Type
                 (Element : not null access constant Element_Type) is private
              with Implicit_Dereference => Element;

16.2/3  {AI05-0212-1}    function Constant_Reference
         (Container : aliased in Set;
                                        Position  : in Cursor)
              return Constant_Reference_Type;

16.3/3  {AI05-0001-1}    procedure Assign
         (Target : in out Set; Source : in Set);

16.4/3  {AI05-0001-1}    function Copy (Source : Set) return Set;

17/2       procedure Move (Target : in out Set;
                           Source : in out Set);

18/2       procedure Insert (Container : in out Set;
                             New_Item  : in     Element_Type;
                             Position  :    out Cursor;
                             Inserted  :    out Boolean);

19/2       procedure Insert (Container : in out Set;
                             New_Item  : in     Element_Type);

20/2       procedure Include (Container : in out Set;
                              New_Item  : in     Element_Type);

21/2       procedure Replace (Container : in out Set;
                              New_Item  : in     Element_Type);

22/2       procedure Exclude (Container : in out Set;
                              Item      : in     Element_Type);

23/2       procedure Delete (Container : in out Set;
                             Item      : in     Element_Type);

24/2       procedure Delete (Container : in out Set;
                             Position  : in out Cursor);

25/2       procedure Delete_First (Container : in out Set);

26/2       procedure Delete_Last (Container : in out Set);

27/2       procedure Union (Target : in out Set;
                            Source : in     Set);

28/2       function Union (Left, Right : Set) return Set;

29/2       function "or" (Left, Right : Set) return Set renames Union;

30/2       procedure Intersection (Target : in out Set;
                                   Source : in     Set);

31/2       function Intersection (Left, Right : Set) return Set;

32/2       function "and" (Left, Right : Set) return Set renames Intersection;

33/2       procedure Difference (Target : in out Set;
                                 Source : in     Set);

34/2       function Difference (Left, Right : Set) return Set;

35/2       function "-" (Left, Right : Set) return Set renames Difference;

36/2       procedure Symmetric_Difference (Target : in out Set;
                                           Source : in     Set);

37/2       function Symmetric_Difference (Left, Right : Set) return Set;

38/2       function "xor" (Left, Right : Set) return Set renames
              Symmetric_Difference;

39/2       function Overlap (Left, Right : Set) return Boolean;

40/2       function Is_Subset (Subset : Set;
                               Of_Set : Set) return Boolean;

41/2       function First (Container : Set) return Cursor;

42/2       function First_Element (Container : Set) return Element_Type;

43/2       function Last (Container : Set) return Cursor;

44/2       function Last_Element (Container : Set) return Element_Type;

45/2       function Next (Position : Cursor) return Cursor;

46/2       procedure Next (Position : in out Cursor);

47/2       function Previous (Position : Cursor) return Cursor;

48/2       procedure Previous (Position : in out Cursor);

49/2       function Find (Container : Set;
                          Item      : Element_Type)
              return Cursor;

50/2       function Floor (Container : Set;
                           Item      : Element_Type)
              return Cursor;

51/2       function Ceiling (Container : Set;
                             Item      : Element_Type)
              return Cursor;

52/2       function Contains (Container : Set;
                              Item      : Element_Type) return Boolean;

53/3    This paragraph was deleted.{AI05-0212-1}

54/2       function "<" (Left, Right : Cursor) return Boolean;

55/2       function ">" (Left, Right : Cursor) return Boolean;

56/2       function "<" (Left : Cursor; Right : Element_Type)
              return Boolean;

57/2       function ">" (Left : Cursor; Right : Element_Type)
              return Boolean;

58/2       function "<" (Left : Element_Type; Right : Cursor)
              return Boolean;

59/2       function ">" (Left : Element_Type; Right : Cursor)
              return Boolean;

60/2       procedure Iterate
             (Container : in Set;
              Process   : not null access procedure (Position : in Cursor));

61/2       procedure Reverse_Iterate
             (Container : in Set;
              Process   : not null access procedure (Position : in Cursor));

61.1/3  {AI05-0212-1}    function Iterate (Container : in Set)
              return Set_Iterator_Interfaces.Reversible_Iterator'Class;

61.2/3  {AI05-0262-1}
           function Iterate (Container : in Set; Start : in Cursor)
              return Set_Iterator_Interfaces.Reversible_Iterator'Class;

62/2       generic
              type Key_Type (<>) is private;
              with function Key (Element : Element_Type) return Key_Type;
              with function "<" (Left, Right : Key_Type)
                 return Boolean is <>;
           package Generic_Keys is

63/2           function Equivalent_Keys (Left, Right : Key_Type)
                  return Boolean;

64/2           function Key (Position : Cursor) return Key_Type;

65/2           function Element (Container : Set;
                                 Key       : Key_Type)
                  return Element_Type;

66/2           procedure Replace (Container : in out Set;
                                  Key       : in     Key_Type;
                                  New_Item  : in     Element_Type);

67/2           procedure Exclude (Container : in out Set;
                                  Key       : in     Key_Type);

68/2           procedure Delete (Container : in out Set;
                                 Key       : in     Key_Type);

69/2           function Find (Container : Set;
                              Key       : Key_Type)
                  return Cursor;

70/2           function Floor (Container : Set;
                               Key       : Key_Type)
                  return Cursor;

71/2           function Ceiling (Container : Set;
                                 Key       : Key_Type)
                  return Cursor;

72/2           function Contains (Container : Set;
                                  Key       : Key_Type) return Boolean;

73/2           procedure Update_Element_Preserving_Key
                 (Container : in out Set;
                  Position  : in     Cursor;
                  Process   : not null access procedure
                                  (Element : in out Element_Type));

73.1/3  {AI05-0212-1}       type Reference_Type
                    (Element : not null access Element_Type) is private
                 with Implicit_Dereference => Element;

73.2/3  {AI05-0212-1}       function Reference_Preserving_Key
         (Container : aliased in out Set;
                                                 Position  : in Cursor)
                 return Reference_Type;

73.3/3  {AI05-0212-1}       function Constant_Reference
         (Container : aliased in Set;
                                           Key       : in Key_Type)
                 return Constant_Reference_Type;

73.4/3  {AI05-0212-1}       function Reference_Preserving_Key
         (Container : aliased in out Set;
                                                 Key       : in Key_Type)
                 return Reference_Type;

74/2       end Generic_Keys;

75/2    private

76/2       ... -- not specified by the language

77/2    end Ada.Containers.Ordered_Sets;

78/2 {AI95-00302-03} Two elements E1 and E2 are equivalent if both E1 < E2 and
E2 < E1 return False, using the generic formal "<" operator for elements.
Function Equivalent_Elements returns True if Left and Right are equivalent,
and False otherwise.

79/3 {AI95-00302-03} {AI05-0044-1} The actual function for the generic formal
function "<" on Element_Type values is expected to return the same value each
time it is called with a particular pair of key values. It should define a
strict weak ordering relationship (see A.18). If the actual for "<" behaves in
some other manner, the behavior of this package is unspecified. Which
subprograms of this package call "<" and how many times they call it, is
unspecified.

79.1/3 {AI05-0044-1} If the actual function for the generic formal function
"=" returns True for any pair of nonequivalent elements, then the behavior of
the container function "=" is unspecified.

80/2 {AI95-00302-03} If the value of an element stored in a set is changed
other than by an operation in this package such that at least one of "<" or
"=" give different results, the behavior of this package is unspecified.

80.a/2      Discussion: See A.18.6, "
            The Generic Package Containers.Ordered_Maps" for a suggested
            implementation, and for justification of the restrictions
            regarding "<" and "=". Note that sets only need to store elements,
            not key/element pairs.

81/3 {AI95-00302-03} {AI05-0262-1} The first element of a nonempty set is the
one which is less than all the other elements in the set. The last element of
a nonempty set is the one which is greater than all the other elements in the
set. The successor of an element is the smallest element that is larger than
the given element. The predecessor of an element is the largest element that
is smaller than the given element. All comparisons are done using the generic
formal "<" operator for elements.

81.1/3  function Copy (Source : Set) return Set;

81.2/3      {AI05-0001-1} Returns a set whose elements are initialized from
            the corresponding elements of Source.

82/2    procedure Delete_First (Container : in out Set);

83/3        {AI95-00302-03} {AI05-0264-1} If Container is empty, Delete_First
            has no effect. Otherwise, the element designated by First
            (Container) is removed from Container. Delete_First tampers with
            the cursors of Container.

84/2    procedure Delete_Last (Container : in out Set);

85/3        {AI95-00302-03} {AI05-0264-1} If Container is empty, Delete_Last
            has no effect. Otherwise, the element designated by Last
            (Container) is removed from Container. Delete_Last tampers with
            the cursors of Container.

86/2    function First_Element (Container : Set) return Element_Type;

87/2        {AI95-00302-03} Equivalent to Element (First (Container)).

88/2    function Last (Container : Set) return Cursor;

89/2        {AI95-00302-03} Returns a cursor that designates the last element
            in Container. If Container is empty, returns No_Element.

90/2    function Last_Element (Container : Set) return Element_Type;

91/2        {AI95-00302-03} Equivalent to Element (Last (Container)).

92/2    function Previous (Position : Cursor) return Cursor;

93/3        {AI95-00302-03} {AI05-0262-1} If Position equals No_Element, then
            Previous returns No_Element. Otherwise, Previous returns a cursor
            designating the predecessor element of the one designated by
            Position. If Position designates the first element, then Previous
            returns No_Element.

94/2    procedure Previous (Position : in out Cursor);

95/2        {AI95-00302-03} Equivalent to Position := Previous (Position).

96/2    function Floor (Container : Set;
                        Item      : Element_Type) return Cursor;

97/3        {AI95-00302-03} {AI05-0264-1} Floor searches for the last element
            which is not greater than Item. If such an element is found, a
            cursor that designates it is returned. Otherwise, No_Element is
            returned.

98/2    function Ceiling (Container : Set;
                          Item      : Element_Type) return Cursor;

99/3        {AI95-00302-03} {AI05-0264-1} Ceiling searches for the first
            element which is not less than Item. If such an element is found,
            a cursor that designates it is returned. Otherwise, No_Element is
            returned.

100/2   function "<" (Left, Right : Cursor) return Boolean;

101/2       {AI95-00302-03} Equivalent to Element (Left) < Element (Right).

102/2   function ">" (Left, Right : Cursor) return Boolean;

103/2       {AI95-00302-03} Equivalent to Element (Right) < Element (Left).

104/2   function "<" (Left : Cursor; Right : Element_Type) return Boolean;

105/2       {AI95-00302-03} Equivalent to Element (Left) < Right.

106/2   function ">" (Left : Cursor; Right : Element_Type) return Boolean;

107/2       {AI95-00302-03} Equivalent to Right < Element (Left).

108/2   function "<" (Left : Element_Type; Right : Cursor) return Boolean;

109/2       {AI95-00302-03} Equivalent to Left < Element (Right).

110/2   function ">" (Left : Element_Type; Right : Cursor) return Boolean;

111/2       {AI95-00302-03} Equivalent to Element (Right) < Left.

112/2   procedure Reverse_Iterate
           (Container : in Set;
            Process   : not null access procedure (Position : in Cursor));

113/3       {AI95-00302-03} {AI05-0212-1} Iterates over the elements in
            Container as per procedure Iterate, with the difference that the
            elements are traversed in predecessor order, starting with the
            last element.

113.1/3 function Iterate (Container : in Set)
           return Set_Iterator_Interfaces.Reversible_Iterator'Class;

113.2/3     {AI05-0212-1} {AI05-0265-1} {AI05-0269-1} Iterate returns a
            reversible iterator object (see 5.5.1) that will generate a value
            for a loop parameter (see 5.5.2) designating each element in
            Container, starting with the first element and moving the cursor
            according to the successor relation when used as a forward
            iterator, and starting with the last element and moving the cursor
            according to the predecessor relation when used as a reverse
            iterator. Tampering with the cursors of Container is prohibited
            while the iterator object exists (in particular, in the
            sequence_of_statements of the loop_statement whose
            iterator_specification denotes this object). The iterator object
            needs finalization.

113.3/3 function Iterate (Container : in Set; Start : in Cursor)
           return Set_Iterator_Interfaces.Reversible_Iterator'Class;

113.4/3     {AI05-0262-1} {AI05-0265-1} {AI05-0269-1} If Start is not
            No_Element and does not designate an item in Container, then
            Program_Error is propagated. If Start is No_Element, then
            Constraint_Error is propagated. Otherwise, Iterate returns a
            reversible iterator object (see 5.5.1) that will generate a value
            for a loop parameter (see 5.5.2) designating each element in
            Container, starting with the element designated by Start and
            moving the cursor according to the successor relation when used as
            a forward iterator, or moving the cursor according to the
            predecessor relation when used as a reverse iterator. Tampering
            with the cursors of Container is prohibited while the iterator
            object exists (in particular, in the sequence_of_statements of the
            loop_statement whose iterator_specification denotes this object).
            The iterator object needs finalization.

113.a/3     Discussion: Exits are allowed from the loops created using the
            iterator objects. In particular, to stop the iteration at a
            particular cursor, just add

113.b/3         exit when Cur = Stop;

113.c/3     in the body of the loop (assuming that Cur is the loop parameter
            and Stop is the cursor that you want to stop at).

114/2 {AI95-00302-03} For any two elements E1 and E2, the boolean values (E1 <
E2) and (Key(E1) < Key(E2)) are expected to be equal. If the actuals for Key
or Generic_Keys."<" behave in some other manner, the behavior of this package
is unspecified. Which subprograms of this package call Key and
Generic_Keys."<", and how many times the functions are called, is unspecified.

115/2 {AI95-00302-03} In addition to the semantics described in A.18.7, the
subprograms in package Generic_Keys named Floor and Ceiling, are equivalent to
the corresponding subprograms in the parent package, with the difference that
the Key subprogram parameter is compared to elements in the container using
the Key and "<" generic formal functions. The function named Equivalent_Keys
in package Generic_Keys returns True if both Left < Right and Right < Left
return False using the generic formal "<" operator, and returns True otherwise.


                            Implementation Advice

116/2 {AI95-00302-03} If N is the length of a set, then the worst-case time
complexity of the Insert, Include, Replace, Delete, Exclude and Find
operations that take an element parameter should be O((log N)**2) or better.
The worst-case time complexity of the subprograms that take a cursor parameter
should be O(1).

116.a/2     Implementation Advice: The worst-case time complexity of the
            Insert, Include, Replace, Delete, Exclude and Find operations of
            Containers.Ordered_Sets that take an element parameter should be
            O((log N)**2). The worst-case time complexity of the subprograms
            of Containers.Ordered_Sets that take a cursor parameter should be
            O(1).

116.b/2     Implementation Note: {AI95-00302-03} See A.18.6, "
            The Generic Package Containers.Ordered_Maps" for implementation
            notes regarding some of the operations of this package.


                            Extensions to Ada 95

116.c/2     {AI95-00302-03} The generic package Containers.Ordered_Sets is
            new.


                       Incompatibilities With Ada 2005

116.d/3     {AI05-0001-1} Subprograms Assign and Copy are added to
            Containers.Ordered_Sets. If an instance of Containers.Ordered_Sets
            is referenced in a use_clause, and an entity E with the same
            defining_identifier as a new entity in Containers.Ordered_Sets is
            defined in a package that is also referenced in a use_clause, the
            entity E may no longer be use-visible, resulting in errors. This
            should be rare and is easily fixed if it does occur.


                           Extensions to Ada 2005

116.e/3     {AI05-0212-1} Added iterator and indexing support to make ordered
            set containers more convenient to use.


                        Wording Changes from Ada 2005

116.f/3     {AI05-0044-1} Correction: Added wording to require the formal
            function be such that equal elements are also equivalent.

116.g/3     {AI05-0044-1} Correction: Redefined "<" actuals to require a
            strict weak ordering; the old definition allowed indeterminant
            comparisons that would not have worked in a container.

116.h/3     {AI05-0084-1} Correction: Added a pragma Remote_Types so that
            containers can be used in distributed programs.


A.18.10 The Generic Package Containers.Multiway_Trees


1/3 {AI05-0136-1} The language-defined generic package
Containers.Multiway_Trees provides private types Tree and Cursor, and a set of
operations for each type. A multiway tree container is well-suited to
represent nested structures.

1.a/3       Discussion: {AI05-0136-1} This tree just provides a basic
            structure, and make no promises about balancing or other automatic
            organization. In this sense, it is different than the indexed
            (Map, Set) forms. Rather, it provides a building block on which to
            construct more complex and more specialized tree containers.

2/4 {AI05-0136-1} {AI12-0078-1} {AI12-0159-1} A multiway tree container object
manages a tree of nodes, consisting of a root node and a set of internal
nodes; each internal node contains an element and pointers to the parent,
first child, last child, next (successor) sibling, and previous (predecessor)
sibling internal nodes. A cursor designates a particular node within a tree
(and by extension the element contained in that node, if any). A cursor keeps
designating the same node (and element) as long as the node is part of the
container, even if the node is moved within the container.

3/4 {AI05-0136-1} {AI05-0269-1} {AI12-0078-1} A subtree is a particular node
(which roots the subtree) and all of its child nodes (including all of the
children of the child nodes, recursively). The root node is always present and
has neither an associated element value nor any parent node; it has pointers
to its first child and its last child, if any. The root node provides a place
to add nodes to an otherwise empty tree and represents the base of the tree.

4/3 {AI05-0136-1} {AI05-0269-1} A node that has no children is called a leaf
node. The ancestors of a node are the node itself, its parent node, the parent
of the parent node, and so on until a node with no parent is reached.
Similarly, the descendants of a node are the node itself, its child nodes, the
children of each child node, and so on.

5/3 {AI05-0136-1} {AI05-0262-1} {AI05-0269-1} The nodes of a subtree can be
visited in several different orders. For a depth-first order, after visiting a
node, the nodes of its child list are each visited in depth-first order, with
each child node visited in natural order (first child to last child).

5.a/3       Ramification: For the depth-first order, when each child node is
            visited, the child list of the child node is visited before the
            next sibling of the child node is visited.


                              Static Semantics

6/3 {AI05-0136-1} The generic library package Containers.Multiway_Trees has
the following declaration:

7/3     {AI05-0136-1} {AI05-0212-1} with Ada.Iterator_Interfaces;
        generic
           type Element_Type is private;
           with function "=" (Left, Right : Element_Type) return Boolean is <>;
        package Ada.Containers.Multiway_Trees is
           pragma Preelaborate(Multiway_Trees);
           pragma Remote_Types(Multiway_Trees);

8/3     {AI05-0136-1} {AI05-0212-1}    type Tree is tagged private
              with Constant_Indexing => Constant_Reference,
                   Variable_Indexing => Reference,
                   Default_Iterator  => Iterate,
                   Iterator_Element  => Element_Type;
           pragma Preelaborable_Initialization(Tree);

9/3        type Cursor is private;
           pragma Preelaborable_Initialization(Cursor);

10/3       Empty_Tree : constant Tree;

11/3       No_Element : constant Cursor;

12/3       function Has_Element (Position : Cursor) return Boolean;

13/3    {AI05-0212-1}    package Tree_Iterator_Interfaces is new
              Ada.Iterator_Interfaces (Cursor, Has_Element);

14/3       function Equal_Subtree (Left_Position : Cursor;
                                   Right_Position: Cursor) return Boolean;

15/3       function "=" (Left, Right : Tree) return Boolean;

16/3       function Is_Empty (Container : Tree) return Boolean;

17/3       function Node_Count (Container : Tree) return Count_Type;

18/3       function Subtree_Node_Count (Position : Cursor) return Count_Type;

19/3       function Depth (Position : Cursor) return Count_Type;

20/3       function Is_Root (Position : Cursor) return Boolean;

21/3       function Is_Leaf (Position : Cursor) return Boolean;

22/3       function Root (Container : Tree) return Cursor;

23/3       procedure Clear (Container : in out Tree);

24/3       function Element (Position : Cursor) return Element_Type;

25/3       procedure Replace_Element (Container : in out Tree;
                                      Position  : in     Cursor;
                                      New_Item  : in     Element_Type);

26/3       procedure Query_Element
             (Position : in Cursor;
              Process  : not null access procedure (Element : in Element_Type));

27/3       procedure Update_Element
             (Container : in out Tree;
              Position  : in     Cursor;
              Process   : not null access procedure
                              (Element : in out Element_Type));

28/3    {AI05-0212-1}    type Constant_Reference_Type
                 (Element : not null access constant Element_Type) is private
              with Implicit_Dereference => Element;

29/3    {AI05-0212-1}    type Reference_Type
         (Element : not null access Element_Type) is private
              with Implicit_Dereference => Element;

30/3    {AI05-0212-1}    function Constant_Reference
         (Container : aliased in Tree;
                                        Position  : in Cursor)
              return Constant_Reference_Type;

31/3    {AI05-0212-1}    function Reference (Container : aliased in out Tree;
                               Position  : in Cursor)
              return Reference_Type;

32/3       procedure Assign (Target : in out Tree; Source : in Tree);

33/3       function Copy (Source : Tree) return Tree;

34/3       procedure Move (Target : in out Tree;
                           Source : in out Tree);

35/3       procedure Delete_Leaf (Container : in out Tree;
                                  Position  : in out Cursor);

36/3       procedure Delete_Subtree (Container : in out Tree;
                                     Position  : in out Cursor);

37/3       procedure Swap (Container : in out Tree;
                           I, J      : in     Cursor);

38/3       function Find (Container : Tree;
                          Item      : Element_Type)
              return Cursor;

39/3    {AI05-0136-1} {AI05-0248-1}    function Find_In_Subtree
         (Position : Cursor;
                                     Item     : Element_Type)
              return Cursor;

40/3    {AI05-0136-1} {AI05-0248-1}    function Ancestor_Find
         (Position : Cursor;
                                   Item     : Element_Type)
              return Cursor;

41/3       function Contains (Container : Tree;
                              Item      : Element_Type) return Boolean;

42/3       procedure Iterate
             (Container : in Tree;
              Process   : not null access procedure (Position : in Cursor));

43/3       procedure Iterate_Subtree
             (Position  : in Cursor;
              Process   : not null access procedure (Position : in Cursor));

44/3    {AI05-0212-1}    function Iterate (Container : in Tree)
              return Tree_Iterator_Interfaces.Forward_Iterator'Class;

45/3    {AI05-0212-1}    function Iterate_Subtree (Position : in Cursor)
              return Tree_Iterator_Interfaces.Forward_Iterator'Class;

46/3       function Child_Count (Parent : Cursor) return Count_Type;

47/3       function Child_Depth (Parent, Child : Cursor) return Count_Type;

48/3       procedure Insert_Child (Container : in out Tree;
                                   Parent    : in     Cursor;
                                   Before    : in     Cursor;
                                   New_Item  : in     Element_Type;
                                   Count     : in     Count_Type := 1);

49/3       procedure Insert_Child (Container : in out Tree;
                                   Parent    : in     Cursor;
                                   Before    : in     Cursor;
                                   New_Item  : in     Element_Type;
                                   Position  :    out Cursor;
                                   Count     : in     Count_Type := 1);

50/3       procedure Insert_Child (Container : in out Tree;
                                   Parent    : in     Cursor;
                                   Before    : in     Cursor;
                                   Position  :    out Cursor;
                                   Count     : in     Count_Type := 1);

51/3       procedure Prepend_Child (Container : in out Tree;
                                    Parent    : in     Cursor;
                                    New_Item  : in     Element_Type;
                                    Count     : in     Count_Type := 1);

52/3       procedure Append_Child (Container : in out Tree;
                                   Parent    : in     Cursor;
                                   New_Item  : in     Element_Type;
                                   Count     : in     Count_Type := 1);

53/3       procedure Delete_Children (Container : in out Tree;
                                      Parent    : in     Cursor);

54/3       procedure Copy_Subtree (Target   : in out Tree;
                                   Parent   : in     Cursor;
                                   Before   : in     Cursor;
                                   Source   : in     Cursor);

55/3       procedure Splice_Subtree (Target   : in out Tree;
                                     Parent   : in     Cursor;
                                     Before   : in     Cursor;
                                     Source   : in out Tree;
                                     Position : in out Cursor);

56/3       procedure Splice_Subtree (Container: in out Tree;
                                     Parent   : in     Cursor;
                                     Before   : in     Cursor;
                                     Position : in     Cursor);

57/3       procedure Splice_Children (Target          : in out Tree;
                                      Target_Parent   : in     Cursor;
                                      Before          : in     Cursor;
                                      Source          : in out Tree;
                                      Source_Parent   : in     Cursor);

58/3       procedure Splice_Children (Container       : in out Tree;
                                      Target_Parent   : in     Cursor;
                                      Before          : in     Cursor;
                                      Source_Parent   : in     Cursor);

59/3       function Parent (Position : Cursor) return Cursor;

60/3       function First_Child (Parent : Cursor) return Cursor;

61/3       function First_Child_Element (Parent : Cursor) return Element_Type;

62/3       function Last_Child (Parent : Cursor) return Cursor;

63/3       function Last_Child_Element (Parent : Cursor) return Element_Type;

64/3       function Next_Sibling (Position : Cursor) return Cursor;

65/3       function Previous_Sibling (Position : Cursor) return Cursor;

66/3       procedure Next_Sibling (Position : in out Cursor);

67/3       procedure Previous_Sibling (Position : in out Cursor);

68/3    {AI05-0136-1} {AI05-0248-1}    procedure Iterate_Children
             (Parent  : in Cursor;
              Process : not null access procedure (Position : in Cursor));

69/3    {AI05-0136-1} {AI05-0248-1}    procedure Reverse_Iterate_Children
             (Parent  : in Cursor;
              Process : not null access procedure (Position : in Cursor));

70/3    {AI05-0212-1}    function Iterate_Children
         (Container : in Tree; Parent : in Cursor)
              return Tree_Iterator_Interfaces.Reversible_Iterator'Class;

71/3    private
           ... -- not specified by the language
        end Ada.Containers.Multiway_Trees;

72/3 {AI05-0136-1} The actual function for the generic formal function "=" on
Element_Type values is expected to define a reflexive and symmetric
relationship and return the same result value each time it is called with a
particular pair of values. If it behaves in some other manner, the functions
Find, Reverse_Find, Equal_Subtree, and "=" on tree values return an
unspecified value. The exact arguments and number of calls of this generic
formal function by the functions Find, Reverse_Find, Equal_Subtree, and "=" on
tree values are unspecified.

73/3 {AI05-0136-1} The type Tree is used to represent trees. The type Tree
needs finalization (see 7.6).

74/3 {AI05-0136-1} {AI05-0248-1} Empty_Tree represents the empty Tree object.
It contains only the root node (Node_Count (Empty_Tree) returns 1). If an
object of type Tree is not otherwise initialized, it is initialized to the
same value as Empty_Tree.

75/3 {AI05-0136-1} No_Element represents a cursor that designates no element.
If an object of type Cursor is not otherwise initialized, it is initialized to
the same value as No_Element.

76/3 {AI05-0136-1} The predefined "=" operator for type Cursor returns True if
both cursors are No_Element, or designate the same element in the same
container.

77/3 {AI05-0136-1} Execution of the default implementation of the Input,
Output, Read, or Write attribute of type Cursor raises Program_Error.

78/3 {AI05-0136-1} {AI05-0248-1} {AI05-0262-1} Tree'Write for a Tree object T
writes Node_Count(T) - 1 elements of the tree to the stream. It also may write
additional information about the tree.

79/3 {AI05-0136-1} {AI05-0248-1} {AI05-0262-1} Tree'Read reads the
representation of a tree from the stream, and assigns to Item a tree with the
same elements and structure as was written by Tree'Write.

79.a/3      Ramification: Streaming more elements than the container holds is
            wrong. For implementation implications of this rule, see the
            Implementation Note in A.18.2.

80/3 {AI05-0136-1} [Some operations of this generic package have
access-to-subprogram parameters. To ensure such operations are well-defined,
they guard against certain actions by the designated subprogram. In
particular, some operations check for "tampering with cursors" of a container
because they depend on the set of elements of the container remaining
constant, and others check for "tampering with elements" of a container
because they depend on elements of the container not being replaced.]

81/3 {AI05-0136-1} A subprogram is said to tamper with cursors of a tree
object T if:

82/3   * it inserts or deletes elements of T, that is, it calls the Clear,
        Delete_Leaf, Insert_Child, Delete_Children, Delete_Subtree, or
        Copy_Subtree procedures with T as a parameter; or

82.a/3      To be honest: Operations which are defined to be equivalent to a
            call on one of these operations also are included. Similarly,
            operations which call one of these as part of their definition are
            included.

83/3   * {AI05-0136-1} {AI05-0248-1} it reorders the elements of T, that is,
        it calls the Splice_Subtree or Splice_Children procedures with T as a
        parameter; or

84/3   * it finalizes T; or

85/3   * it calls Assign with T as the Target parameter; or

85.a.1/3    Ramification: We don't need to explicitly mention
            assignment_statement, because that finalizes the target object as
            part of the operation, and finalization of an object is already
            defined as tampering with cursors.

86/3   * it calls the Move procedure with T as a parameter.

86.a/3      Reason: Swap copies elements rather than reordering them, so it
            doesn't tamper with cursors.

87/3 {AI05-0136-1} A subprogram is said to tamper with elements of a tree
object T if:

88/3   * it tampers with cursors of T; or

89/3   * it replaces one or more elements of T, that is, it calls the
        Replace_Element or Swap procedures with T as a parameter.

89.a/3      Reason: Complete replacement of an element can cause its memory to
            be deallocated while another operation is holding onto a reference
            to it. That can't be allowed. However, a simple modification of
            (part of) an element is not a problem, so Update_Element does not
            cause a problem.

89.a.1/3    Ramification: Assign is defined in terms of Clear and
            Replace_Element, so we don't need to mention it explicitly.
            Similarly, we don't need to explicitly mention
            assignment_statement, because that finalizes the target object as
            part of the operation, and finalization of an object is already
            defined as tampering with the element.

90/4 {AI05-0265-1} {AI12-0110-1} When tampering with cursors is prohibited for
a particular tree object T, Program_Error is propagated by a call of any
language-defined subprogram that is defined to tamper with the cursors of T,
leaving T unmodified. Similarly, when tampering with elements is prohibited
for a particular tree object T, Program_Error is propagated by a call of any
language-defined subprogram that is defined to tamper with the elements of T
[(or tamper with the cursors of T)], leaving T unmodified. These checks are
made before any other defined behavior of the body of the language-defined
subprogram.

90.a/3      Proof: Tampering with elements includes tampering with cursors, so
            we mention it only from completeness in the second sentence.

91/3    function Has_Element (Position : Cursor) return Boolean;

92/3        Returns True if Position designates an element, and returns False
            otherwise. [In particular, Has_Element returns False if the cursor
            designates a root node or equals No_Element.]

92.a/3      To be honest: {AI05-0005-1} {AI05-0136-1} This function might not
            detect cursors that designate deleted elements; such cursors are
            invalid (see below) and the result of calling Has_Element with an
            invalid cursor is unspecified (but not erroneous).

93/3    function Equal_Subtree (Left_Position : Cursor;
                                Right_Position: Cursor) return Boolean;

94/3        {AI05-0136-1} {AI05-0248-1} {AI05-0262-1} {AI05-0264-1} If
            Left_Position or Right_Position equals No_Element, propagates
            Constraint_Error. If the number of child nodes of the element
            designated by Left_Position is different from the number of child
            nodes of the element designated by Right_Position, the function
            returns False. If Left_Position designates a root node and
            Right_Position does not, the function returns False. If
            Right_Position designates a root node and Left_Position does not,
            the function returns False. Unless both cursors designate a root
            node, the elements are compared using the generic formal equality
            operator. If the result of the element comparison is False, the
            function returns False. Otherwise, it calls Equal_Subtree on a
            cursor designating each child element of the element designated by
            Left_Position and a cursor designating the corresponding child
            element of the element designated by Right_Position. If any such
            call returns False, the function returns False; otherwise, it
            returns True. Any exception raised during the evaluation of
            element equality is propagated.

94.a/3      Ramification: Left_Position and Right_Position do not need to be
            from the same tree.

94.b/3      Implementation Note: This wording describes the canonical
            semantics. However, the order and number of calls on the formal
            equality function is unspecified for all of the operations that
            use it in this package, so an implementation can call it as many
            or as few times as it needs to get the correct answer. Similarly,
            a global rule (see the introduction of Annex A) says that
            language-defined routines are not affected by overriding of other
            language-defined routines. This means that no reasonable program
            can tell how many times Equal_Subtree is called, and thus an
            implementation can call it as many or as few times as it needs to
            get the correct answer. Specifically, there is no requirement to
            call the formal equality or Equal_Subtree additional times once
            the answer has been determined.

95/3    function "=" (Left, Right : Tree) return Boolean;

96/3        {AI05-0136-1} {AI05-0262-1} If Left and Right denote the same tree
            object, then the function returns True. Otherwise, it calls
            Equal_Subtree with cursors designating the root nodes of Left and
            Right; the result is returned. Any exception raised during the
            evaluation of Equal_Subtree is propagated.

96.a/3      Implementation Note: Similar considerations apply here as apply to
            Equal_Subtree. The actual number of calls performed is
            unspecified.

97/3    function Node_Count (Container : Tree) return Count_Type;

98/3        {AI05-0136-1} Node_Count returns the number of nodes in Container.

98.a/3      Ramification: Since all tree objects have a root node, this can
            never return a value of 0. Node_Count (Some_Tree) should always
            equal Subtree_Node_Count (Root (Some_Tree)).

99/3    function Subtree_Node_Count (Position : Cursor) return Count_Type;

100/3       {AI05-0136-1} {AI05-0248-1} If Position is No_Element,
            Subtree_Node_Count returns 0; otherwise, Subtree_Node_Count
            returns the number of nodes in the subtree that is rooted by
            Position.

101/3   function Is_Empty (Container : Tree) return Boolean;

102/3       {AI05-0136-1} Equivalent to Node_Count (Container) = 1.

102.a/3     Ramification: An empty tree contains just the root node.

103/3   function Depth (Position : Cursor) return Count_Type;

104/3       {AI05-0136-1} {AI05-0248-1} If Position equals No_Element, Depth
            returns 0; otherwise, Depth returns the number of ancestor nodes
            of the node designated by Position (including the node itself).

104.a/3     Ramification: Depth (Root (Some_Tree)) = 1.

105/3   function Is_Root (Position : Cursor) return Boolean;

106/3       {AI05-0136-1} {AI05-0248-1} Is_Root returns True if the Position
            designates the root node of some tree; and returns False otherwise.

107/3   function Is_Leaf (Position : Cursor) return Boolean;

108/3       {AI05-0136-1} Is_Leaf returns True if Position designates a node
            that does not have any child nodes; and returns False otherwise.

108.a/3     Ramification: Is_Leaf returns False if passed No_Element, since
            No_Element does not designate a node. Is_Leaf can be passed a
            cursor that designates the root node; Is_Leaf will return True if
            passed the root node of an empty tree.

109/3   function Root (Container : Tree) return Cursor;

110/3       {AI05-0136-1} Root returns a cursor that designates the root node
            of Container.

110.a/3     Ramification: There is always a root node, even in an empty
            container, so this function never returns No_Element.

111/3   procedure Clear (Container : in out Tree);

112/3       {AI05-0136-1} Removes all the elements from Container.

112.a/3     Ramification: The root node is not removed; all trees have a root
            node.

113/3   function Element (Position : Cursor) return Element_Type;

114/3       {AI05-0136-1} If Position equals No_Element, then Constraint_Error
            is propagated; if Position designates the root node of a tree,
            then Program_Error is propagated. Otherwise, Element returns the
            element designated by Position.

114.a/3     Ramification: The root node does not contain an element, so that
            value cannot be read or written.

115/3   procedure Replace_Element (Container : in out Tree;
                                   Position  : in     Cursor;
                                   New_Item  : in     Element_Type);

116/3       {AI05-0136-1} {AI05-0264-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container (including if it designates the root node),
            then Program_Error is propagated. Otherwise, Replace_Element
            assigns the value New_Item to the element designated by Position.

117/3   procedure Query_Element
          (Position : in Cursor;
           Process  : not null access procedure (Element : in Element_Type));

118/3       {AI05-0136-1} {AI05-0265-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position designates the root
            node of a tree, then Program_Error is propagated. Otherwise,
            Query_Element calls Process.all with the element designated by
            Position as the argument. Tampering with the elements of the tree
            that contains the element designated by Position is prohibited
            during the execution of the call on Process.all. Any exception
            raised by Process.all is propagated.

119/3   procedure Update_Element
          (Container : in out Tree;
           Position  : in     Cursor;
           Process   : not null access procedure
                           (Element : in out Element_Type));

120/3       {AI05-0136-1} {AI05-0264-1} {AI05-0265-1} If Position equals
            No_Element, then Constraint_Error is propagated; if Position does
            not designate an element in Container (including if it designates
            the root node), then Program_Error is propagated. Otherwise,
            Update_Element calls Process.all with the element designated by
            Position as the argument. Tampering with the elements of Container
            is prohibited during the execution of the call on Process.all. Any
            exception raised by Process.all is propagated.

121/3       If Element_Type is unconstrained and definite, then the actual
            Element parameter of Process.all shall be unconstrained.

121.a/3     Ramification: This means that the elements cannot be directly
            allocated from the heap; it must be possible to change the
            discriminants of the element in place.

122/3   type Constant_Reference_Type
              (Element : not null access constant Element_Type) is private
           with Implicit_Dereference => Element;

123/3   type Reference_Type (Element : not null access Element_Type) is private
           with Implicit_Dereference => Element;

124/3       {AI05-0212-1} The types Constant_Reference_Type and Reference_Type
            need finalization.

125/3       The default initialization of an object of type
            Constant_Reference_Type or Reference_Type propagates Program_Error.

125.a/3     Reason: It is expected that Reference_Type (and
            Constant_Reference_Type) will be a controlled type, for which
            finalization will have some action to terminate the tampering
            check for the associated container. If the object is created by
            default, however, there is no associated container. Since this is
            useless, and supporting this case would take extra work, we define
            it to raise an exception.

126/3   function Constant_Reference (Container : aliased in Tree;
                                     Position  : in Cursor)
           return Constant_Reference_Type;

127/3       {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Constant_Indexing and Implicit_Dereference aspects) provides a
            convenient way to gain read access to an individual element of a
            tree given a cursor.

128/3       {AI05-0212-1} {AI05-0265-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Constant_Reference returns an object whose discriminant is an
            access value that designates the element designated by Position.
            Tampering with the elements of Container is prohibited while the
            object returned by Constant_Reference exists and has not been
            finalized.

129/3   function Reference (Container : aliased in out Tree;
                            Position  : in Cursor)
           return Reference_Type;

130/3       {AI05-0212-1} {AI05-0269-1} This function (combined with the
            Variable_Indexing and Implicit_Dereference aspects) provides a
            convenient way to gain read and write access to an individual
            element of a tree given a cursor.

131/3       {AI05-0212-1} {AI05-0265-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container, then Program_Error is propagated. Otherwise,
            Reference returns an object whose discriminant is an access value
            that designates the element designated by Position. Tampering with
            the elements of Container is prohibited while the object returned
            by Reference exists and has not been finalized.

132/3   procedure Assign (Target : in out Tree; Source : in Tree);

133/3       {AI05-0136-1} {AI05-0248-1} If Target denotes the same object as
            Source, the operation has no effect. Otherwise, the elements of
            Source are copied to Target as for an assignment_statement
            assigning Source to Target.

133.a/3     Ramification: Each element in Target has a parent element that
            corresponds to the parent element of the Source element, and has
            child elements that correspond to the child elements of the Source
            element.

133.b/3     Discussion: {AI05-0005-1} This routine exists for compatibility
            with the bounded tree container. For an unbounded tree, Assign(A,
            B) and A := B behave identically. For a bounded tree, := will
            raise an exception if the container capacities are different,
            while Assign will not raise an exception if there is enough room
            in the target.

134/3   function Copy (Source : Tree) return Tree;

135/3       {AI05-0136-1} Returns a tree with the same structure as Source and
            whose elements are initialized from the corresponding elements of
            Source.

136/3   procedure Move (Target : in out Tree;
                        Source : in out Tree);

137/3       {AI05-0136-1} {AI05-0248-1} If Target denotes the same object as
            Source, then the operation has no effect. Otherwise, Move first
            calls Clear (Target). Then, the nodes other than the root node in
            Source are moved to Target (in the same positions). After Move
            completes, Node_Count (Target) is the number of nodes originally
            in Source, and Node_Count (Source) is 1.

138/3   procedure Delete_Leaf (Container : in out Tree;
                               Position  : in out Cursor);

139/3       {AI05-0136-1} {AI05-0248-1} If Position equals No_Element, then
            Constraint_Error is propagated; if Position does not designate an
            element in Container (including if it designates the root node),
            then Program_Error is propagated. If the element designated by
            position has any child elements, then Constraint_Error is
            propagated. Otherwise, Delete_Leaf removes (from Container) the
            element designated by Position. Finally, Position is set to
            No_Element.

139.a/3     Ramification: The check on Position checks that the cursor does
            not belong to some other Container. This check implies that a
            reference to the container is included in the cursor value. This
            wording is not meant to require detection of dangling cursors;
            such cursors are defined to be invalid, which means that execution
            is erroneous, and any result is allowed (including not raising an
            exception).

139.b/3     The root node cannot be deleted.

140/3   procedure Delete_Subtree (Container : in out Tree;
                                  Position  : in out Cursor);

141/3       {AI05-0136-1} {AI05-0264-1} {AI05-0269-1} If Position equals
            No_Element, then Constraint_Error is propagated. If Position does
            not designate an element in Container (including if it designates
            the root node), then Program_Error is propagated. Otherwise,
            Delete_Subtree removes (from Container) the subtree designated by
            Position (that is, all descendants of the node designated by
            Position including the node itself), and Position is set to
            No_Element.

141.a/3     Ramification: The root node cannot be deleted. To delete the
            entire contents of the tree, call Clear(Container).

142/3   procedure Swap (Container : in out Tree;
                        I, J      : in     Cursor);

143/3       {AI05-0136-1} If either I or J equals No_Element, then
            Constraint_Error is propagated. If either I or J do not designate
            an element in Container (including if either designates the root
            node), then Program_Error is propagated. Otherwise, Swap exchanges
            the values of the elements designated by I and J.

143.a/3     Ramification: After a call to Swap, I designates the element value
            previously designated by J, and J designates the element value
            previously designated by I. The position of the elements do not
            change; for instance, the parent node and the first child node of
            I are unchanged by the operation.

143.b/3     The root nodes do not contain element values, so they cannot be
            swapped.

143.c/3     To be honest: The implementation is not required to actually copy
            the elements if it can do the swap some other way. But it is
            allowed to copy the elements if needed.

144/3   function Find (Container : Tree;
                       Item      : Element_Type)
           return Cursor;

145/3       {AI05-0136-1} {AI05-0262-1} Find searches the elements of
            Container for an element equal to Item (using the generic formal
            equality operator). The search starts at the root node. The search
            traverses the tree in a depth-first order. If no equal element is
            found, then Find returns No_Element. Otherwise, it returns a
            cursor designating the first equal element encountered.

146/3   function Find_In_Subtree (Position : Cursor;
                                  Item     : Element_Type)
           return Cursor;

147/3       {AI05-0136-1} {AI05-0248-1} {AI05-0262-1} If Position equals
            No_Element, then Constraint_Error is propagated. Find_In_Subtree
            searches the subtree rooted by Position for an element equal to
            Item (using the generic formal equality operator). The search
            starts at the element designated by Position. The search traverses
            the subtree in a depth-first order. If no equal element is found,
            then Find returns No_Element. Otherwise, it returns a cursor
            designating the first equal element encountered.

147.a/3     Ramification: Find_In_Subtree does not check any siblings of the
            element designated by Position. The root node does not contain an
            element, and therefore it can never be returned, but it can be
            explicitly passed to Position.

148/3   function Ancestor_Find (Position : Cursor;
                                Item     : Element_Type)
           return Cursor;

149/3       {AI05-0136-1} {AI05-0248-1} If Position equals No_Element, then
            Constraint_Error is propagated. Otherwise, Ancestor_Find searches
            for an element equal to Item (using the generic formal equality
            operator). The search starts at the node designated by Position,
            and checks each ancestor proceeding toward the root of the
            subtree. If no equal element is found, then Ancestor_Find returns
            No_Element. Otherwise, it returns a cursor designating the first
            equal element encountered.

149.a/3     Ramification: {AI05-0248-1} No_Element is returned if Position is
            the root node.

150/3   function Contains (Container : Tree;
                           Item      : Element_Type) return Boolean;

151/3       {AI05-0136-1} Equivalent to Find (Container, Item) /= No_Element.

152/3   procedure Iterate
          (Container : in Tree;
           Process   : not null access procedure (Position : in Cursor));

153/4       {AI05-0136-1} {AI05-0265-1} {AI12-0069-1} Iterate calls
            Process.all with a cursor that designates each element in
            Container, starting from the root node and proceeding in a
            depth-first order. Tampering with the cursors of Container is
            prohibited during the execution of a call on Process.all. Any
            exception raised by Process.all is propagated.

153.a/3     Ramification: Process is not called with the root node, which does
            not have an associated element.

153.b/3     Implementation Note: The purpose of the tamper with cursors check
            is to prevent erroneous execution from the Position parameter of
            Process.all becoming invalid. This check takes place when the
            operations that tamper with the cursors of the container are
            called. The check cannot be made later (say in the body of
            Iterate), because that could cause the Position cursor to be
            invalid and potentially cause execution to become erroneous -
            defeating the purpose of the check.

153.c/3     See Iterate for vectors (A.18.2) for a suggested implementation of
            the check.

154/3   procedure Iterate_Subtree
          (Position  : in Cursor;
           Process   : not null access procedure (Position : in Cursor));

155/4       {AI05-0136-1} {AI05-0265-1} {AI12-0069-1} If Position equals
            No_Element, then Constraint_Error is propagated. Otherwise,
            Iterate_Subtree calls Process.all with a cursor that designates
            each element in the subtree rooted by the node designated by
            Position, starting from the node designated by Position and
            proceeding in a depth-first order. Tampering with the cursors of
            the tree that contains the element designated by Position is
            prohibited during the execution of a call on Process.all. Any
            exception raised by Process.all is propagated.

155.a/3     Ramification: Position can be passed a cursor designating the root
            node; in that case, Process is not called with the root node,
            which does not have an associated element.

156/3   function Iterate (Container : in Tree)
           return Tree_Iterator_Interfaces.Forward_Iterator'Class;

157/4       {AI05-0212-1} {AI05-0265-1} {AI05-0269-1} {AI12-0069-1} Iterate
            returns an iterator object (see 5.5.1) that will generate a value
            for a loop parameter (see 5.5.2) designating each element in
            Container, starting from the root node and proceeding in a
            depth-first order. Tampering with the cursors of Container is
            prohibited while the iterator object exists (in particular, in the
            sequence_of_statements of the loop_statement whose
            iterator_specification denotes this object). The iterator object
            needs finalization.

157.a/3     Discussion: Exits are allowed from the loops created using the
            iterator objects. In particular, to stop the iteration at a
            particular cursor, just add

157.b/3         exit when Cur = Stop;

157.c/3     in the body of the loop (assuming that Cur is the loop parameter
            and Stop is the cursor that you want to stop at).

158/3   function Iterate_Subtree (Position : in Cursor)
           return Tree_Iterator_Interfaces.Forward_Iterator'Class;

159/4       {AI05-0212-1} {AI05-0265-1} {AI05-0269-1} {AI12-0069-1} If
            Position equals No_Element, then Constraint_Error is propagated.
            Otherwise, Iterate_Subtree returns an iterator object (see 5.5.1)
            that will generate a value for a loop parameter (see 5.5.2)
            designating each element in the subtree rooted by the node
            designated by Position, starting from the node designated by
            Position and proceeding in a depth-first order. If Position equals
            No_Element, then Constraint_Error is propagated. Tampering with
            the cursors of the container that contains the node designated by
            Position is prohibited while the iterator object exists (in
            particular, in the sequence_of_statements of the loop_statement
            whose iterator_specification denotes this object). The iterator
            object needs finalization.

160/3   function Child_Count (Parent : Cursor) return Count_Type;

161/3       {AI05-0136-1} Child_Count returns the number of child nodes of the
            node designated by Parent.

162/3   function Child_Depth (Parent, Child : Cursor) return Count_Type;

163/3       {AI05-0136-1} {AI05-0262-1} If Child or Parent is equal to
            No_Element, then Constraint_Error is propagated. Otherwise,
            Child_Depth returns the number of ancestor nodes of Child
            (including Child itself), up to but not including Parent;
            Program_Error is propagated if Parent is not an ancestor of Child.

163.a/3     Ramification: Program_Error is propagated if Parent and Child are
            nodes in different containers.

163.b/3     Child_Depth (Root (Some_Tree), Child) + 1 = Depth (Child) as the
            root is not counted.

164/3   procedure Insert_Child (Container : in out Tree;
                                Parent    : in     Cursor;
                                Before    : in     Cursor;
                                New_Item  : in     Element_Type;
                                Count     : in     Count_Type := 1);

165/3       {AI05-0136-1} {AI05-0248-1} {AI05-0262-1} If Parent equals
            No_Element, then Constraint_Error is propagated. If Parent does
            not designate a node in Container, then Program_Error is
            propagated. If Before is not equal to No_Element, and does not
            designate a node in Container, then Program_Error is propagated.
            If Before is not equal to No_Element, and Parent does not
            designate the parent node of the node designated by Before, then
            Constraint_Error is propagated. Otherwise, Insert_Child allocates
            Count nodes containing copies of New_Item and inserts them as
            children of Parent. If Parent already has child nodes, then the
            new nodes are inserted prior to the node designated by Before, or,
            if Before equals No_Element, the new nodes are inserted after the
            last existing child node of Parent. Any exception raised during
            allocation of internal storage is propagated, and Container is not
            modified.

166/3   procedure Insert_Child (Container : in out Tree;
                                Parent    : in     Cursor;
                                Before    : in     Cursor;
                                New_Item  : in     Element_Type;
                                Position  :    out Cursor;
                                Count     : in     Count_Type := 1);

167/3       {AI05-0136-1} {AI05-0248-1} {AI05-0257-1} {AI05-0262-1} If Parent
            equals No_Element, then Constraint_Error is propagated. If Parent
            does not designate a node in Container, then Program_Error is
            propagated. If Before is not equal to No_Element, and does not
            designate a node in Container, then Program_Error is propagated.
            If Before is not equal to No_Element, and Parent does not
            designate the parent node of the node designated by Before, then
            Constraint_Error is propagated. Otherwise, Insert_Child allocates
            Count nodes containing copies of New_Item and inserts them as
            children of Parent. If Parent already has child nodes, then the
            new nodes are inserted prior to the node designated by Before, or,
            if Before equals No_Element, the new nodes are inserted after the
            last existing child node of Parent. Position designates the first
            newly-inserted node, or if Count equals 0, then Position is
            assigned the value of Before. Any exception raised during
            allocation of internal storage is propagated, and Container is not
            modified.

168/3   procedure Insert_Child (Container : in out Tree;
                                Parent    : in     Cursor;
                                Before    : in     Cursor;
                                Position  :    out Cursor;
                                Count     : in     Count_Type := 1);

169/3       {AI05-0136-1} {AI05-0257-1} {AI05-0262-1} {AI05-0264-1} If Parent
            equals No_Element, then Constraint_Error is propagated. If Parent
            does not designate a node in Container, then Program_Error is
            propagated. If Before is not equal to No_Element, and does not
            designate a node in Container, then Program_Error is propagated.
            If Before is not equal to No_Element, and Parent does not
            designate the parent node of the node designated by Before, then
            Constraint_Error is propagated. Otherwise, Insert_Child allocates
            Count nodes, the elements contained in the new nodes are
            initialized by default (see 3.3.1), and the new nodes are inserted
            as children of Parent. If Parent already has child nodes, then the
            new nodes are inserted prior to the node designated by Before, or,
            if Before equals No_Element, the new nodes are inserted after the
            last existing child node of Parent. Position designates the first
            newly-inserted node, or if Count equals 0, then Position is
            assigned the value of Before. Any exception raised during
            allocation of internal storage is propagated, and Container is not
            modified.

170/3   procedure Prepend_Child (Container : in out Tree;
                                 Parent    : in     Cursor;
                                 New_Item  : in     Element_Type;
                                 Count     : in     Count_Type := 1);

171/3       {AI05-0136-1} Equivalent to Insert_Child (Container, Parent,
            First_Child (Container, Parent), New_Item, Count).

172/3   procedure Append_Child (Container : in out Tree;
                                Parent    : in     Cursor;
                                New_Item  : in     Element_Type;
                                Count     : in     Count_Type := 1);

173/3       {AI05-0136-1} {AI05-0269-1} Equivalent to Insert_Child (Container,
            Parent, No_Element, New_Item, Count).

174/3   procedure Delete_Children (Container : in out Tree;
                                   Parent    : in     Cursor);

175/3       {AI05-0136-1} If Parent equals No_Element, then Constraint_Error
            is propagated. If Parent does not designate a node in Container,
            Program_Error is propagated. Otherwise, Delete_Children removes
            (from Container) all of the descendants of Parent other than
            Parent itself.

175.a/3     Discussion: This routine deletes all of the child subtrees of
            Parent at once. Use Delete_Subtree to delete an individual
            subtree.

176/3   procedure Copy_Subtree (Target   : in out Tree;
                                Parent   : in     Cursor;
                                Before   : in     Cursor;
                                Source   : in     Cursor);

177/3       {AI05-0136-1} {AI05-0248-1} {AI05-0262-1} If Parent equals
            No_Element, then Constraint_Error is propagated. If Parent does
            not designate a node in Target, then Program_Error is propagated.
            If Before is not equal to No_Element, and does not designate a
            node in Target, then Program_Error is propagated. If Before is not
            equal to No_Element, and Parent does not designate the parent node
            of the node designated by Before, then Constraint_Error is
            propagated. If Source designates a root node, then
            Constraint_Error is propagated. If Source is equal to No_Element,
            then the operation has no effect. Otherwise, the subtree rooted by
            Source (which can be from any tree; it does not have to be a
            subtree of Target) is copied (new nodes are allocated to create a
            new subtree with the same structure as the Source subtree, with
            each element initialized from the corresponding element of the
            Source subtree) and inserted into Target as a child of Parent. If
            Parent already has child nodes, then the new nodes are inserted
            prior to the node designated by Before, or, if Before equals
            No_Element, the new nodes are inserted after the last existing
            child node of Parent. The parent of the newly created subtree is
            set to Parent, and the overall count of Target is incremented by
            Subtree_Node_Count (Source). Any exception raised during
            allocation of internal storage is propagated, and Container is not
            modified.

177.a/3     Discussion: We only need one routine here, as the source object is
            not modified, so we can use the same routine for both copying
            within and between containers.

177.b/3     Ramification: We do not allow copying a subtree that includes a
            root node, as that would require inserting a node with no value in
            the middle of the target tree. To copy an entire tree to another
            tree object, use Copy.

178/3   procedure Splice_Subtree (Target   : in out Tree;
                                  Parent   : in     Cursor;
                                  Before   : in     Cursor;
                                  Source   : in out Tree;
                                  Position : in out Cursor);

179/3       {AI05-0136-1} {AI05-0248-1} {AI05-0262-1} {AI05-0269-1} If Parent
            equals No_Element, then Constraint_Error is propagated. If Parent
            does not designate a node in Target, then Program_Error is
            propagated. If Before is not equal to No_Element, and does not
            designate a node in Target, then Program_Error is propagated. If
            Before is not equal to No_Element, and Parent does not designate
            the parent node of the node designated by Before, then
            Constraint_Error is propagated. If Position equals No_Element,
            Constraint_Error is propagated. If Position does not designate a
            node in Source or designates a root node, then Program_Error is
            propagated. If Source denotes the same object as Target, then: if
            Position equals Before there is no effect; if Position designates
            an ancestor of Parent (including Parent itself), Constraint_Error
            is propagated; otherwise, the subtree rooted by the element
            designated by Position is moved to be a child of Parent. If Parent
            already has child nodes, then the moved nodes are inserted prior
            to the node designated by Before, or, if Before equals No_Element,
            the moved nodes are inserted after the last existing child node of
            Parent. In each of these cases, Position and the count of Target
            are unchanged, and the parent of the element designated by
            Position is set to Parent.

179.a/3     Reason: We can't allow moving the subtree of Position to a proper
            descendant node of the subtree, as the descendant node will be
            part of the subtree being moved. The result would be a circularly
            linked tree, or one with inaccessible nodes. Thus we have to check
            Position against Parent, even though such a check is
            O(Depth(Source)).

180/3       {AI05-0136-1} {AI05-0248-1} Otherwise (if Source does not denote
            the same object as Target), the subtree designated by Position is
            removed from Source and moved to Target. The subtree is inserted
            as a child of Parent. If Parent already has child nodes, then the
            moved nodes are inserted prior to the node designated by Before,
            or, if Before equals No_Element, the moved nodes are inserted
            after the last existing child node of Parent. In each of these
            cases, the count of Target is incremented by Subtree_Node_Count
            (Position), and the count of Source is decremented by
            Subtree_Node_Count (Position), Position is updated to represent an
            element in Target.

180.a/3     Ramification: If Source is the same as Target, and Position =
            Before, or Next_Sibling(Position) = Before, Splice_Subtree has no
            effect, as the subtree does not have to move to meet the
            postcondition.

180.b/3     We do not allow splicing a subtree that includes a root node, as
            that would require inserting a node with no value in the middle of
            the target tree. Splice the children of the root node instead.

180.c/3     For this reason there is no operation to splice an entire tree, as
            that would necessarily involve splicing a root node.

181/3   procedure Splice_Subtree (Container: in out Tree;
                                  Parent   : in     Cursor;
                                  Before   : in     Cursor;
                                  Position : in     Cursor);

182/3       {AI05-0136-1} {AI05-0248-1} {AI05-0262-1} {AI05-0269-1} If Parent
            equals No_Element, then Constraint_Error is propagated. If Parent
            does not designate a node in Container, then Program_Error is
            propagated. If Before is not equal to No_Element, and does not
            designate a node in Container, then Program_Error is propagated.
            If Before is not equal to No_Element, and Parent does not
            designate the parent node of the node designated by Before, then
            Constraint_Error is propagated. If Position equals No_Element,
            Constraint_Error is propagated. If Position does not designate a
            node in Container or designates a root node, then Program_Error is
            propagated. If Position equals Before, there is no effect. If
            Position designates an ancestor of Parent (including Parent
            itself), Constraint_Error is propagated. Otherwise, the subtree
            rooted by the element designated by Position is moved to be a
            child of Parent. If Parent already has child nodes, then the moved
            nodes are inserted prior to the node designated by Before, or, if
            Before equals No_Element, the moved nodes are inserted after the
            last existing child node of Parent. The parent of the element
            designated by Position is set to Parent.

182.a/3     Reason: We can't allow moving the subtree of Position to a proper
            descendant node of the subtree, as the descendant node will be
            part of the subtree being moved.

183/3   procedure Splice_Children (Target          : in out Tree;
                                   Target_Parent   : in     Cursor;
                                   Before          : in     Cursor;
                                   Source          : in out Tree;
                                   Source_Parent   : in     Cursor);

184/3       {AI05-0136-1} {AI05-0262-1} If Target_Parent equals No_Element,
            then Constraint_Error is propagated. If Target_Parent does not
            designate a node in Target, then Program_Error is propagated. If
            Before is not equal to No_Element, and does not designate an
            element in Target, then Program_Error is propagated. If
            Source_Parent equals No_Element, then Constraint_Error is
            propagated. If Source_Parent does not designate a node in Source,
            then Program_Error is propagated. If Before is not equal to
            No_Element, and Target_Parent does not designate the parent node
            of the node designated by Before, then Constraint_Error is
            propagated.

185/3       If Source denotes the same object as Target, then:

186/3         * if Target_Parent equals Source_Parent there is no effect; else

187/3         * {AI05-0136-1} {AI05-0269-1} if Source_Parent is an ancestor of
                Target_Parent other than Target_Parent itself, then
                Constraint_Error is propagated; else

188/3         * {AI05-0136-1} {AI05-0248-1} {AI05-0269-1} the child elements
                (and the further descendants) of Source_Parent are moved to be
                child elements of Target_Parent. If Target_Parent already has
                child elements, then the moved elements are inserted prior to
                the node designated by Before, or, if Before equals
                No_Element, the moved elements are inserted after the last
                existing child node of Target_Parent. The parent of each moved
                child element is set to Target_Parent.

188.a/3     Reason: We can't allow moving the children of Source_Parent to a
            proper descendant node, as the descendant node will be part of one
            of the subtrees being moved.

189/3       {AI05-0136-1} {AI05-0248-1} {AI05-0269-1} Otherwise (if Source
            does not denote the same object as Target), the child elements
            (and the further descendants) of Source_Parent are removed from
            Source and moved to Target. The child elements are inserted as
            children of Target_Parent. If Target_Parent already has child
            elements, then the moved elements are inserted prior to the node
            designated by Before, or, if Before equals No_Element, the moved
            elements are inserted after the last existing child node of
            Target_Parent. In each of these cases, the overall count of Target
            is incremented by Subtree_Node_Count (Source_Parent)-1, and the
            overall count of Source is decremented by Subtree_Node_Count
            (Source_Parent)-1.

189.a/3     Ramification: The node designated by Source_Parent is not moved,
            thus we never need to update Source_Parent.

189.b/3     Move (Target, Source) could be written Splice_Children (Target,
            Target.Root, No_Element, Source, Source.Root);

190/3   procedure Splice_Children (Container       : in out Tree;
                                   Target_Parent   : in     Cursor;
                                   Before          : in     Cursor;
                                   Source_Parent   : in     Cursor);

191/3       {AI05-0136-1} {AI05-0248-1} {AI05-0262-1} {AI05-0264-1}
            {AI05-0269-1} If Target_Parent equals No_Element, then
            Constraint_Error is propagated. If Target_Parent does not
            designate a node in Container, then Program_Error is propagated.
            If Before is not equal to No_Element, and does not designate an
            element in Container, then Program_Error is propagated. If
            Source_Parent equals No_Element, then Constraint_Error is
            propagated. If Source_Parent does not designate a node in
            Container, then Program_Error is propagated. If Before is not
            equal to No_Element, and Target_Parent does not designate the
            parent node of the node designated by Before, then
            Constraint_Error is propagated. If Target_Parent equals
            Source_Parent there is no effect. If Source_Parent is an ancestor
            of Target_Parent other than Target_Parent itself, then
            Constraint_Error is propagated. Otherwise, the child elements (and
            the further descendants) of Source_Parent are moved to be child
            elements of Target_Parent. If Target_Parent already has child
            elements, then the moved elements are inserted prior to the node
            designated by Before, or, if Before equals No_Element, the moved
            elements are inserted after the last existing child node of
            Target_Parent. The parent of each moved child element is set to
            Target_Parent.

192/3   function Parent (Position : Cursor) return Cursor;

193/3       {AI05-0136-1} If Position is equal to No_Element or designates a
            root node, No_Element is returned. Otherwise, a cursor designating
            the parent node of the node designated by Position is returned.

194/3   function First_Child (Parent : Cursor) return Cursor;

195/3       {AI05-0136-1} If Parent is equal to No_Element, then
            Constraint_Error is propagated. Otherwise, First_Child returns a
            cursor designating the first child node of the node designated by
            Parent; if there is no such node, No_Element is returned.

196/3   function First_Child_Element (Parent : Cursor) return Element_Type;

197/3       {AI05-0136-1} Equivalent to Element (First_Child (Parent)).

198/3   function Last_Child (Parent : Cursor) return Cursor;

199/3       {AI05-0136-1} If Parent is equal to No_Element, then
            Constraint_Error is propagated. Otherwise, Last_Child returns a
            cursor designating the last child node of the node designated by
            Parent; if there is no such node, No_Element is returned.

200/3   function Last_Child_Element (Parent : Cursor) return Element_Type;

201/3       {AI05-0136-1} Equivalent to Element (Last_Child (Parent)).

202/3   function Next_Sibling (Position : Cursor) return Cursor;

203/3       {AI05-0136-1} If Position equals No_Element or designates the last
            child node of its parent, then Next_Sibling returns the value
            No_Element. Otherwise, it returns a cursor that designates the
            successor (with the same parent) of the node designated by
            Position.

204/3   function Previous_Sibling (Position : Cursor) return Cursor;

205/3       {AI05-0136-1} If Position equals No_Element or designates the
            first child node of its parent, then Previous_Sibling returns the
            value No_Element. Otherwise, it returns a cursor that designates
            the predecessor (with the same parent) of the node designated by
            Position.

206/3   procedure Next_Sibling (Position : in out Cursor);

207/3       {AI05-0136-1} Equivalent to Position := Next_Sibling (Position);

208/3   procedure Previous_Sibling (Position : in out Cursor);

209/3       {AI05-0136-1} Equivalent to Position := Previous_Sibling
            (Position);

210/3   procedure Iterate_Children
          (Parent  : in Cursor;
           Process : not null access procedure (Position : in Cursor));

211/3       {AI05-0136-1} {AI05-0248-1} If Parent equals No_Element, then
            Constraint_Error is propagated.

212/3       Iterate_Children calls Process.all with a cursor that designates
            each child node of Parent, starting with the first child node and
            moving the cursor as per the Next_Sibling function.

213/3       {AI05-0265-1} Tampering with the cursors of the tree containing
            Parent is prohibited during the execution of a call on
            Process.all. Any exception raised by Process.all is propagated.

214/3   procedure Reverse_Iterate_Children
          (Parent  : in Cursor;
           Process : not null access procedure (Position : in Cursor));

215/3       {AI05-0136-1} {AI05-0248-1} If Parent equals No_Element, then
            Constraint_Error is propagated.

216/3       Reverse_Iterate_Children calls Process.all with a cursor that
            designates each child node of Parent, starting with the last child
            node and moving the cursor as per the Previous_Sibling function.

217/3       {AI05-0265-1} Tampering with the cursors of the tree containing
            Parent is prohibited during the execution of a call on
            Process.all. Any exception raised by Process.all is propagated.

218/3   function Iterate_Children (Container : in Tree; Parent : in Cursor)
           return Tree_Iterator_Interfaces.Reversible_Iterator'Class;

219/3       {AI05-0212-1} {AI05-0265-1} Iterate_Children returns a reversible
            iterator object (see 5.5.1) that will generate a value for a loop
            parameter (see 5.5.2) designating each child node of Parent. If
            Parent equals No_Element, then Constraint_Error is propagated. If
            Parent does not designate a node in Container, then Program_Error
            is propagated. Otherwise, when used as a forward iterator, the
            nodes are designated starting with the first child node and moving
            the cursor as per the function Next_Sibling; when used as a
            reverse iterator, the nodes are designated starting with the last
            child node and moving the cursor as per the function
            Previous_Sibling. Tampering with the cursors of Container is
            prohibited while the iterator object exists (in particular, in the
            sequence_of_statements of the loop_statement whose
            iterator_specification denotes this object). The iterator object
            needs finalization.


                          Bounded (Run-Time) Errors

220/3 {AI05-0136-1} {AI05-0248-1} It is a bounded error for the actual
function associated with a generic formal subprogram, when called as part of
an operation of this package, to tamper with elements of any Tree parameter of
the operation. Either Program_Error is raised, or the operation works as
defined on the value of the Tree either prior to, or subsequent to, some or
all of the modifications to the Tree.

221/3 {AI05-0136-1} It is a bounded error to call any subprogram declared in
the visible part of Containers.Multiway_Trees when the associated container
has been finalized. If the operation takes Container as an in out parameter,
then it raises Constraint_Error or Program_Error. Otherwise, the operation
either proceeds as it would for an empty container, or it raises
Constraint_Error or Program_Error.


                             Erroneous Execution

222/3 {AI05-0136-1} A Cursor value is invalid if any of the following have
occurred since it was created:

223/3   * The tree that contains the element it designates has been finalized;

224/3   * The tree that contains the element it designates has been used as
        the Source or Target of a call to Move;

225/3   * The tree that contains the element it designates has been used as
        the Target of a call to Assign or the target of an
        assignment_statement;

226/3   * The element it designates has been removed from the tree that
        previously contained the element.

226.a/3     Reason: We talk about which tree the element was removed from in
            order to handle splicing nodes from one tree to another. The node
            still exists, but any cursors that designate it in the original
            tree are now invalid. This bullet covers removals caused by calls
            to Clear, Delete_Leaf, Delete_Subtree, Delete_Children,
            Splice_Children, and Splice_Subtree.

227/3 The result of "=" or Has_Element is unspecified if it is called with an
invalid cursor parameter. Execution is erroneous if any other subprogram
declared in Containers.Multiway_Trees is called with an invalid cursor
parameter.

227.a/3     Discussion: The list above is intended to be exhaustive. In other
            cases, a cursor value continues to designate its original element
            (or the root node). For instance, cursor values survive the
            insertion and deletion of other nodes.

227.b/3     While it is possible to check for these cases, in many cases the
            overhead necessary to make the check is substantial in time or
            space. Implementations are encouraged to check for as many of
            these cases as possible and raise Program_Error if detected.

228/3 {AI05-0212-1} Execution is erroneous if the tree associated with the
result of a call to Reference or Constant_Reference is finalized before the
result object returned by the call to Reference or Constant_Reference is
finalized.

228.a/3     Reason: Each object of Reference_Type and Constant_Reference_Type
            probably contains some reference to the originating container. If
            that container is prematurely finalized (which is only possible
            via Unchecked_Deallocation, as accessibility checks prevent
            passing a container to Reference that will not live as long as the
            result), the finalization of the object of Reference_Type will try
            to access a nonexistent object. This is a normal case of a
            dangling pointer created by Unchecked_Deallocation; we have to
            explicitly mention it here as the pointer in question is not
            visible in the specification of the type. (This is the same reason
            we have to say this for invalid cursors.)


                         Implementation Requirements

229/3 {AI05-0136-1} No storage associated with a multiway tree object shall be
lost upon assignment or scope exit.

230/3 {AI05-0136-1} {AI05-0262-1} The execution of an assignment_statement for
a tree shall have the effect of copying the elements from the source tree
object to the target tree object and changing the node count of the target
object to that of the source object.

230.a/3     Implementation Note: {AI05-0298-1} An assignment of a Tree is a
            "deep" copy; that is the elements are copied as well the data
            structures. We say "effect of" in order to allow the
            implementation to avoid copying elements immediately if it wishes.
            For instance, an implementation that avoided copying until one of
            the containers is modified would be allowed. (Note that this
            implementation would require care, see A.18.2 for more.)


                            Implementation Advice

231/3 {AI05-0136-1} Containers.Multiway_Trees should be implemented similarly
to a multiway tree. In particular, if N is the overall number of nodes for a
particular tree, then the worst-case time complexity of Element, Parent,
First_Child, Last_Child, Next_Sibling, Previous_Sibling, Insert_Child with
Count=1, and Delete should be O(log N).

231.a/3     Implementation Advice: The worst-case time complexity of the
            Element, Parent, First_Child, Last_Child, Next_Sibling,
            Previous_Sibling, Insert_Child with Count=1, and Delete operations
            of Containers.Multiway_Trees should be O(log N).

231.b/3     Reason: We do not mean to overly constrain implementation
            strategies here. However, it is important for portability that the
            performance of large containers has roughly the same factors on
            different implementations. If a program is moved to an
            implementation that takes O(N) time to access elements, that
            program could be unusable when the trees are large. We allow O(log
            N) access because the proportionality constant and caching effects
            are likely to be larger than the log factor, and we don't want to
            discourage innovative implementations.

232/3 {AI05-0136-1} Move should not copy elements, and should minimize copying
of internal data structures.

232.a/3     Implementation Advice: Containers.Multiway_Trees.Move should not
            copy elements, and should minimize copying of internal data
            structures.

232.b/3     Implementation Note: Usually that can be accomplished simply by
            moving the pointer(s) to the internal data structures from the
            Source container to the Target container.

233/3 {AI05-0136-1} If an exception is propagated from a tree operation, no
storage should be lost, nor any elements removed from a tree unless specified
by the operation.

233.a/3     Implementation Advice: If an exception is propagated from a tree
            operation, no storage should be lost, nor any elements removed
            from a tree unless specified by the operation.

233.b/3     Reason: This is important so that programs can recover from
            errors. But we don't want to require heroic efforts, so we just
            require documentation of cases where this can't be accomplished.


                           Extensions to Ada 2005

233.c/3     {AI05-0136-1} {AI05-0257-1} {AI05-0265-1} {AI05-0269-1} The
            generic package Containers.Multiway_Trees is new.


                        Wording Changes from Ada 2012

233.d/4     {AI12-0069-1} Corrigendum: Fixed the function Iterate so it is
            clear that the root node is never visited.

233.e/4     {AI12-0078-1} Corrigendum: The definition of node is clarified so
            that it it doesn't appear to say all nodes have an element.

233.f/4     {AI12-0110-1} Corrigendum: Clarified that tampering checks precede
            all other checks made by a subprogram (but come after those
            associated with the call).


A.18.11 The Generic Package Containers.Indefinite_Vectors


1/2 {AI95-00302-03} The language-defined generic package
Containers.Indefinite_Vectors provides a private type Vector and a set of
operations. It provides the same operations as the package Containers.Vectors
(see A.18.2), with the difference that the generic formal Element_Type is
indefinite.


                              Static Semantics

2/3 {AI95-00302-03} {AI05-0092-1} The declaration of the generic library
package Containers.Indefinite_Vectors has the same contents and semantics as
Containers.Vectors except:

3/2   * The generic formal Element_Type is indefinite.

4/2   * The procedures with the profiles:

5/2     procedure Insert (Container : in out Vector;
                          Before    : in     Extended_Index;
                          Count     : in     Count_Type := 1);

6/2     procedure Insert (Container : in out Vector;
                          Before    : in     Cursor;
                          Position  :    out Cursor;
                          Count     : in     Count_Type := 1);

7/2     are omitted.

7.a/2       Discussion: These procedures are omitted because there is no way
            to create a default-initialized object of an indefinite type. Note
            that Insert_Space can be used instead of this routine in most
            cases. Omitting the routine completely allows any problems to be
            diagnosed by the compiler when converting from a definite to
            indefinite vector.

8/2   * The actual Element parameter of access subprogram Process of
        Update_Element may be constrained even if Element_Type is
        unconstrained.

9/4   * {AI12-0035-1} The operations "&", Append, Insert, Prepend,
        Replace_Element, and To_Vector that have a formal parameter of type
        Element_Type perform indefinite insertion (see A.18).


                            Extensions to Ada 95

9.a/2       {AI95-00302-03} The generic package Containers.Indefinite_Vectors
            is new.


                        Inconsistencies With Ada 2012

9.b/4       {AI12-0035-1} Corrigendum: Defined some routines to "perform
            indefinite insertion". This could mean that some calls to those
            routines would now raise Program_Error where they previously
            worked. However, this is extremely unlikely, as it would require
            that the package was not implemented in Ada (an Ada allocator
            would raise Program_Error in these circumstances), and that a
            program inserted a more nested tagged type (or access
            discriminant) into a container, and then used that object before
            its type or discriminant went out of scope. All known
            implementations are implemented in Ada, so we believe there is no
            practical incompatibility. As such, we mention this only for
            completeness.


A.18.12 The Generic Package Containers.Indefinite_Doubly_Linked_Lists


1/2 {AI95-00302-03} The language-defined generic package
Containers.Indefinite_Doubly_Linked_Lists provides private types List and
Cursor, and a set of operations for each type. It provides the same operations
as the package Containers.Doubly_Linked_Lists (see A.18.3), with the
difference that the generic formal Element_Type is indefinite.


                              Static Semantics

2/3 {AI95-00302-03} {AI05-0092-1} The declaration of the generic library
package Containers.Indefinite_Doubly_Linked_Lists has the same contents and
semantics as Containers.Doubly_Linked_Lists except:

3/2   * The generic formal Element_Type is indefinite.

4/2   * The procedure with the profile:

5/2     procedure Insert (Container : in out List;
                          Before    : in     Cursor;
                          Position  :    out Cursor;
                          Count     : in     Count_Type := 1);

6/2     is omitted.

6.a/2       Discussion: This procedure is omitted because there is no way to
            create a default-initialized object of an indefinite type. We
            considered having this routine insert an empty element similar to
            the empty elements of a vector, but rejected this possibility
            because the semantics are fairly complex and very different from
            the existing definite container. That would make it more
            error-prone to convert a container from a definite type to an
            indefinite type; by omitting the routine completely, any problems
            will be diagnosed by the compiler.

7/2   * The actual Element parameter of access subprogram Process of
        Update_Element may be constrained even if Element_Type is
        unconstrained.

8/4   * {AI12-0035-1} The operations Append, Insert, Prepend, and
        Replace_Element that have a formal parameter of type Element_Type
        perform indefinite insertion (see A.18).


                            Extensions to Ada 95

8.a/2       {AI95-00302-03} The generic package
            Containers.Indefinite_Doubly_Linked_Lists is new.


                        Inconsistencies With Ada 2012

8.b/4       {AI12-0035-1} Corrigendum: Defined some routines to "perform
            indefinite insertion". This could mean that some calls to those
            routines would now raise Program_Error where they previously
            worked. However, this is extremely unlikely; see
            Inconsistencies With Ada 2012 in A.18.11 for details.


A.18.13 The Generic Package Containers.Indefinite_Hashed_Maps


1/2 {AI95-00302-03} The language-defined generic package
Containers.Indefinite_Hashed_Maps provides a map with the same operations as
the package Containers.Hashed_Maps (see A.18.5), with the difference that the
generic formal types Key_Type and Element_Type are indefinite.


                              Static Semantics

2/3 {AI95-00302-03} {AI05-0092-1} The declaration of the generic library
package Containers.Indefinite_Hashed_Maps has the same contents and semantics
as Containers.Hashed_Maps except:

3/2   * The generic formal Key_Type is indefinite.

4/2   * The generic formal Element_Type is indefinite.

5/2   * The procedure with the profile:

6/2     procedure Insert (Container : in out Map;
                          Key       : in     Key_Type;
                          Position  :    out Cursor;
                          Inserted  :    out Boolean);

7/2     is omitted.

7.a/2       Discussion: This procedure is omitted because there is no way to
            create a default-initialized object of an indefinite type. We
            considered having this routine insert an empty element similar to
            the empty elements of a vector, but rejected this possibility
            because the semantics are fairly complex and very different from
            the existing case. That would make it more error-prone to convert
            a container from a definite type to an indefinite type; by
            omitting the routine completely, any problems will be diagnosed by
            the compiler.

8/2   * The actual Element parameter of access subprogram Process of
        Update_Element may be constrained even if Element_Type is
        unconstrained.

9/4   * {AI12-0035-1} The operations Include, Insert, Replace, and
        Replace_Element that have a formal parameter of type Element_Type
        perform indefinite insertion (see A.18).

9.a/4       Discussion: Some of the named operations also have a formal of the
            indefinite formal type Key_Type and perform indefinite insertion
            using that value, but it is sufficient to mention the formal of
            type Element_Type to cover those.


                            Extensions to Ada 95

9.b/2       {AI95-00302-03} The generic package
            Containers.Indefinite_Hashed_Maps is new.


                        Inconsistencies With Ada 2012

9.c/4       {AI12-0035-1} Corrigendum: Defined some routines to "perform
            indefinite insertion". This could mean that some calls to those
            routines would now raise Program_Error where they previously
            worked. However, this is extremely unlikely; see
            Inconsistencies With Ada 2012 in A.18.11 for details.


A.18.14 The Generic Package Containers.Indefinite_Ordered_Maps


1/2 {AI95-00302-03} The language-defined generic package
Containers.Indefinite_Ordered_Maps provides a map with the same operations as
the package Containers.Ordered_Maps (see A.18.6), with the difference that the
generic formal types Key_Type and Element_Type are indefinite.


                              Static Semantics

2/3 {AI95-00302-03} {AI05-0092-1} The declaration of the generic library
package Containers.Indefinite_Ordered_Maps has the same contents and semantics
as Containers.Ordered_Maps except:

3/2   * The generic formal Key_Type is indefinite.

4/2   * The generic formal Element_Type is indefinite.

5/2   * The procedure with the profile:

6/2     procedure Insert (Container : in out Map;
                          Key       : in     Key_Type;
                          Position  :    out Cursor;
                          Inserted  :    out Boolean);

7/2     is omitted.

7.a/2       Discussion: This procedure is omitted because there is no way to
            create a default-initialized object of an indefinite type. We
            considered having this routine insert an empty element similar to
            the empty elements of a vector, but rejected this possibility
            because the semantics are fairly complex and very different from
            the existing case. That would make it more error-prone to convert
            a container from a definite type to an indefinite type; by
            omitting the routine completely, any problems will be diagnosed by
            the compiler.

8/2   * The actual Element parameter of access subprogram Process of
        Update_Element may be constrained even if Element_Type is
        unconstrained.

9/4   * {AI12-0035-1} The operations Include, Insert, Replace, and
        Replace_Element that have a formal parameter of type Element_Type
        perform indefinite insertion (see A.18).

9.a/4       Discussion: Some of the named operations also have a formal of the
            indefinite formal type Key_Type and perform indefinite insertion
            using that value, but it is sufficient to mention the formal of
            type Element_Type to cover those.


                            Extensions to Ada 95

9.b/2       {AI95-00302-03} The generic package
            Containers.Indefinite_Ordered_Maps is new.


                        Inconsistencies With Ada 2012

9.c/4       {AI12-0035-1} Corrigendum: Defined some routines to "perform
            indefinite insertion". This could mean that some calls to those
            routines would now raise Program_Error where they previously
            worked. However, this is extremely unlikely; see
            Inconsistencies With Ada 2012 in A.18.11 for details.


A.18.15 The Generic Package Containers.Indefinite_Hashed_Sets


1/2 {AI95-00302-03} The language-defined generic package
Containers.Indefinite_Hashed_Sets provides a set with the same operations as
the package Containers.Hashed_Sets (see A.18.8), with the difference that the
generic formal type Element_Type is indefinite.


                              Static Semantics

2/3 {AI95-00302-03} {AI05-0092-1} The declaration of the generic library
package Containers.Indefinite_Hashed_Sets has the same contents and semantics
as Containers.Hashed_Sets except:

3/2   * The generic formal Element_Type is indefinite.

4/2   * The actual Element parameter of access subprogram Process of Update_-
        Element_Preserving_Key may be constrained even if Element_Type is
        unconstrained.

5/4   * {AI12-0035-1} The operations Include, Insert, Replace,
        Replace_Element, and To_Set that have a formal parameter of type
        Element_Type perform indefinite insertion (see A.18).

5.a/4       Ramification: This includes the procedure Replace declared in the
            nested generic package Generic_Keys, as well as the routines
            declared directly in the Containers.Indefinite_Hashed_Sets
            package.


                            Extensions to Ada 95

5.b/2       {AI95-00302-03} The generic package
            Containers.Indefinite_Hashed_Sets is new.


                        Inconsistencies With Ada 2012

5.c/4       {AI12-0035-1} Corrigendum: Defined some routines to "perform
            indefinite insertion". This could mean that some calls to those
            routines would now raise Program_Error where they previously
            worked. However, this is extremely unlikely; see
            Inconsistencies With Ada 2012 in A.18.11 for details.


A.18.16 The Generic Package Containers.Indefinite_Ordered_Sets


1/2 {AI95-00302-03} The language-defined generic package
Containers.Indefinite_Ordered_Sets provides a set with the same operations as
the package Containers.Ordered_Sets (see A.18.9), with the difference that the
generic formal type Element_Type is indefinite.


                              Static Semantics

2/3 {AI95-00302-03} {AI05-0092-1} The declaration of the generic library
package Containers.Indefinite_Ordered_Sets has the same contents and semantics
as Containers.Ordered_Sets except:

3/2   * The generic formal Element_Type is indefinite.

4/2   * The actual Element parameter of access subprogram Process of Update_-
        Element_Preserving_Key may be constrained even if Element_Type is
        unconstrained.

5/4   * {AI12-0035-1} The operations Include, Insert, Replace,
        Replace_Element, and To_Set that have a formal parameter of type
        Element_Type perform indefinite insertion (see A.18).

5.a/4       Ramification: This includes the procedure Replace declared in the
            nested generic package Generic_Keys, as well as the routines
            declared directly in the Containers.Indefinite_Ordered_Sets
            package.


                            Extensions to Ada 95

5.b/2       {AI95-00302-03} The generic package
            Containers.Indefinite_Ordered_Sets is new.


                        Inconsistencies With Ada 2012

5.c/4       {AI12-0035-1} Corrigendum: Defined some routines to "perform
            indefinite insertion". This could mean that some calls to those
            routines would now raise Program_Error where they previously
            worked. However, this is extremely unlikely; see
            Inconsistencies With Ada 2012 in A.18.11 for details.


A.18.17 The Generic Package Containers.Indefinite_Multiway_Trees


1/3 {AI05-0136-1} The language-defined generic package
Containers.Indefinite_Multiway_Trees provides a multiway tree with the same
operations as the package Containers.Multiway_Trees (see A.18.10), with the
difference that the generic formal Element_Type is indefinite.


                              Static Semantics

2/3 {AI05-0136-1} The declaration of the generic library package
Containers.Indefinite_Multiway_Trees has the same contents and semantics as
Containers.Multiway_Trees except:

3/3   * The generic formal Element_Type is indefinite.

4/3   * The procedure with the profile:

5/3     procedure Insert_Child (Container : in out Tree;
                                Parent    : in     Cursor;
                                Before    : in     Cursor;
                                Position  :    out Cursor;
                                Count     : in     Count_Type := 1);

6/3     is omitted.

6.a/3       Discussion: This procedure is omitted because there is no way to
            create a default-initialized object of an indefinite type. We
            considered having this routine insert an empty element similar to
            the empty elements of a vector, but rejected this possibility
            because the semantics are fairly complex and very different from
            the existing case. That would make it more error-prone to convert
            a container from a definite type to an indefinite type; by
            omitting the routine completely, any problems will be diagnosed by
            the compiler.

7/3   * The actual Element parameter of access subprogram Process of
        Update_Element may be constrained even if Element_Type is
        unconstrained.

8/4   * {AI12-0035-1} The operations Append_Child, Insert_Child,
        Prepend_Child, and Replace_Element that have a formal parameter of
        type Element_Type perform indefinite insertion (see A.18).


                           Extensions to Ada 2005

8.a/3       {AI05-0136-1} The generic package
            Containers.Indefinite_Multiway_Trees is new.


                        Inconsistencies With Ada 2012

8.b/4       {AI12-0035-1} Corrigendum: Defined some routines to "perform
            indefinite insertion". This could mean that some calls to those
            routines would now raise Program_Error where they previously
            worked. However, this is extremely unlikely; see
            Inconsistencies With Ada 2012 in A.18.11 for details.


A.18.18 The Generic Package Containers.Indefinite_Holders


1/3 {AI05-0069-1} The language-defined generic package
Containers.Indefinite_Holders provides a private type Holder and a set of
operations for that type. A holder container holds a single element of an
indefinite type.

2/3 {AI05-0069-1} A holder container allows the declaration of an object that
can be used like an uninitialized variable or component of an indefinite type.

3/3 {AI05-0069-1} A holder container may be empty. An empty holder does not
contain an element.


                              Static Semantics

4/3 {AI05-0069-1} The generic library package Containers.Indefinite_Holders
has the following declaration:

5/3     {AI05-0069-1} {AI05-0084-1} generic
           type Element_Type (<>) is private;
           with function "=" (Left, Right : Element_Type) return Boolean is <>;
        package Ada.Containers.Indefinite_Holders is
           pragma Preelaborate(Indefinite_Holders);
           pragma Remote_Types(Indefinite_Holders);

6/3        type Holder is tagged private;
           pragma Preelaborable_Initialization (Holder);

7/3        Empty_Holder : constant Holder;

8/3        function "=" (Left, Right : Holder) return Boolean;

9/3        function To_Holder (New_Item : Element_Type) return Holder;

10/3       function Is_Empty (Container : Holder) return Boolean;

11/3       procedure Clear (Container : in out Holder);

12/3       function Element (Container : Holder) return Element_Type;

13/3       procedure Replace_Element (Container : in out Holder;
                                      New_Item  : in     Element_Type);

14/3       procedure Query_Element
          (Container : in Holder;
           Process   : not null access procedure (Element : in Element_Type));

15/3    {AI05-0069-1} {AI05-0248-1}    procedure Update_Element
          (Container : in out Holder;
           Process   : not null access procedure (Element : in out Element_Type));

16/3    {AI05-0212-1}    type Constant_Reference_Type
              (Element : not null access constant Element_Type) is private
           with Implicit_Dereference => Element;

17/3    {AI05-0212-1}    type Reference_Type
         (Element : not null access Element_Type) is private
           with Implicit_Dereference => Element;

18/3    {AI05-0212-1}    function Constant_Reference
         (Container : aliased in Holder)
           return Constant_Reference_Type;

19/3    {AI05-0212-1}    function Reference
         (Container : aliased in out Holder)
           return Reference_Type;

20/3    {AI05-0001-1}    procedure Assign
         (Target : in out Holder; Source : in Holder);

21/3    {AI05-0001-1}    function Copy (Source : Holder) return Holder;

22/3       procedure Move (Target : in out Holder; Source : in out Holder);

23/3    private

24/3       ... -- not specified by the language

25/3    end Ada.Containers.Indefinite_Holders;

26/3 {AI05-0069-1} The actual function for the generic formal function "=" on
Element_Type values is expected to define a reflexive and symmetric
relationship and return the same result value each time it is called with a
particular pair of values. If it behaves in some other manner, the function
"=" on holder values returns an unspecified value. The exact arguments and
number of calls of this generic formal function by the function "=" on holder
values are unspecified.

26.a/3      Ramification: If the actual function for "=" is not symmetric and
            consistent, the result returned by any of the functions defined to
            use "=" cannot be predicted. The implementation is not required to
            protect against "=" raising an exception, or returning random
            results, or any other "bad" behavior. And it can call "=" in
            whatever manner makes sense. But note that only the results of the
            function "=" is unspecified; other subprograms are not allowed to
            break if "=" is bad.

27/3 {AI05-0069-1} The type Holder is used to represent holder containers. The
type Holder needs finalization (see 7.6).

28/3 {AI05-0069-1} Empty_Holder represents an empty holder object. If an
object of type Holder is not otherwise initialized, it is initialized to the
same value as Empty_Holder.

29/3 {AI05-0069-1} {AI05-0262-1} [Some operations of this generic package have
access-to-subprogram parameters. To ensure such operations are well-defined,
they guard against certain actions by the designated subprogram. In
particular, some operations check for "tampering with the element" of a
container because they depend on the element of the container not being
replaced.]

30/3 {AI05-0069-1} {AI05-0262-1} A subprogram is said to tamper with the
element of a holder object H if:

31/3   * It clears the element contained by H, that is, it calls the Clear
        procedure with H as a parameter;

32/3   * It replaces the element contained by H, that is, it calls the
        Replace_Element procedure with H as a parameter;

33/3   * It calls the Move procedure with H as a parameter;

34/3   * It finalizes H.

34.a/3      Reason: Complete replacement of an element can cause its memory to
            be deallocated while another operation is holding onto a reference
            to it. That can't be allowed. However, a simple modification of
            (part of) an element is not a problem, so Update_Element does not
            cause a problem.

35/4 {AI05-0265-1} {AI12-0110-1} When tampering with the element is prohibited
for a particular holder object H, Program_Error is propagated by a call of any
language-defined subprogram that is defined to tamper with the element of H,
leaving H unmodified. These checks are made before any other defined behavior
of the body of the language-defined subprogram.

36/3    function "=" (Left, Right : Holder) return Boolean;

37/3        {AI05-0069-1} If Left and Right denote the same holder object,
            then the function returns True. Otherwise, it compares the element
            contained in Left to the element contained in Right using the
            generic formal equality operator, returning the result of that
            operation. Any exception raised during the evaluation of element
            equality is propagated.

37.a/3      Implementation Note: This wording describes the canonical
            semantics. However, the order and number of calls on the formal
            equality function is unspecified, so an implementation need not
            call the equality function if the correct answer can be determined
            without doing so.

38/3    function To_Holder (New_Item : Element_Type) return Holder;

39/4        {AI05-0069-1} {AI12-0035-1} Returns a nonempty holder containing
            an element initialized to New_Item. To_Holder performs indefinite
            insertion (see A.18).

40/3    function Is_Empty (Container : Holder) return Boolean;

41/3        {AI05-0069-1} Returns True if Container is empty, and False if it
            contains an element.

42/3    procedure Clear (Container : in out Holder);

43/3        {AI05-0069-1} Removes the element from Container. Container is
            empty after a successful Clear operation.

44/3    function Element (Container : Holder) return Element_Type;

45/3        {AI05-0069-1} If Container is empty, Constraint_Error is
            propagated. Otherwise, returns the element stored in Container.

46/3    procedure Replace_Element (Container : in out Holder;
                                   New_Item  : in     Element_Type);

47/4        {AI05-0069-1} {AI12-0035-1} Replace_Element assigns the value
            New_Item into Container, replacing any preexisting content of
            Container; Replace_Element performs indefinite insertion (see
            A.18). Container is not empty after a successful call to
            Replace_Element.

48/3    procedure Query_Element
          (Container : in Holder;
           Process   : not null access procedure (Element : in Element_Type));

49/3        {AI05-0069-1} {AI05-0262-1} {AI05-0265-1} If Container is empty,
            Constraint_Error is propagated. Otherwise, Query_Element calls
            Process.all with the contained element as the argument. Tampering
            with the element of Container is prohibited during the execution
            of the call on Process.all. Any exception raised by Process.all is
            propagated.

49.a/3      Implementation Note: {AI05-0005-1} The "tamper with the element"
            check is intended to prevent the Element parameter of Process from
            being replaced or deleted outside of Process. The check prevents
            data loss (if Element_Type is passed by copy) or erroneous
            execution (if Element_Type is an unconstrained type).

50/3    {AI05-0069-1} {AI05-0248-1} procedure Update_Element
          (Container : in out Holder;
           Process   : not null access procedure (Element : in out Element_Type));

51/3        {AI05-0069-1} {AI05-0262-1} {AI05-0265-1} If Container is empty,
            Constraint_Error is propagated. Otherwise, Update_Element calls
            Process.all with the contained element as the argument. Tampering
            with the element of Container is prohibited during the execution
            of the call on Process.all. Any exception raised by Process.all is
            propagated.

51.a/3      Implementation Note: The Element parameter of Process.all may be
            constrained even if Element_Type is unconstrained.

52/3    {AI05-0212-1} type Constant_Reference_Type
              (Element : not null access constant Element_Type) is private
           with Implicit_Dereference => Element;

53/3    {AI05-0212-1}
        type Reference_Type (Element : not null access Element_Type) is private
           with Implicit_Dereference => Element;

54/3        {AI05-0212-1} The types Constant_Reference_Type and Reference_Type
            need finalization.

55/3        {AI05-0212-1} The default initialization of an object of type
            Constant_Reference_Type or Reference_Type propagates Program_Error.

55.a/3      Reason: It is expected that Reference_Type (and
            Constant_Reference_Type) will be a controlled type, for which
            finalization will have some action to terminate the tampering
            check for the associated container. If the object is created by
            default, however, there is no associated container. Since this is
            useless, and supporting this case would take extra work, we define
            it to raise an exception.

56/3    {AI05-0212-1}
        function Constant_Reference (Container : aliased in Holder)
           return Constant_Reference_Type;

57/3        {AI05-0212-1} This function (combined with the
            Implicit_Dereference aspect) provides a convenient way to gain
            read access to the contained element of a holder container.

58/3        {AI05-0212-1} {AI05-0262-1} {AI05-0265-1} If Container is empty,
            Constraint_Error is propagated. Otherwise, Constant_Reference
            returns an object whose discriminant is an access value that
            designates the contained element. Tampering with the elements of
            Container is prohibited while the object returned by
            Constant_Reference exists and has not been finalized.

59/3    {AI05-0212-1} function Reference (Container : aliased in out Holder)
           return Reference_Type;

60/3        {AI05-0212-1} This function (combined with the
            Implicit_Dereference aspects) provides a convenient way to gain
            read and write access to the contained element of a holder
            container.

61/3        {AI05-0212-1} {AI05-0262-1} {AI05-0265-1} If Container is empty,
            Constraint_Error is propagated. Otherwise, Reference returns an
            object whose discriminant is an access value that designates the
            contained element. Tampering with the elements of Container is
            prohibited while the object returned by Reference exists and has
            not been finalized.

62/3    procedure Assign (Target : in out Holder; Source : in Holder);

63/3        {AI05-0001-1} If Target denotes the same object as Source, the
            operation has no effect. If Source is empty, Clear (Target) is
            called. Otherwise, Replace_Element (Target, Element (Source)) is
            called.

63.a/3      Discussion: {AI05-0005-1} This routine exists for compatibility
            with the other containers. For a holder, Assign(A, B) and A := B
            behave effectively the same. (Assign Clears the Target, while :=
            finalizes the Target, but these should have similar effects.)

64/3    function Copy (Source : Holder) return Holder;

65/3        {AI05-0001-1} If Source is empty, returns an empty holder
            container; otherwise, returns To_Holder (Element (Source)).

66/3    procedure Move (Target : in out Holder; Source : in out Holder);

67/3        {AI05-0069-1} {AI05-0248-1} If Target denotes the same object as
            Source, then the operation has no effect. Otherwise, the element
            contained by Source (if any) is removed from Source and inserted
            into Target, replacing any preexisting content. Source is empty
            after a successful call to Move.


                          Bounded (Run-Time) Errors

68/3 {AI05-0022-1} {AI05-0069-1} {AI05-0248-1} {AI05-0262-1} It is a bounded
error for the actual function associated with a generic formal subprogram,
when called as part of an operation of this package, to tamper with the
element of any Holder parameter of the operation. Either Program_Error is
raised, or the operation works as defined on the value of the Holder either
prior to, or subsequent to, some or all of the modifications to the Holder.

69/3 {AI05-0027-1} {AI05-0069-1} It is a bounded error to call any subprogram
declared in the visible part of Containers.Indefinite_Holders when the
associated container has been finalized. If the operation takes Container as
an in out parameter, then it raises Constraint_Error or Program_Error.
Otherwise, the operation either proceeds as it would for an empty container,
or it raises Constraint_Error or Program_Error.


                             Erroneous Execution

70/3 {AI05-0212-1} {AI05-0269-1} Execution is erroneous if the holder
container associated with the result of a call to Reference or
Constant_Reference is finalized before the result object returned by the call
to Reference or Constant_Reference is finalized.

70.a/3      Reason: {AI05-0212-1} Each object of Reference_Type and
            Constant_Reference_Type probably contains some reference to the
            originating container. If that container is prematurely finalized
            (which is only possible via Unchecked_Deallocation, as
            accessibility checks prevent passing a container to Reference that
            will not live as long as the result), the finalization of the
            object of Reference_Type will try to access a nonexistent object.
            This is a normal case of a dangling pointer created by
            Unchecked_Deallocation; we have to explicitly mention it here as
            the pointer in question is not visible in the specification of the
            type. (This is the same reason we have to say this for invalid
            cursors.)


                         Implementation Requirements

71/3 {AI05-0069-1} No storage associated with a holder object shall be lost
upon assignment or scope exit.

72/3 {AI05-0069-1} {AI05-0269-1} The execution of an assignment_statement for
a holder container shall have the effect of copying the element (if any) from
the source holder object to the target holder object.

72.a/3      Implementation Note: {AI05-0298-1} An assignment of a holder
            container is a "deep" copy; that is the element is copied as well
            as any data structures. We say "effect of" in order to allow the
            implementation to avoid copying the element immediately if it
            wishes. For instance, an implementation that avoided copying until
            one of the containers is modified would be allowed. (Note that
            this implementation would require care, see A.18.2 for more.)


                            Implementation Advice

73/3 {AI05-0069-1} {AI05-0269-1} Move should not copy the element, and should
minimize copying of internal data structures.

73.a.1/3    Implementation Advice: Containers.Indefinite_Holders.Move should
            not copy the element, and should minimize copying of internal data
            structures.

73.a/3      Implementation Note: Usually that can be accomplished simply by
            moving the pointer(s) to the internal data structures from the
            Source holder to the Target holder.

74/3 {AI05-0069-1} {AI05-0269-1} If an exception is propagated from a holder
operation, no storage should be lost, nor should the element be removed from a
holder container unless specified by the operation.

74.a.1/3    Implementation Advice: If an exception is propagated from a holder
            operation, no storage should be lost, nor should the element be
            removed from a holder container unless specified by the operation.

74.a/3      Reason: This is important so that programs can recover from
            errors. But we don't want to require heroic efforts, so we just
            require documentation of cases where this can't be accomplished.


                           Extensions to Ada 2005

74.b/3      {AI05-0069-1} {AI05-0084-1} {AI05-0265-1} The generic package
            Containers.Indefinite_Holders is new.


                        Inconsistencies With Ada 2012

74.c/4      {AI12-0035-1} Corrigendum: Defined some routines to "perform
            indefinite insertion". This could mean that some calls to those
            routines would now raise Program_Error where they previously
            worked. However, this is extremely unlikely; see
            Inconsistencies With Ada 2012 in A.18.11 for details.


                        Wording Changes from Ada 2012

74.d/4      {AI12-0110-1} Corrigendum: Clarified that tampering checks precede
            all other checks made by a subprogram (but come after those
            associated with the call).


A.18.19 The Generic Package Containers.Bounded_Vectors


1/3 {AI05-0001-1} The language-defined generic package
Containers.Bounded_Vectors provides a private type Vector and a set of
operations. It provides the same operations as the package Containers.Vectors
(see A.18.2), with the difference that the maximum storage is bounded.


                              Static Semantics

2/3 {AI05-0001-1} The declaration of the generic library package
Containers.Bounded_Vectors has the same contents and semantics as
Containers.Vectors except:

3/3   * The pragma Preelaborate is replaced with pragma Pure.

4/3   * The type Vector is declared with a discriminant that specifies the
        capacity:

5/3       type Vector (Capacity : Count_Type) is tagged private;

6/3   * The type Vector needs finalization if and only if type Element_Type
        needs finalization.

6.a/3       Implementation Note: {AI05-0212-1} The type Vector cannot depend
            on package Ada.Finalization unless the element type depends on
            that package. The objects returned from the Iterator and Reference
            functions probably do depend on package Ada.Finalization.
            Restricted environments may need to avoid use of those functions
            and their associated types.

7/3   * In function Copy, if the Capacity parameter is equal to or greater
        than the length of Source, the vector capacity exactly equals the
        value of the Capacity parameter.

8/3   * The description of Reserve_Capacity is replaced with:

9/3         If the specified Capacity is larger than the capacity of
            Container, then Reserve_Capacity propagates Capacity_Error.
            Otherwise, the operation has no effect.


                          Bounded (Run-Time) Errors

10/3 {AI05-0160-1} {AI05-0265-1} It is a bounded error to assign from a
bounded vector object while tampering with elements [or cursors] of that
object is prohibited. Either Program_Error is raised by the assignment,
execution proceeds with the target object prohibiting tampering with elements
[or cursors], or execution proceeds normally.

10.a/3      Proof: Tampering with elements includes tampering with cursors, so
            we only really need to talk about tampering with elements here; we
            mention cursors for clarity.


                             Erroneous Execution

11/3 {AI05-0265-1} When a bounded vector object V is finalized, if tampering
with cursors is prohibited for V other than due to an assignment from another
vector, then execution is erroneous.

11.a/3      Reason: This is a tampering event, but since the implementation is
            not allowed to use Ada.Finalization, it is not possible in a pure
            Ada implementation to detect this error. (There is no Finalize
            routine that will be called that could make the check.) Since the
            check probably cannot be made, the bad effects that could occur
            (such as an iterator going into an infinite loop or accessing a
            nonexistent element) cannot be prevented and we have to allow
            anything. We do allow re-assigning an object that only prohibits
            tampering because it was copied from another object as that cannot
            cause any negative effects.


                         Implementation Requirements

12/3 {AI05-0184-1} {AI05-0264-1} For each instance of Containers.Vectors and
each instance of Containers.Bounded_Vectors, if the two instances meet the
following conditions, then the output generated by the Vector'Output or
Vector'Write subprograms of either instance shall be readable by the
Vector'Input or Vector'Read of the other instance, respectively:

13/3   * {AI05-0184-1} {AI05-0248-1} the Element_Type parameters of the two
        instances are statically matching subtypes of the same type; and

14/3   * {AI05-0184-1} the output generated by Element_Type'Output or
        Element_Type'Write is readable by Element_Type'Input or
        Element_Type'Read, respectively (where Element_Type denotes the type
        of the two actual Element_Type parameters); and

15/3   * {AI05-0184-1} the preceding two conditions also hold for the
        Index_Type parameters of the instances.


                            Implementation Advice

16/3 {AI05-0001-1} Bounded vector objects should be implemented without
implicit pointers or dynamic allocation.

16.a.1/3    Implementation Advice: Bounded vector objects should be
            implemented without implicit pointers or dynamic allocation.

17/3 {AI05-0001-1} The implementation advice for procedure Move to minimize
copying does not apply.

17.a.1/3    Implementation Advice: The implementation advice for procedure
            Move to minimize copying does not apply to bounded vectors.


                           Extensions to Ada 2005

17.a/3      {AI05-0001-1} {AI05-0160-1} {AI05-0184-1} The generic package
            Containers.Bounded_Vectors is new.


A.18.20 The Generic Package Containers.Bounded_Doubly_Linked_Lists


1/3 {AI05-0001-1} The language-defined generic package
Containers.Bounded_Doubly_Linked_Lists provides a private type List and a set
of operations. It provides the same operations as the package
Containers.Doubly_Linked_Lists (see A.18.3), with the difference that the
maximum storage is bounded.


                              Static Semantics

2/3 {AI05-0001-1} The declaration of the generic library package
Containers.Bounded_Doubly_Linked_Lists has the same contents and semantics as
Containers.Doubly_Linked_Lists except:

3/3   * The pragma Preelaborate is replaced with pragma Pure.

4/3   * The type List is declared with a discriminant that specifies the
        capacity (maximum number of elements) as follows:

5/3       type List (Capacity : Count_Type) is tagged private;

6/3   * The type List needs finalization if and only if type Element_Type
        needs finalization.

6.a/3       Implementation Note: {AI05-0212-1} The type List cannot depend on
            package Ada.Finalization unless the element type depends on that
            package. The objects returned from the Iterator and Reference
            functions probably do depend on package Ada.Finalization.
            Restricted environments may need to avoid use of those functions
            and their associated types.

7/3   * The allocation of internal storage includes a check that the capacity
        is not exceeded, and Capacity_Error is raised if this check fails.

8/3   * In procedure Assign, if Source length is greater than Target capacity,
        then Capacity_Error is propagated.

9/3   * The function Copy is replaced with:

10/3      function Copy (Source : List; Capacity : Count_Type := 0)
             return List;

11/3        If Capacity is 0, then the list capacity is the length of Source;
            if Capacity is equal to or greater than the length of Source, the
            list capacity equals the value of the Capacity parameter;
            otherwise, the operation propagates Capacity_Error.

12/3   * In the three-parameter procedure Splice whose Source has type List,
        if the sum of the length of Target and the length of Source is greater
        than the capacity of Target, then Splice propagates Capacity_Error.

13/3   * In the four-parameter procedure Splice, if the length of Target
        equals the capacity of Target, then Splice propagates Capacity_Error.


                          Bounded (Run-Time) Errors

14/3 {AI05-0160-1} {AI05-0265-1} It is a bounded error to assign from a
bounded list object while tampering with elements [or cursors] of that object
is prohibited. Either Program_Error is raised by the assignment, execution
proceeds with the target object prohibiting tampering with elements [or
cursors], or execution proceeds normally.

14.a/3      Proof: Tampering with elements includes tampering with cursors, so
            we only really need to talk about tampering with elements here; we
            mention cursors for clarity.


                             Erroneous Execution

15/3 {AI05-0265-1} When a bounded list object L is finalized, if tampering
with cursors is prohibited for L other than due to an assignment from another
list, then execution is erroneous.

15.a/3      Reason: This is a tampering event, but since the implementation is
            not allowed to use Ada.Finalization, it is not possible in a pure
            Ada implementation to detect this error. (There is no Finalize
            routine that will be called that could make the check.) Since the
            check probably cannot be made, the bad effects that could occur
            (such as an iterator going into an infinite loop or accessing a
            nonexistent element) cannot be prevented and we have to allow
            anything. We do allow re-assigning an object that only prohibits
            tampering because it was copied from another object as that cannot
            cause any negative effects.


                         Implementation Requirements

16/3 {AI05-0184-1} {AI05-0264-1} For each instance of
Containers.Doubly_Linked_Lists and each instance of
Containers.Bounded_Doubly_Linked_Lists, if the two instances meet the
following conditions, then the output generated by the List'Output or
List'Write subprograms of either instance shall be readable by the List'Input
or List'Read of the other instance, respectively:

17/3   * {AI05-0184-1} {AI05-0248-1} the Element_Type parameters of the two
        instances are statically matching subtypes of the same type; and

18/3   * {AI05-0184-1} the output generated by Element_Type'Output or
        Element_Type'Write is readable by Element_Type'Input or
        Element_Type'Read, respectively (where Element_Type denotes the type
        of the two actual Element_Type parameters).


                            Implementation Advice

19/3 {AI05-0001-1} Bounded list objects should be implemented without implicit
pointers or dynamic allocation.

19.a.1/3    Implementation Advice: Bounded list objects should be implemented
            without implicit pointers or dynamic allocation.

20/3 {AI05-0001-1} The implementation advice for procedure Move to minimize
copying does not apply.

20.a.1/3    Implementation Advice: The implementation advice for procedure
            Move to minimize copying does not apply to bounded lists.


                           Extensions to Ada 2005

20.a/3      {AI05-0001-1} {AI05-0160-1} {AI05-0184-1} The generic package
            Containers.Bounded_Doubly_Linked_Lists is new.


A.18.21 The Generic Package Containers.Bounded_Hashed_Maps


1/3 {AI05-0001-1} The language-defined generic package
Containers.Bounded_Hashed_Maps provides a private type Map and a set of
operations. It provides the same operations as the package
Containers.Hashed_Maps (see A.18.5), with the difference that the maximum
storage is bounded.


                              Static Semantics

2/3 {AI05-0001-1} The declaration of the generic library package
Containers.Bounded_Hashed_Maps has the same contents and semantics as
Containers.Hashed_Maps except:

3/3   * The pragma Preelaborate is replaced with pragma Pure.

4/3   * The type Map is declared with discriminants that specify both the
        capacity (number of elements) and modulus (number of distinct hash
        values) of the hash table as follows:

5/3       type Map (Capacity : Count_Type;
                    Modulus  : Hash_Type) is tagged private;

6/3   * The type Map needs finalization if and only if type Key_Type or type
        Element_Type needs finalization.

6.a/3       Implementation Note: {AI05-0212-1} The type Map cannot depend on
            package Ada.Finalization unless the element or key type depends on
            that package. The objects returned from the Iterator and Reference
            functions probably do depend on package Ada.Finalization.
            Restricted environments may need to avoid use of those functions
            and their associated types.

7/3   * The description of Reserve_Capacity is replaced with:

8/3         If the specified Capacity is larger than the capacity of
            Container, then Reserve_Capacity propagates Capacity_Error.
            Otherwise, the operation has no effect.

9/3   * An additional operation is added immediately following
        Reserve_Capacity:

10/3      function Default_Modulus (Capacity : Count_Type) return Hash_Type;

11/3        Default_Modulus returns an implementation-defined value for the
            number of distinct hash values to be used for the given capacity
            (maximum number of elements).

12/3   * The function Copy is replaced with:

13/3      function Copy (Source   : Map;
                         Capacity : Count_Type := 0;
                         Modulus  : Hash_Type := 0) return Map;

14/3        {AI05-0264-1} Returns a map with key/element pairs initialized
            from the values in Source. If Capacity is 0, then the map capacity
            is the length of Source; if Capacity is equal to or greater than
            the length of Source, the map capacity is the value of the
            Capacity parameter; otherwise, the operation propagates
            Capacity_Error. If the Modulus argument is 0, then the map modulus
            is the value returned by a call to Default_Modulus with the map
            capacity as its argument; otherwise, the map modulus is the value
            of the Modulus parameter.


                          Bounded (Run-Time) Errors

15/3 {AI05-0160-1} {AI05-0265-1} It is a bounded error to assign from a
bounded map object while tampering with elements [or cursors] of that object
is prohibited. Either Program_Error is raised by the assignment, execution
proceeds with the target object prohibiting tampering with elements [or
cursors], or execution proceeds normally.

15.a/3      Proof: Tampering with elements includes tampering with cursors, so
            we only really need to talk about tampering with elements here; we
            mention cursors for clarity.


                             Erroneous Execution

16/3 {AI05-0265-1} When a bounded map object M is finalized, if tampering with
cursors is prohibited for M other than due to an assignment from another map,
then execution is erroneous.

16.a/3      Reason: This is a tampering event, but since the implementation is
            not allowed to use Ada.Finalization, it is not possible in a pure
            Ada implementation to detect this error. (There is no Finalize
            routine that will be called that could make the check.) Since the
            check probably cannot be made, the bad effects that could occur
            (such as an iterator going into an infinite loop or accessing a
            nonexistent element) cannot be prevented and we have to allow
            anything. We do allow re-assigning an object that only prohibits
            tampering because it was copied from another object as that cannot
            cause any negative effects.


                         Implementation Requirements

17/3 {AI05-0184-1} {AI05-0264-1} For each instance of Containers.Hashed_Maps
and each instance of Containers.Bounded_Hashed_Maps, if the two instances meet
the following conditions, then the output generated by the Map'Output or
Map'Write subprograms of either instance shall be readable by the Map'Input or
Map'Read of the other instance, respectively:

18/3   * {AI05-0184-1} {AI05-0248-1} the Element_Type parameters of the two
        instances are statically matching subtypes of the same type; and

19/3   * {AI05-0184-1} the output generated by Element_Type'Output or
        Element_Type'Write is readable by Element_Type'Input or
        Element_Type'Read, respectively (where Element_Type denotes the type
        of the two actual Element_Type parameters); and

20/3   * {AI05-0184-1} the preceding two conditions also hold for the Key_Type
        parameters of the instances.


                            Implementation Advice

21/3 {AI05-0001-1} {AI05-0269-1} Bounded hashed map objects should be
implemented without implicit pointers or dynamic allocation.

21.a.1/3    Implementation Advice: Bounded hashed map objects should be
            implemented without implicit pointers or dynamic allocation.

22/3 {AI05-0001-1} The implementation advice for procedure Move to minimize
copying does not apply.

22.a.1/3    Implementation Advice: The implementation advice for procedure
            Move to minimize copying does not apply to bounded hashed maps.


                           Extensions to Ada 2005

22.a/3      {AI05-0001-1} {AI05-0160-1} {AI05-0184-1} The generic package
            Containers.Bounded_Hashed_Maps is new.


A.18.22 The Generic Package Containers.Bounded_Ordered_Maps


1/3 {AI05-0001-1} The language-defined generic package
Containers.Bounded_Ordered_Maps provides a private type Map and a set of
operations. It provides the same operations as the package
Containers.Ordered_Maps (see A.18.6), with the difference that the maximum
storage is bounded.


                              Static Semantics

2/3 {AI05-0001-1} The declaration of the generic library package
Containers.Bounded_Ordered_Maps has the same contents and semantics as
Containers.Ordered_Maps except:

3/3   * The pragma Preelaborate is replaced with pragma Pure.

4/3   * The type Map is declared with a discriminant that specifies the
        capacity (maximum number of elements) as follows:

5/3       type Map (Capacity : Count_Type) is tagged private;

6/3   * The type Map needs finalization if and only if type Key_Type or type
        Element_Type needs finalization.

6.a/3       Implementation Note: {AI05-0212-1} The type Map cannot depend on
            package Ada.Finalization unless the element type depends on that
            package. The objects returned from the Iterator and Reference
            functions probably do depend on package Ada.Finalization.
            Restricted environments may need to avoid use of those functions
            and their associated types.

7/3   * The allocation of a new node includes a check that the capacity is not
        exceeded, and Capacity_Error is raised if this check fails.

8/3   * In procedure Assign, if Source length is greater than Target capacity,
        then Capacity_Error is propagated.

9/3   * The function Copy is replaced with:

10/3      function Copy (Source   : Map;
                         Capacity : Count_Type := 0) return Map;

11/3        Returns a map with key/element pairs initialized from the values
            in Source. If Capacity is 0, then the map capacity is the length
            of Source; if Capacity is equal to or greater than the length of
            Source, the map capacity is the specified value; otherwise, the
            operation propagates Capacity_Error.


                          Bounded (Run-Time) Errors

12/3 {AI05-0160-1} {AI05-0265-1} It is a bounded error to assign from a
bounded map object while tampering with elements [or cursors] of that object
is prohibited. Either Program_Error is raised by the assignment, execution
proceeds with the target object prohibiting tampering with elements [or
cursors], or execution proceeds normally.

12.a/3      Proof: Tampering with elements includes tampering with cursors, so
            we only really need to talk about tampering with elements here; we
            mention cursors for clarity.


                             Erroneous Execution

13/3 {AI05-0265-1} When a bounded map object M is finalized, if tampering with
cursors is prohibited for M other than due to an assignment from another map,
then execution is erroneous.

13.a/3      Reason: This is a tampering event, but since the implementation is
            not allowed to use Ada.Finalization, it is not possible in a pure
            Ada implementation to detect this error. (There is no Finalize
            routine that will be called that could make the check.) Since the
            check probably cannot be made, the bad effects that could occur
            (such as an iterator going into an infinite loop or accessing a
            nonexistent element) cannot be prevented and we have to allow
            anything. We do allow re-assigning an object that only prohibits
            tampering because it was copied from another object as that cannot
            cause any negative effects.


                         Implementation Requirements

14/3 {AI05-0184-1} {AI05-0264-1} For each instance of Containers.Ordered_Maps
and each instance of Containers.Bounded_Ordered_Maps, if the two instances
meet the following conditions, then the output generated by the Map'Output or
Map'Write subprograms of either instance shall be readable by the Map'Input or
Map'Read of the other instance, respectively:

15/3   * {AI05-0184-1} {AI05-0248-1} the Element_Type parameters of the two
        instances are statically matching subtypes of the same type; and

16/3   * {AI05-0184-1} the output generated by Element_Type'Output or
        Element_Type'Write is readable by Element_Type'Input or
        Element_Type'Read, respectively (where Element_Type denotes the type
        of the two actual Element_Type parameters); and

17/3   * {AI05-0184-1} the preceding two conditions also hold for the Key_Type
        parameters of the instances.


                            Implementation Advice

18/3 {AI05-0001-1} {AI05-0269-1} Bounded ordered map objects should be
implemented without implicit pointers or dynamic allocation.

18.a.1/3    Implementation Advice: Bounded ordered map objects should be
            implemented without implicit pointers or dynamic allocation.

19/3 {AI05-0001-1} The implementation advice for procedure Move to minimize
copying does not apply.

19.a.1/3    Implementation Advice: The implementation advice for procedure
            Move to minimize copying does not apply to bounded ordered maps.


                           Extensions to Ada 2005

19.a/3      {AI05-0001-1} {AI05-0160-1} {AI05-0184-1} The generic package
            Containers.Bounded_Ordered_Maps is new.


A.18.23 The Generic Package Containers.Bounded_Hashed_Sets


1/3 {AI05-0001-1} The language-defined generic package
Containers.Bounded_Hashed_Sets provides a private type Set and a set of
operations. It provides the same operations as the package
Containers.Hashed_Sets (see A.18.8), with the difference that the maximum
storage is bounded.


                              Static Semantics

2/3 {AI05-0001-1} The declaration of the generic library package
Containers.Bounded_Hashed_Sets has the same contents and semantics as
Containers.Hashed_Sets except:

3/3   * The pragma Preelaborate is replaced with pragma Pure.

4/3   * The type Set is declared with discriminants that specify both the
        capacity (number of elements) and modulus (number of distinct hash
        values) of the hash table as follows:

5/3       type Set (Capacity : Count_Type;
                    Modulus  : Hash_Type) is tagged private;

6/3   * The type Set needs finalization if and only if type Element_Type needs
        finalization.

6.a/3       Implementation Note: {AI05-0212-1} The type Set cannot depend on
            package Ada.Finalization unless the element or key type depends on
            that package. The objects returned from the Iterator and Reference
            functions probably do depend on package Ada.Finalization.
            Restricted environments may need to avoid use of those functions
            and their associated types.

7/3   * The description of Reserve_Capacity is replaced with:

8/3         If the specified Capacity is larger than the capacity of
            Container, then Reserve_Capacity propagates Capacity_Error.
            Otherwise, the operation has no effect.

9/3   * An additional operation is added immediately following
        Reserve_Capacity:

10/3      function Default_Modulus (Capacity : Count_Type) return Hash_Type;

11/3        Default_Modulus returns an implementation-defined value for the
            number of distinct hash values to be used for the given capacity
            (maximum number of elements).

12/3   * The function Copy is replaced with:

13/3      function Copy (Source   : Set;
                         Capacity : Count_Type := 0;
                         Modulus  : Hash_Type := 0) return Set;

14/3        {AI05-0264-1} Returns a set whose elements are initialized from
            the values in Source. If Capacity is 0, then the set capacity is
            the length of Source; if Capacity is equal to or greater than the
            length of Source, the set capacity is the value of the Capacity
            parameter; otherwise, the operation propagates Capacity_Error. If
            the Modulus argument is 0, then the set modulus is the value
            returned by a call to Default_Modulus with the set capacity as its
            argument; otherwise, the set modulus is the value of the Modulus
            parameter.


                          Bounded (Run-Time) Errors

15/3 {AI05-0160-1} {AI05-0265-1} It is a bounded error to assign from a
bounded set object while tampering with elements [or cursors] of that object
is prohibited. Either Program_Error is raised by the assignment, execution
proceeds with the target object prohibiting tampering with elements [or
cursors], or execution proceeds normally.

15.a/3      Proof: Tampering with elements includes tampering with cursors, so
            we only really need to talk about tampering with elements here; we
            mention cursors for clarity.


                             Erroneous Execution

16/3 {AI05-0265-1} When a bounded set object S is finalized, if tampering with
cursors is prohibited for S other than due to an assignment from another set,
then execution is erroneous.

16.a/3      Reason: This is a tampering event, but since the implementation is
            not allowed to use Ada.Finalization, it is not possible in a pure
            Ada implementation to detect this error. (There is no Finalize
            routine that will be called that could make the check.) Since the
            check probably cannot be made, the bad effects that could occur
            (such as an iterator going into an infinite loop or accessing a
            nonexistent element) cannot be prevented and we have to allow
            anything. We do allow re-assigning an object that only prohibits
            tampering because it was copied from another object as that cannot
            cause any negative effects.


                         Implementation Requirements

17/3 {AI05-0184-1} {AI05-0264-1} For each instance of Containers.Hashed_Sets
and each instance of Containers.Bounded_Hashed_Sets, if the two instances meet
the following conditions, then the output generated by the Set'Output or
Set'Write subprograms of either instance shall be readable by the Set'Input or
Set'Read of the other instance, respectively:

18/3   * {AI05-0184-1} {AI05-0248-1} the Element_Type parameters of the two
        instances are statically matching subtypes of the same type; and

19/3   * {AI05-0184-1} the output generated by Element_Type'Output or
        Element_Type'Write is readable by Element_Type'Input or
        Element_Type'Read, respectively (where Element_Type denotes the type
        of the two actual Element_Type parameters).


                            Implementation Advice

20/3 {AI05-0001-1} {AI05-0269-1} Bounded hashed set objects should be
implemented without implicit pointers or dynamic allocation.

20.a.1/3    Implementation Advice: Bounded hashed set objects should be
            implemented without implicit pointers or dynamic allocation.

21/3 {AI05-0001-1} The implementation advice for procedure Move to minimize
copying does not apply.

21.a.1/3    Implementation Advice: The implementation advice for procedure
            Move to minimize copying does not apply to bounded hashed sets.


                           Extensions to Ada 2005

21.a/3      {AI05-0001-1} {AI05-0160-1} {AI05-0184-1} The generic package
            Containers.Bounded_Hashed_Sets is new.


A.18.24 The Generic Package Containers.Bounded_Ordered_Sets


1/3 {AI05-0001-1} The language-defined generic package
Containers.Bounded_Ordered_Sets provides a private type Set and a set of
operations. It provides the same operations as the package
Containers.Ordered_Sets (see A.18.9), with the difference that the maximum
storage is bounded.


                              Static Semantics

2/3 {AI05-0001-1} The declaration of the generic library package
Containers.Bounded_Ordered_Sets has the same contents and semantics as
Containers.Ordered_Sets except:

3/3   * The pragma Preelaborate is replaced with pragma Pure.

4/3   * The type Set is declared with a discriminant that specifies the
        capacity (maximum number of elements) as follows:

5/3       type Set (Capacity : Count_Type) is tagged private;

6/3   * The type Set needs finalization if and only if type Element_Type needs
        finalization.

6.a/3       Implementation Note: {AI05-0212-1} The type Set cannot depend on
            package Ada.Finalization unless the element type depends on that
            package. The objects returned from the Iterator and Reference
            functions probably do depend on package Ada.Finalization.
            Restricted environments may need to avoid use of those functions
            and their associated types.

7/3   * If Insert (or Include) adds an element, a check is made that the
        capacity is not exceeded, and Capacity_Error is raised if this check
        fails.

8/3   * In procedure Assign, if Source length is greater than Target capacity,
        then Capacity_Error is propagated.

9/3   * The function Copy is replaced with:

10/3      function Copy (Source   : Set;
                         Capacity : Count_Type := 0) return Set;

11/3        Returns a set whose elements are initialized from the values in
            Source. If Capacity is 0, then the set capacity is the length of
            Source; if Capacity is equal to or greater than the length of
            Source, the set capacity is the specified value; otherwise, the
            operation propagates Capacity_Error.


                          Bounded (Run-Time) Errors

12/3 {AI05-0160-1} {AI05-0265-1} It is a bounded error to assign from a
bounded set object while tampering with elements [or cursors] of that object
is prohibited. Either Program_Error is raised by the assignment, execution
proceeds with the target object prohibiting tampering with elements [or
cursors], or execution proceeds normally.

12.a/3      Proof: Tampering with elements includes tampering with cursors, so
            we only really need to talk about tampering with elements here; we
            mention cursors for clarity.


                             Erroneous Execution

13/3 {AI05-0265-1} When a bounded set object S is finalized, if tampering with
cursors is prohibited for S other than due to an assignment from another set,
then execution is erroneous.

13.a/3      Reason: This is a tampering event, but since the implementation is
            not allowed to use Ada.Finalization, it is not possible in a pure
            Ada implementation to detect this error. (There is no Finalize
            routine that will be called that could make the check.) Since the
            check probably cannot be made, the bad effects that could occur
            (such as an iterator going into an infinite loop or accessing a
            nonexistent element) cannot be prevented and we have to allow
            anything. We do allow re-assigning an object that only prohibits
            tampering because it was copied from another object as that cannot
            cause any negative effects.


                         Implementation Requirements

14/3 {AI05-0184-1} {AI05-0264-1} For each instance of Containers.Ordered_Sets
and each instance of Containers.Bounded_Ordered_Sets, if the two instances
meet the following conditions, then the output generated by the Set'Output or
Set'Write subprograms of either instance shall be readable by the Set'Input or
Set'Read of the other instance, respectively:

15/3   * {AI05-0184-1} {AI05-0248-1} the Element_Type parameters of the two
        instances are statically matching subtypes of the same type; and

16/3   * {AI05-0184-1} the output generated by Element_Type'Output or
        Element_Type'Write is readable by Element_Type'Input or
        Element_Type'Read, respectively (where Element_Type denotes the type
        of the two actual Element_Type parameters).


                            Implementation Advice

17/3 {AI05-0001-1} {AI05-0269-1} Bounded ordered set objects should be
implemented without implicit pointers or dynamic allocation.

17.a.1/3    Implementation Advice: Bounded ordered set objects should be
            implemented without implicit pointers or dynamic allocation.

18/3 {AI05-0001-1} The implementation advice for procedure Move to minimize
copying does not apply.

18.a.1/3    Implementation Advice: The implementation advice for procedure
            Move to minimize copying does not apply to bounded ordered sets.


                           Extensions to Ada 2005

18.a/3      {AI05-0001-1} {AI05-0160-1} {AI05-0184-1} The generic package
            Containers.Bounded_Ordered_Sets is new.


A.18.25 The Generic Package Containers.Bounded_Multiway_Trees


1/3 {AI05-0136-1} The language-defined generic package
Containers.Bounded_Multiway_Trees provides a private type Tree and a set of
operations. It provides the same operations as the package
Containers.Multiway_Trees (see A.18.10), with the difference that the maximum
storage is bounded.


                              Static Semantics

2/3 {AI05-0136-1} The declaration of the generic library package
Containers.Bounded_Multiway_Trees has the same contents and semantics as
Containers.Multiway_Trees except:

3/3   * The pragma Preelaborate is replaced with pragma Pure.

4/3   * The type Tree is declared with a discriminant that specifies the
        capacity (maximum number of elements) as follows:

5/3       type Tree (Capacity : Count_Type) is tagged private;

6/3   * The type Tree needs finalization if and only if type Element_Type
        needs finalization.

6.a/3       Implementation Note: {AI05-0212-1} The type Tree cannot depend on
            package Ada.Finalization unless the element type depends on that
            package. The objects returned from the Iterator and Reference
            functions probably do depend on package Ada.Finalization.
            Restricted environments may need to avoid use of those functions
            and their associated types.

7/3   * The allocation of internal storage includes a check that the capacity
        is not exceeded, and Capacity_Error is raised if this check fails.

8/3   * In procedure Assign, if Source length is greater than Target capacity,
        then Capacity_Error is propagated.

9/3   * Function Copy is declared as follows:

10/4    {AI12-0056-1}
          function Copy (Source : Tree; Capacity : Count_Type := 0)
             return Tree;

11/3    If Capacity is 0, then the tree capacity is the count of Source; if
        Capacity is equal to or greater than Source.Count, the tree capacity
        equals the value of the Capacity parameter; otherwise, the operation
        propagates Capacity_Error.

12/3   * {AI05-0136-1} {AI05-0248-1} In the five-parameter procedure
        Splice_Subtree, if Source is not the same object as Target, and if the
        sum of Target.Count and Subtree_Node_Count (Position) is greater than
        Target.Capacity, then Splice_Subtree propagates Capacity_Error.

13/3   * {AI05-0136-1} {AI05-0248-1} In the five-parameter procedure
        Splice_Children, if Source is not the same object as Target, and if
        the sum of Target.Count and Subtree_Node_Count (Source_Parent)-1 is
        greater than Target.Capacity, then Splice_Children propagates
        Capacity_Error.


                          Bounded (Run-Time) Errors

14/3 {AI05-0160-1} {AI05-0265-1} It is a bounded error to assign from a
bounded tree object while tampering with elements [or cursors] of that object
is prohibited. Either Program_Error is raised by the assignment, execution
proceeds with the target object prohibiting tampering with elements [or
cursors], or execution proceeds normally.

14.a/3      Proof: Tampering with elements includes tampering with cursors, so
            we only really need to talk about tampering with elements here; we
            mention cursors for clarity.


                             Erroneous Execution

15/3 {AI05-0265-1} When a bounded tree object T is finalized, if tampering
with cursors is prohibited for T other than due to an assignment from another
tree, then execution is erroneous.

15.a/3      Reason: This is a tampering event, but since the implementation is
            not allowed to use Ada.Finalization, it is not possible in a pure
            Ada implementation to detect this error. (There is no Finalize
            routine that will be called that could make the check.) Since the
            check probably cannot be made, the bad effects that could occur
            (such as an iterator going into an infinite loop or accessing a
            nonexistent element) cannot be prevented and we have to allow
            anything. We do allow re-assigning an object that only prohibits
            tampering because it was copied from another object as that cannot
            cause any negative effects.


                         Implementation Requirements

16/3 {AI05-0184-1} {AI05-0264-1} For each instance of
Containers.Multiway_Trees and each instance of
Containers.Bounded_Multiway_Trees, if the two instances meet the following
conditions, then the output generated by the Tree'Output or Tree'Write
subprograms of either instance shall be readable by the Tree'Input or
Tree'Read of the other instance, respectively:

17/3   * {AI05-0184-1} {AI05-0248-1} the Element_Type parameters of the two
        instances are statically matching subtypes of the same type; and

18/3   * {AI05-0184-1} the output generated by Element_Type'Output or
        Element_Type'Write is readable by Element_Type'Input or
        Element_Type'Read, respectively (where Element_Type denotes the type
        of the two actual Element_Type parameters).


                            Implementation Advice

19/3 {AI05-0136-1} Bounded tree objects should be implemented without implicit
pointers or dynamic allocation.

19.a.1/3    Implementation Advice: Bounded tree objects should be implemented
            without implicit pointers or dynamic allocation.

20/3 {AI05-0136-1} The implementation advice for procedure Move to minimize
copying does not apply.

20.a.1/3    Implementation Advice: The implementation advice for procedure
            Move to minimize copying does not apply to bounded trees.


                           Extensions to Ada 2005

20.a/3      {AI05-0136-1} {AI05-0184-1} The generic package
            Containers.Bounded_Multiway_Trees is new.


A.18.26 Array Sorting


1/3 {AI95-00302-03} {AI05-0001-1} The language-defined generic procedures
Containers.Generic_Array_Sort, Containers.Generic_Constrained_Array_Sort, and
Containers.Generic_Sort provide sorting on arbitrary array types.


                              Static Semantics

2/2 {AI95-00302-03} The generic library procedure
Containers.Generic_Array_Sort has the following declaration:

3/2     generic
           type Index_Type is (<>);
           type Element_Type is private;
           type Array_Type is array (Index_Type range <>) of Element_Type;
           with function "<" (Left, Right : Element_Type)
              return Boolean is <>;
        procedure Ada.Containers.Generic_Array_Sort (Container : in out Array_Type);
        pragma Pure(Ada.Containers.Generic_Array_Sort);

4/2         Reorders the elements of Container such that the elements are
            sorted smallest first as determined by the generic formal "<"
            operator provided. Any exception raised during evaluation of "<"
            is propagated.

5/3         {AI05-0044-1} {AI05-0262-1} The actual function for the generic
            formal function "<" of Generic_Array_Sort is expected to return
            the same value each time it is called with a particular pair of
            element values. It should define a strict weak ordering
            relationship (see A.18); it should not modify Container. If the
            actual for "<" behaves in some other manner, the behavior of the
            instance of Generic_Array_Sort is unspecified. The number of times
            Generic_Array_Sort calls "<" is unspecified.

5.a/2       Ramification: This implies swapping the elements, usually
            including an intermediate copy. This of course means that the
            elements will be copied. Since the elements are nonlimited, this
            usually will not be a problem. Note that there is Implementation
            Advice below that the implementation should use a sort that
            minimizes copying of elements.

5.b/2       The sort is not required to be stable (and the fast algorithm
            required will not be stable). If a stable sort is needed, the user
            can include the original location of the element as an extra "sort
            key". We considered requiring the implementation to do that, but
            it is mostly extra overhead -- usually there is something already
            in the element that provides the needed stability.

6/2 {AI95-00302-03} The generic library procedure
Containers.Generic_Constrained_Array_Sort has the following declaration:

7/2     generic
           type Index_Type is (<>);
           type Element_Type is private;
           type Array_Type is array (Index_Type) of Element_Type;
           with function "<" (Left, Right : Element_Type)
              return Boolean is <>;
        procedure Ada.Containers.Generic_Constrained_Array_Sort
              (Container : in out Array_Type);
        pragma Pure(Ada.Containers.Generic_Constrained_Array_Sort);

8/2         Reorders the elements of Container such that the elements are
            sorted smallest first as determined by the generic formal "<"
            operator provided. Any exception raised during evaluation of "<"
            is propagated.

9/3         {AI05-0044-1} {AI05-0262-1} The actual function for the generic
            formal function "<" of Generic_Constrained_Array_Sort is expected
            to return the same value each time it is called with a particular
            pair of element values. It should define a strict weak ordering
            relationship (see A.18); it should not modify Container. If the
            actual for "<" behaves in some other manner, the behavior of the
            instance of Generic_Constrained_Array_Sort is unspecified. The
            number of times Generic_Constrained_Array_Sort calls "<" is
            unspecified.

9.1/3 {AI05-0001-1} The generic library procedure Containers.Generic_Sort has
the following declaration:

9.2/4   {AI12-0056-1} generic
           type Index_Type is (<>);
           with function Before (Left, Right : Index_Type) return Boolean;
           with procedure Swap (Left, Right : in Index_Type);
        procedure Ada.Containers.Generic_Sort
              (First, Last : Index_Type'Base);
        pragma Pure(Ada.Containers.Generic_Sort);

9.3/3       {AI05-0001-1} {AI05-0248-1} Reorders the elements of an indexable
            structure, over the range First .. Last, such that the elements
            are sorted in the ordering determined by the generic formal
            function Before; Before should return True if Left is to be sorted
            before Right. The generic formal Before compares the elements
            having the given indices, and the generic formal Swap exchanges
            the values of the indicated elements. Any exception raised during
            evaluation of Before or Swap is propagated.

9.4/3       The actual function for the generic formal function Before of
            Generic_Sort is expected to return the same value each time it is
            called with index values that identify a particular pair of
            element values. It should define a strict weak ordering
            relationship (see A.18); it should not modify the elements. The
            actual function for the generic formal Swap should exchange the
            values of the indicated elements. If the actual for either Before
            or Swap behaves in some other manner, the behavior of Generic_Sort
            is unspecified. The number of times the Generic_Sort calls Before
            or Swap is unspecified.


                            Implementation Advice

10/2 {AI95-00302-03} The worst-case time complexity of a call on an instance
of Containers.Generic_Array_Sort or Containers.Generic_Constrained_Array_Sort
should be O(N**2) or better, and the average time complexity should be better
than O(N**2), where N is the length of the Container parameter.

10.a/2      Implementation Advice: Containers.Generic_Array_Sort and
            Containers.Generic_Constrained_Array_Sort should have an average
            time complexity better than O(N**2) and worst case no worse than
            O(N**2).

10.b/2      Discussion: In other words, we're requiring the use of a sorting
            algorithm better than O(N**2), such as Quicksort. No bubble sorts
            allowed!

11/2 {AI95-00302-03} Containers.Generic_Array_Sort and
Containers.Generic_Constrained_Array_Sort should minimize copying of elements.

11.a/2      Implementation Advice: Containers.Generic_Array_Sort and
            Containers.Generic_Constrained_Array_Sort should minimize copying
            of elements.

11.b/2      To be honest: We do not mean "absolutely minimize" here; we're not
            intending to require a single copy for each element. Rather, we
            want to suggest that the sorting algorithm chosen is one that does
            not copy items unnecessarily. Bubble sort would not meet this
            advice, for instance.

12/3 {AI05-0248-1} The worst-case time complexity of a call on an instance of
Containers.Generic_Sort should be O(N**2) or better, and the average time
complexity should be better than O(N**2), where N is the difference between
the Last and First parameters plus 1.

12.a.1/3    Implementation Advice: Containers.Generic_Sort should have an
            average time complexity better than O(N**2) and worst case no
            worse than O(N**2).

13/3 {AI05-0248-1} Containers.Generic_Sort should minimize calls to the
generic formal Swap.

13.a.1/3    Implementation Advice: Containers.Generic_Sort should minimize
            calls to the generic formal Swap.


                            Extensions to Ada 95

13.a/2      {AI95-00302-03} The generic procedures
            Containers.Generic_Array_Sort and
            Containers.Generic_Constrained_Array_Sort are new.


                           Extensions to Ada 2005

13.b/3      {AI05-0001-1} {AI05-0248-1} The generic procedure
            Containers.Generic_Sort is new.


                        Wording Changes from Ada 2005

13.c/3      {AI05-0044-1} Correction: Redefined "<" actuals to require a
            strict weak ordering; the old definition allowed indeterminant
            comparisons that would not have worked in a sort.


A.18.27 The Generic Package Containers.Synchronized_Queue_Interfaces


1/3 {AI05-0159-1} The language-defined generic package
Containers.Synchronized_Queue_Interfaces provides interface type Queue, and a
set of operations for that type. Interface Queue specifies a first-in,
first-out queue.


                              Static Semantics

2/3 {AI05-0159-1} The generic library package
Containers.Synchronized_Queue_Interfaces has the following declaration:

3/3     generic
           type Element_Type is private;
        package Ada.Containers.Synchronized_Queue_Interfaces is
           pragma Pure(Synchronized_Queue_Interfaces);

4/3        type Queue is synchronized interface;

5/3        procedure Enqueue
             (Container : in out Queue;
              New_Item  : in     Element_Type) is abstract
               with Synchronization => By_Entry;

6/3        procedure Dequeue
             (Container : in out Queue;
              Element   :    out Element_Type) is abstract
               with Synchronization => By_Entry;

7/3        function Current_Use
         (Container : Queue) return Count_Type is abstract;
           function Peak_Use
         (Container : Queue) return Count_Type is abstract;

8/3     end Ada.Containers.Synchronized_Queue_Interfaces;

9/3     procedure Enqueue
          (Container : in out Queue;
           New_Item  : in     Element_Type) is abstract;

10/3        {AI05-0159-1} {AI05-0262-1} {AI05-0264-1} A queue type that
            implements this interface is allowed to have a bounded capacity.
            If the queue object has a bounded capacity, and the number of
            existing elements equals the capacity, then Enqueue blocks until
            storage becomes available; otherwise, Enqueue does not block. In
            any case, it then copies New_Item onto the queue.

11/3    procedure Dequeue
          (Container : in out Queue;
           Element   :    out Element_Type) is abstract;

12/3        {AI05-0159-1} {AI05-0251-1} If the queue is empty, then Dequeue
            blocks until an item becomes available. In any case, it then
            assigns the element at the head of the queue to Element, and
            removes it from the queue.

13/3    function Current_Use (Container : Queue) return Count_Type is abstract;

14/3        {AI05-0159-1} Returns the number of elements currently in the
            queue.

15/3    function Peak_Use (Container : Queue) return Count_Type is abstract;

16/3        {AI05-0159-1} Returns the maximum number of elements that have
            been in the queue at any one time.

        NOTES

17/3    51  {AI05-0251-1} Unlike other language-defined containers, there are
        no queues whose element types are indefinite. Elements of an
        indefinite type can be handled by defining the element of the queue to
        be a holder container (see A.18.18) of the indefinite type, or to be
        an explicit access type that designates the indefinite type.

17.a/3      Reason: There are no indefinite queues, as a useful definition for
            Dequeue is not possible. Dequeue cannot be a function, as Ada does
            not have entries that are functions (thus conditional and timed
            calls would not be possible). Moreover, protected functions do not
            allow modifying the queue object (thus it doesn't work even if we
            decided we didn't care about conditional and timed calls). If
            Dequeue is an entry, then the dequeued object would have to be an
            out parameter and that would require the queue client to guess the
            tag and constraints of the value that will be dequeued (otherwise
            Constraint_Error would be raised), and that is rarely going to be
            possible.


                           Extensions to Ada 2005

17.b/3      {AI05-0159-1} {AI05-0251-1} The generic package
            Containers.Synchronized_Queue_Interfaces is new.


A.18.28 The Generic Package Containers.Unbounded_Synchronized_Queues



                              Static Semantics

1/3 {AI05-0159-1} The language-defined generic package
Containers.Unbounded_Synchronized_Queues provides type Queue, which implements
the interface type Containers.Synchronized_Queue_Interfaces.Queue.

2/3     with System;
        with Ada.Containers.Synchronized_Queue_Interfaces;
        generic
           with package Queue_Interfaces is new Ada.Containers.Synchronized_Queue_Interfaces (<>);
           Default_Ceiling : System.Any_Priority := System.Priority'Last;
        package Ada.Containers.Unbounded_Synchronized_Queues is
           pragma Preelaborate(Unbounded_Synchronized_Queues);

3/3        package Implementation is
              ... -- not specified by the language
           end Implementation;

4/3        protected type Queue
                (Ceiling : System.Any_Priority := Default_Ceiling)
                   with Priority => Ceiling is
                new Queue_Interfaces.Queue with

5/3           overriding
              entry Enqueue (New_Item : in Queue_Interfaces.Element_Type);
              overriding
              entry Dequeue (Element : out Queue_Interfaces.Element_Type);

6/3           overriding
              function Current_Use return Count_Type;
              overriding
              function Peak_Use return Count_Type;

7/3        private
              ... -- not specified by the language
           end Queue;

8/3     private

9/3        ... -- not specified by the language

10/3    end Ada.Containers.Unbounded_Synchronized_Queues;

11/3 {AI05-0159-1} The type Queue is used to represent task-safe queues.

12/3 {AI05-0159-1} The capacity for instances of type Queue is unbounded.

12.a/3      Ramification: Enqueue never blocks; if more storage is needed for
            a new element, it is allocated dynamically. We don't need to
            explicitly specify that Queue needs finalization, because it is
            visibly protected.

12.b/3      Discussion: Nested package Implementation can be used to declare
            the types needed to implement the protected type Queue. This
            nested package is necessary as types cannot be declared in the
            private part of a protected type, and the types have to be
            declared within the generic unit in order to depend on the types
            imported with package Queue_Interfaces. Clients should never
            depend on the contents of nested package Implementation.


                           Extensions to Ada 2005

12.c/3      {AI05-0159-1} The generic package
            Containers.Unbounded_Synchronized_Queues is new.


A.18.29 The Generic Package Containers.Bounded_Synchronized_Queues



                              Static Semantics

1/3 {AI05-0159-1} The language-defined generic package
Containers.Bounded_Synchronized_Queues provides type Queue, which implements
the interface type Containers.Synchronized_Queue_Interfaces.Queue.

2/3     with System;
        with Ada.Containers.Synchronized_Queue_Interfaces;
        generic
           with package Queue_Interfaces is new Ada.Containers.Synchronized_Queue_Interfaces (<>);
           Default_Capacity : Count_Type;
           Default_Ceiling  : System.Any_Priority := System.Priority'Last;
        package Ada.Containers.Bounded_Synchronized_Queues is
           pragma Preelaborate(Bounded_Synchronized_Queues);

3/3        package Implementation is
              ... -- not specified by the language
           end Implementation;

4/3        protected type Queue
                (Capacity : Count_Type := Default_Capacity;
                 Ceiling  : System.Any_Priority := Default_Ceiling)
                   with Priority => Ceiling is
                new Queue_Interfaces.Queue with

5/3           overriding
              entry Enqueue (New_Item : in Queue_Interfaces.Element_Type);
              overriding
              entry Dequeue (Element : out Queue_Interfaces.Element_Type);

6/3           overriding
              function Current_Use return Count_Type;
              overriding
              function Peak_Use return Count_Type;

7/3        private
              ... -- not specified by the language
           end Queue;

8/3     private

9/3        ... -- not specified by the language

10/3    end Ada.Containers.Bounded_Synchronized_Queues;

11/3 {AI05-0159-1} The semantics are the same as for
Unbounded_Synchronized_Queues, except:

12/3   * The capacity for instances of type Queue is bounded and specified by
        the discriminant Capacity.

12.a/3      Ramification: Since this type has a bounded capacity, Enqueue
            might block if the queue is full.


                            Implementation Advice

13/3 {AI05-0159-1} Bounded queue objects should be implemented without
implicit pointers or dynamic allocation.

13.a.1/3    Implementation Advice: Bounded queue objects should be implemented
            without implicit pointers or dynamic allocation.


                           Extensions to Ada 2005

13.a/3      {AI05-0159-1} The generic package
            Containers.Bounded_Synchronized_Queues is new.


A.18.30 The Generic Package Containers.Unbounded_Priority_Queues



                              Static Semantics

1/3 {AI05-0159-1} The language-defined generic package
Containers.Unbounded_Priority_Queues provides type Queue, which implements the
interface type Containers.Synchronized_Queue_Interfaces.Queue.

2/3     with System;
        with Ada.Containers.Synchronized_Queue_Interfaces;
        generic
           with package Queue_Interfaces is new Ada.Containers.Synchronized_Queue_Interfaces (<>);
           type Queue_Priority is private;
           with function Get_Priority
             (Element : Queue_Interfaces.Element_Type) return Queue_Priority is <>;
           with function Before
             (Left, Right : Queue_Priority) return Boolean is <>;
           Default_Ceiling : System.Any_Priority := System.Priority'Last;
        package Ada.Containers.Unbounded_Priority_Queues is
           pragma Preelaborate(Unbounded_Priority_Queues);

3/3        package Implementation is
              ... -- not specified by the language
           end Implementation;

4/3        protected type Queue
                (Ceiling : System.Any_Priority := Default_Ceiling)
                   with Priority => Ceiling is
                new Queue_Interfaces.Queue with

5/3           overriding
              entry Enqueue (New_Item : in Queue_Interfaces.Element_Type);
              overriding
              entry Dequeue (Element : out Queue_Interfaces.Element_Type);

6/3     {AI05-0159-1} {AI05-0251-1}       not overriding
              procedure Dequeue_Only_High_Priority
                (At_Least : in     Queue_Priority;
                 Element  : in out Queue_Interfaces.Element_Type;
                 Success  :    out Boolean);

7/3           overriding
              function Current_Use return Count_Type;
              overriding
              function Peak_Use return Count_Type;

8/3        private
              ... -- not specified by the language
           end Queue;

9/3     private

10/3       ... -- not specified by the language

11/3    end Ada.Containers.Unbounded_Priority_Queues;

12/3 {AI05-0159-1} The type Queue is used to represent task-safe priority
queues.

13/3 {AI05-0159-1} The capacity for instances of type Queue is unbounded.

14/3 {AI05-0159-1} Two elements E1 and E2 are equivalent if
Before(Get_Priority(E1), Get_Priority(E2)) and Before(Get_Priority(E2),
Get_Priority(E1)) both return False.

15/3 {AI05-0159-1} {AI05-0248-1} The actual functions for Get_Priority and
Before are expected to return the same value each time they are called with
the same actuals, and should not modify their actuals. Before should define a
strict weak ordering relationship (see A.18). If the actual functions behave
in some other manner, the behavior of Unbounded_Priority_Queues is unspecified.

16/3 {AI05-0159-1} Enqueue inserts an item according to the order specified by
the Before function on the result of Get_Priority on the elements; Before
should return True if Left is to be inserted before Right. If the queue
already contains elements equivalent to New_Item, then it is inserted after
the existing equivalent elements.

16.a/3      Ramification: Enqueue never blocks; if more storage is needed for
            a new element, it is allocated dynamically. We don't need to
            explicitly specify that Queue needs finalization, because it is
            visibly protected.

17/3 {AI05-0159-1} {AI05-0251-1} {AI05-0262-1} For a call on
Dequeue_Only_High_Priority, if the head of the nonempty queue is E, and the
function Before(At_Least, Get_Priority(E)) returns False, then E is assigned
to Element and then removed from the queue, and Success is set to True;
otherwise, Success is set to False and Element is unchanged.

17.a/3      Ramification: {AI05-0251-1} Unlike Dequeue,
            Dequeue_Only_High_Priority is not blocking; it always returns
            immediately.

17.b/3      Reason: {AI05-0251-1} The use of Before is "backwards" so that it
            acts like ">=" (it is defined similarly to ">"); thus we dequeue
            only when it is False.


                           Extensions to Ada 2005

17.c/3      {AI05-0159-1} {AI05-0251-1} The generic package
            Containers.Unbounded_Priority_Queues is new.


A.18.31 The Generic Package Containers.Bounded_Priority_Queues



                              Static Semantics

1/3 {AI05-0159-1} The language-defined generic package
Containers.Bounded_Priority_Queues provides type Queue, which implements the
interface type Containers.Synchronized_Queue_Interfaces.Queue.

2/3     with System;
        with Ada.Containers.Synchronized_Queue_Interfaces;
        generic
           with package Queue_Interfaces is new Ada.Containers.Synchronized_Queue_Interfaces (<>);
           type Queue_Priority is private;
           with function Get_Priority
             (Element : Queue_Interfaces.Element_Type) return Queue_Priority is <>;
           with function Before
             (Left, Right : Queue_Priority) return Boolean is <>;
           Default_Capacity : Count_Type;
           Default_Ceiling  : System.Any_Priority := System.Priority'Last;
        package Ada.Containers.Bounded_Priority_Queues is
           pragma Preelaborate(Bounded_Priority_Queues);

3/3        package Implementation is
              ... -- not specified by the language
           end Implementation;

4/3        protected type Queue
                (Capacity : Count_Type := Default_Capacity;
                 Ceiling  : System.Any_Priority := Default_Ceiling)
                   with Priority => Ceiling is
              new Queue_Interfaces.Queue with

5/3           overriding
              entry Enqueue (New_Item : in Queue_Interfaces.Element_Type);
              overriding
              entry Dequeue (Element : out Queue_Interfaces.Element_Type);

6/3     {AI05-0159-1} {AI05-0251-1}       not overriding
              procedure Dequeue_Only_High_Priority
                (At_Least : in     Queue_Priority;
                 Element  : in out Queue_Interfaces.Element_Type;
                 Success  :    out Boolean);

7/3           overriding
              function Current_Use return Count_Type;
              overriding
              function Peak_Use return Count_Type;

8/3        private
              ... -- not specified by the language
           end Queue;

9/3     private

10/3       ... -- not specified by the language

11/3    end Ada.Containers.Bounded_Priority_Queues;

12/3 {AI05-0159-1} The semantics are the same as for
Unbounded_Priority_Queues, except:

13/3   * The capacity for instances of type Queue is bounded and specified by
        the discriminant Capacity.

13.a/3      Ramification: Since this type has a bounded capacity, Enqueue
            might block if the queue is full.


                            Implementation Advice

14/3 {AI05-0159-1} Bounded priority queue objects should be implemented
without implicit pointers or dynamic allocation.

14.a.1/3    Implementation Advice: Bounded priority queue objects should be
            implemented without implicit pointers or dynamic allocation.


                           Extensions to Ada 2005

14.a/3      {AI05-0159-1} {AI05-0251-1} The generic package
            Containers.Bounded_Priority_Queues is new.


A.18.32 Example of Container Use



                                  Examples

1/3 {AI05-0212-1} The following example is an implementation of Dijkstra's
shortest path algorithm in a directed graph with positive distances. The graph
is represented by a map from nodes to sets of edges.

2/3     with Ada.Containers.Vectors;
        with Ada.Containers.Doubly_Linked_Lists;
        use Ada.Containers;
        generic
           type Node is range <>;
        package Shortest_Paths is
           type Distance is new Float range 0.0 .. Float'Last;
           type Edge is record
              To, From : Node;
              Length   : Distance;
           end record;

3/3        package Node_Maps is new Vectors (Node, Node);
           -- The algorithm builds a map to indicate the node used to reach a given
           -- node in the shortest distance.

4/3        package Adjacency_Lists is new Doubly_Linked_Lists (Edge);
           use Adjacency_Lists;

5/3        package Graphs is new Vectors (Node, Adjacency_Lists.List);

6/3        package Paths is new Doubly_Linked_Lists (Node);

7/3        function Shortest_Path
             (G : Graphs.Vector; Source : Node; Target : Node) return Paths.List
              with Pre => G (Source) /= Adjacency_Lists.Empty_List;

8/3     end Shortest_Paths;

9/3     package body Shortest_Paths is
           function Shortest_Path
             (G : Graphs.Vector; Source : Node; Target : Node) return Paths.List
           is
              use Adjacency_Lists, Node_Maps, Paths, Graphs;
              Reached  : array (Node) of Boolean := (others => False);
              -- The set of nodes whose shortest distance to the source is known.

10/3    {AI05-0299-1}       Reached_From : array (Node) of Node;
              So_Far   : array (Node) of Distance := (others => Distance'Last);
              The_Path : Paths.List := Paths.Empty_List;
              Nearest_Distance : Distance;
              Next     : Node;
           begin
              So_Far(Source)  := 0.0;

11/3          while not Reached(Target) loop
                 Nearest_Distance := Distance'Last;

12/3             -- Find closest node not reached yet, by iterating over all nodes.
                 -- A more efficient algorithm uses a priority queue for this step.

13/3             Next := Source;
                 for N in Node'First .. Node'Last loop
                    if not Reached(N)
                      and then So_Far(N) < Nearest_Distance then
                         Next := N;
                         Nearest_Distance := So_Far(N);
                    end if;
                 end loop;

14/3    {AI05-0299-1}          if Nearest_Distance = Distance'Last then
                    -- No next node found, graph is not connected
                    return Paths.Empty_List;

15/3             else
                    Reached(Next) := True;
                 end if;

16/3             -- Update minimum distance to newly reachable nodes.

17/3    {AI05-0299-1}          for E of G (Next) loop
                    if not Reached(E.To) then
                       Nearest_Distance := E.Length + So_Far(Next);

18/3                   if Nearest_Distance < So_Far(E.To) then
                          Reached_From(E.To) := Next;
                          So_Far(E.To) := Nearest_Distance;
                       end if;
                    end if;
                 end loop;
              end loop;

19/3          -- Rebuild path from target to source.

20/3          declare
                 N : Node := Target;
              begin
                 while N /= Source loop
                    N := Reached_From(N);
                    Prepend (The_Path, N);
                 end loop;
              end;

21/3          return The_Path;
           end;
        end Shortest_Paths;

22/3 {AI05-0212-1} Note that the effect of the Constant_Indexing aspect (on
type Vector) and the Implicit_Dereference aspect (on type Reference_Type) is
that

23/3    G (Next)

24/3 {AI05-0212-1} is a convenient short hand for

25/3    G.Constant_Reference (Next).Element.all

26/3 {AI05-0212-1} Similarly, the effect of the loop:

27/3    for E of G (Next) loop
           if not Reached(E.To) then
              ...
           end if;
        end loop;

28/3 {AI05-0212-1} is the same as:

29/4    {AI12-0080-1} for C in G (Next).Iterate loop
           declare
              E : Edge renames G (Next)(C);
           begin
              if not Reached(E.To) then
                 ...
              end if;
           end;
        end loop;

30/3 {AI05-0212-1} which is the same as:

31/4    {AI12-0080-1} declare
           L : Adjacency_Lists.List renames G (Next);
           C : Adjacency_Lists.Cursor := L.First;
        begin
           while Has_Element (C) loop
              declare
                 E : Edge renames L(C);
              begin
                 if not Reached(E.To) then
                    ...
                 end if;
              end;
              C := L.Next (C);
           end loop;
        end;


                        Wording Changes from Ada 2005

31.a/3      {AI05-0212-1} This example of container use is new.


A.19 The Package Locales


1/3 {AI05-0127-2} {AI05-0248-1} A locale identifies a geopolitical place or
region and its associated language, which can be used to determine other
internationalization-related characteristics.


                              Static Semantics

2/3 {AI05-0127-2} The library package Locales has the following declaration:

3/3     package Ada.Locales is
           pragma Preelaborate(Locales);
           pragma Remote_Types(Locales);

4/4     {AI12-0037-1}    type Language_Code is new String (1 .. 3)
              with Dynamic_Predicate =>
                 (for all E of Language_Code => E in 'a' .. 'z');
           type Country_Code is new String (1 .. 2)
              with Dynamic_Predicate =>
                 (for all E of Country_Code  => E in 'A' .. 'Z');

4.a/4       Discussion: {AI12-0037-1} These types are derived from type String
            so that they can easily be converted to or from type String.
            That's important if one of these values needs to be input or
            displayed (via Text_IO, perhaps). We use the predicate to ensure
            that only possible component values are used. Ada does not allow
            converting between unrelated types with components that don't
            statically match, so we cannot declare new types with constrained
            components if we want conversions to or from type String.

5/3        Language_Unknown : constant Language_Code := "und";
           Country_Unknown : constant Country_Code := "ZZ";

6/3        function Language return Language_Code;
           function Country return Country_Code;

7/3     end Ada.Locales;

8/3 {AI05-0127-2} {AI05-0233-1} The active locale is the locale associated
with the partition of the current task.

8.a/3       Implementation Note: {AI05-0233-1} Some environments define both a
            system locale and the locale of the current user. For such
            environments, the active locale is that of current user if any;
            otherwise (as in a partition running on a server without a user),
            the system locale should be used.

9/3 {AI05-0127-2} Language_Code is a lower-case string representation of an
ISO 639-3 alpha-3 code that identifies a language.

9.a/3       Discussion: Some common language codes are: "eng" - English; "fra"
            - French; "deu" - German; "zho" - Chinese. These are the same
            codes as used by POSIX systems. We considered including constants
            for the most common languages, but that was rejected as the likely
            source of continual arguments about the constant names and which
            languages are important enough to include.

10/3 {AI05-0127-2} Country_Code is an upper-case string representation of an
ISO 3166-1 alpha-2 code that identifies a country.

10.a/3      Discussion: Some common country codes are: "CA" - Canada; "FR" -
            France; "DE" - Germany; "IT" - Italy; "ES" - Spain; "GB" - United
            Kingdom; "US" - United States. These are the same codes as used by
            POSIX systems. We didn't include any country constants for the
            same reasons that we didn't include any language constants.

11/3 {AI05-0127-2} {AI05-0248-1} Function Language returns the code of the
language associated with the active locale. If the Language_Code associated
with the active locale cannot be determined from the environment, then
Language returns Language_Unknown.

12/3 {AI05-0127-2} {AI05-0248-1} Function Country returns the code of the
country associated with the active locale. If the Country_Code associated with
the active locale cannot be determined from the environment, then Country
returns Country_Unknown.


                           Extensions to Ada 2005

12.a/3      {AI05-0127-2} {AI05-0233-1} Package Locales is new.


                        Inconsistencies With Ada 2012

12.b/4      {AI12-0037-1} Corrigendum: Types Language_Code and Country_Code
            are defined with predicates rather than constrained components so
            that they can be converted to/from type String. This changes the
            exception raised from Constraint_Error to Assertion_Error if an
            assignment is attempted with an incorrect value. This could only
            matter if there is a handler specifically for Constraint_Error
            surrounding this assignment; as this exception raise is certainly
            caused by a bug (why would anyone want to use invalid language or
            country codes?), such a handler seems very unlikely. (In addition,
            this is a new Ada 2012 package, so there is not likely to be a lot
            of code using it.)

Generated by dwww version 1.15 on Sun Jun 16 20:23:31 CEST 2024.