Version 1.5 of ais/ai-00128.txt

Unformatted version of ais/ai-00128.txt version 1.5
Other versions for file ais/ai-00128.txt

!standard A.4.3 (68)          99-08-30 AI95-00128/05
!standard A.4.4(101)
!standard A.4.4(102-105)
!standard A.4.5(86-87)
!standard A.4.3(2,74)
!class binding interpretation 96-10-07
!status Corrigendum 2000 99-08-13
!status WG9 approved (8-0-0) 97-07-04
!status ARG approved 12-0-0 96-10-07
!status work item (letter ballot was 6-4-2) 96-10-03
!status ARG approved 7-0-1 (subject to letter ballot) 96-06-17
!status work item 96-04-17
!status received 96-04-04
!priority High
!difficulty Easy
!qualifier Omission
!subject String Packages
!summary
This AI clarifies minor details of the semantics of some of the string-manipulation subprograms:
1. Fixed.Find_Token raises Constraint_Error if the value returned for First is not in Positive.
2. A call to Bounded.Slice with High > Length(Source) raises Index_Error.
3. The functions in Bounded, such as Replace_Slice, are defined in terms of the corresponding functions in Fixed, and the procedures in Bounded are defined in terms of the functions in Bounded.
4. A.4.3(2) takes precedence over any indication to the contrary in the following RM paragraphs.
!question
1. The string packages (e.g., Ada.Strings.Fixed) have a procedure named Find_Token whose profile is:
procedure Find_Token (Source : in String; Set : in Maps.Character_Set; Test : in Membership; First : out Positive; Last : out Natural);
The semantics of this operation states that (RM95-A.4.3(68)) "if no such slice exists, then the value returned for Last is zero, and the value returned for First is Source'First."
What happens when Source'First is not in Positive (which can happen only if Source is a null string)? [It raises Constraint_Error.]
2. The semantics of Bounded.Slice is stated as follows (A.4.4(101)): "Returns the slice at positions Low through High in the string represented by Source; propagates Index_Error if Low > Length(Source)+1."
What happens when Low <= Length(Source)+1 and High > Length(Source)? Should it raise an exception? If so which one? Or should it return all characters from Low to Length(Source)? [It raises Index_Error.]
3. The semantics of many subprograms of package Bounded is defined in terms of the semantics of the corresponding subprograms of package Fixed (A.4.4(102-105). The meaning is clear in most cases, except for Head and Tail.
A.4.4(105) says: "Each of the ... selector subprograms (Trim, Head, Tail) ... has an effect based on its corresponding subprogram in Strings.Fixed ..."
The procedure Fixed.Head has the following profile:
procedure Head (Source : in out String; Count : in Natural; Justify : in Alignment := Left; Pad : in Character := Space);
and the procedure Bounded.Head has a rather different profile:
procedure Head (Source : in out Bounded_String; Count : in Natural; Pad : in Character := Space; Drop : in Truncation := Error);
Because the profiles are different, the "effect based on the corresponding subprogram" is not very clear. It is interesting to note that the semantics of the operations of package Unbounded makes a distinction between functions and procedures (RM95 A.4.5(86-87)), which clarifies very much the meaning. Is the intent similar for Bounded?
The issue seems to be broader than Head and Tail: take for instance procedure Bounded.Replace_Slice. Is it based on the function Fixed.Replace_Slice, or on the procedure Fixed.Replace_Slice? The effect is rather different, since the procedure doesn't change the length of its argument, while the function may return a string of a different length than its argument.
4. Paragraph A.4.3(2) says:
2 For each function that returns a String, the lower bound of the returned value is 1.
However, A.4.3(73) says:
73 function Replace_Slice (Source : in String;
Low : in Positive; High : in Natural; By : in String)
return String;
74 If Low > Source'Last+1, or High < Source'First-1, then Index_ Error is propagated. Otherwise, if High >= Low then the returned string comprises Source(Source'First..Low-1) & By & Source(High+1..Source'Last), and if High < Low then the returned string is Insert(Source, Before=>Low, New_Item=>By).
The lower bounds of the above concatenations give Source'First as the lower bound, which might not be 1.
Is the lower bound really 1? [Yes.]
!recommendation
(See summary.)
!wording
(See corrigendum.)
!discussion
1. Fixed.Find_Token raises Constraint_Error if the value returned for First is not in Positive. Bounded.Find_Token and Unbounded.Find_Token's string argument always has a lower bound of 1 (by definition), so the question does not apply to them.
2. A call to Bounded.Slice with High > Length(Source) raises Index_Error. This is analogous to the normal string slicing operation.
3. The function Bounded.Head is defined in terms of the function Fixed.Head; a call of the function Bounded.Head is equivalent to:
To_Bounded_String(Fixed.Head(To_String(Source), Count, Pad), Drop => Drop)
The procedure Bounded.Head is defined in terms of the function Bounded.Head; a call to the procedure Bounded.Head is equivalent to:
Source := Head(Source, Count, Pad, Drop);
Corresponding rules apply to Tail. In general, the functions in Bounded, such as Replace_Slice, are defined in terms of the corresponding functions in Fixed, and the procedures in Bounded are defined in terms of the functions in Bounded.
4. Clearly, the intent is that the lower bound should always be 1, as stated in A.4.3(2). I think a "friendly" reading is that A.4.3(74) is just telling us the characters of the string (it says "comprises", and not "is equivalent to"), and is not intended to define the bounds.
A.4.3(2) is therefore interpreted as taking precedence over any indication to the contrary in the following paragraphs. This applies in general; A.4.3(2) also takes precedence over A.4.3(78,86) and perhaps other paragraphs.
!corrigendum A.04.03(68)
Replace the paragraph:
Find_Token returns in First and Last the indices of the beginning and end of the first slice of Source all of whose elements satisfy the Test condition, and such that the elements (if any) immediately before and after the slice do not satisfy the Test condition. If no such slice exists, then the value returned for Last is zero, and the value returned for First is Source'First.
by:
Find_Token returns in First and Last the indices of the beginning and end of the first slice of Source all of whose elements satisfy the Test condition, and such that the elements (if any) immediately before and after the slice do not satisfy the Test condition. If no such slice exists, then the value returned for Last is zero, and the value returned for First is Source'First. Constraint_Error is raised if the result for First is not in Positive.
!corrigendum A.04.03(74)
Replace the paragraph:
If Low > Source'Last+1, or High < Source'First-1, then Index_ Error is propagated. Otherwise, if High >= Low then the returned string comprises Source(Source'First..Low-1) & By & Source(High+1..Source'Last), and if High < Low then the returned string is Insert(Source, Before=>Low, New_Item=>By).
by:
If Low > Source'Last+1, or High < Source'First-1, then Index_ Error is propagated. Otherwise, if High >= Low then the returned string comprises Source(Source'First..Low-1) & By & Source(High+1..Source'Last), but with lower bound 1. Otherwise, if High < Low then the returned string is Insert(Source, Before=>Low, New_Item=>By).
!corrigendum A.04.03(86)
Replace the paragraph:
If From <= Through, the returned string is Replace_Slice(Source, From, Through, ""), otherwise it is Source.
by:
If From <= Through, the returned string is Replace_Slice(Source, From, Through, ""), otherwise it is Source, but with lower bound 1.
!corrigendum A.04.03(106)
Replace the paragraph:
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 is (Left-1)*Right & Right otherwise.
by:
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 is (Left-1)*Right & Right, but with lower bound 1, otherwise.
!corrigendum A.04.04(101)
Replace the paragraph:
Returns the slice at positions Low through High in the string represented by Source; propagates Index_Error if Low > Length(Source)+1.
by:
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).
!corrigendum A.04.04(105)
Replace the paragraph:
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."*". For each of these subprograms, 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.
by:
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."*". For each of these functions, the corresponding fixed-length string function is applied to the string represented by the Bounded_String parameter. To_Bounded_String is applied to the result string, with Drop (or Error in the case of Generic_Bounded_Length."*") determining the effect when the string length exceeds Max_Length. For each of these procedures, the corresponding function in Strings.Bounded.Generic_Bounded_Length is applied, with the result assigned into the Source parameter.
!ACATS test
1. It would be possible to create a C-Test to test this case, but it would be of very little value (as the problem can only occur for an unusual null string). 2. Test cases for this should be added to CXA4019. A test that raises Index_Error should be added for Bounded. 3. Functions and procedures in Bounded are adaquately tested in CXA4007. 4. It would be possible to create a C-Test to check that the lower bound of all of these functions is 1, but this does appear to be an important test.
!appendix

!section A.4.3(68)
!subject Behavior of Find_Token when passed a null string with negative 'First
!reference RM95-A.4.3(68)
!from Pascal Leroy 96-03-22
!reference 96-5446.a Pascal Leroy 96-3-22>>
!discussion

The string packages (e.g., Ada.Strings.Fixed) have a procedure named
Find_Token whose profile is:

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

The semantics of this operation states that (RM95-A.4.3(68)) "if no such slice
exists, then the value returned for Last is zero, and the value returned for
First is Source'First."

This definition, together with the profile of Find_Token, have the unfortunate
consequence that, if Find_Token is passed a null string with a negative lower
bound, Find_Token raises Constraint_Error, because Source'First is not in
Positive:

        Null_String : String (-10 .. -20);
        ...
        Find_Token (Source => Null_String, ...);

This is quite inconsistent, because a call to Find_Token with a null string
whose 'First is positive doesn't raise an exception.

_____________________________________________________________________
Pascal Leroy                                    +33.1.30.12.09.68
pleroy@rational.com                             +33.1.30.12.09.66 FAX

****************************************************************

!section A.4.3(68)
!subject Behavior of Find_Token when passed a null string with negative 'First
!reference RM95-A.4.3(68)
!reference 96-5446.a Pascal Leroy 96-3-22
!from Robert Dewar 96-03-23
!reference 96-5448.a Robert Dewar 96-3-23>>
!discussion

I think the constraint error for a negative bound is perfectly fine. Yes,
the language allows such strange null strings, but the normal representation
for a null string should have non-negative bounds, there is no reason to go
outside the index range by more than 1 for a null string.

****************************************************************

!section A.4.3(68)
!subject Behavior of Find_Token when passed a null string with negative 'First
!reference RM95-A.4.3(68)
!reference: 96-5446.a Pascal Leroy 96-3-22
!from Robert Eachus 96-03-25
!reference 96-5449.a Robert I. Eachus 96-3-25>>
!discussion

   Pascal said:

  > This definition, together with the profile of Find_Token, have the
  > unfortunate consequence that, if Find_Token is passed a null
  > string with a negative lower bound, Find_Token raises
  > Constraint_Error, because Source'First is not in Positive...

  > This is quite inconsistent, because a call to Find_Token with a null string
  > whose 'First is positive doesn't raise an exception.

   I think this is pretty pathological.  Since the index subtype of
String is Positive, you can only have the call succeed--without
raising Constraint_Error--with Source'First negative if you explicitly
create a null string value with weird bounds, and call with that null
string as a parameter.

   Normal calls, even normal calls with null slices of ordinary
strings, won't cause any problems.


                                        Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...

****************************************************************

!section A.4.4(101)
!subject What does Bounded.Slice do when High exceeds the upper bound of Source?
!reference RM95-A.4.4(101)
!from Pascal Leroy 96-03-27
!reference 96-5451.a Pascal Leroy 96-3-27>>
!discussion

The semantics of Bounded.Slice is stated as follows: "Returns the slice at
positions Low through High in the string represented by Source; propagates
Index_Error if Low > Length(Source)+1."

>From this definition, I have trouble understanding what Bounded.Slice is
expected to do when Low <= Length(Source)+1 and High > Length(Source).  Should
it raise an exception?  If so which one?  Or should it return all characters
from Low to Length(Source)?


****************************************************************

!section A.4.4(105)
!subject Semantics of Bounded.Head and Bounded.Tail
!reference RM95-A.4.4(105)
!from Pascal Leroy 96-03-27
!reference 96-5451.b Pascal Leroy 96-3-27>>
!discussion

The semantics of many subprograms of package Bounded is defined in terms of
the semantics of the corresponding subprograms of package Fixed (RM95
A.4.4(102-105).  The meaning is clear in most cases, except for Head and Tail.
 RM95 A.4.4(105) says: "Each of the ... selected subprograms (Trim, Head,
Tail) ... has an effect based on its corresponding subprogram in Strings.Fixed
..."

The procedure Fixed.Head has the following profile:

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

and the procedure Bounded.Head has a rather different profile:

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

Because the profiles are different, the "effect based on the corresponding
subprogram" is not very clear.  It is interesting to note that the semantics
of the operations of package Unbounded makes a distinction between functions
and procedures (RM95 A.4.5(86-87)), which clarifies very much the meaning.  Is
the intent similar for Bounded?

The issue seems to be broader than Head and Tail: take for instance procedure
Bounded.Replace_Slice.  Is it based on the function Fixed.Replace_Slice, or on
the procedure Fixed.Replace_Slice?  The effect is rather different, since the
procedure doesn't change the length of its argument, while the function may
return a string of a different length than its argument.

****************************************************************

!section A.4.3(68)
!subject Behavior of Find_Token when passed a null string with negative 'First
!reference RM95-A.4.3(68)
!reference: 96-5446.a Pascal Leroy 96-3-22
!reference: 96-5448.a Robert Dewar 96-3-23
!reference: 96-5449.a Robert I. Eachus 96-3-25
!from Pascal Leroy 96-03-27
!reference 96-5452.a Pascal Leroy 96-3-27>>
!discussion

> I think this is pretty pathological.  Since the index subtype of
> String is Positive, you can only have the call succeed--without
> raising Constraint_Error--with Source'First negative if you explicitly
> create a null string value with weird bounds, and call with that null
> string as a parameter.

> I think the constraint error for a negative bound is perfectly fine. Yes,
> the language allows such strange null strings, but the normal representation
> for a null string should have non-negative bounds, there is no reason to go
> outside the index range by more than 1 for a null string.

I must say that I am not convinced by Robert & Robert's answer who both seem
to say: "this is pathological, you deserved it!"

First, I find String (0..-1) rather less pathological than String
(1000..-1000).  The former will raise an exception, the latter won't.  I see
no reason why.

Second, I find it rather improper than an operation of one of the predefined
packages raises Constraint_Error.  As we all know, you already get
Constraint_Error too often when writing/debugging Ada code.  If I must be
punished for using pathological null strings, then I'd rather get Index_Error
than Constraint_Error.

Third, what bothers me is that this Constraint_Error seems quite unintentional
in the RM: it is not explicit stated, but arises because the parameter subtype
is Positive.  (I know, speculations about what is intentional in the RM and
what is not are sterile...)

_____________________________________________________________________
Pascal Leroy                                    +33.1.30.12.09.68
pleroy@rational.com                             +33.1.30.12.09.66 FAX

****************************************************************

!section A.4.3(68)
!subject Behavior of Find_Token when passed a null string with negative 'First
!reference RM95-A.4.3(68)
!reference: 96-5446.a Pascal Leroy 96-3-22
!reference: 96-5448.a Robert Dewar 96-3-23
!reference: 96-5449.a Robert I. Eachus 96-3-25
!reference 96-5452.a Pascal Leroy 96-3-27
!from Bob Duff
!reference 96-5457.a Robert A Duff 96-4-8>>
!discussion

> > I think this is pretty pathological.  Since the index subtype of
> > String is Positive, you can only have the call succeed--without
> > raising Constraint_Error--with Source'First negative if you explicitly
> > create a null string value with weird bounds, and call with that null
> > string as a parameter.
>
> > I think the constraint error for a negative bound is perfectly fine. Yes,
> > the language allows such strange null strings, but the normal representation
> > for a null string should have non-negative bounds, there is no reason to go
> > outside the index range by more than 1 for a null string.
>
> I must say that I am not convinced by Robert & Robert's answer who both seem
> to say: "this is pathological, you deserved it!"
>
> First, I find String (0..-1) rather less pathological than String
> (1000..-1000).  The former will raise an exception, the latter won't.  I see
> no reason why.

I agree -- they're *both* pathological.  So I don't care if they raise
an exception.  If one raises an exception, and not the other, that seems
fine.  Furthermore, I don't particularly care *which* exception is
raised.

> Second, I find it rather improper than an operation of one of the predefined
> packages raises Constraint_Error.  As we all know, you already get
> Constraint_Error too often when writing/debugging Ada code.  If I must be
> punished for using pathological null strings, then I'd rather get Index_Error
> than Constraint_Error.

Why should we care which exception is raised?

> Third, what bothers me is that this Constraint_Error seems quite
> unintentional in the RM: it is not explicit stated, but arises because
> the parameter subtype is Positive.  (I know, speculations about what
> is intentional in the RM and what is not are sterile...)

Yes, I agree, this was an unintentional oversight in the RM.  But I
don't see any better idea than to raise C_E in this case.  Raising some
other exception seems irrelevant -- any exception in this case indicates
a bug.  The only other possibility is to return a well-defined result --
but the RM clearly requires an out-of-range result, so C_E seems
appropriate.

- Bob

****************************************************************

!section A.4.3(02)
!subject Lower bounds should be 1
!reference RM95-A.4.3(02)
!reference RM95-A.4.3(73)
!from Bob Duff
!reference 96-5475.a Robert A Duff 96-4-12>>
!discussion

Robert Dewar pointed out this problem to me.

A.4.3(2) says:

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

However, A.4.3(73) says:

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

        74   If Low > Source'Last+1, or High < Source'First-1, then Index_
        Error is propagated.  Otherwise, if High >= Low then the returned
        string comprises Source(Source'First..Low-1) & By &
        Source(High+1..Source'Last), and if High < Low then the returned
        string is Insert(Source, Before=>Low, New_Item=>By).

The lower bounds of the above concatenations give Source'First as the
lower bound, which might not be 1.

Clearly, the intent is that the lower bound should always be 1, as
stated in A.4.3(2).  I think a "friendly" reading is that A.4.3(74) is
just telling us the characters of the string (it says "comprises", and
not "is equivalent to"), and is not intended to define the bounds.

- Bob


****************************************************************

!section A.4.3(02)
!subject Lower bounds should be 1
!reference RM95-A.4.3(02)
!reference RM95-A.4.3(73)
!reference 96-5475.a Robert A Duff 96-4-12
!from Pascal Leroy 96-04-16
!reference 96-5490.a Pascal Leroy 96-4-16>>
!discussion

> The lower bounds of the above concatenations give Source'First as the
> lower bound, which might not be 1.
>
> Clearly, the intent is that the lower bound should always be 1, as
> stated in A.4.3(2).  I think a "friendly" reading is that A.4.3(74) is
> just telling us the characters of the string (it says "comprises", and
> not "is equivalent to"), and is not intended to define the bounds.

Note that there are (at least) two other functions to which this comment
applies:

Insert: RM95 A.4.3(78) says "otherwise returns Source (Source'First .. Before
- 1) & New_Item & Source (Before .. Source'Last)."

Delete: RM95 A.4.3(86) says "otherwise it is Source."

There may be other functions for which the wording may also be misleading.  So
I guess that the AI should be worded in a way that makes it clear that it
applies to all functions of package Fixed.  (Maybe by stating that the wording
of all paragraphs in RM95 A.4.3 is just specifying the characters of the
string but not its bounds.)

_____________________________________________________________________
Pascal Leroy                                    +33.1.30.12.09.68
pleroy@rational.com                             +33.1.30.12.09.66 FAX

****************************************************************

!section A.4.4(101)
!subject What does Bounded.Slice do when High exceeds the upper bound of Source?
!reference RM95-A.4.4(101)
!reference 96-5451.a Pascal Leroy 96-3-27
!reference AI95-00128/00
!from Keith Thompson 96-07-16
!reference 96-5622.a Keith Thompson 96-7-16>>
!discussion

Pascal Leroy asked what Bounded.Slice does when Low <= Length(Source)+1
and High > Length(Source) (i.e., when the requested slice overlaps the
end of the string).  The current version of AI-00128 says a call with
High > Length(Source) is equivalent to a call with High = Length(Source).

What is the rationale for this?  The name Slice implies that the function
is intended to correspond to the predefined slice operation on type
String, which raises an exception for such an overlap.

For what it's worth, at least two existing implementations currently
raise Index_Error in this case.

****************************************************************

!section A.4.3(68)
!subject String Packages
!reference AI95-00128/01
!from Norman Cohen
!reference 96-5689.c Norman H. Cohen 96-9-6>>
!discussion

I am startled by the decision (contradicting at least two existing
implementations) that Slice does not raise an exception when called
with an upper bound that is too high.  Perhaps there is a
well thought out justification for this, but if so, it should appear
in a !discussion section.

****************************************************************

!section A.4.5(82)
!subject Lower bound of Unbounded.Slice
!reference RM95-A.4.5(82)
!reference RM95-A.4.4(101)
!reference RM95-A.4.4(1)
!reference RM95-A.4.3(2)
!reference AI95-00128/04
!from Keith Thompson 96-12-03
!reference 96-5777.a Keith Thompson 96-12-3>>
!discussion

Note that this discussion applies equally to
Unbounded.Slice and Bounded.Slice.  (Well,
Bounded.Generic_Bounded_Length.Slice if you want to be picky.)

In a discussion on comp.lang.ada, Pascal Obry asked whether
Ada.Strings.Unbounded.Slice (U, 6, 8) should have bounds 6..8 or 1..3.
Bob Duff replied that the correct bounds are 1..3:

> See A.4.5(82), A.4.4(101), A.4.4(1) "whose low bound is 1", A.4.3(2),
> and AI-128.  The correct result is 1..3.

I don't find any of those references entirely convincing.

Taking the references one at a time:

A.4.5(82) says that Unbounded.Slice has the same effect as Bounded.Slice.

A.4.4(101) says that Bounded.Slice "returns the slice at positions
Low through High in the string represented by Source".  This can
be interpreted to mean that Slice(U, 6, 8) is equivalent to
To_String(U)(6..8), giving bounds of 6..8.

A.4.4(1) says that a Bounded_String represents a String whose low bound
is 1.  This is not directly relevant, since Slice returns a String, not
a Bounded_String.

A.4.3(2) says that "For each function that returns a String, the lower
bound of the returned value is 1", but this refers to the package
Ada.Strings.Fixed, which has no Slice function.  The equivalent of the
Slice function for fixed strings is an array slice operation, which in
the example above yields bounds of 6..8.

Finally, I found nothing in AI95-00128/04 that states that Slice returns
a result with a lower bound of 1.

Robert Dewar made a similar point on comp.lang.ada.

To conclude, I believe the RM implies (perhaps weakly) that the Slice
function of Bounded and Unbounded returns a result whose lower bound is
not necessarily 1.  On the other hand, A.4.3(2) could be taken to imply
that the *intent* was for all functions returning String in all three
packages to return a result with a lower bound of 1.  This needs to be
clarified in the next revision of AI-00128.


****************************************************************

!from Randy Brukardt  99-08-17

1. While the question refers to all versions of Find_Token, the wording change
only applies to Fixed.Find_Token. That's because only it can have a bound
outside of Positive; the others always have a lower bound 1. I added a sentence
to that effect to the discussion.

4. I checked through all of the paragraphs for Ada.Strings.Fixed operations,
and I believe that I gave wording changes for the only ones for which someone
might construe A.4.3(2) to not apply. The discussion implies that A.4.3(78)
needs to be changed, but this paragraph already includes "but lower bound 1.",
so I don't see how anyone could come to any other conclusion about the lower
bound.

****************************************************************


Questions? Ask the ACAA Technical Agent