aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/libgnat
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-10-07 15:28:36 -0700
committerIan Lance Taylor <iant@golang.org>2021-10-07 15:28:36 -0700
commit0b6b70a0733672600644c8df96942cda5bf86d3d (patch)
tree9a1fbd7f782c54df55ab225ed1be057e3f3b0b8a /gcc/ada/libgnat
parenta5b5cabc91c38710adbe5c8a2b53882abe994441 (diff)
parentfba228e259dd5112851527f2dbb62c5601100985 (diff)
downloadgcc-0b6b70a0733672600644c8df96942cda5bf86d3d.zip
gcc-0b6b70a0733672600644c8df96942cda5bf86d3d.tar.gz
gcc-0b6b70a0733672600644c8df96942cda5bf86d3d.tar.bz2
Merge from trunk revision fba228e259dd5112851527f2dbb62c5601100985.
Diffstat (limited to 'gcc/ada/libgnat')
-rw-r--r--gcc/ada/libgnat/a-cbdlli.ads8
-rw-r--r--gcc/ada/libgnat/a-cbhama.ads11
-rw-r--r--gcc/ada/libgnat/a-cbhase.ads9
-rw-r--r--gcc/ada/libgnat/a-cbmutr.ads8
-rw-r--r--gcc/ada/libgnat/a-cborma.ads11
-rw-r--r--gcc/ada/libgnat/a-cborse.ads9
-rw-r--r--gcc/ada/libgnat/a-cfdlli.ads1
-rw-r--r--gcc/ada/libgnat/a-cfhama.ads1
-rw-r--r--gcc/ada/libgnat/a-cfhase.ads1
-rw-r--r--gcc/ada/libgnat/a-cfinve.ads1
-rw-r--r--gcc/ada/libgnat/a-cforma.ads1
-rw-r--r--gcc/ada/libgnat/a-cforse.ads1
-rw-r--r--gcc/ada/libgnat/a-chahan.adb122
-rw-r--r--gcc/ada/libgnat/a-chahan.ads359
-rw-r--r--gcc/ada/libgnat/a-coboho.ads4
-rw-r--r--gcc/ada/libgnat/a-cobove.ads9
-rw-r--r--gcc/ada/libgnat/a-cofove.ads1
-rw-r--r--gcc/ada/libgnat/a-except.adb90
-rw-r--r--gcc/ada/libgnat/a-except.ads9
-rw-r--r--gcc/ada/libgnat/a-strbou.adb2
-rw-r--r--gcc/ada/libgnat/a-strbou.ads2152
-rw-r--r--gcc/ada/libgnat/a-strfix.adb20
-rw-r--r--gcc/ada/libgnat/a-strfix.ads91
-rw-r--r--gcc/ada/libgnat/a-strmap.adb337
-rw-r--r--gcc/ada/libgnat/a-strmap.ads127
-rw-r--r--gcc/ada/libgnat/a-strsea.ads6
-rw-r--r--gcc/ada/libgnat/a-strsup.adb1163
-rw-r--r--gcc/ada/libgnat/a-strsup.ads2383
-rw-r--r--gcc/ada/libgnat/a-strunb.ads8
-rw-r--r--gcc/ada/libgnat/a-strunb__shared.ads3
-rw-r--r--gcc/ada/libgnat/a-textio.adb1
-rw-r--r--gcc/ada/libgnat/a-textio.ads6
-rw-r--r--gcc/ada/libgnat/a-zchhan.adb34
-rw-r--r--gcc/ada/libgnat/a-zchhan.ads29
-rw-r--r--gcc/ada/libgnat/a-zchuni.adb19
-rw-r--r--gcc/ada/libgnat/a-zchuni.ads12
-rw-r--r--gcc/ada/libgnat/g-forstr.adb6
-rw-r--r--gcc/ada/libgnat/i-vxwork.ads9
-rw-r--r--gcc/ada/libgnat/i-vxwork__x86.ads9
-rw-r--r--gcc/ada/libgnat/memtrack.adb127
-rw-r--r--gcc/ada/libgnat/s-arit128.ads7
-rw-r--r--gcc/ada/libgnat/s-arit64.ads7
-rw-r--r--gcc/ada/libgnat/s-imenne.adb170
-rw-r--r--gcc/ada/libgnat/s-imenne.ads85
-rw-r--r--gcc/ada/libgnat/s-imglli.ads4
-rw-r--r--gcc/ada/libgnat/s-parame__vxworks.ads4
-rw-r--r--gcc/ada/libgnat/s-regpat.adb63
-rw-r--r--gcc/ada/libgnat/s-regpat.ads11
-rw-r--r--gcc/ada/libgnat/s-secsta.ads5
49 files changed, 6254 insertions, 1302 deletions
diff --git a/gcc/ada/libgnat/a-cbdlli.ads b/gcc/ada/libgnat/a-cbdlli.ads
index ab55086..f4086ea 100644
--- a/gcc/ada/libgnat/a-cbdlli.ads
+++ b/gcc/ada/libgnat/a-cbdlli.ads
@@ -57,11 +57,11 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Append);
- pragma Preelaborable_Initialization (List);
+ Add_Unnamed => Append),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_List : constant List;
diff --git a/gcc/ada/libgnat/a-cbhama.ads b/gcc/ada/libgnat/a-cbhama.ads
index 8be64c8..cdd4135 100644
--- a/gcc/ada/libgnat/a-cbhama.ads
+++ b/gcc/ada/libgnat/a-cbhama.ads
@@ -59,12 +59,13 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Named => Insert);
+ Add_Named => Insert),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization
+ and
+ Key_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Map);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Map : constant Map;
-- Map objects declared without an initialization expression are
diff --git a/gcc/ada/libgnat/a-cbhase.ads b/gcc/ada/libgnat/a-cbhase.ads
index 92926c1..78b31cf 100644
--- a/gcc/ada/libgnat/a-cbhase.ads
+++ b/gcc/ada/libgnat/a-cbhase.ads
@@ -61,12 +61,11 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Include);
+ Add_Unnamed => Include),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Set);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Set : constant Set;
-- Set objects declared without an initialization expression are
diff --git a/gcc/ada/libgnat/a-cbmutr.ads b/gcc/ada/libgnat/a-cbmutr.ads
index c7e221a..3712039 100644
--- a/gcc/ada/libgnat/a-cbmutr.ads
+++ b/gcc/ada/libgnat/a-cbmutr.ads
@@ -53,11 +53,11 @@ is
with Constant_Indexing => Constant_Reference,
Variable_Indexing => Reference,
Default_Iterator => Iterate,
- Iterator_Element => Element_Type;
- pragma Preelaborable_Initialization (Tree);
+ Iterator_Element => Element_Type,
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Tree : constant Tree;
diff --git a/gcc/ada/libgnat/a-cborma.ads b/gcc/ada/libgnat/a-cborma.ads
index f87522a..9d40a51 100644
--- a/gcc/ada/libgnat/a-cborma.ads
+++ b/gcc/ada/libgnat/a-cborma.ads
@@ -60,12 +60,13 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Named => Insert);
+ Add_Named => Insert),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization
+ and
+ Key_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Map);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Map : constant Map;
diff --git a/gcc/ada/libgnat/a-cborse.ads b/gcc/ada/libgnat/a-cborse.ads
index 06bd20f..31b8b91 100644
--- a/gcc/ada/libgnat/a-cborse.ads
+++ b/gcc/ada/libgnat/a-cborse.ads
@@ -59,12 +59,11 @@ is
Default_Iterator => Iterate,
Iterator_Element => Element_Type,
Aggregate => (Empty => Empty,
- Add_Unnamed => Include);
+ Add_Unnamed => Include),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Set);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Set : constant Set;
diff --git a/gcc/ada/libgnat/a-cfdlli.ads b/gcc/ada/libgnat/a-cfdlli.ads
index 590643e..ded496b 100644
--- a/gcc/ada/libgnat/a-cfdlli.ads
+++ b/gcc/ada/libgnat/a-cfdlli.ads
@@ -44,6 +44,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
type List (Capacity : Count_Type) is private with
diff --git a/gcc/ada/libgnat/a-cfhama.ads b/gcc/ada/libgnat/a-cfhama.ads
index 2b49c13..59e295d 100644
--- a/gcc/ada/libgnat/a-cfhama.ads
+++ b/gcc/ada/libgnat/a-cfhama.ads
@@ -69,6 +69,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
type Map (Capacity : Count_Type; Modulus : Hash_Type) is private with
diff --git a/gcc/ada/libgnat/a-cfhase.ads b/gcc/ada/libgnat/a-cfhase.ads
index 9bcd8ce..23b3b6d 100644
--- a/gcc/ada/libgnat/a-cfhase.ads
+++ b/gcc/ada/libgnat/a-cfhase.ads
@@ -67,6 +67,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
type Set (Capacity : Count_Type; Modulus : Hash_Type) is private with
diff --git a/gcc/ada/libgnat/a-cfinve.ads b/gcc/ada/libgnat/a-cfinve.ads
index 9b95437..bd0c334 100644
--- a/gcc/ada/libgnat/a-cfinve.ads
+++ b/gcc/ada/libgnat/a-cfinve.ads
@@ -60,6 +60,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
subtype Extended_Index is Index_Type'Base
diff --git a/gcc/ada/libgnat/a-cforma.ads b/gcc/ada/libgnat/a-cforma.ads
index a1cad03..048e7cb 100644
--- a/gcc/ada/libgnat/a-cforma.ads
+++ b/gcc/ada/libgnat/a-cforma.ads
@@ -68,6 +68,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
function Equivalent_Keys (Left, Right : Key_Type) return Boolean with
diff --git a/gcc/ada/libgnat/a-cforse.ads b/gcc/ada/libgnat/a-cforse.ads
index e1d7c91..db7c586 100644
--- a/gcc/ada/libgnat/a-cforse.ads
+++ b/gcc/ada/libgnat/a-cforse.ads
@@ -64,6 +64,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
function Equivalent_Elements (Left, Right : Element_Type) return Boolean
diff --git a/gcc/ada/libgnat/a-chahan.adb b/gcc/ada/libgnat/a-chahan.adb
index 827794c..411d485 100644
--- a/gcc/ada/libgnat/a-chahan.adb
+++ b/gcc/ada/libgnat/a-chahan.adb
@@ -29,11 +29,19 @@
-- --
------------------------------------------------------------------------------
+-- Loop invariants in this unit are meant for analysis only, not for run-time
+-- checking, as it would be too costly otherwise. This is enforced by setting
+-- the assertion policy to Ignore.
+
+pragma Assertion_Policy (Loop_Invariant => Ignore);
+
with Ada.Characters.Latin_1; use Ada.Characters.Latin_1;
with Ada.Strings.Maps; use Ada.Strings.Maps;
with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
-package body Ada.Characters.Handling is
+package body Ada.Characters.Handling
+ with SPARK_Mode
+is
------------------------------------
-- Character Classification Table --
@@ -299,9 +307,7 @@ package body Ada.Characters.Handling is
------------------
function Is_Character (Item : Wide_Character) return Boolean is
- begin
- return Wide_Character'Pos (Item) < 256;
- end Is_Character;
+ (Wide_Character'Pos (Item) < 256);
----------------
-- Is_Control --
@@ -344,9 +350,7 @@ package body Ada.Characters.Handling is
----------------
function Is_ISO_646 (Item : Character) return Boolean is
- begin
- return Item in ISO_646;
- end Is_ISO_646;
+ (Item in ISO_646);
-- Note: much more efficient coding of the following function is possible
-- by testing several 16#80# bits in a complete word in a single operation
@@ -357,6 +361,8 @@ package body Ada.Characters.Handling is
if Item (J) not in ISO_646 then
return False;
end if;
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Is_ISO_646 (Item (K)));
end loop;
return True;
@@ -456,6 +462,8 @@ package body Ada.Characters.Handling is
if Wide_Character'Pos (Item (J)) >= 256 then
return False;
end if;
+ pragma Loop_Invariant
+ (for all K in Item'First .. J => Is_Character (Item (K)));
end loop;
return True;
@@ -475,15 +483,18 @@ package body Ada.Characters.Handling is
--------------
function To_Basic (Item : Character) return Character is
- begin
- return Value (Basic_Map, Item);
- end To_Basic;
+ (Value (Basic_Map, Item));
function To_Basic (Item : String) return String is
begin
- return Result : String (1 .. Item'Length) do
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
for J in Item'Range loop
Result (J - (Item'First - 1)) := Value (Basic_Map, Item (J));
+ pragma Loop_Invariant
+ (Result (1 .. J - Item'First + 1)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) = To_Basic (Item (K)));
end loop;
end return;
end To_Basic;
@@ -511,24 +522,25 @@ package body Ada.Characters.Handling is
function To_ISO_646
(Item : Character;
Substitute : ISO_646 := ' ') return ISO_646
- is
- begin
- return (if Item in ISO_646 then Item else Substitute);
- end To_ISO_646;
+ is (if Item in ISO_646 then Item else Substitute);
function To_ISO_646
(Item : String;
Substitute : ISO_646 := ' ') return String
is
- Result : String (1 .. Item'Length);
-
begin
- for J in Item'Range loop
- Result (J - (Item'First - 1)) :=
- (if Item (J) in ISO_646 then Item (J) else Substitute);
- end loop;
-
- return Result;
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
+ for J in Item'Range loop
+ Result (J - (Item'First - 1)) :=
+ (if Item (J) in ISO_646 then Item (J) else Substitute);
+ pragma Loop_Invariant
+ (Result (1 .. J - Item'First + 1)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) =
+ To_ISO_646 (Item (K), Substitute));
+ end loop;
+ end return;
end To_ISO_646;
--------------
@@ -536,15 +548,18 @@ package body Ada.Characters.Handling is
--------------
function To_Lower (Item : Character) return Character is
- begin
- return Value (Lower_Case_Map, Item);
- end To_Lower;
+ (Value (Lower_Case_Map, Item));
function To_Lower (Item : String) return String is
begin
- return Result : String (1 .. Item'Length) do
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
for J in Item'Range loop
Result (J - (Item'First - 1)) := Value (Lower_Case_Map, Item (J));
+ pragma Loop_Invariant
+ (Result (1 .. J - Item'First + 1)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) = To_Lower (Item (K)));
end loop;
end return;
end To_Lower;
@@ -557,34 +572,40 @@ package body Ada.Characters.Handling is
(Item : Wide_String;
Substitute : Character := ' ') return String
is
- Result : String (1 .. Item'Length);
-
begin
- for J in Item'Range loop
- Result (J - (Item'First - 1)) := To_Character (Item (J), Substitute);
- end loop;
-
- return Result;
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
+ for J in Item'Range loop
+ Result (J - (Item'First - 1)) :=
+ To_Character (Item (J), Substitute);
+ pragma Loop_Invariant
+ (Result (1 .. J - (Item'First - 1))'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) =
+ To_Character (Item (K), Substitute));
+ end loop;
+ end return;
end To_String;
--------------
-- To_Upper --
--------------
- function To_Upper
- (Item : Character) return Character
- is
- begin
- return Value (Upper_Case_Map, Item);
- end To_Upper;
+ function To_Upper (Item : Character) return Character is
+ (Value (Upper_Case_Map, Item));
function To_Upper
(Item : String) return String
is
begin
- return Result : String (1 .. Item'Length) do
+ return Result : String (1 .. Item'Length) with Relaxed_Initialization do
for J in Item'Range loop
Result (J - (Item'First - 1)) := Value (Upper_Case_Map, Item (J));
+ pragma Loop_Invariant
+ (Result (1 .. J - Item'First + 1)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) = To_Upper (Item (K)));
end loop;
end return;
end To_Upper;
@@ -607,14 +628,19 @@ package body Ada.Characters.Handling is
function To_Wide_String
(Item : String) return Wide_String
is
- Result : Wide_String (1 .. Item'Length);
-
begin
- for J in Item'Range loop
- Result (J - (Item'First - 1)) := To_Wide_Character (Item (J));
- end loop;
-
- return Result;
+ return Result : Wide_String (1 .. Item'Length)
+ with Relaxed_Initialization
+ do
+ for J in Item'Range loop
+ Result (J - (Item'First - 1)) := To_Wide_Character (Item (J));
+ pragma Loop_Invariant
+ (Result (1 .. J - (Item'First - 1))'Initialized);
+ pragma Loop_Invariant
+ (for all K in Item'First .. J =>
+ Result (K - (Item'First - 1)) = To_Wide_Character (Item (K)));
+ end loop;
+ end return;
end To_Wide_String;
end Ada.Characters.Handling;
diff --git a/gcc/ada/libgnat/a-chahan.ads b/gcc/ada/libgnat/a-chahan.ads
index 2f93e7c..093237d 100644
--- a/gcc/ada/libgnat/a-chahan.ads
+++ b/gcc/ada/libgnat/a-chahan.ads
@@ -33,7 +33,16 @@
-- --
------------------------------------------------------------------------------
-package Ada.Characters.Handling is
+-- Postconditions in this unit are meant for analysis only, not for run-time
+-- checking, in order not to slow down the execution of these functions.
+
+pragma Assertion_Policy (Post => Ignore);
+
+with Ada.Characters.Latin_1;
+
+package Ada.Characters.Handling
+ with SPARK_Mode
+is
pragma Pure;
-- In accordance with Ada 2005 AI-362
@@ -41,54 +50,296 @@ package Ada.Characters.Handling is
-- Character Classification Functions --
----------------------------------------
- function Is_Control (Item : Character) return Boolean;
- function Is_Graphic (Item : Character) return Boolean;
- function Is_Letter (Item : Character) return Boolean;
- function Is_Lower (Item : Character) return Boolean;
- function Is_Upper (Item : Character) return Boolean;
- function Is_Basic (Item : Character) return Boolean;
- function Is_Digit (Item : Character) return Boolean;
+ -- 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.
+ --
+ -- Each of the following classification functions has a formal Character
+ -- parameter, Item, and returns a Boolean result.
+
+ function Is_Control (Item : Character) return Boolean
+ with
+ Post => Is_Control'Result =
+ (Character'Pos (Item) in 0 .. 31 | 127 .. 159);
+ -- 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.
+
+ function Is_Graphic (Item : Character) return Boolean
+ with
+ Post => Is_Graphic'Result =
+ (Character'Pos (Item) in 32 .. 126 | 160 .. 255);
+ -- 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.
+
+ function Is_Letter (Item : Character) return Boolean
+ with
+ Post => Is_Letter'Result =
+ (Item in 'A' .. 'Z' | 'a' .. 'z'
+ or else Character'Pos (Item) in 192 .. 214 | 216 .. 246 | 248 .. 255);
+ -- 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.
+
+ function Is_Lower (Item : Character) return Boolean
+ with
+ Post => Is_Lower'Result =
+ (Item in 'a' .. 'z'
+ or else Character'Pos (Item) in 223 .. 246 | 248 .. 255);
+ -- 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.
+
+ function Is_Upper (Item : Character) return Boolean
+ with
+ Post => Is_Upper'Result =
+ (Item in 'A' .. 'Z'
+ or else Character'Pos (Item) in 192 .. 214 | 216 .. 222);
+ -- 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.
+
+ function Is_Basic (Item : Character) return Boolean
+ with
+ Post => Is_Basic'Result =
+ (Item in 'A' .. 'Z'
+ | 'a' .. 'z'
+ | Latin_1.UC_AE_Diphthong
+ | Latin_1.LC_AE_Diphthong
+ | Latin_1.UC_Icelandic_Eth
+ | Latin_1.LC_Icelandic_Eth
+ | Latin_1.UC_Icelandic_Thorn
+ | Latin_1.LC_Icelandic_Thorn
+ | Latin_1.LC_German_Sharp_S);
+ -- 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: UC_AE_Diphthong, LC_AE_Diphthong, UC_Icelandic_Eth,
+ -- LC_Icelandic_Eth, UC_Icelandic_Thorn, LC_Icelandic_Thorn, or
+ -- LC_German_Sharp_S.
+
+ function Is_Digit (Item : Character) return Boolean
+ with
+ Post => Is_Digit'Result = (Item in '0' .. '9');
+ -- True if Item is a decimal digit. A decimal digit is a character in the
+ -- range '0'..'9'.
+
function Is_Decimal_Digit (Item : Character) return Boolean
renames Is_Digit;
- function Is_Hexadecimal_Digit (Item : Character) return Boolean;
- function Is_Alphanumeric (Item : Character) return Boolean;
- function Is_Special (Item : Character) return Boolean;
- function Is_Line_Terminator (Item : Character) return Boolean;
- function Is_Mark (Item : Character) return Boolean;
- function Is_Other_Format (Item : Character) return Boolean;
- function Is_Punctuation_Connector (Item : Character) return Boolean;
- function Is_Space (Item : Character) return Boolean;
- function Is_NFKC (Item : Character) return Boolean;
+
+ function Is_Hexadecimal_Digit (Item : Character) return Boolean
+ with
+ Post => Is_Hexadecimal_Digit'Result =
+ (Is_Decimal_Digit (Item) or Item in 'A' .. 'F' | 'a' .. 'f');
+ -- 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'.
+
+ function Is_Alphanumeric (Item : Character) return Boolean
+ with
+ Post => Is_Alphanumeric'Result =
+ (Is_Letter (Item) or Is_Decimal_Digit (Item));
+ -- True if Item is an alphanumeric character. An alphanumeric character is
+ -- a character that is either a letter or a decimal digit.
+
+ function Is_Special (Item : Character) return Boolean
+ with
+ Post => Is_Special'Result =
+ (Is_Graphic (Item) and not Is_Alphanumeric (Item));
+ -- True if Item is a special graphic character. A special graphic character
+ -- is a graphic character that is not alphanumeric.
+
+ function Is_Line_Terminator (Item : Character) return Boolean
+ with
+ Post => Is_Line_Terminator'Result =
+ (Character'Pos (Item) in 10 .. 13 | 133);
+ -- True if Item is a character with position 10..13 (Line_Feed,
+ -- Line_Tabulation, Form_Feed, Carriage_Return) or 133 (Next_Line).
+
+ function Is_Mark (Item : Character) return Boolean
+ with
+ Post => Is_Mark'Result = False;
+ -- Never True (no value of type Character has categories Mark, Non-Spacing
+ -- or Mark, Spacing Combining).
+
+ function Is_Other_Format (Item : Character) return Boolean
+ with
+ Post => Is_Other_Format'Result = (Character'Pos (Item) = 173);
+ -- True if Item is a character with position 173 (Soft_Hyphen).
+
+ function Is_Punctuation_Connector (Item : Character) return Boolean
+ with
+ Post => Is_Punctuation_Connector'Result =
+ (Character'Pos (Item) = 95);
+ -- True if Item is a character with position 95 ('_', known as Low_Line or
+ -- Underscore).
+
+ function Is_Space (Item : Character) return Boolean
+ with
+ Post => Is_Space'Result = (Character'Pos (Item) in 32 | 160);
+ -- True if Item is a character with position 32 (' ') or 160
+ -- (No_Break_Space).
+
+ function Is_NFKC (Item : Character) return Boolean
+ with
+ Post => Is_NFKC'Result =
+ (Character'Pos (Item) not in
+ 160 | 168 | 170 | 175 | 178 | 179 | 180
+ | 181 | 184 | 185 | 186 | 188 | 189 | 190);
+ -- True if Item could be present in a string normalized to Normalization
+ -- Form KC (as defined by Clause 21 of ISO/IEC 10646:2017); this includes
+ -- all characters except those with positions 160, 168, 170, 175, 178, 179,
+ -- 180, 181, 184, 185, 186, 188, 189, and 190.
---------------------------------------------------
-- Conversion Functions for Character and String --
---------------------------------------------------
- function To_Lower (Item : Character) return Character;
- function To_Upper (Item : Character) return Character;
- function To_Basic (Item : Character) return Character;
+ -- 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.
+
+ function To_Lower (Item : Character) return Character
+ with
+ Post => To_Lower'Result =
+ (if Is_Upper (Item) then
+ Character'Val (Character'Pos (Item) +
+ (if Item in 'A' .. 'Z' then
+ Character'Pos ('a') - Character'Pos ('A')
+ else
+ Character'Pos (Latin_1.LC_A_Grave)
+ - Character'Pos (Latin_1.UC_A_Grave)))
+ else
+ Item);
+ -- Returns the corresponding lower-case value for Item if Is_Upper(Item),
+ -- and returns Item otherwise.
- function To_Lower (Item : String) return String;
- function To_Upper (Item : String) return String;
- function To_Basic (Item : String) return String;
+ function To_Upper (Item : Character) return Character
+ with
+ Post => To_Upper'Result =
+ (if Is_Lower (Item)
+ and then Item not in Latin_1.LC_German_Sharp_S
+ | Latin_1.LC_Y_Diaeresis
+ then
+ Character'Val (Character'Pos (Item) +
+ (if Item in 'A' .. 'Z' then
+ Character'Pos ('A') - Character'Pos ('a')
+ else
+ Character'Pos (Latin_1.UC_A_Grave)
+ - Character'Pos (Latin_1.LC_A_Grave)))
+ else
+ Item);
+ -- 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 LC_German_Sharp_S and LC_Y_Diaeresis do not have upper case
+ -- forms.
+
+ function To_Basic (Item : Character) return Character
+ with
+ Post => To_Basic'Result =
+ (if not Is_Letter (Item) or else Is_Basic (Item) then
+ Item
+ else
+ (case Item is
+ when Latin_1.UC_A_Grave .. Latin_1.UC_A_Ring => 'A',
+ when Latin_1.UC_C_Cedilla => 'C',
+ when Latin_1.UC_E_Grave .. Latin_1.UC_E_Diaeresis => 'E',
+ when Latin_1.UC_I_Grave .. Latin_1.UC_I_Diaeresis => 'I',
+ when Latin_1.UC_N_Tilde => 'N',
+ when Latin_1.UC_O_Grave .. Latin_1.UC_O_Diaeresis => 'O',
+ when Latin_1.UC_O_Oblique_Stroke => 'O',
+ when Latin_1.UC_U_Grave .. Latin_1.UC_U_Diaeresis => 'U',
+ when Latin_1.UC_Y_Acute => 'Y',
+ when Latin_1.LC_A_Grave .. Latin_1.LC_A_Ring => 'a',
+ when Latin_1.LC_C_Cedilla => 'c',
+ when Latin_1.LC_E_Grave .. Latin_1.LC_E_Diaeresis => 'e',
+ when Latin_1.LC_I_Grave .. Latin_1.LC_I_Diaeresis => 'i',
+ when Latin_1.LC_N_Tilde => 'n',
+ when Latin_1.LC_O_Grave .. Latin_1.LC_O_Diaeresis => 'o',
+ when Latin_1.LC_O_Oblique_Stroke => 'o',
+ when Latin_1.LC_U_Grave .. Latin_1.LC_U_Diaeresis => 'u',
+ when Latin_1.LC_Y_Acute => 'y',
+ when Latin_1.LC_Y_Diaeresis => 'y',
+ when others => raise Program_Error));
+ -- Returns the letter corresponding to Item but with no diacritical mark,
+ -- if Item is a letter but not a basic letter; returns Item otherwise.
+
+ function To_Lower (Item : String) return String
+ with
+ Post => To_Lower'Result'First = 1
+ and then To_Lower'Result'Length = Item'Length
+ and then
+ (for all J in To_Lower'Result'Range =>
+ To_Lower'Result (J) = To_Lower (Item (Item'First + (J - 1))));
+
+ function To_Upper (Item : String) return String
+ with
+ Post => To_Upper'Result'First = 1
+ and then To_Upper'Result'Length = Item'Length
+ and then
+ (for all J in To_Upper'Result'Range =>
+ To_Upper'Result (J) = To_Upper (Item (Item'First + (J - 1))));
+
+ function To_Basic (Item : String) return String
+ with
+ Post => To_Basic'Result'First = 1
+ and then To_Basic'Result'Length = Item'Length
+ and then
+ (for all J in To_Basic'Result'Range =>
+ To_Basic'Result (J) = To_Basic (Item (Item'First + (J - 1))));
----------------------------------------------------------------------
-- Classifications of and Conversions Between Character and ISO 646 --
----------------------------------------------------------------------
+ -- The following set of functions test for membership in the ISO 646
+ -- character range, or convert between ISO 646 and Character.
+
subtype ISO_646 is
Character range Character'Val (0) .. Character'Val (127);
- function Is_ISO_646 (Item : Character) return Boolean;
- function Is_ISO_646 (Item : String) return Boolean;
+ function Is_ISO_646 (Item : Character) return Boolean
+ with
+ Post => Is_ISO_646'Result = (Item in ISO_646);
+ -- The function whose formal parameter, Item, is of type Character returns
+ -- True if Item is in the subtype ISO_646.
+
+ function Is_ISO_646 (Item : String) return Boolean
+ with
+ Post => Is_ISO_646'Result =
+ (for all J in Item'Range => Is_ISO_646 (Item (J)));
+ -- 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.
function To_ISO_646
(Item : Character;
- Substitute : ISO_646 := ' ') return ISO_646;
+ Substitute : ISO_646 := ' ') return ISO_646
+ with
+ Post => To_ISO_646'Result =
+ (if Is_ISO_646 (Item) then Item else Substitute);
+ -- 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.
function To_ISO_646
(Item : String;
- Substitute : ISO_646 := ' ') return String;
+ Substitute : ISO_646 := ' ') return String
+ with
+ Post => To_ISO_646'Result'First = 1
+ and then To_ISO_646'Result'Length = Item'Length
+ and then
+ (for all J in To_ISO_646'Result'Range =>
+ To_ISO_646'Result (J) =
+ To_ISO_646 (Item (Item'First + (J - 1)), Substitute));
+ -- 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.
------------------------------------------------------
-- Classifications of Wide_Character and Characters --
@@ -103,8 +354,18 @@ package Ada.Characters.Handling is
-- We do however have to flag these if the pragma No_Obsolescent_Features
-- restriction is active (see Restrict.Check_Obsolescent_2005_Entity).
- function Is_Character (Item : Wide_Character) return Boolean;
- function Is_String (Item : Wide_String) return Boolean;
+ function Is_Character (Item : Wide_Character) return Boolean
+ with
+ Post => Is_Character'Result =
+ (Wide_Character'Pos (Item) <= Character'Pos (Character'Last));
+ -- Returns True if Wide_Character'Pos(Item) <=
+ -- Character'Pos(Character'Last).
+
+ function Is_String (Item : Wide_String) return Boolean
+ with
+ Post => Is_String'Result =
+ (for all I in Item'Range => Is_Character (Item (I)));
+ -- Returns True if Is_Character(Item(I)) is True for each I in Item'Range.
------------------------------------------------------
-- Conversions between Wide_Character and Character --
@@ -121,17 +382,49 @@ package Ada.Characters.Handling is
function To_Character
(Item : Wide_Character;
- Substitute : Character := ' ') return Character;
+ Substitute : Character := ' ') return Character
+ with
+ Post => To_Character'Result =
+ (if Is_Character (Item) then
+ Character'Val (Wide_Character'Pos (Item))
+ else
+ Substitute);
+ -- Returns the Character corresponding to Item if Is_Character(Item), and
+ -- returns the Substitute Character otherwise.
function To_String
(Item : Wide_String;
- Substitute : Character := ' ') return String;
+ Substitute : Character := ' ') return String
+ with
+ Post => To_String'Result'First = 1
+ and then To_String'Result'Length = Item'Length
+ and then
+ (for all J in To_String'Result'Range =>
+ To_String'Result (J) =
+ To_Character (Item (Item'First + (J - 1)), Substitute));
+ -- 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.
function To_Wide_Character
- (Item : Character) return Wide_Character;
+ (Item : Character) return Wide_Character
+ with
+ Post => To_Wide_Character'Result =
+ Wide_Character'Val (Character'Pos (Item));
+ -- Returns the Wide_Character X such that Character'Pos(Item) =
+ -- Wide_Character'Pos (X).
function To_Wide_String
- (Item : String) return Wide_String;
+ (Item : String) return Wide_String
+ with
+ Post => To_Wide_String'Result'First = 1
+ and then To_Wide_String'Result'Length = Item'Length
+ and then
+ (for all J in To_Wide_String'Result'Range =>
+ To_Wide_String'Result (J) =
+ To_Wide_Character (Item (Item'First + (J - 1))));
+ -- 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.
private
pragma Inline (Is_Alphanumeric);
diff --git a/gcc/ada/libgnat/a-coboho.ads b/gcc/ada/libgnat/a-coboho.ads
index 086f194..44269f0 100644
--- a/gcc/ada/libgnat/a-coboho.ads
+++ b/gcc/ada/libgnat/a-coboho.ads
@@ -70,7 +70,9 @@ package Ada.Containers.Bounded_Holders is
-- System.Storage_Unit; e.g. creating Holders from 5-bit objects won't
-- work.
- type Holder is private;
+ type Holder is private
+ with Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
function "=" (Left, Right : Holder) return Boolean;
diff --git a/gcc/ada/libgnat/a-cobove.ads b/gcc/ada/libgnat/a-cobove.ads
index 67c4419..5f3e1a7 100644
--- a/gcc/ada/libgnat/a-cobove.ads
+++ b/gcc/ada/libgnat/a-cobove.ads
@@ -63,12 +63,11 @@ package Ada.Containers.Bounded_Vectors is
Aggregate => (Empty => Empty,
Add_Unnamed => Append,
New_Indexed => New_Vector,
- Assign_Indexed => Replace_Element);
+ Assign_Indexed => Replace_Element),
+ Preelaborable_Initialization
+ => Element_Type'Preelaborable_Initialization;
- pragma Preelaborable_Initialization (Vector);
-
- type Cursor is private;
- pragma Preelaborable_Initialization (Cursor);
+ type Cursor is private with Preelaborable_Initialization;
Empty_Vector : constant Vector;
diff --git a/gcc/ada/libgnat/a-cofove.ads b/gcc/ada/libgnat/a-cofove.ads
index a4ed7e5..6d3f486 100644
--- a/gcc/ada/libgnat/a-cofove.ads
+++ b/gcc/ada/libgnat/a-cofove.ads
@@ -50,6 +50,7 @@ is
pragma Assertion_Policy (Pre => Ignore);
pragma Assertion_Policy (Post => Ignore);
+ pragma Assertion_Policy (Contract_Cases => Ignore);
pragma Annotate (CodePeer, Skip_Analysis);
subtype Extended_Index is Index_Type'Base
diff --git a/gcc/ada/libgnat/a-except.adb b/gcc/ada/libgnat/a-except.adb
index c332afa..5933928 100644
--- a/gcc/ada/libgnat/a-except.adb
+++ b/gcc/ada/libgnat/a-except.adb
@@ -629,6 +629,96 @@ package body Ada.Exceptions is
pragma No_Return (Rcheck_CE_Invalid_Data_Ext);
pragma No_Return (Rcheck_CE_Range_Check_Ext);
+ -- Make all of these procedures callable from strub contexts.
+ -- These attributes are not visible to callers; they are made
+ -- visible in trans.c:build_raise_check.
+
+ pragma Machine_Attribute (Rcheck_CE_Access_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Null_Access_Parameter,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Discriminant_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Divide_By_Zero,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Explicit_Raise,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Index_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Invalid_Data,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Length_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Null_Exception_Id,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Null_Not_Allowed,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Overflow_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Partition_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Range_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Tag_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Access_Before_Elaboration,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Accessibility_Check,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Address_Of_Intrinsic,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Aliased_Parameters,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_All_Guards_Closed,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Bad_Predicated_Generic_Type,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Build_In_Place_Mismatch,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Current_Task_In_Entry_Body,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Duplicated_Entry_Address,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Explicit_Raise,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Implicit_Return,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Misaligned_Address_Value,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Missing_Return,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Non_Transportable_Actual,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Overlaid_Controlled_Object,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Potentially_Blocking_Operation,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Stream_Operation_Not_Allowed,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Stubbed_Subprogram_Called,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Unchecked_Union_Restriction,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_PE_Finalize_Raised_Exception,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_SE_Empty_Storage_Pool,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_SE_Explicit_Raise,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_SE_Infinite_Recursion,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_SE_Object_Too_Large,
+ "strub", "callable");
+
+ pragma Machine_Attribute (Rcheck_CE_Access_Check_Ext,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Index_Check_Ext,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Invalid_Data_Ext,
+ "strub", "callable");
+ pragma Machine_Attribute (Rcheck_CE_Range_Check_Ext,
+ "strub", "callable");
+
---------------------------------------------
-- Reason Strings for Run-Time Check Calls --
---------------------------------------------
diff --git a/gcc/ada/libgnat/a-except.ads b/gcc/ada/libgnat/a-except.ads
index 2b27adb..1608e79 100644
--- a/gcc/ada/libgnat/a-except.ads
+++ b/gcc/ada/libgnat/a-except.ads
@@ -184,6 +184,15 @@ private
-- Raise_Exception_Always if it can determine this is the case. The Export
-- allows this routine to be accessed from Pure units.
+ -- Make these callable from strub contexts.
+ pragma Machine_Attribute (Raise_Exception_Always,
+ "strub", "callable");
+ pragma Machine_Attribute (Raise_Exception,
+ "strub", "callable");
+ -- This property should arguably be visible to callers, but let's
+ -- keep it private for now. In practice, it doesn't matter, since
+ -- it's only checked in the back end.
+
procedure Raise_From_Controlled_Operation (X : Exception_Occurrence);
pragma No_Return (Raise_From_Controlled_Operation);
pragma Export
diff --git a/gcc/ada/libgnat/a-strbou.adb b/gcc/ada/libgnat/a-strbou.adb
index 61b3d73..01a2002 100644
--- a/gcc/ada/libgnat/a-strbou.adb
+++ b/gcc/ada/libgnat/a-strbou.adb
@@ -29,7 +29,7 @@
-- --
------------------------------------------------------------------------------
-package body Ada.Strings.Bounded is
+package body Ada.Strings.Bounded with SPARK_Mode is
package body Generic_Bounded_Length is
diff --git a/gcc/ada/libgnat/a-strbou.ads b/gcc/ada/libgnat/a-strbou.ads
index f0cf7b2..e820184 100644
--- a/gcc/ada/libgnat/a-strbou.ads
+++ b/gcc/ada/libgnat/a-strbou.ads
@@ -33,25 +33,41 @@
-- --
------------------------------------------------------------------------------
--- Preconditions in this unit are meant for analysis only, not for run-time
--- checking, so that the expected exceptions are raised. This is enforced by
--- setting the corresponding assertion policy to Ignore.
-
-pragma Assertion_Policy (Pre => Ignore);
-
-with Ada.Strings.Maps;
+-- 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.
+
+with Ada.Strings.Maps; use type Ada.Strings.Maps.Character_Mapping_Function;
with Ada.Strings.Superbounded;
+with Ada.Strings.Search;
-package Ada.Strings.Bounded is
+package Ada.Strings.Bounded with SPARK_Mode is
pragma Preelaborate;
generic
Max : Positive;
-- Maximum length of a Bounded_String
- package Generic_Bounded_Length with
- Initial_Condition => Length (Null_Bounded_String) = 0
+ package Generic_Bounded_Length with SPARK_Mode,
+ Initial_Condition => Length (Null_Bounded_String) = 0,
+ Abstract_State => null
is
+ -- Preconditions in this unit are meant for analysis only, not for
+ -- run-time checking, so that the expected exceptions are raised. This
+ -- is enforced by setting the corresponding assertion policy to Ignore.
+ -- Postconditions and contract cases should not be executed at runtime
+ -- as well, in order not to slow down the execution of these functions.
+
+ pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Contract_Cases => Ignore,
+ Ghost => Ignore);
Max_Length : constant Positive := Max;
@@ -59,11 +75,16 @@ package Ada.Strings.Bounded is
pragma Preelaborable_Initialization (Bounded_String);
Null_Bounded_String : constant Bounded_String;
+ -- 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.
subtype Length_Range is Natural range 0 .. Max_Length;
function Length (Source : Bounded_String) return Length_Range with
Global => null;
+ -- The Length function returns the length of the string represented by
+ -- Source.
--------------------------------------------------------
-- Conversion, Concatenation, and Selection Functions --
@@ -73,163 +94,466 @@ package Ada.Strings.Bounded is
(Source : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Source'Length > Max_Length then Drop /= Error),
- Post =>
- Length (To_Bounded_String'Result)
- = Natural'Min (Max_Length, Source'Length),
- Global => null;
+ Pre => (if Source'Length > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Source'Length <= Max_Length
+ =>
+ To_String (To_Bounded_String'Result) = Source,
+
+ Source'Length > Max_Length and then Drop = Left
+ =>
+ To_String (To_Bounded_String'Result) =
+ Source (Source'Last - Max_Length + 1 .. Source'Last),
+
+ others -- Drop = Right
+ =>
+ To_String (To_Bounded_String'Result) =
+ Source (Source'First .. Source'First - 1 + Max_Length));
+ -- If Source'Length <= Max_Length, then this function returns a
+ -- Bounded_String that represents Source. Otherwise, the effect
+ -- depends on the value of Drop:
+ --
+ -- * If Drop=Left, then the result is a Bounded_String that represents
+ -- the string comprising the rightmost Max_Length characters of
+ -- Source.
+ --
+ -- * If Drop=Right, then the result is a Bounded_String that represents
+ -- the string comprising the leftmost Max_Length characters of Source.
+ --
+ -- * If Drop=Error, then Strings.Length_Error is propagated.
function To_String (Source : Bounded_String) return String with
- Post => To_String'Result'Length = Length (Source),
Global => null;
+ -- 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)).
procedure Set_Bounded_String
(Target : out Bounded_String;
Source : String;
Drop : Truncation := Error)
with
- Pre => (if Source'Length > Max_Length then Drop /= Error),
- Post => Length (Target) = Natural'Min (Max_Length, Source'Length),
- Global => null;
+ Pre => (if Source'Length > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Source'Length <= Max_Length
+ =>
+ To_String (Target) = Source,
+
+ Source'Length > Max_Length and then Drop = Left
+ =>
+ To_String (Target) =
+ Source (Source'Last - Max_Length + 1 .. Source'Last),
+
+ others -- Drop = Right
+ =>
+ To_String (Target) =
+ Source (Source'First .. Source'First - 1 + Max_Length));
pragma Ada_05 (Set_Bounded_String);
+ -- Equivalent to Target := To_Bounded_String (Source, Drop);
+
+ -- 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.
function Append
(Left : Bounded_String;
Right : Bounded_String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
(if Length (Left) > Max_Length - Length (Right)
then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, Length (Left) + Length (Right)),
- Global => null;
+ Contract_Cases =>
+ (Length (Left) <= Max_Length - Length (Right)
+ =>
+ Length (Append'Result) = Length (Left) + Length (Right)
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Length (Right) > 0 then
+ Slice (Append'Result,
+ Length (Left) + 1, Length (Append'Result)) =
+ To_String (Right)),
+
+ Length (Left) > Max_Length - Length (Right)
+ and then Drop = Strings.Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ (if Length (Right) < Max_Length then
+ Slice (Append'Result, 1, Max_Length - Length (Right)) =
+ Slice (Left,
+ Length (Left) - Max_Length + Length (Right) + 1,
+ Length (Left)))
+ and then
+ Slice (Append'Result,
+ Max_Length - Length (Right) + 1, Max_Length) =
+ To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Length (Left) < Max_Length then
+ Slice (Append'Result, Length (Left) + 1, Max_Length) =
+ Slice (Right, 1, Max_Length - Length (Left))));
function Append
(Left : Bounded_String;
Right : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
(if Right'Length > Max_Length - Length (Left)
then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, Length (Left) + Right'Length),
- Global => null;
-
+ Contract_Cases =>
+ (Length (Left) <= Max_Length - Right'Length
+ =>
+ Length (Append'Result) = Length (Left) + Right'Length
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Right'Length > 0 then
+ Slice (Append'Result,
+ Length (Left) + 1, Length (Append'Result)) =
+ Right),
+
+ Length (Left) > Max_Length - Right'Length
+ and then Drop = Strings.Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ (if Right'Length < Max_Length then
+
+ -- The result is the end of Left followed by Right
+
+ Slice (Append'Result, 1, Max_Length - Right'Length) =
+ Slice (Left,
+ Length (Left) - Max_Length + Right'Length + 1,
+ Length (Left))
+ and then
+ Slice (Append'Result,
+ Max_Length - Right'Length + 1, Max_Length) =
+ Right
+ else
+ -- The result is the last Max_Length characters of Right
+
+ To_String (Append'Result) =
+ Right (Right'Last - Max_Length + 1 .. Right'Last)),
+
+ others -- Drop = Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Length (Left) < Max_Length then
+ Slice (Append'Result, Length (Left) + 1, Max_Length) =
+ Right (Right'First
+ .. Max_Length - Length (Left) - 1 + Right'First)));
function Append
(Left : String;
Right : Bounded_String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
(if Left'Length > Max_Length - Length (Right)
then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, Left'Length + Length (Right)),
- Global => null;
+ Contract_Cases =>
+ (Left'Length <= Max_Length - Length (Right)
+ =>
+ Length (Append'Result) = Left'Length + Length (Right)
+ and then Slice (Append'Result, 1, Left'Length) = Left
+ and then
+ (if Length (Right) > 0 then
+ Slice (Append'Result,
+ Left'Length + 1, Length (Append'Result)) =
+ To_String (Right)),
+
+ Left'Length > Max_Length - Length (Right)
+ and then Drop = Strings.Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ (if Length (Right) < Max_Length then
+ Slice (Append'Result, 1, Max_Length - Length (Right)) =
+ Left (Left'Last - Max_Length + Length (Right) + 1
+ .. Left'Last))
+ and then
+ Slice (Append'Result,
+ Max_Length - Length (Right) + 1, Max_Length) =
+ To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ (if Left'Length < Max_Length then
+
+ -- The result is Left followed by the beginning of Right
+
+ Slice (Append'Result, 1, Left'Length) = Left
+ and then
+ Slice (Append'Result, Left'Length + 1, Max_Length) =
+ Slice (Right, 1, Max_Length - Left'Length)
+ else
+ -- The result is the first Max_Length characters of Left
+
+ To_String (Append'Result) =
+ Left (Left'First .. Max_Length - 1 + Left'First)));
function Append
(Left : Bounded_String;
Right : Character;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Length (Left) = Max_Length then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, Length (Left) + 1),
- Global => null;
+ Pre => (if Length (Left) = Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Length (Left) < Max_Length
+ =>
+ Length (Append'Result) = Length (Left) + 1
+ and then
+ Slice (Append'Result, 1, Length (Left)) = To_String (Left)
+ and then Element (Append'Result, Length (Left) + 1) = Right,
+
+ Length (Left) = Max_Length and then Drop = Strings.Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then To_String (Append'Result) = To_String (Left),
+
+ others -- Drop = Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ Slice (Append'Result, 1, Max_Length - 1) =
+ Slice (Left, 2, Max_Length)
+ and then Element (Append'Result, Max_Length) = Right);
function Append
(Left : Character;
Right : Bounded_String;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Length (Right) = Max_Length then Drop /= Error),
- Post =>
- Length (Append'Result)
- = Natural'Min (Max_Length, 1 + Length (Right)),
- Global => null;
+ Pre => (if Length (Right) = Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Length (Right) < Max_Length
+ =>
+ Length (Append'Result) = Length (Right) + 1
+ and then
+ Slice (Append'Result, 2, Length (Right) + 1) =
+ To_String (Right)
+ and then Element (Append'Result, 1) = Left,
+
+ Length (Right) = Max_Length and then Drop = Strings.Left
+ =>
+ Length (Append'Result) = Max_Length
+ and then To_String (Append'Result) = To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Length (Append'Result) = Max_Length
+ and then
+ Slice (Append'Result, 2, Max_Length) =
+ Slice (Right, 1, Max_Length - 1)
+ and then Element (Append'Result, 1) = Left);
+
+ -- Each of the procedures Append(Source, New_Item, Drop) has the same
+ -- effect as the corresponding assignment
+ -- Source := Append(Source, New_Item, Drop).
procedure Append
(Source : in out Bounded_String;
New_Item : Bounded_String;
Drop : Truncation := Error)
with
- Pre =>
+ Pre =>
(if Length (Source) > Max_Length - Length (New_Item)
then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + Length (New_Item)),
- Global => null;
+ Contract_Cases =>
+ (Length (Source) <= Max_Length - Length (New_Item)
+ =>
+ Length (Source) = Length (Source'Old) + Length (New_Item)
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ (if Length (New_Item) > 0 then
+ Slice (Source, Length (Source'Old) + 1, Length (Source)) =
+ To_String (New_Item)),
+
+ Length (Source) > Max_Length - Length (New_Item)
+ and then Drop = Left
+ =>
+ Length (Source) = Max_Length
+ and then
+ (if Length (New_Item) < Max_Length then
+ Slice (Source, 1, Max_Length - Length (New_Item)) =
+ Slice (Source'Old,
+ Length (Source'Old) - Max_Length + Length (New_Item)
+ + 1,
+ Length (Source'Old)))
+ and then
+ Slice (Source, Max_Length - Length (New_Item) + 1, Max_Length)
+ = To_String (New_Item),
+
+ others -- Drop = Right
+ =>
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ (if Length (Source'Old) < Max_Length then
+ Slice (Source, Length (Source'Old) + 1, Max_Length) =
+ Slice (New_Item, 1, Max_Length - Length (Source'Old))));
procedure Append
(Source : in out Bounded_String;
New_Item : String;
Drop : Truncation := Error)
with
- Pre =>
+ Pre =>
(if New_Item'Length > Max_Length - Length (Source)
then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + New_Item'Length),
- Global => null;
+ Contract_Cases =>
+ (Length (Source) <= Max_Length - New_Item'Length
+ =>
+ Length (Source) = Length (Source'Old) + New_Item'Length
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ (if New_Item'Length > 0 then
+ Slice (Source, Length (Source'Old) + 1, Length (Source)) =
+ New_Item),
+
+ Length (Source) > Max_Length - New_Item'Length
+ and then Drop = Left
+ =>
+ Length (Source) = Max_Length
+ and then
+ (if New_Item'Length < Max_Length then
+
+ -- The result is the end of Source followed by New_Item
+
+ Slice (Source, 1, Max_Length - New_Item'Length) =
+ Slice (Source'Old,
+ Length (Source'Old) - Max_Length + New_Item'Length + 1,
+ Length (Source'Old))
+ and then
+ Slice (Source,
+ Max_Length - New_Item'Length + 1, Max_Length) =
+ New_Item
+ else
+ -- The result is the last Max_Length characters of
+ -- New_Item.
+
+ To_String (Source) = New_Item
+ (New_Item'Last - Max_Length + 1 .. New_Item'Last)),
+
+ others -- Drop = Right
+ =>
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ (if Length (Source'Old) < Max_Length then
+ Slice (Source, Length (Source'Old) + 1, Max_Length) =
+ New_Item (New_Item'First
+ .. Max_Length - Length (Source'Old) - 1
+ + New_Item'First)));
procedure Append
(Source : in out Bounded_String;
New_Item : Character;
Drop : Truncation := Error)
with
- Pre => (if Length (Source) = Max_Length then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + 1),
- Global => null;
+ Pre => (if Length (Source) = Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Length (Source) < Max_Length
+ =>
+ Length (Source) = Length (Source'Old) + 1
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then Element (Source, Length (Source'Old) + 1) = New_Item,
+
+ Length (Source) = Max_Length and then Drop = Right
+ =>
+ Length (Source) = Max_Length
+ and then To_String (Source) = To_String (Source'Old),
+
+ others -- Drop = Left
+ =>
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Max_Length - 1) =
+ Slice (Source'Old, 2, Max_Length)
+ and then Element (Source, Max_Length) = New_Item);
+
+ -- Each of the "&" functions has the same effect as the corresponding
+ -- Append function, with Error as the Drop parameter.
function "&"
(Left : Bounded_String;
Right : Bounded_String) return Bounded_String
with
- Pre => Length (Left) <= Max_Length - Length (Right),
- Post => Length ("&"'Result) = Length (Left) + Length (Right),
- Global => null;
+ Pre => Length (Left) <= Max_Length - Length (Right),
+ Post => Length ("&"'Result) = Length (Left) + Length (Right)
+ and then Slice ("&"'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Length (Right) > 0 then
+ Slice ("&"'Result, Length (Left) + 1, Length ("&"'Result)) =
+ To_String (Right));
function "&"
(Left : Bounded_String;
Right : String) return Bounded_String
with
- Pre => Right'Length <= Max_Length - Length (Left),
- Post => Length ("&"'Result) = Length (Left) + Right'Length,
- Global => null;
+ Pre => Right'Length <= Max_Length - Length (Left),
+ Post => Length ("&"'Result) = Length (Left) + Right'Length
+ and then Slice ("&"'Result, 1, Length (Left)) = To_String (Left)
+ and then
+ (if Right'Length > 0 then
+ Slice ("&"'Result, Length (Left) + 1, Length ("&"'Result)) =
+ Right);
function "&"
(Left : String;
Right : Bounded_String) return Bounded_String
with
- Pre => Left'Length <= Max_Length - Length (Right),
- Post => Length ("&"'Result) = Left'Length + Length (Right),
- Global => null;
+ Pre => Left'Length <= Max_Length - Length (Right),
+ Post => Length ("&"'Result) = Left'Length + Length (Right)
+ and then Slice ("&"'Result, 1, Left'Length) = Left
+ and then
+ (if Length (Right) > 0 then
+ Slice ("&"'Result, Left'Length + 1, Length ("&"'Result)) =
+ To_String (Right));
function "&"
(Left : Bounded_String;
Right : Character) return Bounded_String
with
- Pre => Length (Left) < Max_Length,
- Post => Length ("&"'Result) = Length (Left) + 1,
- Global => null;
+ Pre => Length (Left) < Max_Length,
+ Post => Length ("&"'Result) = Length (Left) + 1
+ and then Slice ("&"'Result, 1, Length (Left)) = To_String (Left)
+ and then Element ("&"'Result, Length (Left) + 1) = Right;
function "&"
(Left : Character;
Right : Bounded_String) return Bounded_String
with
- Pre => Length (Right) < Max_Length,
- Post => Length ("&"'Result) = 1 + Length (Right),
- Global => null;
+ Pre => Length (Right) < Max_Length,
+ Post => Length ("&"'Result) = 1 + Length (Right)
+ and then Element ("&"'Result, 1) = Left
+ and then
+ Slice ("&"'Result, 2, Length ("&"'Result)) = To_String (Right);
function Element
(Source : Bounded_String;
@@ -237,6 +561,8 @@ package Ada.Strings.Bounded is
with
Pre => Index <= Length (Source),
Global => null;
+ -- Returns the character at position Index in the string represented by
+ -- Source; propagates Index_Error if Index > Length(Source).
procedure Replace_Element
(Source : in out Bounded_String;
@@ -244,8 +570,14 @@ package Ada.Strings.Bounded is
By : Character)
with
Pre => Index <= Length (Source),
- Post => Length (Source) = Length (Source)'Old,
+ Post => Length (Source) = Length (Source'Old)
+ and then (for all K in 1 .. Length (Source) =>
+ Element (Source, K) =
+ (if K = Index then By else Element (Source'Old, K))),
Global => null;
+ -- Updates Source such that the character at position Index in the
+ -- string represented by Source is By; propagates Index_Error if
+ -- Index > Length(Source).
function Slice
(Source : Bounded_String;
@@ -253,8 +585,11 @@ package Ada.Strings.Bounded is
High : Natural) return String
with
Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
- Post => Slice'Result'Length = Natural'Max (0, High - Low + 1),
Global => null;
+ -- 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.
function Bounded_Slice
(Source : Bounded_String;
@@ -262,10 +597,12 @@ package Ada.Strings.Bounded is
High : Natural) return Bounded_String
with
Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
- Post =>
- Length (Bounded_Slice'Result) = Natural'Max (0, High - Low + 1),
+ Post => To_String (Bounded_Slice'Result) = Slice (Source, Low, High),
Global => null;
pragma Ada_05 (Bounded_Slice);
+ -- 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).
procedure Bounded_Slice
(Source : Bounded_String;
@@ -274,112 +611,181 @@ package Ada.Strings.Bounded is
High : Natural)
with
Pre => Low - 1 <= Length (Source) and then High <= Length (Source),
- Post => Length (Target) = Natural'Max (0, High - Low + 1),
+ Post => To_String (Target) = Slice (Source, Low, High),
Global => null;
pragma Ada_05 (Bounded_Slice);
+ -- Equivalent to Target := Bounded_Slice (Source, Low, High);
+
+ -- 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.
function "="
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => "="'Result = (To_String (Left) = To_String (Right)),
Global => null;
function "="
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => "="'Result = (To_String (Left) = Right),
Global => null;
function "="
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => "="'Result = (Left = To_String (Right)),
Global => null;
function "<"
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => "<"'Result = (To_String (Left) < To_String (Right)),
Global => null;
function "<"
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => "<"'Result = (To_String (Left) < Right),
Global => null;
function "<"
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => "<"'Result = (Left < To_String (Right)),
Global => null;
function "<="
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => "<="'Result = (To_String (Left) <= To_String (Right)),
Global => null;
function "<="
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => "<="'Result = (To_String (Left) <= Right),
Global => null;
function "<="
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => "<="'Result = (Left <= To_String (Right)),
Global => null;
function ">"
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => ">"'Result = (To_String (Left) > To_String (Right)),
Global => null;
function ">"
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => ">"'Result = (To_String (Left) > Right),
Global => null;
function ">"
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => ">"'Result = (Left > To_String (Right)),
Global => null;
function ">="
(Left : Bounded_String;
Right : Bounded_String) return Boolean
with
+ Post => ">="'Result = (To_String (Left) >= To_String (Right)),
Global => null;
function ">="
(Left : Bounded_String;
Right : String) return Boolean
with
+ Post => ">="'Result = (To_String (Left) >= Right),
Global => null;
function ">="
(Left : String;
Right : Bounded_String) return Boolean
with
+ Post => ">="'Result = (Left >= To_String (Right)),
Global => null;
----------------------
-- Search Functions --
----------------------
+ -- 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.
+
function Index
(Source : Bounded_String;
Pattern : String;
Going : Direction := Forward;
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
with
- Pre => Pattern'Length /= 0,
- Global => null;
+ Pre => Pattern'Length > 0,
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Length (Source) = 0
+ =>
+ Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Length (Source) > 0
+ and then
+ (for some J in 1 .. Length (Source) - (Pattern'Length - 1) =>
+ Search.Match (To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in 1 .. Length (Source) - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (To_String (Source), Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if (if Going = Forward
+ then J <= Index'Result - 1
+ else J - 1 in Index'Result
+ .. Length (Source) - Pattern'Length)
+ then not (Search.Match
+ (To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
+ Global => null;
function Index
(Source : Bounded_String;
@@ -387,8 +793,52 @@ package Ada.Strings.Bounded is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre => Pattern'Length /= 0,
- Global => null;
+ Pre => Pattern'Length /= 0 and then Mapping /= null,
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Length (Source) = 0
+ =>
+ Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Length (Source) > 0
+ and then
+ (for some J in 1 .. Length (Source) - (Pattern'Length - 1) =>
+ Search.Match (To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in 1 .. Length (Source) - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (To_String (Source), Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if (if Going = Forward
+ then J <= Index'Result - 1
+ else J - 1 in Index'Result
+ .. Length (Source) - Pattern'Length)
+ then not (Search.Match
+ (To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
+ Global => null;
function Index
(Source : Bounded_String;
@@ -396,7 +846,43 @@ package Ada.Strings.Bounded is
Test : Membership := Inside;
Going : Direction := Forward) return Natural
with
- Global => null;
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If no character of Source satisfies the property Test on Set,
+ -- then 0 is returned.
+
+ ((for all C of To_String (Source) =>
+ (Test = Inside) /= Maps.Is_In (C, Set))
+ =>
+ Index'Result = 0,
+
+ -- Otherwise, an index in the range of Source is returned
+
+ others
+ =>
+ -- The result is in the range of Source
+
+ Index'Result in 1 .. Length (Source)
+
+ -- The character at the returned index satisfies the property
+ -- Test on Set.
+
+ and then
+ (Test = Inside) =
+ Maps.Is_In (Element (Source, Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if J /= Index'Result
+ and then (J < Index'Result) = (Going = Forward)
+ then (Test = Inside)
+ /= Maps.Is_In (Element (Source, J), Set)))),
+ Global => null;
function Index
(Source : Bounded_String;
@@ -405,11 +891,60 @@ package Ada.Strings.Bounded is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
with
- Pre =>
- (if Length (Source) /= 0
- then From <= Length (Source))
- and then Pattern'Length /= 0,
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source))
+ and then Pattern'Length /= 0,
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Length (Source) = 0
+ =>
+ Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Length (Source) > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Length (Source) else From)
+ - (Pattern'Length - 1) =>
+ Search.Match (To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Length (Source) else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (To_String (Source), Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if (if Going = Forward
+ then J in From .. Index'Result - 1
+ else J - 1 in Index'Result
+ .. From - Pattern'Length)
+ then not (Search.Match
+ (To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
+ Global => null;
pragma Ada_05 (Index);
function Index
@@ -419,11 +954,61 @@ package Ada.Strings.Bounded is
Going : Direction := Forward;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre =>
- (if Length (Source) /= 0
- then From <= Length (Source))
- and then Pattern'Length /= 0,
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source))
+ and then Pattern'Length /= 0
+ and then Mapping /= null,
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Length (Source) = 0
+ =>
+ Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Length (Source) > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Length (Source) else From)
+ - (Pattern'Length - 1) =>
+ Search.Match (To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Length (Source) else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (To_String (Source), Pattern, Mapping, Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if (if Going = Forward
+ then J in From .. Index'Result - 1
+ else J - 1 in Index'Result
+ .. From - Pattern'Length)
+ then not (Search.Match
+ (To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Index'Result = 0),
+ Global => null;
pragma Ada_05 (Index);
function Index
@@ -433,23 +1018,147 @@ package Ada.Strings.Bounded is
Test : Membership := Inside;
Going : Direction := Forward) return Natural
with
- Pre => (if Length (Source) /= 0 then From <= Length (Source)),
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source)),
+ Post => Index'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or no character of the considered
+ -- slice of Source satisfies the property Test on Set, then 0 is
+ -- returned.
+
+ (Length (Source) = 0
+ or else
+ (for all J in 1 .. Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set)))
+ =>
+ Index'Result = 0,
+
+ -- Otherwise, an index in the considered range of Source is
+ -- returned.
+
+ others
+ =>
+ -- The result is in the considered range of Source
+
+ Index'Result in 1 .. Length (Source)
+ and then
+ (Index'Result = From
+ or else (Index'Result > From) = (Going = Forward))
+
+ -- The character at the returned index satisfies the property
+ -- Test on Set.
+
+ and then
+ (Test = Inside) =
+ Maps.Is_In (Element (Source, Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if J /= Index'Result
+ and then (J < Index'Result) = (Going = Forward)
+ and then (J = From
+ or else (J > From) = (Going = Forward))
+ then (Test = Inside)
+ /= Maps.Is_In (Element (Source, J), Set)))),
+ Global => null;
pragma Ada_05 (Index);
function Index_Non_Blank
(Source : Bounded_String;
Going : Direction := Forward) return Natural
with
- Global => null;
+ Post => Index_Non_Blank'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If all characters of Source are Space characters, then 0 is
+ -- returned.
+
+ ((for all C of To_String (Source) => C = ' ')
+ =>
+ Index_Non_Blank'Result = 0,
+
+ -- Otherwise, an index in the range of Source is returned
+
+ others
+ =>
+ -- The result is in the range of Source
+
+ Index_Non_Blank'Result in 1 .. Length (Source)
+
+ -- The character at the returned index is not a Space character
+
+ and then Element (Source, Index_Non_Blank'Result) /= ' '
+
+ -- The result is the smallest or largest index which is not a
+ -- Space character, respectively when Going = Forward and Going
+ -- = Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if J /= Index_Non_Blank'Result
+ and then
+ (J < Index_Non_Blank'Result) = (Going = Forward)
+ then Element (Source, J) = ' '))),
+ Global => null;
function Index_Non_Blank
(Source : Bounded_String;
From : Positive;
Going : Direction := Forward) return Natural
with
- Pre => (if Length (Source) /= 0 then From <= Length (Source)),
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source)),
+ Post => Index_Non_Blank'Result <= Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or all characters of the
+ -- considered slice of Source are Space characters, then 0
+ -- is returned.
+
+ (Length (Source) = 0
+ or else
+ (for all J in 1 .. Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ Element (Source, J) = ' '))
+ =>
+ Index_Non_Blank'Result = 0,
+
+ -- Otherwise, an index in the considered range of Source is
+ -- returned.
+
+ others
+ =>
+ -- The result is in the considered range of Source
+
+ Index_Non_Blank'Result in 1 .. Length (Source)
+ and then
+ (Index_Non_Blank'Result = From
+ or else
+ (Index_Non_Blank'Result > From) = (Going = Forward))
+
+ -- The character at the returned index is not a Space character
+
+ and then Element (Source, Index_Non_Blank'Result) /= ' '
+
+ -- The result is the smallest or largest index which isn't a
+ -- Space character, respectively when Going = Forward and Going
+ -- = Backward.
+
+ and then
+ (for all J in 1 .. Length (Source) =>
+ (if J /= Index_Non_Blank'Result
+ and then
+ (J < Index_Non_Blank'Result) = (Going = Forward)
+ and then (J = From
+ or else (J > From) = (Going = Forward))
+ then Element (Source, J) = ' '))),
+ Global => null;
pragma Ada_05 (Index_Non_Blank);
function Count
@@ -465,7 +1174,7 @@ package Ada.Strings.Bounded is
Pattern : String;
Mapping : Maps.Character_Mapping_Function) return Natural
with
- Pre => Pattern'Length /= 0,
+ Pre => Pattern'Length /= 0 and then Mapping /= null,
Global => null;
function Count
@@ -482,8 +1191,53 @@ package Ada.Strings.Bounded is
First : out Positive;
Last : out Natural)
with
- Pre => (if Length (Source) /= 0 then From <= Length (Source)),
- Global => null;
+ Pre =>
+ (if Length (Source) /= 0 then From <= Length (Source)),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or if no character of the
+ -- considered slice of Source satisfies the property Test on
+ -- Set, then First is set to From and Last is set to 0.
+
+ (Length (Source) = 0
+ or else
+ (for all J in From .. Length (Source) =>
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set))
+ =>
+ First = From and then Last = 0,
+
+ -- Otherwise, First and Last are set to valid indexes
+
+ others
+ =>
+ -- First and Last are in the considered range of Source
+
+ First in From .. Length (Source)
+ and then Last in First .. Length (Source)
+
+ -- No character between From and First satisfies the property
+ -- Test on Set.
+
+ and then
+ (for all J in From .. First - 1 =>
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set))
+
+ -- All characters between First and Last satisfy the property
+ -- Test on Set.
+
+ and then
+ (for all J in First .. Last =>
+ (Test = Inside) = Maps.Is_In (Element (Source, J), Set))
+
+ -- If Last is not Source'Last, then the character at position
+ -- Last + 1 does not satify the property Test on Set.
+
+ and then
+ (if Last < Length (Source)
+ then
+ (Test = Inside)
+ /= Maps.Is_In (Element (Source, Last + 1), Set))),
+ Global => null;
pragma Ada_2012 (Find_Token);
procedure Find_Token
@@ -493,44 +1247,127 @@ package Ada.Strings.Bounded is
First : out Positive;
Last : out Natural)
with
- Global => null;
+ Contract_Cases =>
+
+ -- If Source is the empty string, or if no character of the
+ -- considered slice of Source satisfies the property Test on
+ -- Set, then First is set to 1 and Last is set to 0.
+
+ (Length (Source) = 0
+ or else
+ (for all J in 1 .. Length (Source) =>
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set))
+ =>
+ First = 1 and then Last = 0,
+
+ -- Otherwise, First and Last are set to valid indexes
+
+ others
+ =>
+ -- First and Last are in the considered range of Source
+
+ First in 1 .. Length (Source)
+ and then Last in First .. Length (Source)
+
+ -- No character between 1 and First satisfies the property Test
+ -- on Set.
+
+ and then
+ (for all J in 1 .. First - 1 =>
+ (Test = Inside) /= Maps.Is_In (Element (Source, J), Set))
+
+ -- All characters between First and Last satisfy the property
+ -- Test on Set.
+
+ and then
+ (for all J in First .. Last =>
+ (Test = Inside) = Maps.Is_In (Element (Source, J), Set))
+
+ -- If Last is not Source'Last, then the character at position
+ -- Last + 1 does not satify the property Test on Set.
+
+ and then
+ (if Last < Length (Source)
+ then
+ (Test = Inside)
+ /= Maps.Is_In (Element (Source, Last + 1), Set))),
+ Global => null;
------------------------------------
-- String Translation Subprograms --
------------------------------------
+ -- 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.
+
function Translate
(Source : Bounded_String;
Mapping : Maps.Character_Mapping) return Bounded_String
with
- Post => Length (Translate'Result) = Length (Source),
+ Post => Length (Translate'Result) = Length (Source)
+ and then
+ (for all K in 1 .. Length (Source) =>
+ Element (Translate'Result, K) =
+ Ada.Strings.Maps.Value (Mapping, Element (Source, K))),
Global => null;
procedure Translate
(Source : in out Bounded_String;
Mapping : Maps.Character_Mapping)
with
- Post => Length (Source) = Length (Source)'Old,
+ Post => Length (Source) = Length (Source'Old)
+ and then
+ (for all K in 1 .. Length (Source) =>
+ Element (Source, K) =
+ Ada.Strings.Maps.Value (Mapping, Element (Source'Old, K))),
Global => null;
function Translate
(Source : Bounded_String;
Mapping : Maps.Character_Mapping_Function) return Bounded_String
with
- Post => Length (Translate'Result) = Length (Source),
+ Pre => Mapping /= null,
+ Post => Length (Translate'Result) = Length (Source)
+ and then
+ (for all K in 1 .. Length (Source) =>
+ Element (Translate'Result, K) = Mapping (Element (Source, K))),
Global => null;
procedure Translate
(Source : in out Bounded_String;
Mapping : Maps.Character_Mapping_Function)
with
- Post => Length (Source) = Length (Source)'Old,
+ Pre => Mapping /= null,
+ Post => Length (Source) = Length (Source'Old)
+ and then
+ (for all K in 1 .. Length (Source) =>
+ Element (Source, K) = Mapping (Element (Source'Old, K))),
Global => null;
---------------------------------------
-- String Transformation Subprograms --
---------------------------------------
+ -- 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.
+
function Replace_Slice
(Source : Bounded_String;
Low : Positive;
@@ -541,23 +1378,127 @@ package Ada.Strings.Bounded is
Pre =>
Low - 1 <= Length (Source)
and then
- (if Drop = Error
- then (if High >= Low
- then Low - 1
- <= Max_Length - By'Length
- - Natural'Max (Length (Source) - High, 0)
- else Length (Source) <= Max_Length - By'Length)),
+ (if Drop = Error
+ then (if High >= Low
+ then Low - 1
+ <= Max_Length - By'Length
+ - Integer'Max (Length (Source) - High, 0)
+ else Length (Source) <= Max_Length - By'Length)),
Contract_Cases =>
- (High >= Low =>
- Length (Replace_Slice'Result)
- = Natural'Min
- (Max_Length,
- Low - 1 + By'Length + Natural'Max (Length (Source) - High,
- 0)),
- others =>
- Length (Replace_Slice'Result)
- = Natural'Min (Max_Length, Length (Source) + By'Length)),
- Global => null;
+ (Low - 1 <= Max_Length - By'Length
+ - Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ -- Note that if High < Low, the insertion is done before Low,
+ -- so in all cases the starting position of the slice of Source
+ -- remaining after the replaced Slice is Integer'Max (High + 1,
+ -- Low).
+
+ Length (Replace_Slice'Result) = Low - 1 + By'Length
+ + Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then
+ Slice (Replace_Slice'Result, 1, Low - 1) =
+ Slice (Source, 1, Low - 1)
+ and then
+ Slice (Replace_Slice'Result, Low, Low - 1 + By'Length) = By
+ and then
+ (if Integer'Max (High, Low - 1) < Length (Source) then
+ Slice (Replace_Slice'Result,
+ Low + By'Length, Length (Replace_Slice'Result)) =
+ Slice (Source,
+ Integer'Max (High + 1, Low), Length (Source))),
+
+ Low - 1 > Max_Length - By'Length
+ - Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then Drop = Left
+ =>
+ -- Final_Slice is the length of the slice of Source remaining
+ -- after the replaced part.
+ (declare
+ Final_Slice : constant Natural :=
+ Integer'Max
+ (Length (Source) - Integer'Max (High, Low - 1), 0);
+ begin
+ -- The result is of maximal length and ends by the last
+ -- Final_Slice characters of Source.
+
+ Length (Replace_Slice'Result) = Max_Length
+ and then
+ (if Final_Slice > 0 then
+ Slice (Replace_Slice'Result,
+ Max_Length - Final_Slice + 1, Max_Length) =
+ Slice (Source,
+ Integer'Max (High + 1, Low), Length (Source)))
+
+ -- Depending on when we reach Max_Length, either the first
+ -- part of Source is fully dropped and By is partly dropped,
+ -- or By is fully added and the first part of Source is
+ -- partly dropped.
+
+ and then
+ (if Max_Length - Final_Slice - By'Length <= 0 then
+
+ -- The first (possibly zero) characters of By are
+ -- dropped.
+
+ (if Final_Slice < Max_Length then
+ Slice (Replace_Slice'Result,
+ 1, Max_Length - Final_Slice) =
+ By (By'Last - Max_Length + Final_Slice + 1
+ .. By'Last))
+
+ else -- By is added to the result
+
+ Slice (Replace_Slice'Result,
+ Max_Length - Final_Slice - By'Length + 1,
+ Max_Length - Final_Slice) =
+ By
+
+ -- The first characters of Source (1 .. Low - 1) are
+ -- dropped.
+
+ and then Slice (Replace_Slice'Result, 1,
+ Max_Length - Final_Slice - By'Length) =
+ Slice (Source,
+ Low - Max_Length + Final_Slice + By'Length,
+ Low - 1))),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first Low -
+ -- 1 characters of Source.
+
+ Length (Replace_Slice'Result) = Max_Length
+ and then
+ Slice (Replace_Slice'Result, 1, Low - 1) =
+ Slice (Source, 1, Low - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and By is partly dropped, or By
+ -- is fully added and the last part of Source is partly
+ -- dropped.
+
+ and then
+ (if Low - 1 >= Max_Length - By'Length then
+
+ -- The last characters of By are dropped
+
+ Slice (Replace_Slice'Result, Low, Max_Length) =
+ By (By'First .. Max_Length - Low + By'First)
+
+ else -- By is fully added
+
+ Slice (Replace_Slice'Result, Low, Low + By'Length - 1) = By
+
+ -- Then Source starting from Integer'Max (High + 1, Low)
+ -- is added but the last characters are dropped.
+
+ and then Slice (Replace_Slice'Result,
+ Low + By'Length, Max_Length) =
+ Slice (Source, Integer'Max (High + 1, Low),
+ Integer'Max (High + 1, Low) +
+ (Max_Length - Low - By'Length))));
procedure Replace_Slice
(Source : in out Bounded_String;
@@ -569,23 +1510,119 @@ package Ada.Strings.Bounded is
Pre =>
Low - 1 <= Length (Source)
and then
- (if Drop = Error
- then (if High >= Low
- then Low - 1
- <= Max_Length - By'Length
- - Natural'Max (Length (Source) - High, 0)
- else Length (Source) <= Max_Length - By'Length)),
+ (if Drop = Error
+ then (if High >= Low
+ then Low - 1
+ <= Max_Length - By'Length
+ - Natural'Max (Length (Source) - High, 0)
+ else Length (Source) <= Max_Length - By'Length)),
Contract_Cases =>
- (High >= Low =>
- Length (Source)
- = Natural'Min
- (Max_Length,
- Low - 1 + By'Length + Natural'Max (Length (Source)'Old - High,
- 0)),
- others =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + By'Length)),
- Global => null;
+ (Low - 1 <= Max_Length - By'Length
+ - Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ -- Note that if High < Low, the insertion is done before Low,
+ -- so in all cases the starting position of the slice of Source
+ -- remaining after the replaced Slice is Integer'Max (High + 1,
+ -- Low).
+
+ Length (Source) = Low - 1 + By'Length + Integer'Max
+ (Length (Source'Old) - Integer'Max (High, Low - 1), 0)
+ and then
+ Slice (Source, 1, Low - 1) = Slice (Source'Old, 1, Low - 1)
+ and then Slice (Source, Low, Low - 1 + By'Length) = By
+ and then
+ (if Integer'Max (High, Low - 1) < Length (Source'Old) then
+ Slice (Source, Low + By'Length, Length (Source)) =
+ Slice (Source'Old,
+ Integer'Max (High + 1, Low), Length (Source'Old))),
+
+ Low - 1 > Max_Length - By'Length
+ - Integer'Max (Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then Drop = Left
+ =>
+ -- Final_Slice is the length of the slice of Source remaining
+ -- after the replaced part.
+ (declare
+ Final_Slice : constant Integer :=
+ Integer'Max (0,
+ Length (Source'Old) - Integer'Max (High, Low - 1));
+ begin
+ -- The result is of maximal length and ends by the last
+ -- Final_Slice characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ (if Final_Slice > 0 then
+ Slice (Source,
+ Max_Length - Final_Slice + 1, Max_Length) =
+ Slice (Source'Old,
+ Integer'Max (High + 1, Low), Length (Source'Old)))
+
+ -- Depending on when we reach Max_Length, either the first
+ -- part of Source is fully dropped and By is partly dropped,
+ -- or By is fully added and the first part of Source is
+ -- partly dropped.
+
+ and then
+ (if Max_Length - Final_Slice - By'Length <= 0 then
+
+ -- The first characters of By are dropped
+
+ (if Final_Slice < Max_Length then
+ Slice (Source, 1, Max_Length - Final_Slice) =
+ By (By'Last - Max_Length + Final_Slice + 1
+ .. By'Last))
+
+ else -- By is added to the result
+
+ Slice (Source,
+ Max_Length - Final_Slice - By'Length + 1,
+ Max_Length - Final_Slice) = By
+
+ -- The first characters of Source (1 .. Low - 1) are
+ -- dropped.
+
+ and then Slice (Source, 1,
+ Max_Length - Final_Slice - By'Length) =
+ Slice (Source'Old,
+ Low - Max_Length + Final_Slice + By'Length,
+ Low - 1))),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first Low -
+ -- 1 characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Low - 1) = Slice (Source'Old, 1, Low - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and By is partly dropped, or By
+ -- is fully added and the last part of Source is partly
+ -- dropped.
+
+ and then
+ (if Low - 1 >= Max_Length - By'Length then
+
+ -- The last characters of By are dropped
+
+ Slice (Source, Low, Max_Length) =
+ By (By'First .. Max_Length - Low + By'First)
+
+ else -- By is fully added
+
+ Slice (Source, Low, Low + By'Length - 1) = By
+
+ -- Then Source starting from Natural'Max (High + 1, Low)
+ -- is added but the last characters are dropped.
+
+ and then Slice (Source, Low + By'Length, Max_Length) =
+ Slice (Source'Old, Integer'Max (High + 1, Low),
+ Integer'Max (High + 1, Low) +
+ (Max_Length - Low - By'Length))));
function Insert
(Source : Bounded_String;
@@ -593,14 +1630,113 @@ package Ada.Strings.Bounded is
New_Item : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
Before - 1 <= Length (Source)
and then (if New_Item'Length > Max_Length - Length (Source)
then Drop /= Error),
- Post =>
- Length (Insert'Result)
- = Natural'Min (Max_Length, Length (Source) + New_Item'Length),
- Global => null;
+ Contract_Cases =>
+ (Length (Source) <= Max_Length - New_Item'Length
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ Length (Insert'Result) = Length (Source) + New_Item'Length
+ and then
+ Slice (Insert'Result, 1, Before - 1) =
+ Slice (Source, 1, Before - 1)
+ and then
+ Slice (Insert'Result, Before, Before - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Before <= Length (Source) then
+ Slice (Insert'Result,
+ Before + New_Item'Length, Length (Insert'Result)) =
+ Slice (Source, Before, Length (Source))),
+
+ Length (Source) > Max_Length - New_Item'Length and then Drop = Left
+ =>
+ -- The result is of maximal length and ends by the last
+ -- characters of Source.
+
+ Length (Insert'Result) = Max_Length
+ and then
+ (if Before <= Length (Source) then
+ Slice (Insert'Result,
+ Max_Length - Length (Source) + Before, Max_Length) =
+ Slice (Source, Before, Length (Source)))
+
+ -- Depending on when we reach Max_Length, either the first part
+ -- of Source is fully dropped and New_Item is partly dropped,
+ -- or New_Item is fully added and the first part of Source is
+ -- partly dropped.
+
+ and then
+ (if Max_Length - Length (Source) - 1 + Before
+ < New_Item'Length
+ then
+ -- The first characters of New_Item are dropped
+
+ (if Length (Source) - Before + 1 < Max_Length then
+ Slice (Insert'Result,
+ 1, Max_Length - Length (Source) - 1 + Before) =
+ New_Item
+ (New_Item'Last - Max_Length + Length (Source)
+ - Before + 2
+ .. New_Item'Last))
+
+ else -- New_Item is added to the result
+
+ Slice (Insert'Result,
+ Max_Length - Length (Source) - New_Item'Length + Before,
+ Max_Length - Length (Source) - 1 + Before) = New_Item
+
+ -- The first characters of Source (1 .. Before - 1) are
+ -- dropped.
+
+ and then Slice (Insert'Result,
+ 1, Max_Length - Length (Source) - New_Item'Length
+ - 1 + Before) =
+ Slice (Source,
+ Length (Source) - Max_Length + New_Item'Length
+ + 1,
+ Before - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Length (Insert'Result) = Max_Length
+ and then
+ Slice (Insert'Result, 1, Before - 1) =
+ Slice (Source, 1, Before - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and New_Item is partly dropped,
+ -- or New_Item is fully added and the last part of Source is
+ -- partly dropped.
+
+ and then
+ (if Before - 1 >= Max_Length - New_Item'Length then
+
+ -- The last characters of New_Item are dropped
+
+ Slice (Insert'Result, Before, Max_Length) =
+ New_Item (New_Item'First
+ .. Max_Length - Before + New_Item'First)
+
+ else -- New_Item is fully added
+
+ Slice (Insert'Result,
+ Before, Before + New_Item'Length - 1) =
+ New_Item
+
+ -- Then Source starting from Before is added but the
+ -- last characters are dropped.
+
+ and then Slice (Insert'Result,
+ Before + New_Item'Length, Max_Length) =
+ Slice (Source,
+ Before, Max_Length - New_Item'Length)));
procedure Insert
(Source : in out Bounded_String;
@@ -608,14 +1744,112 @@ package Ada.Strings.Bounded is
New_Item : String;
Drop : Truncation := Error)
with
- Pre =>
+ Pre =>
Before - 1 <= Length (Source)
and then (if New_Item'Length > Max_Length - Length (Source)
then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Min (Max_Length, Length (Source)'Old + New_Item'Length),
- Global => null;
+ Contract_Cases =>
+ (Length (Source) <= Max_Length - New_Item'Length
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ Length (Source) = Length (Source'Old) + New_Item'Length
+ and then
+ Slice (Source, 1, Before - 1) =
+ Slice (Source'Old, 1, Before - 1)
+ and then
+ Slice (Source, Before, Before - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Before <= Length (Source'Old) then
+ Slice (Source, Before + New_Item'Length, Length (Source)) =
+ Slice (Source'Old, Before, Length (Source'Old))),
+
+ Length (Source) > Max_Length - New_Item'Length and then Drop = Left
+ =>
+ -- The result is of maximal length and ends by the last
+ -- characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ (if Before <= Length (Source'Old) then
+ Slice (Source,
+ Max_Length - Length (Source'Old) + Before, Max_Length) =
+ Slice (Source'Old, Before, Length (Source'Old)))
+
+ -- Depending on when we reach Max_Length, either the first part
+ -- of Source is fully dropped and New_Item is partly dropped,
+ -- or New_Item is fully added and the first part of Source is
+ -- partly dropped.
+
+ and then
+ (if Max_Length - Length (Source'Old) - 1 + Before
+ < New_Item'Length
+ then
+ -- The first characters of New_Item are dropped
+
+ (if Length (Source'Old) - Before + 1 < Max_Length then
+ Slice (Source,
+ 1, Max_Length - Length (Source'Old) - 1 + Before) =
+ New_Item
+ (New_Item'Last - Max_Length + Length (Source'Old)
+ - Before + 2
+ .. New_Item'Last))
+
+ else -- New_Item is added to the result
+
+ Slice (Source,
+ Max_Length - Length (Source'Old) - New_Item'Length
+ + Before,
+ Max_Length - Length (Source'Old) - 1 + Before) = New_Item
+
+ -- The first characters of Source (1 .. Before - 1) are
+ -- dropped.
+
+ and then Slice (Source, 1,
+ Max_Length - Length (Source'Old) - New_Item'Length
+ - 1 + Before) =
+ Slice (Source'Old,
+ Length (Source'Old)
+ - Max_Length + New_Item'Length + 1,
+ Before - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Before - 1) =
+ Slice (Source'Old, 1, Before - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and New_Item is partly dropped,
+ -- or New_Item is fully added and the last part of Source is
+ -- partly dropped.
+
+ and then
+ (if Before - 1 >= Max_Length - New_Item'Length then
+
+ -- The last characters of New_Item are dropped
+
+ Slice (Source, Before, Max_Length) =
+ New_Item (New_Item'First
+ .. Max_Length - Before + New_Item'First)
+
+ else -- New_Item is fully added
+
+ Slice (Source, Before, Before + New_Item'Length - 1) =
+ New_Item
+
+ -- Then Source starting from Before is added but the
+ -- last characters are dropped.
+
+ and then
+ Slice (Source, Before + New_Item'Length, Max_Length) =
+ Slice (Source'Old,
+ Before, Max_Length - New_Item'Length)));
function Overwrite
(Source : Bounded_String;
@@ -623,16 +1857,85 @@ package Ada.Strings.Bounded is
New_Item : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
+ Pre =>
Position - 1 <= Length (Source)
and then (if New_Item'Length > Max_Length - (Position - 1)
then Drop /= Error),
- Post =>
- Length (Overwrite'Result)
- = Natural'Max
- (Length (Source),
- Natural'Min (Max_Length, Position - 1 + New_Item'Length)),
- Global => null;
+ Contract_Cases =>
+ (Position - 1 <= Max_Length - New_Item'Length
+ =>
+ -- The length is unchanged, unless New_Item overwrites further
+ -- than the end of Source. In this contract case, we suppose
+ -- New_Item doesn't overwrite further than Max_Length.
+
+ Length (Overwrite'Result) =
+ Integer'Max (Length (Source), Position - 1 + New_Item'Length)
+ and then
+ Slice (Overwrite'Result, 1, Position - 1) =
+ Slice (Source, 1, Position - 1)
+ and then Slice (Overwrite'Result,
+ Position, Position - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Position - 1 + New_Item'Length < Length (Source) then
+
+ -- There are some unchanged characters of Source remaining
+ -- after New_Item.
+
+ Slice (Overwrite'Result,
+ Position + New_Item'Length, Length (Source)) =
+ Slice (Source,
+ Position + New_Item'Length, Length (Source))),
+
+ Position - 1 > Max_Length - New_Item'Length and then Drop = Left
+ =>
+ Length (Overwrite'Result) = Max_Length
+
+ -- If a part of the result has to be dropped, it means New_Item
+ -- is overwriting further than the end of Source. Thus the
+ -- result is necessarily ending by New_Item. However, we don't
+ -- know whether New_Item covers all Max_Length characters or
+ -- some characters of Source are remaining at the left.
+
+ and then
+ (if New_Item'Length > Max_Length then
+
+ -- New_Item covers all Max_Length characters
+
+ To_String (Overwrite'Result) =
+ New_Item
+ (New_Item'Last - Max_Length + 1 .. New_Item'Last)
+ else
+ -- New_Item fully appears at the end
+
+ Slice (Overwrite'Result,
+ Max_Length - New_Item'Length + 1, Max_Length) =
+ New_Item
+
+ -- The left of Source is cut
+
+ and then
+ Slice (Overwrite'Result,
+ 1, Max_Length - New_Item'Length) =
+ Slice (Source,
+ Position - Max_Length + New_Item'Length,
+ Position - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Length (Overwrite'Result) = Max_Length
+ and then
+ Slice (Overwrite'Result, 1, Position - 1) =
+ Slice (Source, 1, Position - 1)
+
+ -- Then New_Item is written until Max_Length
+
+ and then Slice (Overwrite'Result, Position, Max_Length) =
+ New_Item
+ (New_Item'First .. Max_Length - Position + New_Item'First));
procedure Overwrite
(Source : in out Bounded_String;
@@ -640,16 +1943,84 @@ package Ada.Strings.Bounded is
New_Item : String;
Drop : Truncation := Error)
with
- Pre =>
+ Pre =>
Position - 1 <= Length (Source)
and then (if New_Item'Length > Max_Length - (Position - 1)
then Drop /= Error),
- Post =>
- Length (Source)
- = Natural'Max
- (Length (Source)'Old,
- Natural'Min (Max_Length, Position - 1 + New_Item'Length)),
- Global => null;
+ Contract_Cases =>
+ (Position - 1 <= Max_Length - New_Item'Length
+ =>
+ -- The length of Source is unchanged, unless New_Item overwrites
+ -- further than the end of Source. In this contract case, we
+ -- suppose New_Item doesn't overwrite further than Max_Length.
+
+ Length (Source) = Integer'Max
+ (Length (Source'Old), Position - 1 + New_Item'Length)
+ and then
+ Slice (Source, 1, Position - 1) =
+ Slice (Source'Old, 1, Position - 1)
+ and then Slice (Source,
+ Position, Position - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Position - 1 + New_Item'Length < Length (Source'Old) then
+
+ -- There are some unchanged characters of Source remaining
+ -- after New_Item.
+
+ Slice (Source,
+ Position + New_Item'Length, Length (Source'Old)) =
+ Slice (Source'Old,
+ Position + New_Item'Length, Length (Source'Old))),
+
+ Position - 1 > Max_Length - New_Item'Length and then Drop = Left
+ =>
+ Length (Source) = Max_Length
+
+ -- If a part of the result has to be dropped, it means New_Item
+ -- is overwriting further than the end of Source. Thus the
+ -- result is necessarily ending by New_Item. However, we don't
+ -- know whether New_Item covers all Max_Length characters or
+ -- some characters of Source are remaining at the left.
+
+ and then
+ (if New_Item'Length > Max_Length then
+
+ -- New_Item covers all Max_Length characters
+
+ To_String (Source) =
+ New_Item
+ (New_Item'Last - Max_Length + 1 .. New_Item'Last)
+ else
+ -- New_Item fully appears at the end
+
+ Slice (Source,
+ Max_Length - New_Item'Length + 1, Max_Length) =
+ New_Item
+
+ -- The left of Source is cut
+
+ and then
+ Slice (Source, 1, Max_Length - New_Item'Length) =
+ Slice (Source'Old,
+ Position - Max_Length + New_Item'Length,
+ Position - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Position - 1) =
+ Slice (Source'Old, 1, Position - 1)
+
+ -- New_Item is written until Max_Length
+
+ and then Slice (Source, Position, Max_Length) =
+ New_Item
+ (New_Item'First .. Max_Length - Position + New_Item'First));
function Delete
(Source : Bounded_String;
@@ -657,13 +2028,20 @@ package Ada.Strings.Bounded is
Through : Natural) return Bounded_String
with
Pre =>
- (if Through <= From then From - 1 <= Length (Source)),
+ (if Through >= From then From - 1 <= Length (Source)),
Contract_Cases =>
(Through >= From =>
- Length (Delete'Result) = Length (Source) - (Through - From + 1),
+ Length (Delete'Result) =
+ From - 1 + Natural'Max (Length (Source) - Through, 0)
+ and then
+ Slice (Delete'Result, 1, From - 1) =
+ Slice (Source, 1, From - 1)
+ and then
+ (if Through < Length (Source) then
+ Slice (Delete'Result, From, Length (Delete'Result)) =
+ Slice (Source, Through + 1, Length (Source))),
others =>
- Length (Delete'Result) = Length (Source)),
-
+ Delete'Result = Source),
Global => null;
procedure Delete
@@ -672,12 +2050,19 @@ package Ada.Strings.Bounded is
Through : Natural)
with
Pre =>
- (if Through <= From then From - 1 <= Length (Source)),
+ (if Through >= From then From - 1 <= Length (Source)),
Contract_Cases =>
(Through >= From =>
- Length (Source) = Length (Source)'Old - (Through - From + 1),
+ Length (Source) =
+ From - 1 + Natural'Max (Length (Source'Old) - Through, 0)
+ and then
+ Slice (Source, 1, From - 1) = Slice (Source'Old, 1, From - 1)
+ and then
+ (if Through < Length (Source) then
+ Slice (Source, From, Length (Source)) =
+ Slice (Source'Old, Through + 1, Length (Source'Old))),
others =>
- Length (Source) = Length (Source)'Old),
+ Source = Source'Old),
Global => null;
---------------------------------
@@ -688,31 +2073,111 @@ package Ada.Strings.Bounded is
(Source : Bounded_String;
Side : Trim_End) return Bounded_String
with
- Post => Length (Trim'Result) <= Length (Source),
- Global => null;
+ Contract_Cases =>
+ -- If all characters in Source are Space, the returned string is
+ -- empty.
+
+ ((for all C of To_String (Source) => C = ' ')
+ =>
+ Length (Trim'Result) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then 1
+ else Index_Non_Blank (Source, Forward));
+ High : constant Positive :=
+ (if Side = Left then Length (Source)
+ else Index_Non_Blank (Source, Backward));
+ begin
+ To_String (Trim'Result) = Slice (Source, Low, High))),
+ Global => null;
procedure Trim
(Source : in out Bounded_String;
Side : Trim_End)
with
- Post => Length (Source) <= Length (Source)'Old,
- Global => null;
+ Contract_Cases =>
+ -- If all characters in Source are Space, the returned string is
+ -- empty.
+
+ ((for all C of To_String (Source) => C = ' ')
+ =>
+ Length (Source) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then 1
+ else Index_Non_Blank (Source'Old, Forward));
+ High : constant Positive :=
+ (if Side = Left then Length (Source'Old)
+ else Index_Non_Blank (Source'Old, Backward));
+ begin
+ To_String (Source) = Slice (Source'Old, Low, High))),
+ Global => null;
function Trim
(Source : Bounded_String;
Left : Maps.Character_Set;
Right : Maps.Character_Set) return Bounded_String
with
- Post => Length (Trim'Result) <= Length (Source),
- Global => null;
+ Contract_Cases =>
+ -- If all characters in Source are contained in one of the sets Left
+ -- or Right, then the returned string is empty.
+
+ ((for all C of To_String (Source) => Maps.Is_In (C, Left))
+ or else
+ (for all C of To_String (Source) => Maps.Is_In (C, Right))
+ =>
+ Length (Trim'Result) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ Index (Source, Left, Outside, Forward);
+ High : constant Positive :=
+ Index (Source, Right, Outside, Backward);
+ begin
+ To_String (Trim'Result) = Slice (Source, Low, High))),
+ Global => null;
procedure Trim
(Source : in out Bounded_String;
Left : Maps.Character_Set;
Right : Maps.Character_Set)
with
- Post => Length (Source) <= Length (Source)'Old,
- Global => null;
+ Contract_Cases =>
+ -- If all characters in Source are contained in one of the sets Left
+ -- or Right, then the returned string is empty.
+
+ ((for all C of To_String (Source) => Maps.Is_In (C, Left))
+ or else
+ (for all C of To_String (Source) => Maps.Is_In (C, Right))
+ =>
+ Length (Source) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ Index (Source'Old, Left, Outside, Forward);
+ High : constant Positive :=
+ Index (Source'Old, Right, Outside, Backward);
+ begin
+ To_String (Source) = Slice (Source'Old, Low, High))),
+ Global => null;
function Head
(Source : Bounded_String;
@@ -720,9 +2185,54 @@ package Ada.Strings.Bounded is
Pad : Character := Space;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post => Length (Head'Result) = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count <= Length (Source)
+ =>
+ -- Source is cut
+
+ To_String (Head'Result) = Slice (Source, 1, Count),
+
+ Count > Length (Source) and then Count <= Max_Length
+ =>
+ -- Source is followed by Pad characters
+
+ Length (Head'Result) = Count
+ and then
+ Slice (Head'Result, 1, Length (Source)) = To_String (Source)
+ and then
+ Slice (Head'Result, Length (Source) + 1, Count) =
+ (1 .. Count - Length (Source) => Pad),
+
+ Count > Max_Length and then Drop = Right
+ =>
+ -- Source is followed by Pad characters
+
+ Length (Head'Result) = Max_Length
+ and then
+ Slice (Head'Result, 1, Length (Source)) = To_String (Source)
+ and then
+ Slice (Head'Result, Length (Source) + 1, Max_Length) =
+ (1 .. Max_Length - Length (Source) => Pad),
+
+ Count - Length (Source) > Max_Length and then Drop = Left
+ =>
+ -- Source is fully dropped at the left
+
+ To_String (Head'Result) = (1 .. Max_Length => Pad),
+
+ others
+ =>
+ -- Source is partly dropped at the left
+
+ Length (Head'Result) = Max_Length
+ and then
+ Slice (Head'Result, 1, Max_Length - Count + Length (Source)) =
+ Slice (Source, Count - Max_Length + 1, Length (Source))
+ and then
+ Slice (Head'Result,
+ Max_Length - Count + Length (Source) + 1, Max_Length) =
+ (1 .. Count - Length (Source) => Pad));
procedure Head
(Source : in out Bounded_String;
@@ -730,9 +2240,57 @@ package Ada.Strings.Bounded is
Pad : Character := Space;
Drop : Truncation := Error)
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post => Length (Source) = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count <= Length (Source)
+ =>
+ -- Source is cut
+
+ To_String (Source) = Slice (Source'Old, 1, Count),
+
+ Count > Length (Source) and then Count <= Max_Length
+ =>
+ -- Source is followed by Pad characters
+
+ Length (Source) = Count
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ Slice (Source, Length (Source'Old) + 1, Count) =
+ (1 .. Count - Length (Source'Old) => Pad),
+
+ Count > Max_Length and then Drop = Right
+ =>
+ -- Source is followed by Pad characters
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Length (Source'Old)) =
+ To_String (Source'Old)
+ and then
+ Slice (Source, Length (Source'Old) + 1, Max_Length) =
+ (1 .. Max_Length - Length (Source'Old) => Pad),
+
+ Count - Length (Source) > Max_Length and then Drop = Left
+ =>
+ -- Source is fully dropped on the left
+
+ To_String (Source) = (1 .. Max_Length => Pad),
+
+ others
+ =>
+ -- Source is partly dropped on the left
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Max_Length - Count + Length (Source'Old)) =
+ Slice (Source'Old,
+ Count - Max_Length + 1, Length (Source'Old))
+ and then
+ Slice (Source,
+ Max_Length - Count + Length (Source'Old) + 1, Max_Length) =
+ (1 .. Count - Length (Source'Old) => Pad));
function Tail
(Source : Bounded_String;
@@ -740,9 +2298,60 @@ package Ada.Strings.Bounded is
Pad : Character := Space;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post => Length (Tail'Result) = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count < Length (Source)
+ =>
+ -- Source is cut
+
+ (if Count > 0 then
+ To_String (Tail'Result) =
+ Slice (Source, Length (Source) - Count + 1, Length (Source))
+ else Length (Tail'Result) = 0),
+
+ Count >= Length (Source) and then Count < Max_Length
+ =>
+ -- Source is preceded by Pad characters
+
+ Length (Tail'Result) = Count
+ and then
+ Slice (Tail'Result, 1, Count - Length (Source)) =
+ (1 .. Count - Length (Source) => Pad)
+ and then
+ Slice (Tail'Result, Count - Length (Source) + 1, Count) =
+ To_String (Source),
+
+ Count >= Max_Length and then Drop = Left
+ =>
+ -- Source is preceded by Pad characters
+
+ Length (Tail'Result) = Max_Length
+ and then
+ Slice (Tail'Result, 1, Max_Length - Length (Source)) =
+ (1 .. Max_Length - Length (Source) => Pad)
+ and then
+ (if Length (Source) > 0 then
+ Slice (Tail'Result,
+ Max_Length - Length (Source) + 1, Max_Length) =
+ To_String (Source)),
+
+ Count - Length (Source) >= Max_Length and then Drop /= Left
+ =>
+ -- Source is fully dropped on the right
+
+ To_String (Tail'Result) = (1 .. Max_Length => Pad),
+
+ others
+ =>
+ -- Source is partly dropped on the right
+
+ Length (Tail'Result) = Max_Length
+ and then
+ Slice (Tail'Result, 1, Count - Length (Source)) =
+ (1 .. Count - Length (Source) => Pad)
+ and then
+ Slice (Tail'Result, Count - Length (Source) + 1, Max_Length) =
+ Slice (Source, 1, Max_Length - Count + Length (Source)));
procedure Tail
(Source : in out Bounded_String;
@@ -750,9 +2359,62 @@ package Ada.Strings.Bounded is
Pad : Character := Space;
Drop : Truncation := Error)
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post => Length (Source) = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count < Length (Source)
+ =>
+ -- Source is cut
+
+ (if Count > 0 then
+ To_String (Source) =
+ Slice (Source'Old,
+ Length (Source'Old) - Count + 1, Length (Source'Old))
+ else Length (Source) = 0),
+
+ Count >= Length (Source) and then Count < Max_Length
+ =>
+ -- Source is preceded by Pad characters
+
+ Length (Source) = Count
+ and then
+ Slice (Source, 1, Count - Length (Source'Old)) =
+ (1 .. Count - Length (Source'Old) => Pad)
+ and then
+ Slice (Source, Count - Length (Source'Old) + 1, Count) =
+ To_String (Source'Old),
+
+ Count >= Max_Length and then Drop = Left
+ =>
+ -- Source is preceded by Pad characters
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Max_Length - Length (Source'Old)) =
+ (1 .. Max_Length - Length (Source'Old) => Pad)
+ and then
+ (if Length (Source'Old) > 0 then
+ Slice (Source,
+ Max_Length - Length (Source'Old) + 1, Max_Length) =
+ To_String (Source'Old)),
+
+ Count - Length (Source) >= Max_Length and then Drop /= Left
+ =>
+ -- Source is fully dropped at the right
+
+ To_String (Source) = (1 .. Max_Length => Pad),
+
+ others
+ =>
+ -- Source is partly dropped at the right
+
+ Length (Source) = Max_Length
+ and then
+ Slice (Source, 1, Count - Length (Source'Old)) =
+ (1 .. Count - Length (Source'Old) => Pad)
+ and then
+ Slice (Source, Count - Length (Source'Old) + 1, Max_Length) =
+ Slice (Source'Old,
+ 1, Max_Length - Count + Length (Source'Old)));
------------------------------------
-- String Constructor Subprograms --
@@ -762,64 +2424,113 @@ package Ada.Strings.Bounded is
(Left : Natural;
Right : Character) return Bounded_String
with
- Pre => Left <= Max_Length,
- Post => Length ("*"'Result) = Left,
- Global => null;
+ Pre => Left <= Max_Length,
+ Post => To_String ("*"'Result) = (1 .. Left => Right);
function "*"
(Left : Natural;
Right : String) return Bounded_String
with
- Pre => (if Left /= 0 then Right'Length <= Max_Length / Left),
- Post => Length ("*"'Result) = Left * Right'Length,
- Global => null;
+ Pre => (if Left /= 0 then Right'Length <= Max_Length / Left),
+ Post =>
+ Length ("*"'Result) = Left * Right'Length
+ and then
+ (if Right'Length > 0 then
+ (for all K in 1 .. Left * Right'Length =>
+ Element ("*"'Result, K) =
+ Right (Right'First + (K - 1) mod Right'Length)));
function "*"
(Left : Natural;
Right : Bounded_String) return Bounded_String
with
- Pre => (if Left /= 0 then Length (Right) <= Max_Length / Left),
- Post => Length ("*"'Result) = Left * Length (Right),
- Global => null;
+ Pre => (if Left /= 0 then Length (Right) <= Max_Length / Left),
+ Post =>
+ Length ("*"'Result) = Left * Length (Right)
+ and then
+ (if Length (Right) > 0 then
+ (for all K in 1 .. Left * Length (Right) =>
+ Element ("*"'Result, K) =
+ Element (Right, 1 + (K - 1) mod Length (Right))));
function Replicate
(Count : Natural;
Item : Character;
Drop : Truncation := Error) return Bounded_String
with
- Pre => (if Count > Max_Length then Drop /= Error),
- Post =>
- Length (Replicate'Result)
- = Natural'Min (Max_Length, Count),
- Global => null;
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Post =>
+ To_String (Replicate'Result) =
+ (1 .. Natural'Min (Max_Length, Count) => Item);
function Replicate
(Count : Natural;
Item : String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
- (if Item'Length /= 0
- and then Count > Max_Length / Item'Length
+ Pre =>
+ (if Count /= 0 and then Item'Length > Max_Length / Count
then Drop /= Error),
- Post =>
- Length (Replicate'Result)
- = Natural'Min (Max_Length, Count * Item'Length),
- Global => null;
+ Contract_Cases =>
+ (Count = 0 or else Item'Length <= Max_Length / Count
+ =>
+ Length (Replicate'Result) = Count * Item'Length
+ and then
+ (if Item'Length > 0 then
+ (for all K in 1 .. Count * Item'Length =>
+ Element (Replicate'Result, K) =
+ Item (Item'First + (K - 1) mod Item'Length))),
+ Count /= 0
+ and then Item'Length > Max_Length / Count
+ and then Drop = Right
+ =>
+ Length (Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Element (Replicate'Result, K) =
+ Item (Item'First + (K - 1) mod Item'Length)),
+ others -- Drop = Left
+ =>
+ Length (Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Element (Replicate'Result, K) =
+ Item (Item'Last - (Max_Length - K) mod Item'Length)));
function Replicate
(Count : Natural;
Item : Bounded_String;
Drop : Truncation := Error) return Bounded_String
with
- Pre =>
- (if Length (Item) /= 0
- and then Count > Max_Length / Length (Item)
+ Pre =>
+ (if Count /= 0 and then Length (Item) > Max_Length / Count
then Drop /= Error),
- Post =>
- Length (Replicate'Result)
- = Natural'Min (Max_Length, Count * Length (Item)),
- Global => null;
+ Contract_Cases =>
+ ((if Count /= 0 then Length (Item) <= Max_Length / Count)
+ =>
+ Length (Replicate'Result) = Count * Length (Item)
+ and then
+ (if Length (Item) > 0 then
+ (for all K in 1 .. Count * Length (Item) =>
+ Element (Replicate'Result, K) =
+ Element (Item, 1 + (K - 1) mod Length (Item)))),
+ Count /= 0
+ and then Length (Item) > Max_Length / Count
+ and then Drop = Right
+ =>
+ Length (Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Element (Replicate'Result, K) =
+ Element (Item, 1 + (K - 1) mod Length (Item))),
+ others -- Drop = Left
+ =>
+ Length (Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Element (Replicate'Result, K) =
+ Element (Item,
+ Length (Item) - (Max_Length - K) mod Length (Item))));
private
-- Most of the implementation is in the separate non generic package
@@ -843,7 +2554,8 @@ package Ada.Strings.Bounded is
-- the generic instantiation is compatible with the Super_String
-- type declared in the Superbounded package.
- function From_String (Source : String) return Bounded_String;
+ function From_String (Source : String) return Bounded_String
+ with Pre => Source'Length <= Max_Length;
-- Private routine used only by Stream_Convert
pragma Stream_Convert (Bounded_String, From_String, To_String);
diff --git a/gcc/ada/libgnat/a-strfix.adb b/gcc/ada/libgnat/a-strfix.adb
index 00967c4..31dea6c 100644
--- a/gcc/ada/libgnat/a-strfix.adb
+++ b/gcc/ada/libgnat/a-strfix.adb
@@ -214,7 +214,8 @@ package body Ada.Strings.Fixed with SPARK_Mode is
-- Lemma_Split --
-----------------
- procedure Lemma_Split (Result : String) is
+ procedure Lemma_Split (Result : String)
+ is
begin
for K in Ptr + 1 .. Ptr + Right'Length loop
Lemma_Mod (K - 1);
@@ -307,7 +308,8 @@ package body Ada.Strings.Fixed with SPARK_Mode is
From : Positive;
Through : Natural;
Justify : Alignment := Left;
- Pad : Character := Space) with SPARK_Mode => Off is
+ Pad : Character := Space)
+ is
begin
Move (Source => Delete (Source, From, Through),
Target => Source,
@@ -403,7 +405,8 @@ package body Ada.Strings.Fixed with SPARK_Mode is
(Source : in out String;
Before : Positive;
New_Item : String;
- Drop : Truncation := Error) with SPARK_Mode => Off is
+ Drop : Truncation := Error)
+ is
begin
Move (Source => Insert (Source, Before, New_Item),
Target => Source,
@@ -419,7 +422,8 @@ package body Ada.Strings.Fixed with SPARK_Mode is
Target : out String;
Drop : Truncation := Error;
Justify : Alignment := Left;
- Pad : Character := Space) with SPARK_Mode => Off
+ Pad : Character := Space)
+ with SPARK_Mode => Off
is
Sfirst : constant Integer := Source'First;
Slast : constant Integer := Source'Last;
@@ -571,7 +575,8 @@ package body Ada.Strings.Fixed with SPARK_Mode is
(Source : in out String;
Position : Positive;
New_Item : String;
- Drop : Truncation := Right) with SPARK_Mode => Off is
+ Drop : Truncation := Right)
+ is
begin
Move (Source => Overwrite (Source, Position, New_Item),
Target => Source,
@@ -648,7 +653,8 @@ package body Ada.Strings.Fixed with SPARK_Mode is
By : String;
Drop : Truncation := Error;
Justify : Alignment := Left;
- Pad : Character := Space) with SPARK_Mode => Off is
+ Pad : Character := Space)
+ is
begin
Move (Replace_Slice (Source, Low, High, By), Source, Drop, Justify, Pad);
end Replace_Slice;
@@ -865,7 +871,7 @@ package body Ada.Strings.Fixed with SPARK_Mode is
High, Low : Integer;
begin
- Low := Index (Source, Set => Left, Test => Outside, Going => Forward);
+ Low := Index (Source, Set => Left, Test => Outside, Going => Forward);
-- Case where source comprises only characters in Left
diff --git a/gcc/ada/libgnat/a-strfix.ads b/gcc/ada/libgnat/a-strfix.ads
index 1a5ee94..1d9fd1b 100644
--- a/gcc/ada/libgnat/a-strfix.ads
+++ b/gcc/ada/libgnat/a-strfix.ads
@@ -382,7 +382,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
=>
Index'Result = 0,
- -- Otherwise, a index in the range of Source is returned
+ -- Otherwise, an index in the range of Source is returned
others
=>
@@ -392,7 +392,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
Index'Result in Source'Range
-- The character at the returned index satisfies the property
- -- Test on Set
+ -- Test on Set.
and then
(Test = Inside)
@@ -433,7 +433,7 @@ package Ada.Strings.Fixed with SPARK_Mode is
=>
Index'Result = 0,
- -- Otherwise, a index in the considered range of Source is returned
+ -- Otherwise, an index in the considered range of Source is returned
others
=>
@@ -904,7 +904,15 @@ package Ada.Strings.Fixed with SPARK_Mode is
Justify : Alignment := Left;
Pad : Character := Space)
with
- Pre => Low - 1 <= Source'Last,
+ Pre =>
+ Low - 1 <= Source'Last
+ and then High >= Source'First - 1
+ and then (if High >= Low
+ then Natural'Max (0, Low - Source'First)
+ <= Natural'Last
+ - By'Length
+ - Natural'Max (Source'Last - High, 0)
+ else Source'Length <= Natural'Last - By'Length),
-- Incomplete contract
@@ -966,7 +974,9 @@ package Ada.Strings.Fixed with SPARK_Mode is
New_Item : String;
Drop : Truncation := Error)
with
- Pre => Before - 1 in Source'First - 1 .. Source'Last,
+ Pre =>
+ Before - 1 in Source'First - 1 .. Source'Last
+ and then Source'Length <= Natural'Last - New_Item'Length,
-- Incomplete contract
@@ -1033,7 +1043,11 @@ package Ada.Strings.Fixed with SPARK_Mode is
New_Item : String;
Drop : Truncation := Right)
with
- Pre => Position - 1 in Source'First - 1 .. Source'Last,
+ Pre =>
+ Position - 1 in Source'First - 1 .. Source'Last
+ and then
+ (if Position - Source'First >= Source'Length - New_Item'Length
+ then Position - Source'First <= Natural'Last - New_Item'Length),
-- Incomplete contract
@@ -1133,31 +1147,15 @@ package Ada.Strings.Fixed with SPARK_Mode is
-- Otherwise, the returned string is a slice of Source
else
- (for some Low in Source'Range =>
- (for some High in Source'Range =>
-
- -- Trim returns the slice of Source between Low and High
-
- Trim'Result = Source (Low .. High)
-
- -- Values of Low and High and the characters at their
- -- position depend on Side.
-
- and then
- (if Side = Left then High = Source'Last
- else Source (High) /= ' ')
- and then
- (if Side = Right then Low = Source'First
- else Source (Low) /= ' ')
-
- -- All characters outside range Low .. High are
- -- Space characters.
-
- and then
- (for all J in Source'Range =>
- (if J < Low then Source (J) = ' ')
- and then
- (if J > High then Source (J) = ' '))))),
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then Source'First
+ else Index_Non_Blank (Source, Forward));
+ High : constant Positive :=
+ (if Side = Left then Source'Last
+ else Index_Non_Blank (Source, Backward));
+ begin
+ Trim'Result = Source (Low .. High))),
Global => null;
-- Returns the string obtained by removing from Source all leading Space
-- characters (if Side = Left), all trailing Space characters (if
@@ -1203,30 +1201,13 @@ package Ada.Strings.Fixed with SPARK_Mode is
-- Otherwise, the returned string is a slice of Source
else
- (for some Low in Source'Range =>
- (for some High in Source'Range =>
-
- -- Trim returns the slice of Source between Low and High
-
- Trim'Result = Source (Low .. High)
-
- -- Characters at the bounds of the returned string are
- -- not contained in Left or Right.
-
- and then not Ada.Strings.Maps.Is_In (Source (Low), Left)
- and then not Ada.Strings.Maps.Is_In (Source (High), Right)
-
- -- All characters before Low are contained in Left.
- -- All characters after High are contained in Right.
-
- and then
- (for all K in Source'Range =>
- (if K < Low
- then
- Ada.Strings.Maps.Is_In (Source (K), Left))
- and then
- (if K > High then
- Ada.Strings.Maps.Is_In (Source (K), Right)))))),
+ (declare
+ Low : constant Positive :=
+ Index (Source, Left, Outside, Forward);
+ High : constant Positive :=
+ Index (Source, Right, Outside, Backward);
+ begin
+ Trim'Result = Source (Low .. High))),
Global => null;
-- Returns the string obtained by removing from Source all leading
-- characters in Left and all trailing characters in Right.
diff --git a/gcc/ada/libgnat/a-strmap.adb b/gcc/ada/libgnat/a-strmap.adb
index 8ad9f12..c87f4e5 100644
--- a/gcc/ada/libgnat/a-strmap.adb
+++ b/gcc/ada/libgnat/a-strmap.adb
@@ -35,7 +35,17 @@
-- is bit-by-bit or character-by-character and therefore rather slow.
-- Generally for character sets we favor the full 32-byte representation.
-package body Ada.Strings.Maps is
+-- Assertions, ghost code and loop invariants in this unit are meant for
+-- analysis only, not for run-time checking, as it would be too costly
+-- otherwise. This is enforced by setting the assertion policy to Ignore.
+
+pragma Assertion_Policy (Assert => Ignore,
+ Ghost => Ignore,
+ Loop_Invariant => Ignore);
+
+package body Ada.Strings.Maps
+ with SPARK_Mode
+is
---------
-- "-" --
@@ -102,9 +112,7 @@ package body Ada.Strings.Maps is
(Element : Character;
Set : Character_Set) return Boolean
is
- begin
- return Set (Element);
- end Is_In;
+ (Set (Element));
---------------
-- Is_Subset --
@@ -122,18 +130,37 @@ package body Ada.Strings.Maps is
-- To_Domain --
---------------
- function To_Domain (Map : Character_Mapping) return Character_Sequence
- is
- Result : String (1 .. Map'Length);
+ function To_Domain (Map : Character_Mapping) return Character_Sequence is
+ Result : String (1 .. Map'Length) with Relaxed_Initialization;
J : Natural;
+ type Character_Index is array (Character) of Natural with Ghost;
+ Indexes : Character_Index := (others => 0) with Ghost;
+
begin
J := 0;
for C in Map'Range loop
if Map (C) /= C then
J := J + 1;
Result (J) := C;
+ Indexes (C) := J;
end if;
+
+ pragma Loop_Invariant (if Map = Identity then J = 0);
+ pragma Loop_Invariant (J <= Character'Pos (C) + 1);
+ pragma Loop_Invariant (Result (1 .. J)'Initialized);
+ pragma Loop_Invariant (for all K in 1 .. J => Result (K) <= C);
+ pragma Loop_Invariant
+ (SPARK_Proof_Sorted_Character_Sequence (Result (1 .. J)));
+ pragma Loop_Invariant
+ (for all D in Map'First .. C =>
+ (if Map (D) = D then
+ Indexes (D) = 0
+ else
+ Indexes (D) in 1 .. J
+ and then Result (Indexes (D)) = D));
+ pragma Loop_Invariant
+ (for all Char of Result (1 .. J) => Map (Char) /= Char);
end loop;
return Result (1 .. J);
@@ -146,7 +173,7 @@ package body Ada.Strings.Maps is
function To_Mapping
(From, To : Character_Sequence) return Character_Mapping
is
- Result : Character_Mapping;
+ Result : Character_Mapping with Relaxed_Initialization;
Inserted : Character_Set := Null_Set;
From_Len : constant Natural := From'Length;
To_Len : constant Natural := To'Length;
@@ -158,6 +185,9 @@ package body Ada.Strings.Maps is
for Char in Character loop
Result (Char) := Char;
+ pragma Loop_Invariant (Result (Result'First .. Char)'Initialized);
+ pragma Loop_Invariant
+ (for all C in Result'First .. Char => Result (C) = C);
end loop;
for J in From'Range loop
@@ -167,6 +197,23 @@ package body Ada.Strings.Maps is
Result (From (J)) := To (J - From'First + To'First);
Inserted (From (J)) := True;
+
+ pragma Loop_Invariant (Result'Initialized);
+ pragma Loop_Invariant
+ (for all K in From'First .. J =>
+ Result (From (K)) = To (K - From'First + To'First)
+ and then Inserted (From (K)));
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ (Inserted (Char) =
+ (for some K in From'First .. J => Char = From (K))));
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ (if not Inserted (Char) then Result (Char) = Char));
+ pragma Loop_Invariant
+ (if (for all K in From'First .. J =>
+ From (K) = To (J - From'First + To'First))
+ then Result = Identity);
end loop;
return Result;
@@ -176,19 +223,195 @@ package body Ada.Strings.Maps is
-- To_Range --
--------------
- function To_Range (Map : Character_Mapping) return Character_Sequence
- is
- Result : String (1 .. Map'Length);
+ function To_Range (Map : Character_Mapping) return Character_Sequence is
+
+ -- Extract from the postcondition of To_Domain the essential properties
+ -- that define Seq as the domain of Map.
+ function Is_Domain
+ (Map : Character_Mapping;
+ Seq : Character_Sequence)
+ return Boolean
+ is
+ (Seq'First = 1
+ and then
+ SPARK_Proof_Sorted_Character_Sequence (Seq)
+ and then
+ (for all Char in Character =>
+ (if (for all X of Seq => X /= Char)
+ then Map (Char) = Char))
+ and then
+ (for all Char of Seq => Map (Char) /= Char))
+ with
+ Ghost;
+
+ -- Given Map, there is a unique sequence Seq for which
+ -- Is_Domain(Map,Seq) holds.
+ procedure Lemma_Domain_Unicity
+ (Map : Character_Mapping;
+ Seq1, Seq2 : Character_Sequence)
+ with
+ Ghost,
+ Pre => Is_Domain (Map, Seq1)
+ and then Is_Domain (Map, Seq2),
+ Post => Seq1 = Seq2;
+
+ -- Isolate the proof that To_Domain(Map) returns a sequence for which
+ -- Is_Domain holds.
+ procedure Lemma_Is_Domain (Map : Character_Mapping)
+ with
+ Ghost,
+ Post => Is_Domain (Map, To_Domain (Map));
+
+ -- Deduce the alternative expression of sortedness from the one in
+ -- SPARK_Proof_Sorted_Character_Sequence which compares consecutive
+ -- elements.
+ procedure Lemma_Is_Sorted (Seq : Character_Sequence)
+ with
+ Ghost,
+ Pre => SPARK_Proof_Sorted_Character_Sequence (Seq),
+ Post => (for all J in Seq'Range =>
+ (for all K in Seq'Range =>
+ (if J < K then Seq (J) < Seq (K))));
+
+ --------------------------
+ -- Lemma_Domain_Unicity --
+ --------------------------
+
+ procedure Lemma_Domain_Unicity
+ (Map : Character_Mapping;
+ Seq1, Seq2 : Character_Sequence)
+ is
+ J : Positive := 1;
+
+ begin
+ while J <= Seq1'Last
+ and then J <= Seq2'Last
+ and then Seq1 (J) = Seq2 (J)
+ loop
+ pragma Loop_Invariant
+ (Seq1 (Seq1'First .. J) = Seq2 (Seq2'First .. J));
+
+ if J = Positive'Last then
+ return;
+ end if;
+
+ J := J + 1;
+ end loop;
+
+ Lemma_Is_Sorted (Seq1);
+ Lemma_Is_Sorted (Seq2);
+
+ if J <= Seq1'Last
+ and then J <= Seq2'Last
+ then
+ if Seq1 (J) < Seq2 (J) then
+ pragma Assert (for all X of Seq2 => X /= Seq1 (J));
+ pragma Assert (Map (Seq1 (J)) = Seq1 (J));
+ pragma Assert (False);
+ else
+ pragma Assert (for all X of Seq1 => X /= Seq2 (J));
+ pragma Assert (Map (Seq2 (J)) = Seq2 (J));
+ pragma Assert (False);
+ end if;
+
+ elsif J <= Seq1'Last then
+ pragma Assert (for all X of Seq2 => X /= Seq1 (J));
+ pragma Assert (Map (Seq1 (J)) = Seq1 (J));
+ pragma Assert (False);
+
+ elsif J <= Seq2'Last then
+ pragma Assert (for all X of Seq1 => X /= Seq2 (J));
+ pragma Assert (Map (Seq2 (J)) = Seq2 (J));
+ pragma Assert (False);
+ end if;
+ end Lemma_Domain_Unicity;
+
+ ---------------------
+ -- Lemma_Is_Domain --
+ ---------------------
+
+ procedure Lemma_Is_Domain (Map : Character_Mapping) is
+ Ignore : constant Character_Sequence := To_Domain (Map);
+ begin
+ null;
+ end Lemma_Is_Domain;
+
+ ---------------------
+ -- Lemma_Is_Sorted --
+ ---------------------
+
+ procedure Lemma_Is_Sorted (Seq : Character_Sequence) is
+ begin
+ for A in Seq'Range loop
+ exit when A = Positive'Last;
+
+ for B in A + 1 .. Seq'Last loop
+ pragma Loop_Invariant
+ (for all K in A + 1 .. B => Seq (A) < Seq (K));
+ end loop;
+
+ pragma Loop_Invariant
+ (for all J in Seq'First .. A =>
+ (for all K in Seq'Range =>
+ (if J < K then Seq (J) < Seq (K))));
+ end loop;
+ end Lemma_Is_Sorted;
+
+ -- Local variables
+
+ Result : String (1 .. Map'Length) with Relaxed_Initialization;
J : Natural;
+
+ -- Repeat the computation from To_Domain in ghost code, in order to
+ -- prove the relationship between Result and To_Domain(Map).
+
+ Domain : String (1 .. Map'Length) with Ghost, Relaxed_Initialization;
+ type Character_Index is array (Character) of Natural with Ghost;
+ Indexes : Character_Index := (others => 0) with Ghost;
+
+ -- Start of processing for To_Range
+
begin
J := 0;
for C in Map'Range loop
if Map (C) /= C then
J := J + 1;
Result (J) := Map (C);
+ Domain (J) := C;
+ Indexes (C) := J;
end if;
+
+ -- Repeat the loop invariants from To_Domain regarding Domain and
+ -- Indexes. Add similar loop invariants for Result and Indexes.
+
+ pragma Loop_Invariant (J <= Character'Pos (C) + 1);
+ pragma Loop_Invariant (Result (1 .. J)'Initialized);
+ pragma Loop_Invariant (Domain (1 .. J)'Initialized);
+ pragma Loop_Invariant (for all K in 1 .. J => Domain (K) <= C);
+ pragma Loop_Invariant
+ (SPARK_Proof_Sorted_Character_Sequence (Domain (1 .. J)));
+ pragma Loop_Invariant
+ (for all D in Map'First .. C =>
+ (if Map (D) = D then
+ Indexes (D) = 0
+ else
+ Indexes (D) in 1 .. J
+ and then Domain (Indexes (D)) = D
+ and then Result (Indexes (D)) = Map (D)));
+ pragma Loop_Invariant
+ (for all Char of Domain (1 .. J) => Map (Char) /= Char);
+ pragma Loop_Invariant
+ (for all K in 1 .. J => Result (K) = Map (Domain (K)));
end loop;
+ -- Show the equality of Domain and To_Domain(Map)
+
+ Lemma_Is_Domain (Map);
+ Lemma_Domain_Unicity (Map, Domain (1 .. J), To_Domain (Map));
+ pragma Assert
+ (for all K in 1 .. J => Domain (K) = To_Domain (Map) (K));
+ pragma Assert (To_Domain (Map)'Length = J);
+
return Result (1 .. J);
end To_Range;
@@ -197,18 +420,26 @@ package body Ada.Strings.Maps is
---------------
function To_Ranges (Set : Character_Set) return Character_Ranges is
- Max_Ranges : Character_Ranges (1 .. Set'Length / 2 + 1);
+ Max_Ranges : Character_Ranges (1 .. Set'Length / 2 + 1)
+ with Relaxed_Initialization;
Range_Num : Natural;
C : Character;
+ C_Iter : Character with Ghost;
begin
C := Character'First;
Range_Num := 0;
loop
+ C_Iter := C;
+
-- Skip gap between subsets
while not Set (C) loop
+ pragma Loop_Invariant
+ (Character'Pos (C) >= Character'Pos (C'Loop_Entry));
+ pragma Loop_Invariant
+ (for all Char in C'Loop_Entry .. C => not Set (Char));
exit when C = Character'Last;
C := Character'Succ (C);
end loop;
@@ -221,16 +452,45 @@ package body Ada.Strings.Maps is
-- Span a subset
loop
+ pragma Loop_Invariant
+ (Character'Pos (C) >= Character'Pos (C'Loop_Entry));
+ pragma Loop_Invariant
+ (for all Char in C'Loop_Entry .. C =>
+ (if Char /= C then Set (Char)));
exit when not Set (C) or else C = Character'Last;
C := Character'Succ (C);
end loop;
if Set (C) then
- Max_Ranges (Range_Num). High := C;
+ Max_Ranges (Range_Num).High := C;
exit;
else
- Max_Ranges (Range_Num). High := Character'Pred (C);
+ Max_Ranges (Range_Num).High := Character'Pred (C);
end if;
+
+ pragma Assert
+ (for all Char in C_Iter .. C =>
+ (Set (Char) =
+ (Char in Max_Ranges (Range_Num).Low ..
+ Max_Ranges (Range_Num).High)));
+ pragma Assert
+ (for all Char in Character'First .. C_Iter =>
+ (if Char /= C_Iter then
+ (Set (Char) =
+ (for some Span of Max_Ranges (1 .. Range_Num - 1) =>
+ Char in Span.Low .. Span.High))));
+
+ pragma Loop_Invariant (2 * Range_Num <= Character'Pos (C) + 1);
+ pragma Loop_Invariant (Max_Ranges (1 .. Range_Num)'Initialized);
+ pragma Loop_Invariant (not Set (C));
+ pragma Loop_Invariant
+ (for all Char in Character'First .. C =>
+ (Set (Char) =
+ (for some Span of Max_Ranges (1 .. Range_Num) =>
+ Char in Span.Low .. Span.High)));
+ pragma Loop_Invariant
+ (for all Span of Max_Ranges (1 .. Range_Num) =>
+ (for all Char in Span.Low .. Span.High => Set (Char)));
end loop;
return Max_Ranges (1 .. Range_Num);
@@ -241,7 +501,8 @@ package body Ada.Strings.Maps is
-----------------
function To_Sequence (Set : Character_Set) return Character_Sequence is
- Result : String (1 .. Character'Pos (Character'Last) + 1);
+ Result : String (1 .. Character'Pos (Character'Last) + 1)
+ with Relaxed_Initialization;
Count : Natural := 0;
begin
for Char in Set'Range loop
@@ -249,6 +510,17 @@ package body Ada.Strings.Maps is
Count := Count + 1;
Result (Count) := Char;
end if;
+
+ pragma Loop_Invariant (Count <= Character'Pos (Char) + 1);
+ pragma Loop_Invariant (Result (1 .. Count)'Initialized);
+ pragma Loop_Invariant (for all K in 1 .. Count => Result (K) <= Char);
+ pragma Loop_Invariant
+ (SPARK_Proof_Sorted_Character_Sequence (Result (1 .. Count)));
+ pragma Loop_Invariant
+ (for all C in Set'First .. Char =>
+ (Set (C) = (for some X of Result (1 .. Count) => C = X)));
+ pragma Loop_Invariant
+ (for all Char of Result (1 .. Count) => Is_In (Char, Set));
end loop;
return Result (1 .. Count);
@@ -259,30 +531,37 @@ package body Ada.Strings.Maps is
------------
function To_Set (Ranges : Character_Ranges) return Character_Set is
- Result : Character_Set;
+ Result : Character_Set := Null_Set;
begin
- for C in Result'Range loop
- Result (C) := False;
- end loop;
-
for R in Ranges'Range loop
for C in Ranges (R).Low .. Ranges (R).High loop
Result (C) := True;
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ Result (Char) =
+ ((for some Prev in Ranges'First .. R - 1 =>
+ Char in Ranges (Prev).Low .. Ranges (Prev).High)
+ or else (Char in Ranges (R).Low .. C)));
end loop;
+
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ Result (Char) =
+ (for some Prev in Ranges'First .. R =>
+ Char in Ranges (Prev).Low .. Ranges (Prev).High));
end loop;
return Result;
end To_Set;
function To_Set (Span : Character_Range) return Character_Set is
- Result : Character_Set;
+ Result : Character_Set := Null_Set;
begin
- for C in Result'Range loop
- Result (C) := False;
- end loop;
-
for C in Span.Low .. Span.High loop
Result (C) := True;
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ Result (Char) = (Char in Span.Low .. C));
end loop;
return Result;
@@ -293,6 +572,10 @@ package body Ada.Strings.Maps is
begin
for J in Sequence'Range loop
Result (Sequence (J)) := True;
+ pragma Loop_Invariant
+ (for all Char in Character =>
+ Result (Char) =
+ (for some K in Sequence'First .. J => Char = Sequence (K)));
end loop;
return Result;
@@ -313,8 +596,6 @@ package body Ada.Strings.Maps is
(Map : Character_Mapping;
Element : Character) return Character
is
- begin
- return Map (Element);
- end Value;
+ (Map (Element));
end Ada.Strings.Maps;
diff --git a/gcc/ada/libgnat/a-strmap.ads b/gcc/ada/libgnat/a-strmap.ads
index c35c392..1a15d5d 100644
--- a/gcc/ada/libgnat/a-strmap.ads
+++ b/gcc/ada/libgnat/a-strmap.ads
@@ -33,15 +33,24 @@
-- --
------------------------------------------------------------------------------
+-- The package Strings.Maps defines the types, operations, and other entities
+-- needed for character sets and character-to-character mappings.
+
-- Preconditions in this unit are meant for analysis only, not for run-time
-- checking, so that the expected exceptions are raised. This is enforced by
--- setting the corresponding assertion policy to Ignore.
+-- setting the corresponding assertion policy to Ignore. Postconditions and
+-- ghost code should not be executed at runtime as well, in order not to slow
+-- down the execution of these functions.
-pragma Assertion_Policy (Pre => Ignore);
+pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Ghost => Ignore);
with Ada.Characters.Latin_1;
-package Ada.Strings.Maps is
+package Ada.Strings.Maps
+ with SPARK_Mode
+is
pragma Pure;
-- In accordance with Ada 2005 AI-362
@@ -51,9 +60,10 @@ package Ada.Strings.Maps is
type Character_Set is private;
pragma Preelaborable_Initialization (Character_Set);
- -- Representation for a set of character values:
+ -- An object of type Character_Set represents a set of characters.
Null_Set : constant Character_Set;
+ -- Null_Set represents the set containing no characters.
---------------------------
-- Constructors for Sets --
@@ -63,9 +73,12 @@ package Ada.Strings.Maps is
Low : Character;
High : Character;
end record;
- -- Represents Character range Low .. High
+ -- An object Obj of type Character_Range represents the set of characters
+ -- in the range Obj.Low .. Obj.High.
type Character_Ranges is array (Positive range <>) of Character_Range;
+ -- An object Obj of type Character_Ranges represents the union of the sets
+ -- corresponding to Obj(I) for I in Obj'Range.
function To_Set (Ranges : Character_Ranges) return Character_Set with
Post =>
@@ -78,6 +91,8 @@ package Ada.Strings.Maps is
(for all Span of Ranges =>
(for all Char in Span.Low .. Span.High =>
Is_In (Char, To_Set'Result)));
+ -- If Ranges'Length=0 then Null_Set is returned; otherwise, the returned
+ -- value represents the set corresponding to Ranges.
function To_Set (Span : Character_Range) return Character_Set with
Post =>
@@ -87,6 +102,7 @@ package Ada.Strings.Maps is
(if Is_In (Char, To_Set'Result) then Char in Span.Low .. Span.High))
and then
(for all Char in Span.Low .. Span.High => Is_In (Char, To_Set'Result));
+ -- The returned value represents the set containing each character in Span.
function To_Ranges (Set : Character_Set) return Character_Ranges with
Post =>
@@ -100,6 +116,12 @@ package Ada.Strings.Maps is
and then
(for all Span of To_Ranges'Result =>
(for all Char in Span.Low .. Span.High => Is_In (Char, Set)));
+ -- 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.
+ --
+ -- The postcondition above does not express that the result is the shortest
+ -- array and that it is sorted.
----------------------------------
-- Operations on Character Sets --
@@ -111,6 +133,13 @@ package Ada.Strings.Maps is
=
(for all Char in Character =>
(Is_In (Char, Left) = Is_In (Char, Right)));
+ -- The function "=" returns True if Left and Right represent identical
+ -- sets, and False otherwise.
+
+ -- 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.
function "not" (Right : Character_Set) return Character_Set with
Post =>
@@ -146,10 +175,12 @@ package Ada.Strings.Maps is
(Is_In (Char, "-"'Result)
=
(Is_In (Char, Left) and not Is_In (Char, Right))));
+ -- "-"(Left, Right) is equivalent to "and"(Left, "not"(Right)).
function Is_In
(Element : Character;
Set : Character_Set) return Boolean;
+ -- Is_In returns True if Element is in Set, and False otherwise.
function Is_Subset
(Elements : Character_Set;
@@ -160,6 +191,8 @@ package Ada.Strings.Maps is
=
(for all Char in Character =>
(if Is_In (Char, Elements) then Is_In (Char, Set)));
+ -- Is_Subset returns True if Elements is a subset of Set, and False
+ -- otherwise.
function "<="
(Left : Character_Set;
@@ -167,7 +200,23 @@ package Ada.Strings.Maps is
renames Is_Subset;
subtype Character_Sequence is String;
- -- Alternative representation for a set of character values
+ -- 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.
+
+ function SPARK_Proof_Sorted_Character_Sequence
+ (Seq : Character_Sequence) return Boolean
+ is
+ (for all J in Seq'Range =>
+ (if J /= Seq'Last then Seq (J) < Seq (J + 1)))
+ with
+ Ghost;
+ -- Check whether the Character_Sequence is sorted in stricly increasing
+ -- order, as expected from the result of To_Sequence and To_Domain.
+
+ -- 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.
function To_Set (Sequence : Character_Sequence) return Character_Set with
Post =>
@@ -197,10 +246,10 @@ package Ada.Strings.Maps is
and then
(for all Char of To_Sequence'Result => Is_In (Char, Set))
and then
- (for all J in To_Sequence'Result'Range =>
- (for all K in To_Sequence'Result'Range =>
- (if J /= K
- then To_Sequence'Result (J) /= To_Sequence'Result (K))));
+ SPARK_Proof_Sorted_Character_Sequence (To_Sequence'Result);
+ -- 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.
------------------------------------
-- Character Mapping Declarations --
@@ -208,13 +257,39 @@ package Ada.Strings.Maps is
type Character_Mapping is private;
pragma Preelaborable_Initialization (Character_Mapping);
- -- Representation for a character to character mapping:
+ -- An object of type Character_Mapping represents a Character-to-Character
+ -- mapping.
+
+ type SPARK_Proof_Character_Mapping_Model is
+ array (Character) of Character
+ with Ghost;
+ -- Publicly visible model of a Character_Mapping
+
+ function SPARK_Proof_Model
+ (Map : Character_Mapping)
+ return SPARK_Proof_Character_Mapping_Model
+ with Ghost;
+ -- Creation of a publicly visible model of a Character_Mapping
function Value
(Map : Character_Mapping;
- Element : Character) return Character;
+ Element : Character) return Character
+ with
+ Post => Value'Result = SPARK_Proof_Model (Map) (Element);
+ -- The function Value returns the Character value to which Element maps
+ -- with respect to the mapping represented by Map.
+
+ -- 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.
+
+ -- String handling subprograms that deal with character mappings have
+ -- parameters whose type is Character_Mapping.
Identity : constant Character_Mapping;
+ -- Identity maps each Character to itself.
----------------------------
-- Operations on Mappings --
@@ -240,6 +315,10 @@ package Ada.Strings.Maps is
and then
(if (for all X of From => Char /= X)
then Value (To_Mapping'Result, Char) = Char)));
+ -- 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.
function To_Domain
(Map : Character_Mapping) return Character_Sequence with
@@ -248,24 +327,40 @@ package Ada.Strings.Maps is
and then
To_Domain'Result'First = 1
and then
+ SPARK_Proof_Sorted_Character_Sequence (To_Domain'Result)
+ and then
(for all Char in Character =>
(if (for all X of To_Domain'Result => X /= Char)
then Value (Map, Char) = Char))
and then
(for all Char of To_Domain'Result => Value (Map, Char) /= Char);
+ -- 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.
function To_Range
(Map : Character_Mapping) return Character_Sequence with
Post =>
To_Range'Result'First = 1
and then
- To_Range'Result'Last = To_Domain (Map)'Last
+ To_Range'Result'Length = To_Domain (Map)'Length
and then
(for all J in To_Range'Result'Range =>
To_Range'Result (J) = Value (Map, To_Domain (Map) (J)));
+ -- 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.
+ --
+ -- A direct encoding of the Ada RM would be the postcondition
+ -- To_Range'Result'Last = To_Domain (Map)'Last
+ -- which is not provable unless the postcondition of To_Domain is also
+ -- strengthened to state the value of the high bound for an empty result.
type Character_Mapping_Function is
access function (From : Character) return Character;
+ -- 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.
private
pragma Inline (Is_In);
@@ -285,6 +380,12 @@ private
type Character_Mapping is array (Character) of Character;
+ function SPARK_Proof_Model
+ (Map : Character_Mapping)
+ return SPARK_Proof_Character_Mapping_Model
+ is
+ (SPARK_Proof_Character_Mapping_Model (Map));
+
package L renames Ada.Characters.Latin_1;
Identity : constant Character_Mapping :=
diff --git a/gcc/ada/libgnat/a-strsea.ads b/gcc/ada/libgnat/a-strsea.ads
index 4396747..f4e7d36 100644
--- a/gcc/ada/libgnat/a-strsea.ads
+++ b/gcc/ada/libgnat/a-strsea.ads
@@ -213,7 +213,7 @@ package Ada.Strings.Search with SPARK_Mode is
=>
Index'Result = 0,
- -- Otherwise, a index in the range of Source is returned
+ -- Otherwise, an index in the range of Source is returned
others =>
@@ -222,7 +222,7 @@ package Ada.Strings.Search with SPARK_Mode is
Index'Result in Source'Range
-- The character at the returned index satisfies the property
- -- Test on Set
+ -- Test on Set.
and then (Test = Inside)
= Ada.Strings.Maps.Is_In (Source (Index'Result), Set)
@@ -377,7 +377,7 @@ package Ada.Strings.Search with SPARK_Mode is
=>
Index'Result = 0,
- -- Otherwise, a index in the considered range of Source is returned
+ -- Otherwise, an index in the considered range of Source is returned
others =>
diff --git a/gcc/ada/libgnat/a-strsup.adb b/gcc/ada/libgnat/a-strsup.adb
index 1e85cc2..a94d6ca 100644
--- a/gcc/ada/libgnat/a-strsup.adb
+++ b/gcc/ada/libgnat/a-strsup.adb
@@ -29,10 +29,17 @@
-- --
------------------------------------------------------------------------------
-with Ada.Strings.Maps; use Ada.Strings.Maps;
-with Ada.Strings.Search;
+-- Ghost code, loop invariants and assertions in this unit are meant for
+-- analysis only, not for run-time checking, as it would be too costly
+-- otherwise. This is enforced by setting the assertion policy to Ignore.
-package body Ada.Strings.Superbounded is
+pragma Assertion_Policy (Ghost => Ignore,
+ Loop_Invariant => Ignore,
+ Assert => Ignore);
+
+with Ada.Strings.Maps; use Ada.Strings.Maps;
+
+package body Ada.Strings.Superbounded with SPARK_Mode is
------------
-- Concat --
@@ -53,9 +60,13 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
- Result.Current_Length := Nlen;
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
+
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
+ end if;
+
+ Result.Current_Length := Nlen;
end;
end return;
end Concat;
@@ -74,9 +85,13 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
- Result.Current_Length := Nlen;
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Nlen) := Right;
+
+ if Right'Length > 0 then
+ Result.Data (Llen + 1 .. Nlen) := Super_String_Data (Right);
+ end if;
+
+ Result.Current_Length := Nlen;
end;
end return;
end Concat;
@@ -97,9 +112,13 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
+ Result.Data (1 .. Llen) := Super_String_Data (Left);
+
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
+ end if;
+
Result.Current_Length := Nlen;
- Result.Data (1 .. Llen) := Left;
- Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
end;
end return;
end Concat;
@@ -117,9 +136,9 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
- Result.Current_Length := Llen + 1;
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Result.Current_Length) := Right;
+ Result.Data (Llen + 1) := Right;
+ Result.Current_Length := Llen + 1;
end;
end return;
end Concat;
@@ -137,10 +156,9 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
end if;
- Result.Current_Length := Rlen + 1;
Result.Data (1) := Left;
- Result.Data (2 .. Result.Current_Length) :=
- Right.Data (1 .. Rlen);
+ Result.Data (2 .. Rlen + 1) := Right.Data (1 .. Rlen);
+ Result.Current_Length := Rlen + 1;
end;
end return;
end Concat;
@@ -154,9 +172,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Current_Length = Right.Current_Length
- and then Left.Data (1 .. Left.Current_Length) =
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) = Super_To_String (Right);
end "=";
function Equal
@@ -164,8 +180,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Current_Length = Right'Length
- and then Left.Data (1 .. Left.Current_Length) = Right;
+ return Super_To_String (Left) = Right;
end Equal;
function Equal
@@ -173,8 +188,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left'Length = Right.Current_Length
- and then Left = Right.Data (1 .. Right.Current_Length);
+ return Left = Super_To_String (Right);
end Equal;
-------------
@@ -186,8 +200,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) >
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) > Super_To_String (Right);
end Greater;
function Greater
@@ -195,7 +208,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) > Right;
+ return Super_To_String (Left) > Right;
end Greater;
function Greater
@@ -203,7 +216,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left > Right.Data (1 .. Right.Current_Length);
+ return Left > Super_To_String (Right);
end Greater;
----------------------
@@ -215,8 +228,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) >=
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) >= Super_To_String (Right);
end Greater_Or_Equal;
function Greater_Or_Equal
@@ -224,7 +236,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) >= Right;
+ return Super_To_String (Left) >= Right;
end Greater_Or_Equal;
function Greater_Or_Equal
@@ -232,7 +244,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left >= Right.Data (1 .. Right.Current_Length);
+ return Left >= Super_To_String (Right);
end Greater_Or_Equal;
----------
@@ -244,8 +256,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) <
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) < Super_To_String (Right);
end Less;
function Less
@@ -253,7 +264,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) < Right;
+ return Super_To_String (Left) < Right;
end Less;
function Less
@@ -261,7 +272,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left < Right.Data (1 .. Right.Current_Length);
+ return Left < Super_To_String (Right);
end Less;
-------------------
@@ -273,8 +284,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) <=
- Right.Data (1 .. Right.Current_Length);
+ return Super_To_String (Left) <= Super_To_String (Right);
end Less_Or_Equal;
function Less_Or_Equal
@@ -282,7 +292,7 @@ package body Ada.Strings.Superbounded is
Right : String) return Boolean
is
begin
- return Left.Data (1 .. Left.Current_Length) <= Right;
+ return Super_To_String (Left) <= Right;
end Less_Or_Equal;
function Less_Or_Equal
@@ -290,7 +300,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Boolean
is
begin
- return Left <= Right.Data (1 .. Right.Current_Length);
+ return Left <= Super_To_String (Right);
end Less_Or_Equal;
----------------------
@@ -307,20 +317,20 @@ package body Ada.Strings.Superbounded is
begin
if Slen <= Max_Length then
+ Target.Data (1 .. Slen) := Super_String_Data (Source);
Target.Current_Length := Slen;
- Target.Data (1 .. Slen) := Source;
else
case Drop is
when Strings.Right =>
+ Target.Data (1 .. Max_Length) := Super_String_Data
+ (Source (Source'First .. Source'First - 1 + Max_Length));
Target.Current_Length := Max_Length;
- Target.Data (1 .. Max_Length) :=
- Source (Source'First .. Source'First - 1 + Max_Length);
when Strings.Left =>
+ Target.Data (1 .. Max_Length) := Super_String_Data
+ (Source (Source'Last - (Max_Length - 1) .. Source'Last));
Target.Current_Length := Max_Length;
- Target.Data (1 .. Max_Length) :=
- Source (Source'Last - (Max_Length - 1) .. Source'Last);
when Strings.Error =>
raise Ada.Strings.Length_Error;
@@ -343,17 +353,18 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Max_Length);
Llen : constant Natural := Left.Current_Length;
Rlen : constant Natural := Right.Current_Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Result.Current_Length := Nlen;
+ if Llen <= Max_Length - Rlen then
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Nlen) := Right.Data (1 .. Rlen);
- else
- Result.Current_Length := Max_Length;
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data (1 .. Rlen);
+ end if;
+
+ Result.Current_Length := Llen + Rlen;
+ else
case Drop is
when Strings.Right =>
if Llen >= Max_Length then -- only case is Llen = Max_Length
@@ -379,6 +390,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -392,16 +405,15 @@ package body Ada.Strings.Superbounded is
Max_Length : constant Positive := Source.Max_Length;
Llen : constant Natural := Source.Current_Length;
Rlen : constant Natural := New_Item.Current_Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Source.Current_Length := Nlen;
- Source.Data (Llen + 1 .. Nlen) := New_Item.Data (1 .. Rlen);
+ if Llen <= Max_Length - Rlen then
+ if Rlen > 0 then
+ Source.Data (Llen + 1 .. Llen + Rlen) := New_Item.Data (1 .. Rlen);
+ Source.Current_Length := Llen + Rlen;
+ end if;
else
- Source.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
if Llen < Max_Length then
@@ -423,6 +435,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Append;
@@ -438,17 +452,18 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Max_Length);
Llen : constant Natural := Left.Current_Length;
Rlen : constant Natural := Right'Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Result.Current_Length := Nlen;
+ if Llen <= Max_Length - Rlen then
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Nlen) := Right;
- else
- Result.Current_Length := Max_Length;
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Llen + Rlen) := Super_String_Data (Right);
+ end if;
+
+ Result.Current_Length := Llen + Rlen;
+ else
case Drop is
when Strings.Right =>
if Llen >= Max_Length then -- only case is Llen = Max_Length
@@ -456,27 +471,29 @@ package body Ada.Strings.Superbounded is
else
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
- Result.Data (Llen + 1 .. Max_Length) :=
- Right (Right'First .. Right'First - 1 +
- Max_Length - Llen);
+ Result.Data (Llen + 1 .. Max_Length) := Super_String_Data
+ (Right
+ (Right'First .. Right'First - 1 - Llen + Max_Length));
end if;
when Strings.Left =>
if Rlen >= Max_Length then
- Result.Data (1 .. Max_Length) :=
- Right (Right'Last - (Max_Length - 1) .. Right'Last);
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (Right (Right'Last - (Max_Length - 1) .. Right'Last));
else
Result.Data (1 .. Max_Length - Rlen) :=
Left.Data (Llen - (Max_Length - Rlen - 1) .. Llen);
Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
- Right;
+ Super_String_Data (Right);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -490,40 +507,42 @@ package body Ada.Strings.Superbounded is
Max_Length : constant Positive := Source.Max_Length;
Llen : constant Natural := Source.Current_Length;
Rlen : constant Natural := New_Item'Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Source.Current_Length := Nlen;
- Source.Data (Llen + 1 .. Nlen) := New_Item;
+ if Llen <= Max_Length - Rlen then
+ if Rlen > 0 then
+ Source.Data (Llen + 1 .. Llen + Rlen) :=
+ Super_String_Data (New_Item);
+ Source.Current_Length := Llen + Rlen;
+ end if;
else
- Source.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
if Llen < Max_Length then
- Source.Data (Llen + 1 .. Max_Length) :=
- New_Item (New_Item'First ..
- New_Item'First - 1 + Max_Length - Llen);
+ Source.Data (Llen + 1 .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'First ..
+ New_Item'First - 1 - Llen + Max_Length));
end if;
when Strings.Left =>
if Rlen >= Max_Length then
- Source.Data (1 .. Max_Length) :=
- New_Item (New_Item'Last - (Max_Length - 1) ..
- New_Item'Last);
+ Source.Data (1 .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'Last - (Max_Length - 1) ..
+ New_Item'Last));
else
Source.Data (1 .. Max_Length - Rlen) :=
Source.Data (Llen - (Max_Length - Rlen - 1) .. Llen);
Source.Data (Max_Length - Rlen + 1 .. Max_Length) :=
- New_Item;
+ Super_String_Data (New_Item);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Append;
@@ -539,25 +558,25 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Max_Length);
Llen : constant Natural := Left'Length;
Rlen : constant Natural := Right.Current_Length;
- Nlen : constant Natural := Llen + Rlen;
begin
- if Nlen <= Max_Length then
- Result.Current_Length := Nlen;
- Result.Data (1 .. Llen) := Left;
- Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data (1 .. Rlen);
+ if Llen <= Max_Length - Rlen then
+ Result.Data (1 .. Llen) := Super_String_Data (Left);
- else
- Result.Current_Length := Max_Length;
+ if Rlen > 0 then
+ Result.Data (Llen + 1 .. Llen + Rlen) := Right.Data (1 .. Rlen);
+ end if;
+ Result.Current_Length := Llen + Rlen;
+ else
case Drop is
when Strings.Right =>
if Llen >= Max_Length then
- Result.Data (1 .. Max_Length) :=
- Left (Left'First .. Left'First + (Max_Length - 1));
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (Left (Left'First .. Left'First + (Max_Length - 1)));
else
- Result.Data (1 .. Llen) := Left;
+ Result.Data (1 .. Llen) := Super_String_Data (Left);
Result.Data (Llen + 1 .. Max_Length) :=
Right.Data (1 .. Max_Length - Llen);
end if;
@@ -568,8 +587,8 @@ package body Ada.Strings.Superbounded is
Right.Data (Rlen - (Max_Length - 1) .. Rlen);
else
- Result.Data (1 .. Max_Length - Rlen) :=
- Left (Left'Last - (Max_Length - Rlen - 1) .. Left'Last);
+ Result.Data (1 .. Max_Length - Rlen) := Super_String_Data
+ (Left (Left'Last - (Max_Length - Rlen - 1) .. Left'Last));
Result.Data (Max_Length - Rlen + 1 .. Max_Length) :=
Right.Data (1 .. Rlen);
end if;
@@ -577,6 +596,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -595,9 +616,9 @@ package body Ada.Strings.Superbounded is
begin
if Llen < Max_Length then
- Result.Current_Length := Llen + 1;
Result.Data (1 .. Llen) := Left.Data (1 .. Llen);
Result.Data (Llen + 1) := Right;
+ Result.Current_Length := Llen + 1;
return Result;
else
@@ -606,10 +627,10 @@ package body Ada.Strings.Superbounded is
return Left;
when Strings.Left =>
- Result.Current_Length := Max_Length;
Result.Data (1 .. Max_Length - 1) :=
Left.Data (2 .. Max_Length);
Result.Data (Max_Length) := Right;
+ Result.Current_Length := Max_Length;
return Result;
when Strings.Error =>
@@ -628,12 +649,10 @@ package body Ada.Strings.Superbounded is
begin
if Llen < Max_Length then
- Source.Current_Length := Llen + 1;
Source.Data (Llen + 1) := New_Item;
+ Source.Current_Length := Llen + 1;
else
- Source.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
null;
@@ -663,18 +682,18 @@ package body Ada.Strings.Superbounded is
begin
if Rlen < Max_Length then
- Result.Current_Length := Rlen + 1;
Result.Data (1) := Left;
Result.Data (2 .. Rlen + 1) := Right.Data (1 .. Rlen);
+ Result.Current_Length := Rlen + 1;
return Result;
else
case Drop is
when Strings.Right =>
- Result.Current_Length := Max_Length;
Result.Data (1) := Left;
Result.Data (2 .. Max_Length) :=
Right.Data (1 .. Max_Length - 1);
+ Result.Current_Length := Max_Length;
return Result;
when Strings.Left =>
@@ -696,9 +715,7 @@ package body Ada.Strings.Superbounded is
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
is
begin
- return
- Search.Count
- (Source.Data (1 .. Source.Current_Length), Pattern, Mapping);
+ return Search.Count (Super_To_String (Source), Pattern, Mapping);
end Super_Count;
function Super_Count
@@ -707,9 +724,7 @@ package body Ada.Strings.Superbounded is
Mapping : Maps.Character_Mapping_Function) return Natural
is
begin
- return
- Search.Count
- (Source.Data (1 .. Source.Current_Length), Pattern, Mapping);
+ return Search.Count (Super_To_String (Source), Pattern, Mapping);
end Super_Count;
function Super_Count
@@ -717,7 +732,7 @@ package body Ada.Strings.Superbounded is
Set : Maps.Character_Set) return Natural
is
begin
- return Search.Count (Source.Data (1 .. Source.Current_Length), Set);
+ return Search.Count (Super_To_String (Source), Set);
end Super_Count;
------------------
@@ -737,19 +752,19 @@ package body Ada.Strings.Superbounded is
if Num_Delete <= 0 then
return Source;
- elsif From > Slen + 1 then
+ elsif From - 1 > Slen then
raise Ada.Strings.Index_Error;
elsif Through >= Slen then
- Result.Current_Length := From - 1;
Result.Data (1 .. From - 1) := Source.Data (1 .. From - 1);
+ Result.Current_Length := From - 1;
return Result;
else
- Result.Current_Length := Slen - Num_Delete;
Result.Data (1 .. From - 1) := Source.Data (1 .. From - 1);
- Result.Data (From .. Result.Current_Length) :=
+ Result.Data (From .. Slen - Num_Delete) :=
Source.Data (Through + 1 .. Slen);
+ Result.Current_Length := Slen - Num_Delete;
return Result;
end if;
end Super_Delete;
@@ -766,7 +781,7 @@ package body Ada.Strings.Superbounded is
if Num_Delete <= 0 then
return;
- elsif From > Slen + 1 then
+ elsif From - 1 > Slen then
raise Ada.Strings.Index_Error;
elsif Through >= Slen then
@@ -779,22 +794,6 @@ package body Ada.Strings.Superbounded is
end if;
end Super_Delete;
- -------------------
- -- Super_Element --
- -------------------
-
- function Super_Element
- (Source : Super_String;
- Index : Positive) return Character
- is
- begin
- if Index <= Source.Current_Length then
- return Source.Data (Index);
- else
- raise Strings.Index_Error;
- end if;
- end Super_Element;
-
----------------------
-- Super_Find_Token --
----------------------
@@ -809,7 +808,7 @@ package body Ada.Strings.Superbounded is
is
begin
Search.Find_Token
- (Source.Data (From .. Source.Current_Length), Set, Test, First, Last);
+ (Super_To_String (Source), Set, From, Test, First, Last);
end Super_Find_Token;
procedure Super_Find_Token
@@ -820,8 +819,7 @@ package body Ada.Strings.Superbounded is
Last : out Natural)
is
begin
- Search.Find_Token
- (Source.Data (1 .. Source.Current_Length), Set, Test, First, Last);
+ Search.Find_Token (Super_To_String (Source), Set, Test, First, Last);
end Super_Find_Token;
----------------
@@ -841,21 +839,22 @@ package body Ada.Strings.Superbounded is
begin
if Npad <= 0 then
- Result.Current_Length := Count;
Result.Data (1 .. Count) := Source.Data (1 .. Count);
+ Result.Current_Length := Count;
elsif Count <= Max_Length then
- Result.Current_Length := Count;
Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
Result.Data (Slen + 1 .. Count) := (others => Pad);
+ Result.Current_Length := Count;
else
- Result.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
- Result.Data (Slen + 1 .. Max_Length) := (others => Pad);
+
+ if Slen < Max_Length then
+ Result.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ end if;
when Strings.Left =>
if Npad >= Max_Length then
@@ -871,6 +870,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -885,22 +886,22 @@ package body Ada.Strings.Superbounded is
Max_Length : constant Positive := Source.Max_Length;
Slen : constant Natural := Source.Current_Length;
Npad : constant Integer := Count - Slen;
- Temp : String (1 .. Max_Length);
+ Temp : Super_String_Data (1 .. Max_Length);
begin
if Npad <= 0 then
Source.Current_Length := Count;
elsif Count <= Max_Length then
- Source.Current_Length := Count;
Source.Data (Slen + 1 .. Count) := (others => Pad);
+ Source.Current_Length := Count;
else
- Source.Current_Length := Max_Length;
-
case Drop is
when Strings.Right =>
- Source.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ if Slen < Max_Length then
+ Source.Data (Slen + 1 .. Max_Length) := (others => Pad);
+ end if;
when Strings.Left =>
if Npad > Max_Length then
@@ -910,15 +911,15 @@ package body Ada.Strings.Superbounded is
Temp := Source.Data;
Source.Data (1 .. Max_Length - Npad) :=
Temp (Count - Max_Length + 1 .. Slen);
-
- for J in Max_Length - Npad + 1 .. Max_Length loop
- Source.Data (J) := Pad;
- end loop;
+ Source.Data (Max_Length - Npad + 1 .. Max_Length) :=
+ (others => Pad);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Head;
@@ -933,8 +934,7 @@ package body Ada.Strings.Superbounded is
Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
is
begin
- return Search.Index
- (Source.Data (1 .. Source.Current_Length), Pattern, Going, Mapping);
+ return Search.Index (Super_To_String (Source), Pattern, Going, Mapping);
end Super_Index;
function Super_Index
@@ -944,8 +944,7 @@ package body Ada.Strings.Superbounded is
Mapping : Maps.Character_Mapping_Function) return Natural
is
begin
- return Search.Index
- (Source.Data (1 .. Source.Current_Length), Pattern, Going, Mapping);
+ return Search.Index (Super_To_String (Source), Pattern, Going, Mapping);
end Super_Index;
function Super_Index
@@ -955,8 +954,7 @@ package body Ada.Strings.Superbounded is
Going : Strings.Direction := Strings.Forward) return Natural
is
begin
- return Search.Index
- (Source.Data (1 .. Source.Current_Length), Set, Test, Going);
+ return Search.Index (Super_To_String (Source), Set, Test, Going);
end Super_Index;
function Super_Index
@@ -968,8 +966,7 @@ package body Ada.Strings.Superbounded is
is
begin
return Search.Index
- (Source.Data (1 .. Source.Current_Length),
- Pattern, From, Going, Mapping);
+ (Super_To_String (Source), Pattern, From, Going, Mapping);
end Super_Index;
function Super_Index
@@ -981,8 +978,7 @@ package body Ada.Strings.Superbounded is
is
begin
return Search.Index
- (Source.Data (1 .. Source.Current_Length),
- Pattern, From, Going, Mapping);
+ (Super_To_String (Source), Pattern, From, Going, Mapping);
end Super_Index;
function Super_Index
@@ -993,8 +989,15 @@ package body Ada.Strings.Superbounded is
Going : Direction := Forward) return Natural
is
begin
- return Search.Index
- (Source.Data (1 .. Source.Current_Length), Set, From, Test, Going);
+ return Result : Natural do
+ Result :=
+ Search.Index (Super_To_String (Source), Set, From, Test, Going);
+ pragma Assert
+ (if (for all J in 1 .. Super_Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ (Test = Inside) /= Maps.Is_In (Source.Data (J), Set)))
+ then Result = 0);
+ end return;
end Super_Index;
---------------------------
@@ -1006,9 +1009,7 @@ package body Ada.Strings.Superbounded is
Going : Strings.Direction := Strings.Forward) return Natural
is
begin
- return
- Search.Index_Non_Blank
- (Source.Data (1 .. Source.Current_Length), Going);
+ return Search.Index_Non_Blank (Super_To_String (Source), Going);
end Super_Index_Non_Blank;
function Super_Index_Non_Blank
@@ -1017,9 +1018,7 @@ package body Ada.Strings.Superbounded is
Going : Direction := Forward) return Natural
is
begin
- return
- Search.Index_Non_Blank
- (Source.Data (1 .. Source.Current_Length), From, Going);
+ return Search.Index_Non_Blank (Super_To_String (Source), From, Going);
end Super_Index_Non_Blank;
------------------
@@ -1031,60 +1030,71 @@ package body Ada.Strings.Superbounded is
Before : Positive;
New_Item : String;
Drop : Strings.Truncation := Strings.Error) return Super_String
+ with SPARK_Mode => Off
is
Max_Length : constant Positive := Source.Max_Length;
Result : Super_String (Max_Length);
Slen : constant Natural := Source.Current_Length;
Nlen : constant Natural := New_Item'Length;
- Tlen : constant Natural := Slen + Nlen;
Blen : constant Natural := Before - 1;
Alen : constant Integer := Slen - Blen;
- Droplen : constant Integer := Tlen - Max_Length;
+ Droplen : constant Integer := Slen - Max_Length + Nlen;
- -- Tlen is the length of the total string before possible truncation.
-- Blen, Alen are the lengths of the before and after pieces of the
- -- source string.
+ -- source string. The number of dropped characters is Natural'Max (0,
+ -- Droplen).
begin
if Alen < 0 then
raise Ada.Strings.Index_Error;
elsif Droplen <= 0 then
- Result.Current_Length := Tlen;
Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
- Result.Data (Before .. Before + Nlen - 1) := New_Item;
- Result.Data (Before + Nlen .. Tlen) :=
- Source.Data (Before .. Slen);
+ Result.Data (Before .. Before - 1 + Nlen) :=
+ Super_String_Data (New_Item);
- else
- Result.Current_Length := Max_Length;
+ if Before <= Slen then
+ Result.Data (Before + Nlen .. Slen + Nlen) :=
+ Source.Data (Before .. Slen);
+ end if;
+ Result.Current_Length := Slen + Nlen;
+
+ else
case Drop is
when Strings.Right =>
Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
- if Droplen > Alen then
- Result.Data (Before .. Max_Length) :=
- New_Item (New_Item'First
- .. New_Item'First + Max_Length - Before);
+ if Droplen >= Alen then
+ Result.Data (Before .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'First
+ .. New_Item'First - Before + Max_Length));
+ pragma Assert
+ (String (Result.Data (Before .. Max_Length)) =
+ New_Item (New_Item'First
+ .. New_Item'First - Before + Max_Length));
else
- Result.Data (Before .. Before + Nlen - 1) := New_Item;
+ Result.Data (Before .. Before - 1 + Nlen) :=
+ Super_String_Data (New_Item);
Result.Data (Before + Nlen .. Max_Length) :=
Source.Data (Before .. Slen - Droplen);
end if;
when Strings.Left =>
- Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
- Source.Data (Before .. Slen);
+ if Alen > 0 then
+ Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
+ Source.Data (Before .. Slen);
+ end if;
- if Droplen >= Blen then
- Result.Data (1 .. Max_Length - Alen) :=
- New_Item (New_Item'Last - (Max_Length - Alen) + 1
- .. New_Item'Last);
+ if Droplen > Blen then
+ if Alen < Max_Length then
+ Result.Data (1 .. Max_Length - Alen) := Super_String_Data
+ (New_Item (New_Item'Last - (Max_Length - Alen) + 1
+ .. New_Item'Last));
+ end if;
else
- Result.Data
- (Blen - Droplen + 1 .. Max_Length - Alen) :=
- New_Item;
+ Result.Data (Blen - Droplen + 1 .. Max_Length - Alen) :=
+ Super_String_Data (New_Item);
Result.Data (1 .. Blen - Droplen) :=
Source.Data (Droplen + 1 .. Blen);
end if;
@@ -1092,6 +1102,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -1111,15 +1123,6 @@ package body Ada.Strings.Superbounded is
Source := Super_Insert (Source, Before, New_Item, Drop);
end Super_Insert;
- ------------------
- -- Super_Length --
- ------------------
-
- function Super_Length (Source : Super_String) return Natural is
- begin
- return Source.Current_Length;
- end Super_Length;
-
---------------------
-- Super_Overwrite --
---------------------
@@ -1132,61 +1135,61 @@ package body Ada.Strings.Superbounded is
is
Max_Length : constant Positive := Source.Max_Length;
Result : Super_String (Max_Length);
- Endpos : constant Natural := Position + New_Item'Length - 1;
Slen : constant Natural := Source.Current_Length;
Droplen : Natural;
begin
- if Position > Slen + 1 then
+ if Position - 1 > Slen then
raise Ada.Strings.Index_Error;
elsif New_Item'Length = 0 then
return Source;
- elsif Endpos <= Slen then
- Result.Current_Length := Source.Current_Length;
+ elsif Position - 1 <= Slen - New_Item'Length then
Result.Data (1 .. Slen) := Source.Data (1 .. Slen);
- Result.Data (Position .. Endpos) := New_Item;
+ Result.Data (Position .. Position - 1 + New_Item'Length) :=
+ Super_String_Data (New_Item);
+ Result.Current_Length := Source.Current_Length;
return Result;
- elsif Endpos <= Max_Length then
- Result.Current_Length := Endpos;
+ elsif Position - 1 <= Max_Length - New_Item'Length then
Result.Data (1 .. Position - 1) := Source.Data (1 .. Position - 1);
- Result.Data (Position .. Endpos) := New_Item;
+ Result.Data (Position .. Position - 1 + New_Item'Length) :=
+ Super_String_Data (New_Item);
+ Result.Current_Length := Position - 1 + New_Item'Length;
return Result;
else
- Result.Current_Length := Max_Length;
- Droplen := Endpos - Max_Length;
+ Droplen := Position - 1 - Max_Length + New_Item'Length;
case Drop is
when Strings.Right =>
Result.Data (1 .. Position - 1) :=
Source.Data (1 .. Position - 1);
- Result.Data (Position .. Max_Length) :=
- New_Item (New_Item'First .. New_Item'Last - Droplen);
- return Result;
+ Result.Data (Position .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'First .. New_Item'Last - Droplen));
when Strings.Left =>
if New_Item'Length >= Max_Length then
- Result.Data (1 .. Max_Length) :=
- New_Item (New_Item'Last - Max_Length + 1 ..
- New_Item'Last);
- return Result;
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'Last - Max_Length + 1 ..
+ New_Item'Last));
else
Result.Data (1 .. Max_Length - New_Item'Length) :=
Source.Data (Droplen + 1 .. Position - 1);
Result.Data
(Max_Length - New_Item'Length + 1 .. Max_Length) :=
- New_Item;
- return Result;
+ Super_String_Data (New_Item);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
+ return Result;
end if;
end Super_Overwrite;
@@ -1195,50 +1198,52 @@ package body Ada.Strings.Superbounded is
Position : Positive;
New_Item : String;
Drop : Strings.Truncation := Strings.Error)
+ with SPARK_Mode => Off
is
Max_Length : constant Positive := Source.Max_Length;
- Endpos : constant Positive := Position + New_Item'Length - 1;
Slen : constant Natural := Source.Current_Length;
Droplen : Natural;
begin
- if Position > Slen + 1 then
+ if Position - 1 > Slen then
raise Ada.Strings.Index_Error;
- elsif Endpos <= Slen then
- Source.Data (Position .. Endpos) := New_Item;
+ elsif Position - 1 <= Slen - New_Item'Length then
+ Source.Data (Position .. Position - 1 + New_Item'Length) :=
+ Super_String_Data (New_Item);
- elsif Endpos <= Max_Length then
- Source.Data (Position .. Endpos) := New_Item;
- Source.Current_Length := Endpos;
+ elsif Position - 1 <= Max_Length - New_Item'Length then
+ Source.Data (Position .. Position - 1 + New_Item'Length) :=
+ Super_String_Data (New_Item);
+ Source.Current_Length := Position - 1 + New_Item'Length;
else
- Source.Current_Length := Max_Length;
- Droplen := Endpos - Max_Length;
+ Droplen := Position - 1 - Max_Length + New_Item'Length;
case Drop is
when Strings.Right =>
- Source.Data (Position .. Max_Length) :=
- New_Item (New_Item'First .. New_Item'Last - Droplen);
+ Source.Data (Position .. Max_Length) := Super_String_Data
+ (New_Item (New_Item'First .. New_Item'Last - Droplen));
when Strings.Left =>
if New_Item'Length > Max_Length then
- Source.Data (1 .. Max_Length) :=
- New_Item (New_Item'Last - Max_Length + 1 ..
- New_Item'Last);
+ Source.Data (1 .. Max_Length) := Super_String_Data
+ (New_Item
+ (New_Item'Last - Max_Length + 1 .. New_Item'Last));
else
Source.Data (1 .. Max_Length - New_Item'Length) :=
Source.Data (Droplen + 1 .. Position - 1);
-
Source.Data
(Max_Length - New_Item'Length + 1 .. Max_Length) :=
- New_Item;
+ Super_String_Data (New_Item);
end if;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Overwrite;
@@ -1269,12 +1274,13 @@ package body Ada.Strings.Superbounded is
High : Natural;
By : String;
Drop : Strings.Truncation := Strings.Error) return Super_String
+ with SPARK_Mode => Off
is
Max_Length : constant Positive := Source.Max_Length;
Slen : constant Natural := Source.Current_Length;
begin
- if Low > Slen + 1 then
+ if Low - 1 > Slen then
raise Strings.Index_Error;
elsif High < Low then
@@ -1282,51 +1288,58 @@ package body Ada.Strings.Superbounded is
else
declare
- Blen : constant Natural := Natural'Max (0, Low - 1);
+ Blen : constant Natural := Low - 1;
Alen : constant Natural := Natural'Max (0, Slen - High);
- Tlen : constant Natural := Blen + By'Length + Alen;
- Droplen : constant Integer := Tlen - Max_Length;
+ Droplen : constant Integer := Blen + Alen - Max_Length + By'Length;
Result : Super_String (Max_Length);
- -- Tlen is the total length of the result string before any
- -- truncation. Blen and Alen are the lengths of the pieces
- -- of the original string that end up in the result string
- -- before and after the replaced slice.
+ -- Blen and Alen are the lengths of the pieces of the original
+ -- string that end up in the result string before and after the
+ -- replaced slice. The number of dropped characters is Natural'Max
+ -- (0, Droplen).
begin
if Droplen <= 0 then
- Result.Current_Length := Tlen;
Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
- Result.Data (Low .. Low + By'Length - 1) := By;
- Result.Data (Low + By'Length .. Tlen) :=
- Source.Data (High + 1 .. Slen);
+ Result.Data (Low .. Blen + By'Length) :=
+ Super_String_Data (By);
- else
- Result.Current_Length := Max_Length;
+ if Alen > 0 then
+ Result.Data (Low + By'Length .. Blen + By'Length + Alen) :=
+ Source.Data (High + 1 .. Slen);
+ end if;
+ Result.Current_Length := Blen + By'Length + Alen;
+
+ else
case Drop is
when Strings.Right =>
Result.Data (1 .. Blen) := Source.Data (1 .. Blen);
- if Droplen > Alen then
- Result.Data (Low .. Max_Length) :=
- By (By'First .. By'First + Max_Length - Low);
+ if Droplen >= Alen then
+ Result.Data (Low .. Max_Length) := Super_String_Data
+ (By (By'First .. By'First - Low + Max_Length));
else
- Result.Data (Low .. Low + By'Length - 1) := By;
+ Result.Data (Low .. Low - 1 + By'Length) :=
+ Super_String_Data (By);
Result.Data (Low + By'Length .. Max_Length) :=
Source.Data (High + 1 .. Slen - Droplen);
end if;
when Strings.Left =>
- Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
- Source.Data (High + 1 .. Slen);
+ if Alen > 0 then
+ Result.Data (Max_Length - (Alen - 1) .. Max_Length) :=
+ Source.Data (High + 1 .. Slen);
+ end if;
if Droplen >= Blen then
Result.Data (1 .. Max_Length - Alen) :=
- By (By'Last - (Max_Length - Alen) + 1 .. By'Last);
+ Super_String_Data (By
+ (By'Last - (Max_Length - Alen) + 1 .. By'Last));
else
Result.Data
- (Blen - Droplen + 1 .. Max_Length - Alen) := By;
+ (Blen - Droplen + 1 .. Max_Length - Alen) :=
+ Super_String_Data (By);
Result.Data (1 .. Blen - Droplen) :=
Source.Data (Droplen + 1 .. Blen);
end if;
@@ -1334,6 +1347,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -1370,16 +1385,17 @@ package body Ada.Strings.Superbounded is
begin
if Count <= Max_Length then
+ Result.Data (1 .. Count) := (others => Item);
Result.Current_Length := Count;
elsif Drop = Strings.Error then
raise Ada.Strings.Length_Error;
else
+ Result.Data (1 .. Max_Length) := (others => Item);
Result.Current_Length := Max_Length;
end if;
- Result.Data (1 .. Result.Current_Length) := (others => Item);
return Result;
end Super_Replicate;
@@ -1389,52 +1405,203 @@ package body Ada.Strings.Superbounded is
Drop : Truncation := Error;
Max_Length : Positive) return Super_String
is
- Length : constant Integer := Count * Item'Length;
Result : Super_String (Max_Length);
- Indx : Positive;
+ Indx : Natural;
+ Ilen : constant Natural := Item'Length;
+
+ -- Parts of the proof involving manipulations with the modulo operator
+ -- are complicated for the prover and can't be done automatically in
+ -- the global subprogram. That's why we isolate them in these two ghost
+ -- lemmas.
+
+ procedure Lemma_Mod (K : Natural; Q : Natural) with
+ Ghost,
+ Pre => Ilen /= 0
+ and then Q mod Ilen = 0
+ and then K - Q in 0 .. Ilen - 1,
+ Post => K mod Ilen = K - Q;
+ -- Lemma_Mod is applied to an index considered in Lemma_Split to prove
+ -- that it has the right value modulo Item'Length.
+
+ procedure Lemma_Mod_Zero (X : Natural) with
+ Ghost,
+ Pre => Ilen /= 0
+ and then X mod Ilen = 0
+ and then X <= Natural'Last - Ilen,
+ Post => (X + Ilen) mod Ilen = 0;
+ -- Lemma_Mod_Zero is applied to prove that the length of the range
+ -- of indexes considered in the loop, when dropping on the Left, is
+ -- a multiple of Item'Length.
+
+ procedure Lemma_Split (Going : Direction) with
+ Ghost,
+ Pre =>
+ Ilen /= 0
+ and then Indx in 0 .. Max_Length - Ilen
+ and then
+ (if Going = Forward
+ then Indx mod Ilen = 0
+ else (Max_Length - Indx - Ilen) mod Ilen = 0)
+ and then Result.Data (Indx + 1 .. Indx + Ilen)'Initialized
+ and then String (Result.Data (Indx + 1 .. Indx + Ilen)) = Item,
+ Post =>
+ (if Going = Forward then
+ (for all J in Indx + 1 .. Indx + Ilen =>
+ Result.Data (J) = Item (Item'First + (J - 1) mod Ilen))
+ else
+ (for all J in Indx + 1 .. Indx + Ilen =>
+ Result.Data (J) =
+ Item (Item'Last - (Max_Length - J) mod Ilen)));
+ -- Lemma_Split is used after Result.Data (Indx + 1 .. Indx + Ilen) is
+ -- updated to Item and concludes that the characters match for each
+ -- index when taken modulo Item'Length, as the considered slice starts
+ -- at index 1 (or ends at index Max_Length, if Going = Backward) modulo
+ -- Item'Length.
+
+ ---------------
+ -- Lemma_Mod --
+ ---------------
+
+ procedure Lemma_Mod (K : Natural; Q : Natural) is null;
+
+ --------------------
+ -- Lemma_Mod_Zero --
+ --------------------
+
+ procedure Lemma_Mod_Zero (X : Natural) is null;
+
+ -----------------
+ -- Lemma_Split --
+ -----------------
+
+ procedure Lemma_Split (Going : Direction) is
+ begin
+ if Going = Forward then
+ for K in Indx + 1 .. Indx + Ilen loop
+ Lemma_Mod (K - 1, Indx);
+ pragma Loop_Invariant
+ (for all J in Indx + 1 .. K =>
+ Result.Data (J) = Item (Item'First + (J - 1) mod Ilen));
+ end loop;
+ else
+ for K in Indx + 1 .. Indx + Ilen loop
+ Lemma_Mod (Max_Length - K, Max_Length - Indx - Ilen);
+ pragma Loop_Invariant
+ (for all J in Indx + 1 .. K =>
+ Result.Data (J) =
+ Item (Item'Last - (Max_Length - J) mod Ilen));
+ end loop;
+ end if;
+ end Lemma_Split;
begin
- if Length <= Max_Length then
- Result.Current_Length := Length;
-
- if Length > 0 then
- Indx := 1;
+ if Count = 0 or else Ilen <= Max_Length / Count then
+ if Count * Ilen > 0 then
+ Indx := 0;
for J in 1 .. Count loop
- Result.Data (Indx .. Indx + Item'Length - 1) := Item;
- Indx := Indx + Item'Length;
+ Result.Data (Indx + 1 .. Indx + Ilen) :=
+ Super_String_Data (Item);
+ pragma Assert
+ (for all K in 1 .. Ilen =>
+ Result.Data (Indx + K) = Item (Item'First - 1 + K));
+ pragma Assert
+ (String (Result.Data (Indx + 1 .. Indx + Ilen)) = Item);
+ Lemma_Split (Forward);
+ Indx := Indx + Ilen;
+ pragma Loop_Invariant (Indx = J * Ilen);
+ pragma Loop_Invariant (Result.Data (1 .. Indx)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. Indx =>
+ Result.Data (K) =
+ Item (Item'First + (K - 1) mod Ilen));
end loop;
end if;
- else
- Result.Current_Length := Max_Length;
+ Result.Current_Length := Count * Ilen;
+ else
case Drop is
when Strings.Right =>
- Indx := 1;
-
- while Indx + Item'Length <= Max_Length + 1 loop
- Result.Data (Indx .. Indx + Item'Length - 1) := Item;
- Indx := Indx + Item'Length;
+ Indx := 0;
+
+ while Indx < Max_Length - Ilen loop
+ Result.Data (Indx + 1 .. Indx + Ilen) :=
+ Super_String_Data (Item);
+ pragma Assert
+ (for all K in 1 .. Ilen =>
+ Result.Data (Indx + K) = Item (Item'First - 1 + K));
+ pragma Assert
+ (String (Result.Data (Indx + 1 .. Indx + Ilen)) = Item);
+ Lemma_Split (Forward);
+ Indx := Indx + Ilen;
+ pragma Loop_Invariant (Indx mod Ilen = 0);
+ pragma Loop_Invariant (Indx in 0 .. Max_Length - 1);
+ pragma Loop_Invariant (Result.Data (1 .. Indx)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. Indx =>
+ Result.Data (K) =
+ Item (Item'First + (K - 1) mod Ilen));
end loop;
- Result.Data (Indx .. Max_Length) :=
- Item (Item'First .. Item'First + Max_Length - Indx);
+ Result.Data (Indx + 1 .. Max_Length) := Super_String_Data
+ (Item (Item'First .. Item'First + (Max_Length - Indx - 1)));
+ pragma Assert
+ (for all J in Indx + 1 .. Max_Length =>
+ Result.Data (J) = Item (Item'First - 1 - Indx + J));
+
+ for J in Indx + 1 .. Max_Length loop
+ Lemma_Mod (J - 1, Indx);
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Result.Data (K) =
+ Item (Item'First + (K - 1) mod Ilen));
+ end loop;
when Strings.Left =>
Indx := Max_Length;
- while Indx - Item'Length >= 1 loop
- Result.Data (Indx - (Item'Length - 1) .. Indx) := Item;
- Indx := Indx - Item'Length;
+ while Indx > Ilen loop
+ Indx := Indx - Ilen;
+ Result.Data (Indx + 1 .. Indx + Ilen) :=
+ Super_String_Data (Item);
+ pragma Assert
+ (for all K in 1 .. Ilen =>
+ Result.Data (Indx + K) = Item (Item'First - 1 + K));
+ pragma Assert
+ (String (Result.Data (Indx + 1 .. Indx + Ilen)) = Item);
+ Lemma_Split (Backward);
+ Lemma_Mod_Zero (Max_Length - Indx - Ilen);
+ pragma Loop_Invariant
+ ((Max_Length - Indx) mod Ilen = 0);
+ pragma Loop_Invariant (Indx in 1 .. Max_Length);
+ pragma Loop_Invariant
+ (Result.Data (Indx + 1 .. Max_Length)'Initialized);
+ pragma Loop_Invariant
+ (for all K in Indx + 1 .. Max_Length =>
+ Result.Data (K) =
+ Item (Item'Last - (Max_Length - K) mod Ilen));
end loop;
Result.Data (1 .. Indx) :=
- Item (Item'Last - Indx + 1 .. Item'Last);
+ Super_String_Data (Item (Item'Last - Indx + 1 .. Item'Last));
+ pragma Assert
+ (for all J in 1 .. Indx =>
+ Result.Data (J) = Item (Item'Last - Indx + J));
+
+ for J in reverse 1 .. Indx loop
+ Lemma_Mod (Max_Length - J, Max_Length - Indx);
+ pragma Loop_Invariant
+ (for all K in J .. Max_Length =>
+ Result.Data (K) =
+ Item (Item'Last - (Max_Length - K) mod Ilen));
+ end loop;
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -1447,11 +1614,7 @@ package body Ada.Strings.Superbounded is
is
begin
return
- Super_Replicate
- (Count,
- Item.Data (1 .. Item.Current_Length),
- Drop,
- Item.Max_Length);
+ Super_Replicate (Count, Super_To_String (Item), Drop, Item.Max_Length);
end Super_Replicate;
-----------------
@@ -1461,42 +1624,20 @@ package body Ada.Strings.Superbounded is
function Super_Slice
(Source : Super_String;
Low : Positive;
- High : Natural) return String
- is
- begin
- -- Note: test of High > Length is in accordance with AI95-00128
-
- return R : String (Low .. High) do
- if Low > Source.Current_Length + 1
- or else High > Source.Current_Length
- then
- raise Index_Error;
- end if;
-
- -- Note: in this case, superflat bounds are not a problem, we just
- -- get the null string in accordance with normal Ada slice rules.
-
- R := Source.Data (Low .. High);
- end return;
- end Super_Slice;
-
- function Super_Slice
- (Source : Super_String;
- Low : Positive;
High : Natural) return Super_String
is
begin
return Result : Super_String (Source.Max_Length) do
- if Low > Source.Current_Length + 1
+ if Low - 1 > Source.Current_Length
or else High > Source.Current_Length
then
raise Index_Error;
end if;
- -- Note: the Max operation here deals with the superflat case
-
- Result.Current_Length := Integer'Max (0, High - Low + 1);
- Result.Data (1 .. Result.Current_Length) := Source.Data (Low .. High);
+ if High >= Low then
+ Result.Data (1 .. High - Low + 1) := Source.Data (Low .. High);
+ Result.Current_Length := High - Low + 1;
+ end if;
end return;
end Super_Slice;
@@ -1507,16 +1648,18 @@ package body Ada.Strings.Superbounded is
High : Natural)
is
begin
- if Low > Source.Current_Length + 1
+ if Low - 1 > Source.Current_Length
or else High > Source.Current_Length
then
raise Index_Error;
end if;
- -- Note: the Max operation here deals with the superflat case
-
- Target.Current_Length := Integer'Max (0, High - Low + 1);
- Target.Data (1 .. Target.Current_Length) := Source.Data (Low .. High);
+ if High >= Low then
+ Target.Data (1 .. High - Low + 1) := Source.Data (Low .. High);
+ Target.Current_Length := High - Low + 1;
+ else
+ Target.Current_Length := 0;
+ end if;
end Super_Slice;
----------------
@@ -1536,18 +1679,22 @@ package body Ada.Strings.Superbounded is
begin
if Npad <= 0 then
- Result.Current_Length := Count;
- Result.Data (1 .. Count) :=
- Source.Data (Slen - (Count - 1) .. Slen);
+ if Count > 0 then
+ Result.Data (1 .. Count) :=
+ Source.Data (Slen - (Count - 1) .. Slen);
+ Result.Current_Length := Count;
+ end if;
elsif Count <= Max_Length then
- Result.Current_Length := Count;
Result.Data (1 .. Npad) := (others => Pad);
- Result.Data (Npad + 1 .. Count) := Source.Data (1 .. Slen);
- else
- Result.Current_Length := Max_Length;
+ if Slen > 0 then
+ Result.Data (Npad + 1 .. Count) := Source.Data (1 .. Slen);
+ end if;
+
+ Result.Current_Length := Count;
+ else
case Drop is
when Strings.Right =>
if Npad >= Max_Length then
@@ -1567,6 +1714,8 @@ package body Ada.Strings.Superbounded is
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Result.Current_Length := Max_Length;
end if;
return Result;
@@ -1582,22 +1731,27 @@ package body Ada.Strings.Superbounded is
Slen : constant Natural := Source.Current_Length;
Npad : constant Integer := Count - Slen;
- Temp : constant String (1 .. Max_Length) := Source.Data;
+ Temp : constant Super_String_Data (1 .. Max_Length) := Source.Data;
begin
if Npad <= 0 then
Source.Current_Length := Count;
- Source.Data (1 .. Count) :=
- Temp (Slen - (Count - 1) .. Slen);
+
+ if Count > 0 then
+ Source.Data (1 .. Count) :=
+ Temp (Slen - (Count - 1) .. Slen);
+ end if;
elsif Count <= Max_Length then
- Source.Current_Length := Count;
Source.Data (1 .. Npad) := (others => Pad);
- Source.Data (Npad + 1 .. Count) := Temp (1 .. Slen);
- else
- Source.Current_Length := Max_Length;
+ if Slen > 0 then
+ Source.Data (Npad + 1 .. Count) := Temp (1 .. Slen);
+ end if;
+ Source.Current_Length := Count;
+
+ else
case Drop is
when Strings.Right =>
if Npad >= Max_Length then
@@ -1610,31 +1764,19 @@ package body Ada.Strings.Superbounded is
end if;
when Strings.Left =>
- for J in 1 .. Max_Length - Slen loop
- Source.Data (J) := Pad;
- end loop;
-
+ Source.Data (1 .. Max_Length - Slen) := (others => Pad);
Source.Data (Max_Length - Slen + 1 .. Max_Length) :=
Temp (1 .. Slen);
when Strings.Error =>
raise Ada.Strings.Length_Error;
end case;
+
+ Source.Current_Length := Max_Length;
end if;
end Super_Tail;
---------------------
- -- Super_To_String --
- ---------------------
-
- function Super_To_String (Source : Super_String) return String is
- begin
- return R : String (1 .. Source.Current_Length) do
- R := Source.Data (1 .. Source.Current_Length);
- end return;
- end Super_To_String;
-
- ---------------------
-- Super_Translate --
---------------------
@@ -1645,12 +1787,15 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Source.Max_Length);
begin
- Result.Current_Length := Source.Current_Length;
-
for J in 1 .. Source.Current_Length loop
Result.Data (J) := Value (Mapping, Source.Data (J));
+ pragma Loop_Invariant (Result.Data (1 .. J)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Result.Data (K) = Value (Mapping, Source.Data (K)));
end loop;
+ Result.Current_Length := Source.Current_Length;
return Result;
end Super_Translate;
@@ -1661,6 +1806,9 @@ package body Ada.Strings.Superbounded is
begin
for J in 1 .. Source.Current_Length loop
Source.Data (J) := Value (Mapping, Source.Data (J));
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Source.Data (K) = Value (Mapping, Source'Loop_Entry.Data (K)));
end loop;
end Super_Translate;
@@ -1671,12 +1819,15 @@ package body Ada.Strings.Superbounded is
Result : Super_String (Source.Max_Length);
begin
- Result.Current_Length := Source.Current_Length;
-
for J in 1 .. Source.Current_Length loop
Result.Data (J) := Mapping.all (Source.Data (J));
+ pragma Loop_Invariant (Result.Data (1 .. J)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Result.Data (K) = Mapping (Source.Data (K)));
end loop;
+ Result.Current_Length := Source.Current_Length;
return Result;
end Super_Translate;
@@ -1687,6 +1838,9 @@ package body Ada.Strings.Superbounded is
begin
for J in 1 .. Source.Current_Length loop
Source.Data (J) := Mapping.all (Source.Data (J));
+ pragma Loop_Invariant
+ (for all K in 1 .. J =>
+ Source.Data (K) = Mapping (Source'Loop_Entry.Data (K)));
end loop;
end Super_Translate;
@@ -1699,24 +1853,62 @@ package body Ada.Strings.Superbounded is
Side : Trim_End) return Super_String
is
Result : Super_String (Source.Max_Length);
- Last : Natural := Source.Current_Length;
- First : Positive := 1;
+ Last : constant Natural := Source.Current_Length;
begin
- if Side = Left or else Side = Both then
- while First <= Last and then Source.Data (First) = ' ' loop
- First := First + 1;
- end loop;
- end if;
+ case Side is
+ when Strings.Left =>
+ declare
+ Low : constant Natural :=
+ Super_Index_Non_Blank (Source, Forward);
+ begin
+ -- All blanks case
- if Side = Right or else Side = Both then
- while Last >= First and then Source.Data (Last) = ' ' loop
- Last := Last - 1;
- end loop;
- end if;
+ if Low = 0 then
+ return Result;
+ end if;
+
+ Result.Data (1 .. Last - Low + 1) := Source.Data (Low .. Last);
+ Result.Current_Length := Last - Low + 1;
+ end;
+
+ when Strings.Right =>
+ declare
+ High : constant Natural :=
+ Super_Index_Non_Blank (Source, Backward);
+ begin
+ -- All blanks case
+
+ if High = 0 then
+ return Result;
+ end if;
+
+ Result.Data (1 .. High) := Source.Data (1 .. High);
+ Result.Current_Length := High;
+ end;
+
+ when Strings.Both =>
+ declare
+ Low : constant Natural :=
+ Super_Index_Non_Blank (Source, Forward);
+ begin
+ -- All blanks case
+
+ if Low = 0 then
+ return Result;
+ end if;
+
+ declare
+ High : constant Natural :=
+ Super_Index_Non_Blank (Source, Backward);
+ begin
+ Result.Data (1 .. High - Low + 1) :=
+ Source.Data (Low .. High);
+ Result.Current_Length := High - Low + 1;
+ end;
+ end;
+ end case;
- Result.Current_Length := Last - First + 1;
- Result.Data (1 .. Result.Current_Length) := Source.Data (First .. Last);
return Result;
end Super_Trim;
@@ -1724,28 +1916,54 @@ package body Ada.Strings.Superbounded is
(Source : in out Super_String;
Side : Trim_End)
is
- Max_Length : constant Positive := Source.Max_Length;
- Last : Natural := Source.Current_Length;
- First : Positive := 1;
- Temp : String (1 .. Max_Length);
-
+ Last : constant Natural := Source.Current_Length;
begin
- Temp (1 .. Last) := Source.Data (1 .. Last);
-
- if Side = Left or else Side = Both then
- while First <= Last and then Temp (First) = ' ' loop
- First := First + 1;
- end loop;
- end if;
+ case Side is
+ when Strings.Left =>
+ declare
+ Low : constant Natural :=
+ Super_Index_Non_Blank (Source, Forward);
+ begin
+ -- All blanks case
- if Side = Right or else Side = Both then
- while Last >= First and then Temp (Last) = ' ' loop
- Last := Last - 1;
- end loop;
- end if;
-
- Source.Current_Length := Last - First + 1;
- Source.Data (1 .. Source.Current_Length) := Temp (First .. Last);
+ if Low = 0 then
+ Source.Current_Length := 0;
+ else
+ Source.Data (1 .. Last - Low + 1) :=
+ Source.Data (Low .. Last);
+ Source.Current_Length := Last - Low + 1;
+ end if;
+ end;
+
+ when Strings.Right =>
+ declare
+ High : constant Natural :=
+ Super_Index_Non_Blank (Source, Backward);
+ begin
+ Source.Current_Length := High;
+ end;
+
+ when Strings.Both =>
+ declare
+ Low : constant Natural :=
+ Super_Index_Non_Blank (Source, Forward);
+ begin
+ -- All blanks case
+
+ if Low = 0 then
+ Source.Current_Length := 0;
+ else
+ declare
+ High : constant Natural :=
+ Super_Index_Non_Blank (Source, Backward);
+ begin
+ Source.Data (1 .. High - Low + 1) :=
+ Source.Data (Low .. High);
+ Source.Current_Length := High - Low + 1;
+ end;
+ end if;
+ end;
+ end case;
end Super_Trim;
function Super_Trim
@@ -1754,22 +1972,31 @@ package body Ada.Strings.Superbounded is
Right : Maps.Character_Set) return Super_String
is
Result : Super_String (Source.Max_Length);
+ Low : Natural;
+ High : Natural;
begin
- for First in 1 .. Source.Current_Length loop
- if not Is_In (Source.Data (First), Left) then
- for Last in reverse First .. Source.Current_Length loop
- if not Is_In (Source.Data (Last), Right) then
- Result.Current_Length := Last - First + 1;
- Result.Data (1 .. Result.Current_Length) :=
- Source.Data (First .. Last);
- return Result;
- end if;
- end loop;
- end if;
- end loop;
+ Low := Super_Index (Source, Left, Outside, Forward);
+
+ -- Case where source comprises only characters in Left
+
+ if Low = 0 then
+ return Result;
+ end if;
+
+ High := Super_Index (Source, Right, Outside, Backward);
+
+ -- Case where source comprises only characters in Right
+
+ if High = 0 then
+ return Result;
+ end if;
+
+ if High >= Low then
+ Result.Data (1 .. High - Low + 1) := Source.Data (Low .. High);
+ Result.Current_Length := High - Low + 1;
+ end if;
- Result.Current_Length := 0;
return Result;
end Super_Trim;
@@ -1778,29 +2005,39 @@ package body Ada.Strings.Superbounded is
Left : Maps.Character_Set;
Right : Maps.Character_Set)
is
+ Last : constant Natural := Source.Current_Length;
+ Temp : Super_String_Data (1 .. Last);
+ Low : Natural;
+ High : Natural;
+
begin
- for First in 1 .. Source.Current_Length loop
- if not Is_In (Source.Data (First), Left) then
- for Last in reverse First .. Source.Current_Length loop
- if not Is_In (Source.Data (Last), Right) then
- if First = 1 then
- Source.Current_Length := Last;
- return;
- else
- Source.Current_Length := Last - First + 1;
- Source.Data (1 .. Source.Current_Length) :=
- Source.Data (First .. Last);
- return;
- end if;
- end if;
- end loop;
+ Temp := Source.Data (1 .. Last);
+ Low := Super_Index (Source, Left, Outside, Forward);
+
+ -- Case where source comprises only characters in Left
+
+ if Low = 0 then
+ Source.Current_Length := 0;
+
+ else
+ High := Super_Index (Source, Right, Outside, Backward);
+ -- Case where source comprises only characters in Right
+
+ if High = 0 then
Source.Current_Length := 0;
- return;
- end if;
- end loop;
- Source.Current_Length := 0;
+ elsif Low = 1 then
+ Source.Current_Length := High;
+
+ elsif High < Low then
+ Source.Current_Length := 0;
+
+ else
+ Source.Data (1 .. High - Low + 1) := Temp (Low .. High);
+ Source.Current_Length := High - Low + 1;
+ end if;
+ end if;
end Super_Trim;
-----------
@@ -1819,11 +2056,14 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
else
- Result.Current_Length := Left;
-
for J in 1 .. Left loop
Result.Data (J) := Right;
+ pragma Loop_Invariant (Result.Data (1 .. J)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. J => Result.Data (K) = Right);
end loop;
+
+ Result.Current_Length := Left;
end if;
return Result;
@@ -1835,23 +2075,88 @@ package body Ada.Strings.Superbounded is
Max_Length : Positive) return Super_String
is
Result : Super_String (Max_Length);
- Pos : Positive := 1;
+ Pos : Natural := 0;
Rlen : constant Natural := Right'Length;
Nlen : constant Natural := Left * Rlen;
+ -- Parts of the proof involving manipulations with the modulo operator
+ -- are complicated for the prover and can't be done automatically in
+ -- the global subprogram. That's why we isolate them in these two ghost
+ -- lemmas.
+
+ procedure Lemma_Mod (K : Integer) with
+ Ghost,
+ Pre =>
+ Rlen /= 0
+ and then Pos mod Rlen = 0
+ and then Pos in 0 .. Max_Length - Rlen
+ and then K in Pos .. Pos + Rlen - 1,
+ Post => K mod Rlen = K - Pos;
+ -- Lemma_Mod is applied to an index considered in Lemma_Split to prove
+ -- that it has the right value modulo Right'Length.
+
+ procedure Lemma_Split with
+ Ghost,
+ Pre =>
+ Rlen /= 0
+ and then Pos mod Rlen = 0
+ and then Pos in 0 .. Max_Length - Rlen
+ and then Result.Data (1 .. Pos + Rlen)'Initialized
+ and then String (Result.Data (Pos + 1 .. Pos + Rlen)) = Right,
+ Post =>
+ (for all K in Pos + 1 .. Pos + Rlen =>
+ Result.Data (K) = Right (Right'First + (K - 1) mod Rlen));
+ -- Lemma_Split is used after Result.Data (Pos + 1 .. Pos + Rlen) is
+ -- updated to Right and concludes that the characters match for each
+ -- index when taken modulo Right'Length, as the considered slice starts
+ -- at index 1 modulo Right'Length.
+
+ ---------------
+ -- Lemma_Mod --
+ ---------------
+
+ procedure Lemma_Mod (K : Integer) is null;
+
+ -----------------
+ -- Lemma_Split --
+ -----------------
+
+ procedure Lemma_Split is
+ begin
+ for K in Pos + 1 .. Pos + Rlen loop
+ Lemma_Mod (K - 1);
+ pragma Loop_Invariant
+ (for all J in Pos + 1 .. K =>
+ Result.Data (J) = Right (Right'First + (J - 1) mod Rlen));
+ end loop;
+ end Lemma_Split;
+
begin
if Nlen > Max_Length then
raise Ada.Strings.Length_Error;
else
- Result.Current_Length := Nlen;
-
if Nlen > 0 then
for J in 1 .. Left loop
- Result.Data (Pos .. Pos + Rlen - 1) := Right;
+ Result.Data (Pos + 1 .. Pos + Rlen) :=
+ Super_String_Data (Right);
+ pragma Assert
+ (for all K in 1 .. Rlen => Result.Data (Pos + K) =
+ Right (Right'First - 1 + K));
+ pragma Assert
+ (String (Result.Data (Pos + 1 .. Pos + Rlen)) = Right);
+ Lemma_Split;
Pos := Pos + Rlen;
+ pragma Loop_Invariant (Pos = J * Rlen);
+ pragma Loop_Invariant (Result.Data (1 .. Pos)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. Pos =>
+ Result.Data (K) =
+ Right (Right'First + (K - 1) mod Rlen));
end loop;
end if;
+
+ Result.Current_Length := Nlen;
end if;
return Result;
@@ -1862,7 +2167,7 @@ package body Ada.Strings.Superbounded is
Right : Super_String) return Super_String
is
Result : Super_String (Right.Max_Length);
- Pos : Positive := 1;
+ Pos : Natural := 0;
Rlen : constant Natural := Right.Current_Length;
Nlen : constant Natural := Left * Rlen;
@@ -1871,15 +2176,21 @@ package body Ada.Strings.Superbounded is
raise Ada.Strings.Length_Error;
else
- Result.Current_Length := Nlen;
-
if Nlen > 0 then
for J in 1 .. Left loop
- Result.Data (Pos .. Pos + Rlen - 1) :=
+ Result.Data (Pos + 1 .. Pos + Rlen) :=
Right.Data (1 .. Rlen);
Pos := Pos + Rlen;
+ pragma Loop_Invariant (Pos = J * Rlen);
+ pragma Loop_Invariant (Result.Data (1 .. Pos)'Initialized);
+ pragma Loop_Invariant
+ (for all K in 1 .. Pos =>
+ Result.Data (K) =
+ Right.Data (1 + (K - 1) mod Rlen));
end loop;
end if;
+
+ Result.Current_Length := Nlen;
end if;
return Result;
@@ -1891,7 +2202,7 @@ package body Ada.Strings.Superbounded is
function To_Super_String
(Source : String;
- Max_Length : Natural;
+ Max_Length : Positive;
Drop : Truncation := Error) return Super_String
is
Result : Super_String (Max_Length);
@@ -1899,20 +2210,20 @@ package body Ada.Strings.Superbounded is
begin
if Slen <= Max_Length then
+ Result.Data (1 .. Slen) := Super_String_Data (Source);
Result.Current_Length := Slen;
- Result.Data (1 .. Slen) := Source;
else
case Drop is
when Strings.Right =>
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (Source (Source'First .. Source'First - 1 + Max_Length));
Result.Current_Length := Max_Length;
- Result.Data (1 .. Max_Length) :=
- Source (Source'First .. Source'First - 1 + Max_Length);
when Strings.Left =>
+ Result.Data (1 .. Max_Length) := Super_String_Data
+ (Source (Source'Last - (Max_Length - 1) .. Source'Last));
Result.Current_Length := Max_Length;
- Result.Data (1 .. Max_Length) :=
- Source (Source'Last - (Max_Length - 1) .. Source'Last);
when Strings.Error =>
raise Ada.Strings.Length_Error;
diff --git a/gcc/ada/libgnat/a-strsup.ads b/gcc/ada/libgnat/a-strsup.ads
index 9e568a8..7428e9c 100644
--- a/gcc/ada/libgnat/a-strsup.ads
+++ b/gcc/ada/libgnat/a-strsup.ads
@@ -36,28 +36,47 @@
-- length as the discriminant. Individual instantiations of Strings.Bounded
-- use this type with an appropriate discriminant value set.
-with Ada.Strings.Maps;
+-- Preconditions in this unit are meant for analysis only, not for run-time
+-- checking, so that the expected exceptions are raised. This is enforced by
+-- setting the corresponding assertion policy to Ignore. Postconditions and
+-- contract cases should not be executed at runtime as well, in order not to
+-- slow down the execution of these functions.
-package Ada.Strings.Superbounded is
+pragma Assertion_Policy (Pre => Ignore,
+ Post => Ignore,
+ Contract_Cases => Ignore,
+ Ghost => Ignore);
+
+with Ada.Strings.Maps; use type Ada.Strings.Maps.Character_Mapping_Function;
+with Ada.Strings.Search;
+
+package Ada.Strings.Superbounded with SPARK_Mode is
pragma Preelaborate;
-- Type Bounded_String in Ada.Strings.Bounded.Generic_Bounded_Length is
-- derived from Super_String, with the constraint of the maximum length.
+ type Super_String_Data is new String with Relaxed_Initialization;
+
type Super_String (Max_Length : Positive) is record
Current_Length : Natural := 0;
- Data : String (1 .. Max_Length);
+ Data : Super_String_Data (1 .. Max_Length);
-- A previous version had a default initial value for Data, which is
-- no longer necessary, because we now special-case this type in the
-- compiler, so "=" composes properly for descendants of this type.
-- Leaving it out is more efficient.
- end record;
+ end record
+ with
+ Predicate =>
+ Current_Length <= Max_Length
+ and then Data (1 .. Current_Length)'Initialized;
-- The subprograms defined for Super_String are similar to those
-- defined for Bounded_String, except that they have different names, so
-- that they can be renamed in Ada.Strings.Bounded.Generic_Bounded_Length.
- function Super_Length (Source : Super_String) return Natural;
+ function Super_Length (Source : Super_String) return Natural
+ is (Source.Current_Length);
--------------------------------------------------------
-- Conversion, Concatenation, and Selection Functions --
@@ -65,109 +84,606 @@ package Ada.Strings.Superbounded is
function To_Super_String
(Source : String;
- Max_Length : Natural;
- Drop : Truncation := Error) return Super_String;
+ Max_Length : Positive;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre => (if Source'Length > Max_Length then Drop /= Error),
+ Post => To_Super_String'Result.Max_Length = Max_Length,
+ Contract_Cases =>
+ (Source'Length <= Max_Length
+ =>
+ Super_To_String (To_Super_String'Result) = Source,
+
+ Source'Length > Max_Length and then Drop = Left
+ =>
+ Super_To_String (To_Super_String'Result) =
+ Source (Source'Last - Max_Length + 1 .. Source'Last),
+
+ others -- Drop = Right
+ =>
+ Super_To_String (To_Super_String'Result) =
+ Source (Source'First .. Source'First - 1 + Max_Length)),
+ Global => null;
-- Note the additional parameter Max_Length, which specifies the maximum
-- length setting of the resulting Super_String value.
-- The following procedures have declarations (and semantics) that are
-- exactly analogous to those declared in Ada.Strings.Bounded.
- function Super_To_String (Source : Super_String) return String;
+ function Super_To_String (Source : Super_String) return String
+ is (String (Source.Data (1 .. Source.Current_Length)));
procedure Set_Super_String
(Target : out Super_String;
Source : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ (if Source'Length > Target.Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Source'Length <= Target.Max_Length
+ =>
+ Super_To_String (Target) = Source,
+
+ Source'Length > Target.Max_Length and then Drop = Left
+ =>
+ Super_To_String (Target) =
+ Source (Source'Last - Target.Max_Length + 1 .. Source'Last),
+
+ others -- Drop = Right
+ =>
+ Super_To_String (Target) =
+ Source (Source'First .. Source'First - 1 + Target.Max_Length)),
+ Global => null;
function Super_Append
(Left : Super_String;
Right : Super_String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ Left.Max_Length = Right.Max_Length
+ and then
+ (if Super_Length (Left) > Left.Max_Length - Super_Length (Right)
+ then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Left.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Left) <= Left.Max_Length - Super_Length (Right)
+ =>
+ Super_Length (Super_Append'Result) =
+ Super_Length (Left) + Super_Length (Right)
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Super_Length (Right) > 0 then
+ Super_Slice (Super_Append'Result,
+ Super_Length (Left) + 1,
+ Super_Length (Super_Append'Result)) =
+ Super_To_String (Right)),
+
+ Super_Length (Left) > Left.Max_Length - Super_Length (Right)
+ and then Drop = Strings.Left
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ (if Super_Length (Right) < Left.Max_Length then
+ String'(Super_Slice (Super_Append'Result,
+ 1, Left.Max_Length - Super_Length (Right))) =
+ Super_Slice (Left,
+ Super_Length (Left) - Left.Max_Length
+ + Super_Length (Right) + 1,
+ Super_Length (Left)))
+ and then
+ Super_Slice (Super_Append'Result,
+ Left.Max_Length - Super_Length (Right) + 1, Left.Max_Length) =
+ Super_To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Super_Length (Left) < Left.Max_Length then
+ String'(Super_Slice (Super_Append'Result,
+ Super_Length (Left) + 1, Left.Max_Length)) =
+ Super_Slice (Right,
+ 1, Left.Max_Length - Super_Length (Left)))),
+ Global => null;
function Super_Append
(Left : Super_String;
Right : String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Right'Length > Left.Max_Length - Super_Length (Left)
+ then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Left.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Left) <= Left.Max_Length - Right'Length
+ =>
+ Super_Length (Super_Append'Result) =
+ Super_Length (Left) + Right'Length
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Right'Length > 0 then
+ Super_Slice (Super_Append'Result,
+ Super_Length (Left) + 1,
+ Super_Length (Super_Append'Result)) =
+ Right),
+
+ Super_Length (Left) > Left.Max_Length - Right'Length
+ and then Drop = Strings.Left
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ (if Right'Length < Left.Max_Length then
+
+ -- The result is the end of Left followed by Right
+
+ String'(Super_Slice (Super_Append'Result,
+ 1, Left.Max_Length - Right'Length)) =
+ Super_Slice (Left,
+ Super_Length (Left) - Left.Max_Length + Right'Length
+ + 1,
+ Super_Length (Left))
+ and then
+ Super_Slice (Super_Append'Result,
+ Left.Max_Length - Right'Length + 1, Left.Max_Length) =
+ Right
+ else
+ -- The result is the last Max_Length characters of Right
+
+ Super_To_String (Super_Append'Result) =
+ Right (Right'Last - Left.Max_Length + 1 .. Right'Last)),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Super_Length (Left) < Left.Max_Length then
+ Super_Slice (Super_Append'Result,
+ Super_Length (Left) + 1, Left.Max_Length) =
+ Right (Right'First
+ .. Left.Max_Length - Super_Length (Left)
+ - 1 + Right'First))),
+ Global => null;
function Super_Append
(Left : String;
Right : Super_String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Left'Length > Right.Max_Length - Super_Length (Right)
+ then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Right.Max_Length,
+ Contract_Cases =>
+ (Left'Length <= Right.Max_Length - Super_Length (Right)
+ =>
+ Super_Length (Super_Append'Result) =
+ Left'Length + Super_Length (Right)
+ and then Super_Slice (Super_Append'Result, 1, Left'Length) = Left
+ and then
+ (if Super_Length (Right) > 0 then
+ Super_Slice (Super_Append'Result,
+ Left'Length + 1, Super_Length (Super_Append'Result)) =
+ Super_To_String (Right)),
+
+ Left'Length > Right.Max_Length - Super_Length (Right)
+ and then Drop = Strings.Left
+ =>
+ Super_Length (Super_Append'Result) = Right.Max_Length
+ and then
+ (if Super_Length (Right) < Right.Max_Length then
+ Super_Slice (Super_Append'Result,
+ 1, Right.Max_Length - Super_Length (Right)) =
+ Left
+ (Left'Last - Right.Max_Length + Super_Length (Right) + 1
+ .. Left'Last))
+ and then
+ Super_Slice (Super_Append'Result,
+ Right.Max_Length - Super_Length (Right) + 1,
+ Right.Max_Length) =
+ Super_To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Super_Append'Result) = Right.Max_Length
+ and then
+ (if Left'Length < Right.Max_Length then
+
+ -- The result is Left followed by the beginning of Right
+
+ Super_Slice (Super_Append'Result, 1, Left'Length) = Left
+ and then
+ String'(Super_Slice (Super_Append'Result,
+ Left'Length + 1, Right.Max_Length)) =
+ Super_Slice (Right, 1, Right.Max_Length - Left'Length)
+ else
+ -- The result is the first Max_Length characters of Left
+
+ Super_To_String (Super_Append'Result) =
+ Left (Left'First .. Right.Max_Length - 1 + Left'First))),
+ Global => null;
function Super_Append
(Left : Super_String;
Right : Character;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Super_Length (Left) = Left.Max_Length then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Left.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Left) < Left.Max_Length
+ =>
+ Super_Length (Super_Append'Result) = Super_Length (Left) + 1
+ and then
+ Super_Slice (Super_Append'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ Super_Element (Super_Append'Result, Super_Length (Left) + 1) =
+ Right,
+
+ Super_Length (Left) = Left.Max_Length and then Drop = Strings.Right
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ Super_To_String (Super_Append'Result) = Super_To_String (Left),
+
+ others -- Drop = Left
+ =>
+ Super_Length (Super_Append'Result) = Left.Max_Length
+ and then
+ String'(Super_Slice (Super_Append'Result,
+ 1, Left.Max_Length - 1)) =
+ Super_Slice (Left, 2, Left.Max_Length)
+ and then
+ Super_Element (Super_Append'Result, Left.Max_Length) = Right),
+ Global => null;
function Super_Append
(Left : Character;
Right : Super_String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Super_Length (Right) = Right.Max_Length then Drop /= Error),
+ Post => Super_Append'Result.Max_Length = Right.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Right) < Right.Max_Length
+ =>
+ Super_Length (Super_Append'Result) = Super_Length (Right) + 1
+ and then
+ Super_Slice (Super_Append'Result, 2, Super_Length (Right) + 1) =
+ Super_To_String (Right)
+ and then Super_Element (Super_Append'Result, 1) = Left,
+
+ Super_Length (Right) = Right.Max_Length and then Drop = Strings.Left
+ =>
+ Super_Length (Super_Append'Result) = Right.Max_Length
+ and then
+ Super_To_String (Super_Append'Result) = Super_To_String (Right),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Super_Append'Result) = Right.Max_Length
+ and then
+ String'(Super_Slice (Super_Append'Result, 2, Right.Max_Length)) =
+ Super_Slice (Right, 1, Right.Max_Length - 1)
+ and then Super_Element (Super_Append'Result, 1) = Left),
+ Global => null;
procedure Super_Append
(Source : in out Super_String;
New_Item : Super_String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ Source.Max_Length = New_Item.Max_Length
+ and then
+ (if Super_Length (Source) >
+ Source.Max_Length - Super_Length (New_Item)
+ then Drop /= Error),
+ Contract_Cases =>
+ (Super_Length (Source) <= Source.Max_Length - Super_Length (New_Item)
+ =>
+ Super_Length (Source) =
+ Super_Length (Source'Old) + Super_Length (New_Item)
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ (if Super_Length (New_Item) > 0 then
+ Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Super_Length (Source)) =
+ Super_To_String (New_Item)),
+
+ Super_Length (Source) > Source.Max_Length - Super_Length (New_Item)
+ and then Drop = Left
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ (if Super_Length (New_Item) < Source.Max_Length then
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - Super_Length (New_Item))) =
+ Super_Slice (Source'Old,
+ Super_Length (Source'Old) - Source.Max_Length
+ + Super_Length (New_Item) + 1,
+ Super_Length (Source'Old)))
+ and then
+ Super_Slice (Source,
+ Source.Max_Length - Super_Length (New_Item) + 1,
+ Source.Max_Length) =
+ Super_To_String (New_Item),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ (if Super_Length (Source'Old) < Source.Max_Length then
+ String'(Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Source.Max_Length)) =
+ Super_Slice (New_Item,
+ 1, Source.Max_Length - Super_Length (Source'Old)))),
+ Global => null;
procedure Super_Append
(Source : in out Super_String;
New_Item : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ (if New_Item'Length > Source.Max_Length - Super_Length (Source)
+ then Drop /= Error),
+ Contract_Cases =>
+ (Super_Length (Source) <= Source.Max_Length - New_Item'Length
+ =>
+ Super_Length (Source) = Super_Length (Source'Old) + New_Item'Length
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ (if New_Item'Length > 0 then
+ Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Super_Length (Source)) =
+ New_Item),
+
+ Super_Length (Source) > Source.Max_Length - New_Item'Length
+ and then Drop = Left
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ (if New_Item'Length < Source.Max_Length then
+
+ -- The result is the end of Source followed by New_Item
+
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - New_Item'Length)) =
+ Super_Slice (Source'Old,
+ Super_Length (Source'Old) - Source.Max_Length
+ + New_Item'Length + 1,
+ Super_Length (Source'Old))
+ and then
+ Super_Slice (Source,
+ Source.Max_Length - New_Item'Length + 1,
+ Source.Max_Length) =
+ New_Item
+ else
+ -- The result is the last Max_Length characters of
+ -- New_Item.
+
+ Super_To_String (Source) = New_Item
+ (New_Item'Last - Source.Max_Length + 1 .. New_Item'Last)),
+
+ others -- Drop = Right
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ (if Super_Length (Source'Old) < Source.Max_Length then
+ Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Super_Length (Source'Old) - 1
+ + New_Item'First))),
+ Global => null;
procedure Super_Append
(Source : in out Super_String;
New_Item : Character;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ (if Super_Length (Source) = Source.Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Super_Length (Source) < Source.Max_Length
+ =>
+ Super_Length (Source) = Super_Length (Source'Old) + 1
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ Super_Element (Source, Super_Length (Source'Old) + 1) = New_Item,
+
+ Super_Length (Source) = Source.Max_Length and then Drop = Right
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then Super_To_String (Source) = Super_To_String (Source'Old),
+
+ others -- Drop = Left
+ =>
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source, 1, Source.Max_Length - 1)) =
+ Super_Slice (Source'Old, 2, Source.Max_Length)
+ and then Super_Element (Source, Source.Max_Length) = New_Item),
+ Global => null;
function Concat
(Left : Super_String;
- Right : Super_String) return Super_String;
+ Right : Super_String) return Super_String
+ with
+ Pre => Left.Max_Length = Right.Max_Length
+ and then Super_Length (Left) <= Left.Max_Length - Super_Length (Right),
+ Post => Concat'Result.Max_Length = Left.Max_Length
+ and then
+ Super_Length (Concat'Result) =
+ Super_Length (Left) + Super_Length (Right)
+ and then
+ Super_Slice (Concat'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Super_Length (Right) > 0 then
+ Super_Slice (Concat'Result,
+ Super_Length (Left) + 1, Super_Length (Concat'Result)) =
+ Super_To_String (Right)),
+ Global => null;
function Concat
(Left : Super_String;
- Right : String) return Super_String;
+ Right : String) return Super_String
+ with
+ Pre => Right'Length <= Left.Max_Length - Super_Length (Left),
+ Post => Concat'Result.Max_Length = Left.Max_Length
+ and then
+ Super_Length (Concat'Result) = Super_Length (Left) + Right'Length
+ and then
+ Super_Slice (Concat'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then
+ (if Right'Length > 0 then
+ Super_Slice (Concat'Result,
+ Super_Length (Left) + 1, Super_Length (Concat'Result)) =
+ Right),
+ Global => null;
function Concat
(Left : String;
- Right : Super_String) return Super_String;
+ Right : Super_String) return Super_String
+ with
+ Pre => Left'Length <= Right.Max_Length - Super_Length (Right),
+ Post => Concat'Result.Max_Length = Right.Max_Length
+ and then
+ Super_Length (Concat'Result) = Left'Length + Super_Length (Right)
+ and then Super_Slice (Concat'Result, 1, Left'Length) = Left
+ and then
+ (if Super_Length (Right) > 0 then
+ Super_Slice (Concat'Result,
+ Left'Length + 1, Super_Length (Concat'Result)) =
+ Super_To_String (Right)),
+ Global => null;
function Concat
(Left : Super_String;
- Right : Character) return Super_String;
+ Right : Character) return Super_String
+ with
+ Pre => Super_Length (Left) < Left.Max_Length,
+ Post => Concat'Result.Max_Length = Left.Max_Length
+ and then Super_Length (Concat'Result) = Super_Length (Left) + 1
+ and then
+ Super_Slice (Concat'Result, 1, Super_Length (Left)) =
+ Super_To_String (Left)
+ and then Super_Element (Concat'Result, Super_Length (Left) + 1) = Right,
+ Global => null;
function Concat
(Left : Character;
- Right : Super_String) return Super_String;
+ Right : Super_String) return Super_String
+ with
+ Pre => Super_Length (Right) < Right.Max_Length,
+ Post => Concat'Result.Max_Length = Right.Max_Length
+ and then Super_Length (Concat'Result) = 1 + Super_Length (Right)
+ and then Super_Element (Concat'Result, 1) = Left
+ and then
+ Super_Slice (Concat'Result, 2, Super_Length (Concat'Result)) =
+ Super_To_String (Right),
+ Global => null;
function Super_Element
(Source : Super_String;
- Index : Positive) return Character;
+ Index : Positive) return Character
+ is (if Index <= Source.Current_Length
+ then Source.Data (Index)
+ else raise Index_Error)
+ with Pre => Index <= Super_Length (Source);
procedure Super_Replace_Element
(Source : in out Super_String;
Index : Positive;
- By : Character);
+ By : Character)
+ with
+ Pre => Index <= Super_Length (Source),
+ Post => Super_Length (Source) = Super_Length (Source'Old)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Source, K) =
+ (if K = Index then By else Super_Element (Source'Old, K))),
+ Global => null;
function Super_Slice
(Source : Super_String;
Low : Positive;
- High : Natural) return String;
+ High : Natural) return String
+ is (if Low - 1 > Source.Current_Length or else High > Source.Current_Length
+
+ -- Note: test of High > Length is in accordance with AI95-00128
+
+ then raise Index_Error
+ else
+ -- Note: in this case, superflat bounds are not a problem, we just
+ -- get the null string in accordance with normal Ada slice rules.
+
+ String (Source.Data (Low .. High)))
+ with Pre => Low - 1 <= Super_Length (Source)
+ and then High <= Super_Length (Source);
function Super_Slice
(Source : Super_String;
Low : Positive;
- High : Natural) return Super_String;
+ High : Natural) return Super_String
+ with
+ Pre =>
+ Low - 1 <= Super_Length (Source) and then High <= Super_Length (Source),
+ Post => Super_Slice'Result.Max_Length = Source.Max_Length
+ and then
+ Super_To_String (Super_Slice'Result) =
+ Super_Slice (Source, Low, High),
+ Global => null;
procedure Super_Slice
(Source : Super_String;
Target : out Super_String;
Low : Positive;
- High : Natural);
+ High : Natural)
+ with
+ Pre => Source.Max_Length = Target.Max_Length
+ and then Low - 1 <= Super_Length (Source)
+ and then High <= Super_Length (Source),
+ Post => Super_To_String (Target) = Super_Slice (Source, Low, High),
+ Global => null;
function "="
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post => "="'Result = (Super_To_String (Left) = Super_To_String (Right)),
+ Global => null;
function Equal
(Left : Super_String;
@@ -175,59 +691,111 @@ package Ada.Strings.Superbounded is
function Equal
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Equal'Result = (Super_To_String (Left) = Right),
+ Global => null;
function Equal
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Equal'Result = (Left = Super_To_String (Right)),
+ Global => null;
function Less
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post =>
+ Less'Result = (Super_To_String (Left) < Super_To_String (Right)),
+ Global => null;
function Less
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Less'Result = (Super_To_String (Left) < Right),
+ Global => null;
function Less
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Less'Result = (Left < Super_To_String (Right)),
+ Global => null;
function Less_Or_Equal
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post =>
+ Less_Or_Equal'Result =
+ (Super_To_String (Left) <= Super_To_String (Right)),
+ Global => null;
function Less_Or_Equal
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Less_Or_Equal'Result = (Super_To_String (Left) <= Right),
+ Global => null;
function Less_Or_Equal
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Less_Or_Equal'Result = (Left <= Super_To_String (Right)),
+ Global => null;
function Greater
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post =>
+ Greater'Result = (Super_To_String (Left) > Super_To_String (Right)),
+ Global => null;
function Greater
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Greater'Result = (Super_To_String (Left) > Right),
+ Global => null;
function Greater
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Greater'Result = (Left > Super_To_String (Right)),
+ Global => null;
function Greater_Or_Equal
(Left : Super_String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Pre => Left.Max_Length = Right.Max_Length,
+ Post =>
+ Greater_Or_Equal'Result =
+ (Super_To_String (Left) >= Super_To_String (Right)),
+ Global => null;
function Greater_Or_Equal
(Left : Super_String;
- Right : String) return Boolean;
+ Right : String) return Boolean
+ with
+ Post => Greater_Or_Equal'Result = (Super_To_String (Left) >= Right),
+ Global => null;
function Greater_Or_Equal
(Left : String;
- Right : Super_String) return Boolean;
+ Right : Super_String) return Boolean
+ with
+ Post => Greater_Or_Equal'Result = (Left >= Super_To_String (Right)),
+ Global => null;
----------------------
-- Search Functions --
@@ -237,63 +805,449 @@ package Ada.Strings.Superbounded is
(Source : Super_String;
Pattern : String;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping := Maps.Identity) return Natural;
+ Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
+ with
+ Pre => Pattern'Length > 0,
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Super_Length (Source) = 0
+ =>
+ Super_Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Super_Length (Source) > 0
+ and then
+ (for some J in 1 .. Super_Length (Source) - (Pattern'Length - 1) =>
+ Search.Match (Super_To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in
+ 1 .. Super_Length (Source) - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (Super_To_String (Source), Pattern, Mapping, Super_Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if (if Going = Forward
+ then J <= Super_Index'Result - 1
+ else J - 1 in Super_Index'Result
+ .. Super_Length (Source) - Pattern'Length)
+ then not (Search.Match
+ (Super_To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Super_Index'Result = 0),
+ Global => null;
function Super_Index
(Source : Super_String;
Pattern : String;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping_Function) return Natural;
+ Mapping : Maps.Character_Mapping_Function) return Natural
+ with
+ Pre => Pattern'Length /= 0 and then Mapping /= null,
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Super_Length (Source) = 0
+ =>
+ Super_Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Super_Length (Source) > 0
+ and then
+ (for some J in 1 .. Super_Length (Source) - (Pattern'Length - 1) =>
+ Search.Match (Super_To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in
+ 1 .. Super_Length (Source) - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (Super_To_String (Source), Pattern, Mapping, Super_Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if (if Going = Forward
+ then J <= Super_Index'Result - 1
+ else J - 1 in Super_Index'Result
+ .. Super_Length (Source) - Pattern'Length)
+ then not (Search.Match
+ (Super_To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Super_Index'Result = 0),
+ Global => null;
function Super_Index
(Source : Super_String;
Set : Maps.Character_Set;
Test : Membership := Inside;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If no character of Source satisfies the property Test on Set,
+ -- then 0 is returned.
+
+ ((for all C of Super_To_String (Source) =>
+ (Test = Inside) /= Maps.Is_In (C, Set))
+ =>
+ Super_Index'Result = 0,
+
+ -- Otherwise, an index in the range of Source is returned
+
+ others
+ =>
+ -- The result is in the range of Source
+
+ Super_Index'Result in 1 .. Super_Length (Source)
+
+ -- The character at the returned index satisfies the property
+ -- Test on Set.
+
+ and then
+ (Test = Inside) =
+ Maps.Is_In (Super_Element (Source, Super_Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J /= Super_Index'Result
+ and then (J < Super_Index'Result) = (Going = Forward)
+ then (Test = Inside)
+ /= Maps.Is_In (Super_Element (Source, J), Set)))),
+ Global => null;
function Super_Index
(Source : Super_String;
Pattern : String;
From : Positive;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping := Maps.Identity) return Natural;
+ Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source))
+ and then Pattern'Length /= 0,
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Super_Length (Source) = 0
+ =>
+ Super_Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Super_Length (Source) > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Super_Length (Source) else From)
+ - (Pattern'Length - 1) =>
+ Search.Match (Super_To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Super_Length (Source) else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (Super_To_String (Source), Pattern, Mapping, Super_Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if (if Going = Forward
+ then J in From .. Super_Index'Result - 1
+ else J - 1 in Super_Index'Result
+ .. From - Pattern'Length)
+ then not (Search.Match
+ (Super_To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Super_Index'Result = 0),
+ Global => null;
function Super_Index
(Source : Super_String;
Pattern : String;
From : Positive;
Going : Direction := Forward;
- Mapping : Maps.Character_Mapping_Function) return Natural;
+ Mapping : Maps.Character_Mapping_Function) return Natural
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source))
+ and then Pattern'Length /= 0
+ and then Mapping /= null,
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, then 0 is returned
+
+ (Super_Length (Source) = 0
+ =>
+ Super_Index'Result = 0,
+
+ -- If some slice of Source matches Pattern, then a valid index is
+ -- returned.
+
+ Super_Length (Source) > 0
+ and then
+ (for some J in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Super_Length (Source) else From)
+ - (Pattern'Length - 1) =>
+ Search.Match (Super_To_String (Source), Pattern, Mapping, J))
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in
+ (if Going = Forward then From else 1)
+ .. (if Going = Forward then Super_Length (Source) else From)
+ - (Pattern'Length - 1)
+
+ -- The slice beginning at the returned index matches Pattern
+
+ and then Search.Match
+ (Super_To_String (Source), Pattern, Mapping, Super_Index'Result)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the matching, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if (if Going = Forward
+ then J in From .. Super_Index'Result - 1
+ else J - 1 in Super_Index'Result
+ .. From - Pattern'Length)
+ then not (Search.Match
+ (Super_To_String (Source), Pattern, Mapping, J)))),
+
+ -- Otherwise, 0 is returned
+
+ others
+ =>
+ Super_Index'Result = 0),
+ Global => null;
function Super_Index
(Source : Super_String;
Set : Maps.Character_Set;
From : Positive;
Test : Membership := Inside;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source)),
+ Post => Super_Index'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or no character of the considered
+ -- slice of Source satisfies the property Test on Set, then 0 is
+ -- returned.
+
+ (Super_Length (Source) = 0
+ or else
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, J), Set)))
+ =>
+ Super_Index'Result = 0,
+
+ -- Otherwise, an index in the considered range of Source is returned
+
+ others
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index'Result in 1 .. Super_Length (Source)
+ and then
+ (Super_Index'Result = From
+ or else (Super_Index'Result > From) = (Going = Forward))
+
+ -- The character at the returned index satisfies the property
+ -- Test on Set.
+
+ and then
+ (Test = Inside) =
+ Maps.Is_In (Super_Element (Source, Super_Index'Result), Set)
+
+ -- The result is the smallest or largest index which satisfies
+ -- the property, respectively when Going = Forward and Going =
+ -- Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J /= Super_Index'Result
+ and then (J < Super_Index'Result) = (Going = Forward)
+ and then (J = From
+ or else (J > From) = (Going = Forward))
+ then (Test = Inside)
+ /= Maps.Is_In (Super_Element (Source, J), Set)))),
+ Global => null;
function Super_Index_Non_Blank
(Source : Super_String;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Post => Super_Index_Non_Blank'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If all characters of Source are Space characters, then 0 is
+ -- returned.
+
+ ((for all C of Super_To_String (Source) => C = ' ')
+ =>
+ Super_Index_Non_Blank'Result = 0,
+
+ -- Otherwise, an index in the range of Source is returned
+
+ others
+ =>
+ -- The result is in the range of Source
+
+ Super_Index_Non_Blank'Result in 1 .. Super_Length (Source)
+
+ -- The character at the returned index is not a Space character
+
+ and then
+ Super_Element (Source, Super_Index_Non_Blank'Result) /= ' '
+
+ -- The result is the smallest or largest index which is not a
+ -- Space character, respectively when Going = Forward and Going
+ -- = Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J /= Super_Index_Non_Blank'Result
+ and then
+ (J < Super_Index_Non_Blank'Result) = (Going = Forward)
+ then Super_Element (Source, J) = ' '))),
+ Global => null;
function Super_Index_Non_Blank
(Source : Super_String;
From : Positive;
- Going : Direction := Forward) return Natural;
+ Going : Direction := Forward) return Natural
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source)),
+ Post => Super_Index_Non_Blank'Result <= Super_Length (Source),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or all characters of the
+ -- considered slice of Source are Space characters, then 0
+ -- is returned.
+
+ (Super_Length (Source) = 0
+ or else
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J = From or else (J > From) = (Going = Forward) then
+ Super_Element (Source, J) = ' '))
+ =>
+ Super_Index_Non_Blank'Result = 0,
+
+ -- Otherwise, an index in the considered range of Source is returned
+
+ others
+ =>
+ -- The result is in the considered range of Source
+
+ Super_Index_Non_Blank'Result in 1 .. Super_Length (Source)
+ and then
+ (Super_Index_Non_Blank'Result = From
+ or else
+ (Super_Index_Non_Blank'Result > From) = (Going = Forward))
+
+ -- The character at the returned index is not a Space character
+
+ and then
+ Super_Element (Source, Super_Index_Non_Blank'Result) /= ' '
+
+ -- The result is the smallest or largest index which isn't a
+ -- Space character, respectively when Going = Forward and Going
+ -- = Backward.
+
+ and then
+ (for all J in 1 .. Super_Length (Source) =>
+ (if J /= Super_Index_Non_Blank'Result
+ and then
+ (J < Super_Index_Non_Blank'Result) = (Going = Forward)
+ and then (J = From
+ or else (J > From) = (Going = Forward))
+ then Super_Element (Source, J) = ' '))),
+ Global => null;
function Super_Count
(Source : Super_String;
Pattern : String;
- Mapping : Maps.Character_Mapping := Maps.Identity) return Natural;
+ Mapping : Maps.Character_Mapping := Maps.Identity) return Natural
+ with
+ Pre => Pattern'Length /= 0,
+ Global => null;
function Super_Count
(Source : Super_String;
Pattern : String;
- Mapping : Maps.Character_Mapping_Function) return Natural;
+ Mapping : Maps.Character_Mapping_Function) return Natural
+ with
+ Pre => Pattern'Length /= 0 and then Mapping /= null,
+ Global => null;
function Super_Count
(Source : Super_String;
- Set : Maps.Character_Set) return Natural;
+ Set : Maps.Character_Set) return Natural
+ with
+ Global => null;
procedure Super_Find_Token
(Source : Super_String;
@@ -301,14 +1255,112 @@ package Ada.Strings.Superbounded is
From : Positive;
Test : Membership;
First : out Positive;
- Last : out Natural);
+ Last : out Natural)
+ with
+ Pre =>
+ (if Super_Length (Source) /= 0 then From <= Super_Length (Source)),
+ Contract_Cases =>
+
+ -- If Source is the empty string, or if no character of the
+ -- considered slice of Source satisfies the property Test on
+ -- Set, then First is set to From and Last is set to 0.
+
+ (Super_Length (Source) = 0
+ or else
+ (for all J in From .. Super_Length (Source) =>
+ (Test = Inside) /= Maps.Is_In (Super_Element (Source, J), Set))
+ =>
+ First = From and then Last = 0,
+
+ -- Otherwise, First and Last are set to valid indexes
+
+ others
+ =>
+ -- First and Last are in the considered range of Source
+
+ First in From .. Super_Length (Source)
+ and then Last in First .. Super_Length (Source)
+
+ -- No character between From and First satisfies the property
+ -- Test on Set.
+
+ and then
+ (for all J in From .. First - 1 =>
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, J), Set))
+
+ -- All characters between First and Last satisfy the property
+ -- Test on Set.
+
+ and then
+ (for all J in First .. Last =>
+ (Test = Inside) =
+ Maps.Is_In (Super_Element (Source, J), Set))
+
+ -- If Last is not Source'Last, then the character at position
+ -- Last + 1 does not satify the property Test on Set.
+
+ and then
+ (if Last < Super_Length (Source)
+ then
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, Last + 1), Set))),
+ Global => null;
procedure Super_Find_Token
(Source : Super_String;
Set : Maps.Character_Set;
Test : Membership;
First : out Positive;
- Last : out Natural);
+ Last : out Natural)
+ with
+ Contract_Cases =>
+
+ -- If Source is the empty string, or if no character of the considered
+ -- slice of Source satisfies the property Test on Set, then First is
+ -- set to 1 and Last is set to 0.
+
+ (Super_Length (Source) = 0
+ or else
+ (for all J in 1 .. Super_Length (Source) =>
+ (Test = Inside) /= Maps.Is_In (Super_Element (Source, J), Set))
+ =>
+ First = 1 and then Last = 0,
+
+ -- Otherwise, First and Last are set to valid indexes
+
+ others
+ =>
+ -- First and Last are in the considered range of Source
+
+ First in 1 .. Super_Length (Source)
+ and then Last in First .. Super_Length (Source)
+
+ -- No character between 1 and First satisfies the property Test on
+ -- Set.
+
+ and then
+ (for all J in 1 .. First - 1 =>
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, J), Set))
+
+ -- All characters between First and Last satisfy the property
+ -- Test on Set.
+
+ and then
+ (for all J in First .. Last =>
+ (Test = Inside) =
+ Maps.Is_In (Super_Element (Source, J), Set))
+
+ -- If Last is not Source'Last, then the character at position
+ -- Last + 1 does not satify the property Test on Set.
+
+ and then
+ (if Last < Super_Length (Source)
+ then
+ (Test = Inside) /=
+ Maps.Is_In (Super_Element (Source, Last + 1), Set))),
+ Global => null;
------------------------------------
-- String Translation Subprograms --
@@ -316,19 +1368,51 @@ package Ada.Strings.Superbounded is
function Super_Translate
(Source : Super_String;
- Mapping : Maps.Character_Mapping) return Super_String;
+ Mapping : Maps.Character_Mapping) return Super_String
+ with
+ Post => Super_Translate'Result.Max_Length = Source.Max_Length
+ and then Super_Length (Super_Translate'Result) = Super_Length (Source)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Super_Translate'Result, K) =
+ Ada.Strings.Maps.Value (Mapping, Super_Element (Source, K))),
+ Global => null;
procedure Super_Translate
(Source : in out Super_String;
- Mapping : Maps.Character_Mapping);
+ Mapping : Maps.Character_Mapping)
+ with
+ Post => Super_Length (Source) = Super_Length (Source'Old)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Source, K) =
+ Ada.Strings.Maps.Value (Mapping, Super_Element (Source'Old, K))),
+ Global => null;
function Super_Translate
(Source : Super_String;
- Mapping : Maps.Character_Mapping_Function) return Super_String;
+ Mapping : Maps.Character_Mapping_Function) return Super_String
+ with
+ Pre => Mapping /= null,
+ Post => Super_Translate'Result.Max_Length = Source.Max_Length
+ and then Super_Length (Super_Translate'Result) = Super_Length (Source)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Super_Translate'Result, K) =
+ Mapping (Super_Element (Source, K))),
+ Global => null;
procedure Super_Translate
(Source : in out Super_String;
- Mapping : Maps.Character_Mapping_Function);
+ Mapping : Maps.Character_Mapping_Function)
+ with
+ Pre => Mapping /= null,
+ Post => Super_Length (Source) = Super_Length (Source'Old)
+ and then
+ (for all K in 1 .. Super_Length (Source) =>
+ Super_Element (Source, K) =
+ Mapping (Super_Element (Source'Old, K))),
+ Global => null;
---------------------------------------
-- String Transformation Subprograms --
@@ -339,48 +1423,756 @@ package Ada.Strings.Superbounded is
Low : Positive;
High : Natural;
By : String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ Low - 1 <= Super_Length (Source)
+ and then
+ (if Drop = Error
+ then (if High >= Low
+ then Low - 1
+ <= Source.Max_Length - By'Length
+ - Integer'Max (Super_Length (Source) - High, 0)
+ else Super_Length (Source) <=
+ Source.Max_Length - By'Length)),
+ Post =>
+ Super_Replace_Slice'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Low - 1 <= Source.Max_Length - By'Length - Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ -- Note that if High < Low, the insertion is done before Low, so in
+ -- all cases the starting position of the slice of Source remaining
+ -- after the replaced Slice is Integer'Max (High + 1, Low).
+
+ Super_Length (Super_Replace_Slice'Result) =
+ Low - 1 + By'Length + Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then
+ String'(Super_Slice (Super_Replace_Slice'Result, 1, Low - 1)) =
+ Super_Slice (Source, 1, Low - 1)
+ and then
+ Super_Slice (Super_Replace_Slice'Result,
+ Low, Low - 1 + By'Length) = By
+ and then
+ (if Integer'Max (High, Low - 1) < Super_Length (Source) then
+ String'(Super_Slice (Super_Replace_Slice'Result,
+ Low + By'Length,
+ Super_Length (Super_Replace_Slice'Result))) =
+ Super_Slice (Source,
+ Integer'Max (High + 1, Low), Super_Length (Source))),
+
+ Low - 1 > Source.Max_Length - By'Length - Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then Drop = Left
+ =>
+ -- Final_Super_Slice is the length of the slice of Source remaining
+ -- after the replaced part.
+ (declare
+ Final_Super_Slice : constant Natural :=
+ Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0);
+ begin
+ -- The result is of maximal length and ends by the last
+ -- Final_Super_Slice characters of Source.
+
+ Super_Length (Super_Replace_Slice'Result) = Source.Max_Length
+ and then
+ (if Final_Super_Slice > 0 then
+ String'(Super_Slice (Super_Replace_Slice'Result,
+ Source.Max_Length - Final_Super_Slice + 1,
+ Source.Max_Length)) =
+ Super_Slice (Source,
+ Integer'Max (High + 1, Low), Super_Length (Source)))
+
+ -- Depending on when we reach Max_Length, either the first
+ -- part of Source is fully dropped and By is partly dropped,
+ -- or By is fully added and the first part of Source is partly
+ -- dropped.
+
+ and then
+ (if Source.Max_Length - Final_Super_Slice - By'Length <= 0 then
+
+ -- The first (possibly zero) characters of By are dropped
+
+ (if Final_Super_Slice < Source.Max_Length then
+ Super_Slice (Super_Replace_Slice'Result,
+ 1, Source.Max_Length - Final_Super_Slice) =
+ By (By'Last - Source.Max_Length + Final_Super_Slice
+ + 1
+ .. By'Last))
+
+ else -- By is added to the result
+
+ Super_Slice (Super_Replace_Slice'Result,
+ Source.Max_Length - Final_Super_Slice - By'Length + 1,
+ Source.Max_Length - Final_Super_Slice) =
+ By
+
+ -- The first characters of Source (1 .. Low - 1) are
+ -- dropped.
+
+ and then
+ String'(Super_Slice (Super_Replace_Slice'Result, 1,
+ Source.Max_Length - Final_Super_Slice - By'Length)) =
+ Super_Slice (Source,
+ Low - Source.Max_Length
+ + Final_Super_Slice + By'Length,
+ Low - 1))),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first Low - 1
+ -- characters of Source.
+
+ Super_Length (Super_Replace_Slice'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Replace_Slice'Result, 1, Low - 1)) =
+ Super_Slice (Source, 1, Low - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and By is partly dropped, or By
+ -- is fully added and the last part of Source is partly dropped.
+
+ and then
+ (if Low - 1 >= Source.Max_Length - By'Length then
+
+ -- The last characters of By are dropped
+
+ Super_Slice (Super_Replace_Slice'Result,
+ Low, Source.Max_Length) =
+ By (By'First .. Source.Max_Length - Low + By'First)
+
+ else -- By is fully added
+
+ Super_Slice (Super_Replace_Slice'Result,
+ Low, Low + By'Length - 1) = By
+
+ -- Then Source starting from Natural'Max (High + 1, Low)
+ -- is added but the last characters are dropped.
+
+ and then
+ String'(Super_Slice (Super_Replace_Slice'Result,
+ Low + By'Length, Source.Max_Length)) =
+ Super_Slice (Source, Integer'Max (High + 1, Low),
+ Integer'Max (High + 1, Low) +
+ (Source.Max_Length - Low - By'Length)))),
+ Global => null;
procedure Super_Replace_Slice
(Source : in out Super_String;
Low : Positive;
High : Natural;
By : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ Low - 1 <= Super_Length (Source)
+ and then
+ (if Drop = Error
+ then (if High >= Low
+ then Low - 1
+ <= Source.Max_Length - By'Length
+ - Natural'Max (Super_Length (Source) - High, 0)
+ else Super_Length (Source) <=
+ Source.Max_Length - By'Length)),
+ Contract_Cases =>
+ (Low - 1 <= Source.Max_Length - By'Length - Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ -- Note that if High < Low, the insertion is done before Low, so in
+ -- all cases the starting position of the slice of Source remaining
+ -- after the replaced Slice is Integer'Max (High + 1, Low).
+
+ Super_Length (Source) = Low - 1 + By'Length + Integer'Max
+ (Super_Length (Source'Old) - Integer'Max (High, Low - 1), 0)
+ and then
+ String'(Super_Slice (Source, 1, Low - 1)) =
+ Super_Slice (Source'Old, 1, Low - 1)
+ and then Super_Slice (Source, Low, Low - 1 + By'Length) = By
+ and then
+ (if Integer'Max (High, Low - 1) < Super_Length (Source'Old) then
+ String'(Super_Slice (Source,
+ Low + By'Length, Super_Length (Source))) =
+ Super_Slice (Source'Old,
+ Integer'Max (High + 1, Low),
+ Super_Length (Source'Old))),
+
+ Low - 1 > Source.Max_Length - By'Length - Integer'Max
+ (Super_Length (Source) - Integer'Max (High, Low - 1), 0)
+ and then Drop = Left
+ =>
+ -- Final_Super_Slice is the length of the slice of Source remaining
+ -- after the replaced part.
+ (declare
+ Final_Super_Slice : constant Natural :=
+ Integer'Max (0,
+ Super_Length (Source'Old) - Integer'Max (High, Low - 1));
+ begin
+ -- The result is of maximal length and ends by the last
+ -- Final_Super_Slice characters of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ (if Final_Super_Slice > 0 then
+ String'(Super_Slice (Source,
+ Source.Max_Length - Final_Super_Slice + 1,
+ Source.Max_Length)) =
+ Super_Slice (Source'Old,
+ Integer'Max (High + 1, Low),
+ Super_Length (Source'Old)))
+
+ -- Depending on when we reach Max_Length, either the first
+ -- part of Source is fully dropped and By is partly dropped,
+ -- or By is fully added and the first part of Source is partly
+ -- dropped.
+
+ and then
+ (if Source.Max_Length - Final_Super_Slice - By'Length <= 0
+ then
+ -- The first characters of By are dropped
+
+ (if Final_Super_Slice < Source.Max_Length then
+ Super_Slice (Source,
+ 1, Source.Max_Length - Final_Super_Slice) =
+ By (By'Last - Source.Max_Length + Final_Super_Slice
+ + 1
+ .. By'Last))
+
+ else -- By is added to the result
+
+ Super_Slice (Source,
+ Source.Max_Length - Final_Super_Slice - By'Length + 1,
+ Source.Max_Length - Final_Super_Slice) = By
+
+ -- The first characters of Source (1 .. Low - 1) are
+ -- dropped.
+
+ and then
+ String'(Super_Slice (Source, 1,
+ Source.Max_Length - Final_Super_Slice - By'Length)) =
+ Super_Slice (Source'Old,
+ Low - Source.Max_Length + Final_Super_Slice
+ + By'Length,
+ Low - 1))),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first Low - 1
+ -- characters of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source, 1, Low - 1)) =
+ Super_Slice (Source'Old, 1, Low - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and By is partly dropped, or By
+ -- is fully added and the last part of Source is partly dropped.
+
+ and then
+ (if Low - 1 >= Source.Max_Length - By'Length then
+
+ -- The last characters of By are dropped
+
+ Super_Slice (Source, Low, Source.Max_Length) =
+ By (By'First .. Source.Max_Length - Low + By'First)
+
+ else -- By is fully added
+
+ Super_Slice (Source, Low, Low + By'Length - 1) = By
+
+ -- Then Source starting from Natural'Max (High + 1, Low)
+ -- is added but the last characters are dropped.
+
+ and then
+ String'(Super_Slice (Source,
+ Low + By'Length, Source.Max_Length)) =
+ Super_Slice (Source'Old, Integer'Max (High + 1, Low),
+ Integer'Max (High + 1, Low) +
+ (Source.Max_Length - Low - By'Length)))),
+ Global => null;
function Super_Insert
(Source : Super_String;
Before : Positive;
New_Item : String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ Before - 1 <= Super_Length (Source)
+ and then
+ (if New_Item'Length > Source.Max_Length - Super_Length (Source)
+ then Drop /= Error),
+ Post => Super_Insert'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Super_Length (Source) <= Source.Max_Length - New_Item'Length
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ Super_Length (Super_Insert'Result) =
+ Super_Length (Source) + New_Item'Length
+ and then
+ String'(Super_Slice (Super_Insert'Result, 1, Before - 1)) =
+ Super_Slice (Source, 1, Before - 1)
+ and then
+ Super_Slice (Super_Insert'Result,
+ Before, Before - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Before <= Super_Length (Source) then
+ String'(Super_Slice (Super_Insert'Result,
+ Before + New_Item'Length,
+ Super_Length (Super_Insert'Result))) =
+ Super_Slice (Source, Before, Super_Length (Source))),
+
+ Super_Length (Source) > Source.Max_Length - New_Item'Length
+ and then Drop = Left
+ =>
+ -- The result is of maximal length and ends by the last characters
+ -- of Source.
+
+ Super_Length (Super_Insert'Result) = Source.Max_Length
+ and then
+ (if Before <= Super_Length (Source) then
+ String'(Super_Slice (Super_Insert'Result,
+ Source.Max_Length - Super_Length (Source) + Before,
+ Source.Max_Length)) =
+ Super_Slice (Source, Before, Super_Length (Source)))
+
+ -- Depending on when we reach Max_Length, either the first part
+ -- of Source is fully dropped and New_Item is partly dropped, or
+ -- New_Item is fully added and the first part of Source is partly
+ -- dropped.
+
+ and then
+ (if Source.Max_Length - Super_Length (Source) - 1 + Before
+ < New_Item'Length
+ then
+ -- The first characters of New_Item are dropped
+
+ (if Super_Length (Source) - Before + 1 < Source.Max_Length
+ then
+ Super_Slice (Super_Insert'Result, 1,
+ Source.Max_Length - Super_Length (Source) - 1 + Before) =
+ New_Item
+ (New_Item'Last - Source.Max_Length
+ + Super_Length (Source) - Before + 2
+ .. New_Item'Last))
+
+ else -- New_Item is added to the result
+
+ Super_Slice (Super_Insert'Result,
+ Source.Max_Length - Super_Length (Source) - New_Item'Length
+ + Before,
+ Source.Max_Length - Super_Length (Source) - 1 + Before) =
+ New_Item
+
+ -- The first characters of Source (1 .. Before - 1) are
+ -- dropped.
+
+ and then
+ String'(Super_Slice (Super_Insert'Result,
+ 1, Source.Max_Length - Super_Length (Source)
+ - New_Item'Length - 1 + Before)) =
+ Super_Slice (Source,
+ Super_Length (Source) - Source.Max_Length
+ + New_Item'Length + 1,
+ Before - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Super_Length (Super_Insert'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Insert'Result, 1, Before - 1)) =
+ Super_Slice (Source, 1, Before - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and New_Item is partly dropped, or
+ -- New_Item is fully added and the last part of Source is partly
+ -- dropped.
+
+ and then
+ (if Before - 1 >= Source.Max_Length - New_Item'Length then
+
+ -- The last characters of New_Item are dropped
+
+ Super_Slice (Super_Insert'Result, Before, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Before + New_Item'First)
+
+ else -- New_Item is fully added
+
+ Super_Slice (Super_Insert'Result,
+ Before, Before + New_Item'Length - 1) =
+ New_Item
+
+ -- Then Source starting from Before is added but the
+ -- last characters are dropped.
+
+ and then
+ String'(Super_Slice (Super_Insert'Result,
+ Before + New_Item'Length, Source.Max_Length)) =
+ Super_Slice (Source,
+ Before, Source.Max_Length - New_Item'Length))),
+ Global => null;
procedure Super_Insert
(Source : in out Super_String;
Before : Positive;
New_Item : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ Before - 1 <= Super_Length (Source)
+ and then
+ (if New_Item'Length > Source.Max_Length - Super_Length (Source)
+ then Drop /= Error),
+ Contract_Cases =>
+ (Super_Length (Source) <= Source.Max_Length - New_Item'Length
+ =>
+ -- Total length is lower than Max_Length: nothing is dropped
+
+ Super_Length (Source) = Super_Length (Source'Old) + New_Item'Length
+ and then
+ String'(Super_Slice (Source, 1, Before - 1)) =
+ Super_Slice (Source'Old, 1, Before - 1)
+ and then
+ Super_Slice (Source, Before, Before - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Before <= Super_Length (Source'Old) then
+ String'(Super_Slice (Source,
+ Before + New_Item'Length, Super_Length (Source))) =
+ Super_Slice (Source'Old,
+ Before, Super_Length (Source'Old))),
+
+ Super_Length (Source) > Source.Max_Length - New_Item'Length
+ and then Drop = Left
+ =>
+ -- The result is of maximal length and ends by the last characters
+ -- of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ (if Before <= Super_Length (Source'Old) then
+ String'(Super_Slice (Source,
+ Source.Max_Length - Super_Length (Source'Old) + Before,
+ Source.Max_Length)) =
+ Super_Slice (Source'Old,
+ Before, Super_Length (Source'Old)))
+
+ -- Depending on when we reach Max_Length, either the first part
+ -- of Source is fully dropped and New_Item is partly dropped, or
+ -- New_Item is fully added and the first part of Source is partly
+ -- dropped.
+
+ and then
+ (if Source.Max_Length - Super_Length (Source'Old) - 1 + Before
+ < New_Item'Length
+ then
+ -- The first characters of New_Item are dropped
+
+ (if Super_Length (Source'Old) - Before + 1 < Source.Max_Length
+ then
+ Super_Slice (Source,
+ 1, Source.Max_Length - Super_Length (Source'Old)
+ - 1 + Before) =
+ New_Item
+ (New_Item'Last - Source.Max_Length
+ + Super_Length (Source'Old) - Before + 2
+ .. New_Item'Last))
+
+ else -- New_Item is added to the result
+
+ Super_Slice (Source,
+ Source.Max_Length - Super_Length (Source'Old)
+ - New_Item'Length + Before,
+ Source.Max_Length - Super_Length (Source'Old) - 1 + Before)
+ = New_Item
+
+ -- The first characters of Source (1 .. Before - 1) are
+ -- dropped.
+
+ and then
+ String'(Super_Slice (Source, 1,
+ Source.Max_Length - Super_Length (Source'Old)
+ - New_Item'Length - 1 + Before)) =
+ Super_Slice (Source'Old,
+ Super_Length (Source'Old)
+ - Source.Max_Length + New_Item'Length + 1,
+ Before - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source, 1, Before - 1)) =
+ Super_Slice (Source'Old, 1, Before - 1)
+
+ -- Depending on when we reach Max_Length, either the last part
+ -- of Source is fully dropped and New_Item is partly dropped, or
+ -- New_Item is fully added and the last part of Source is partly
+ -- dropped.
+
+ and then
+ (if Before - 1 >= Source.Max_Length - New_Item'Length then
+
+ -- The last characters of New_Item are dropped
+
+ Super_Slice (Source, Before, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Before + New_Item'First)
+
+ else -- New_Item is fully added
+
+ Super_Slice (Source, Before, Before + New_Item'Length - 1) =
+ New_Item
+
+ -- Then Source starting from Before is added but the
+ -- last characters are dropped.
+
+ and then
+ String'(Super_Slice (Source,
+ Before + New_Item'Length, Source.Max_Length)) =
+ Super_Slice (Source'Old,
+ Before, Source.Max_Length - New_Item'Length))),
+ Global => null;
function Super_Overwrite
(Source : Super_String;
Position : Positive;
New_Item : String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ Position - 1 <= Super_Length (Source)
+ and then (if New_Item'Length > Source.Max_Length - (Position - 1)
+ then Drop /= Error),
+ Post => Super_Overwrite'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Position - 1 <= Source.Max_Length - New_Item'Length
+ =>
+ -- The length is unchanged, unless New_Item overwrites further than
+ -- the end of Source. In this contract case, we suppose New_Item
+ -- doesn't overwrite further than Max_Length.
+
+ Super_Length (Super_Overwrite'Result) =
+ Integer'Max (Super_Length (Source), Position - 1 + New_Item'Length)
+ and then
+ String'(Super_Slice (Super_Overwrite'Result, 1, Position - 1)) =
+ Super_Slice (Source, 1, Position - 1)
+ and then Super_Slice (Super_Overwrite'Result,
+ Position, Position - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Position - 1 + New_Item'Length < Super_Length (Source) then
+
+ -- There are some unchanged characters of Source remaining
+ -- after New_Item.
+
+ String'(Super_Slice (Super_Overwrite'Result,
+ Position + New_Item'Length, Super_Length (Source))) =
+ Super_Slice (Source,
+ Position + New_Item'Length, Super_Length (Source))),
+
+ Position - 1 > Source.Max_Length - New_Item'Length and then Drop = Left
+ =>
+ Super_Length (Super_Overwrite'Result) = Source.Max_Length
+
+ -- If a part of the result has to be dropped, it means New_Item is
+ -- overwriting further than the end of Source. Thus the result is
+ -- necessarily ending by New_Item. However, we don't know whether
+ -- New_Item covers all Max_Length characters or some characters of
+ -- Source are remaining at the left.
+
+ and then
+ (if New_Item'Length > Source.Max_Length then
+
+ -- New_Item covers all Max_Length characters
+
+ Super_To_String (Super_Overwrite'Result) =
+ New_Item
+ (New_Item'Last - Source.Max_Length + 1 .. New_Item'Last)
+ else
+ -- New_Item fully appears at the end
+
+ Super_Slice (Super_Overwrite'Result,
+ Source.Max_Length - New_Item'Length + 1,
+ Source.Max_Length) =
+ New_Item
+
+ -- The left of Source is cut
+
+ and then
+ String'(Super_Slice (Super_Overwrite'Result,
+ 1, Source.Max_Length - New_Item'Length)) =
+ Super_Slice (Source,
+ Position - Source.Max_Length + New_Item'Length,
+ Position - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Super_Length (Super_Overwrite'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Overwrite'Result, 1, Position - 1)) =
+ Super_Slice (Source, 1, Position - 1)
+
+ -- Then New_Item is written until Max_Length
+
+ and then Super_Slice (Super_Overwrite'Result,
+ Position, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Position + New_Item'First)),
+ Global => null;
procedure Super_Overwrite
(Source : in out Super_String;
Position : Positive;
New_Item : String;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre =>
+ Position - 1 <= Super_Length (Source)
+ and then (if New_Item'Length > Source.Max_Length - (Position - 1)
+ then Drop /= Error),
+ Contract_Cases =>
+ (Position - 1 <= Source.Max_Length - New_Item'Length
+ =>
+ -- The length is unchanged, unless New_Item overwrites further than
+ -- the end of Source. In this contract case, we suppose New_Item
+ -- doesn't overwrite further than Max_Length.
+
+ Super_Length (Source) = Integer'Max
+ (Super_Length (Source'Old), Position - 1 + New_Item'Length)
+ and then
+ String'(Super_Slice (Source, 1, Position - 1)) =
+ Super_Slice (Source'Old, 1, Position - 1)
+ and then Super_Slice (Source,
+ Position, Position - 1 + New_Item'Length) =
+ New_Item
+ and then
+ (if Position - 1 + New_Item'Length < Super_Length (Source'Old)
+ then
+ -- There are some unchanged characters of Source remaining
+ -- after New_Item.
+
+ String'(Super_Slice (Source,
+ Position + New_Item'Length, Super_Length (Source'Old))) =
+ Super_Slice (Source'Old,
+ Position + New_Item'Length, Super_Length (Source'Old))),
+
+ Position - 1 > Source.Max_Length - New_Item'Length and then Drop = Left
+ =>
+ Super_Length (Source) = Source.Max_Length
+
+ -- If a part of the result has to be dropped, it means New_Item is
+ -- overwriting further than the end of Source. Thus the result is
+ -- necessarily ending by New_Item. However, we don't know whether
+ -- New_Item covers all Max_Length characters or some characters of
+ -- Source are remaining at the left.
+
+ and then
+ (if New_Item'Length > Source.Max_Length then
+
+ -- New_Item covers all Max_Length characters
+
+ Super_To_String (Source) =
+ New_Item
+ (New_Item'Last - Source.Max_Length + 1 .. New_Item'Last)
+ else
+ -- New_Item fully appears at the end
+
+ Super_Slice (Source,
+ Source.Max_Length - New_Item'Length + 1,
+ Source.Max_Length) =
+ New_Item
+
+ -- The left of Source is cut
+
+ and then
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - New_Item'Length)) =
+ Super_Slice (Source'Old,
+ Position - Source.Max_Length + New_Item'Length,
+ Position - 1)),
+
+ others -- Drop = Right
+ =>
+ -- The result is of maximal length and starts by the first
+ -- characters of Source.
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source, 1, Position - 1)) =
+ Super_Slice (Source'Old, 1, Position - 1)
+
+ -- New_Item is written until Max_Length
+
+ and then Super_Slice (Source, Position, Source.Max_Length) =
+ New_Item (New_Item'First
+ .. Source.Max_Length - Position + New_Item'First)),
+ Global => null;
function Super_Delete
(Source : Super_String;
From : Positive;
- Through : Natural) return Super_String;
+ Through : Natural) return Super_String
+ with
+ Pre =>
+ (if Through >= From then From - 1 <= Super_Length (Source)),
+ Post => Super_Delete'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Through >= From =>
+ Super_Length (Super_Delete'Result) =
+ From - 1 + Natural'Max (Super_Length (Source) - Through, 0)
+ and then
+ String'(Super_Slice (Super_Delete'Result, 1, From - 1)) =
+ Super_Slice (Source, 1, From - 1)
+ and then
+ (if Through < Super_Length (Source) then
+ String'(Super_Slice (Super_Delete'Result,
+ From, Super_Length (Super_Delete'Result))) =
+ Super_Slice (Source, Through + 1, Super_Length (Source))),
+ others =>
+ Super_Delete'Result = Source),
+ Global => null;
procedure Super_Delete
(Source : in out Super_String;
From : Positive;
- Through : Natural);
+ Through : Natural)
+ with
+ Pre =>
+ (if Through >= From then From - 1 <= Super_Length (Source)),
+ Contract_Cases =>
+ (Through >= From =>
+ Super_Length (Source) =
+ From - 1 + Natural'Max (Super_Length (Source'Old) - Through, 0)
+ and then
+ String'(Super_Slice (Source, 1, From - 1)) =
+ Super_Slice (Source'Old, 1, From - 1)
+ and then
+ (if Through < Super_Length (Source) then
+ String'(Super_Slice (Source, From, Super_Length (Source))) =
+ Super_Slice (Source'Old,
+ Through + 1, Super_Length (Source'Old))),
+ others =>
+ Source = Source'Old),
+ Global => null;
---------------------------------
-- String Selector Subprograms --
@@ -388,45 +2180,376 @@ package Ada.Strings.Superbounded is
function Super_Trim
(Source : Super_String;
- Side : Trim_End) return Super_String;
+ Side : Trim_End) return Super_String
+ with
+ Post => Super_Trim'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+
+ -- If all characters in Source are Space, the returned string is empty
+
+ ((for all C of Super_To_String (Source) => C = ' ')
+ =>
+ Super_Length (Super_Trim'Result) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then 1
+ else Super_Index_Non_Blank (Source, Forward));
+ High : constant Positive :=
+ (if Side = Left then Super_Length (Source)
+ else Super_Index_Non_Blank (Source, Backward));
+ begin
+ Super_To_String (Super_Trim'Result) =
+ Super_Slice (Source, Low, High))),
+ Global => null;
procedure Super_Trim
(Source : in out Super_String;
- Side : Trim_End);
+ Side : Trim_End)
+ with
+ Contract_Cases =>
+
+ -- If all characters in Source are Space, the returned string is empty
+
+ ((for all C of Super_To_String (Source) => C = ' ')
+ =>
+ Super_Length (Source) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ (if Side = Right then 1
+ else Super_Index_Non_Blank (Source'Old, Forward));
+ High : constant Positive :=
+ (if Side = Left then Super_Length (Source'Old)
+ else Super_Index_Non_Blank (Source'Old, Backward));
+ begin
+ Super_To_String (Source) = Super_Slice (Source'Old, Low, High))),
+ Global => null;
function Super_Trim
(Source : Super_String;
Left : Maps.Character_Set;
- Right : Maps.Character_Set) return Super_String;
+ Right : Maps.Character_Set) return Super_String
+ with
+ Post => Super_Trim'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+
+ -- If all characters in Source are contained in one of the sets Left or
+ -- Right, then the returned string is empty.
+
+ ((for all C of Super_To_String (Source) => Maps.Is_In (C, Left))
+ or else
+ (for all C of Super_To_String (Source) => Maps.Is_In (C, Right))
+ =>
+ Super_Length (Super_Trim'Result) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ Super_Index (Source, Left, Outside, Forward);
+ High : constant Positive :=
+ Super_Index (Source, Right, Outside, Backward);
+ begin
+ Super_To_String (Super_Trim'Result) =
+ Super_Slice (Source, Low, High))),
+ Global => null;
procedure Super_Trim
(Source : in out Super_String;
Left : Maps.Character_Set;
- Right : Maps.Character_Set);
+ Right : Maps.Character_Set)
+ with
+ Contract_Cases =>
+
+ -- If all characters in Source are contained in one of the sets Left or
+ -- Right, then the returned string is empty.
+
+ ((for all C of Super_To_String (Source) => Maps.Is_In (C, Left))
+ or else
+ (for all C of Super_To_String (Source) => Maps.Is_In (C, Right))
+ =>
+ Super_Length (Source) = 0,
+
+ -- Otherwise, the returned string is a slice of Source
+
+ others
+ =>
+ (declare
+ Low : constant Positive :=
+ Super_Index (Source'Old, Left, Outside, Forward);
+ High : constant Positive :=
+ Super_Index (Source'Old, Right, Outside, Backward);
+ begin
+ Super_To_String (Source) = Super_Slice (Source'Old, Low, High))),
+ Global => null;
function Super_Head
(Source : Super_String;
Count : Natural;
Pad : Character := Space;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre => (if Count > Source.Max_Length then Drop /= Error),
+ Post => Super_Head'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Count <= Super_Length (Source)
+ =>
+ -- Source is cut
+
+ Super_To_String (Super_Head'Result) = Super_Slice (Source, 1, Count),
+ Count > Super_Length (Source) and then Count <= Source.Max_Length
+ =>
+ -- Source is followed by Pad characters
+
+ Super_Length (Super_Head'Result) = Count
+ and then
+ Super_Slice (Super_Head'Result, 1, Super_Length (Source)) =
+ Super_To_String (Source)
+ and then
+ String'(Super_Slice (Super_Head'Result,
+ Super_Length (Source) + 1, Count)) =
+ (1 .. Count - Super_Length (Source) => Pad),
+ Count > Source.Max_Length and then Drop = Right
+ =>
+ -- Source is followed by Pad characters
+
+ Super_Length (Super_Head'Result) = Source.Max_Length
+ and then
+ Super_Slice (Super_Head'Result, 1, Super_Length (Source)) =
+ Super_To_String (Source)
+ and then
+ String'(Super_Slice (Super_Head'Result,
+ Super_Length (Source) + 1, Source.Max_Length)) =
+ (1 .. Source.Max_Length - Super_Length (Source) => Pad),
+ Count - Super_Length (Source) > Source.Max_Length and then Drop = Left
+ =>
+ -- Source is fully dropped on the left
+
+ Super_To_String (Super_Head'Result) =
+ (1 .. Source.Max_Length => Pad),
+ others
+ =>
+ -- Source is partly dropped on the left
+
+ Super_Length (Super_Head'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Head'Result,
+ 1, Source.Max_Length - Count + Super_Length (Source))) =
+ Super_Slice (Source,
+ Count - Source.Max_Length + 1, Super_Length (Source))
+ and then
+ String'(Super_Slice (Super_Head'Result,
+ Source.Max_Length - Count + Super_Length (Source) + 1,
+ Source.Max_Length)) =
+ (1 .. Count - Super_Length (Source) => Pad)),
+ Global => null;
procedure Super_Head
(Source : in out Super_String;
Count : Natural;
Pad : Character := Space;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre => (if Count > Source.Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count <= Super_Length (Source)
+ =>
+ -- Source is cut
+
+ Super_To_String (Source) = Super_Slice (Source'Old, 1, Count),
+ Count > Super_Length (Source) and then Count <= Source.Max_Length
+ =>
+ -- Source is followed by Pad characters
+
+ Super_Length (Source) = Count
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ String'(Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Count)) =
+ (1 .. Count - Super_Length (Source'Old) => Pad),
+ Count > Source.Max_Length and then Drop = Right
+ =>
+ -- Source is followed by Pad characters
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ Super_Slice (Source, 1, Super_Length (Source'Old)) =
+ Super_To_String (Source'Old)
+ and then
+ String'(Super_Slice (Source,
+ Super_Length (Source'Old) + 1, Source.Max_Length)) =
+ (1 .. Source.Max_Length - Super_Length (Source'Old) => Pad),
+ Count - Super_Length (Source) > Source.Max_Length and then Drop = Left
+ =>
+ -- Source is fully dropped on the left
+
+ Super_To_String (Source) = (1 .. Source.Max_Length => Pad),
+ others
+ =>
+ -- Source is partly dropped on the left
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - Count + Super_Length (Source'Old))) =
+ Super_Slice (Source'Old,
+ Count - Source.Max_Length + 1, Super_Length (Source'Old))
+ and then
+ String'(Super_Slice (Source,
+ Source.Max_Length - Count + Super_Length (Source'Old) + 1,
+ Source.Max_Length)) =
+ (1 .. Count - Super_Length (Source'Old) => Pad)),
+ Global => null;
function Super_Tail
(Source : Super_String;
Count : Natural;
Pad : Character := Space;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre => (if Count > Source.Max_Length then Drop /= Error),
+ Post => Super_Tail'Result.Max_Length = Source.Max_Length,
+ Contract_Cases =>
+ (Count < Super_Length (Source)
+ =>
+ -- Source is cut
+
+ (if Count > 0 then
+ Super_To_String (Super_Tail'Result) =
+ Super_Slice (Source,
+ Super_Length (Source) - Count + 1, Super_Length (Source))
+ else Super_Length (Super_Tail'Result) = 0),
+ Count >= Super_Length (Source) and then Count < Source.Max_Length
+ =>
+ -- Source is preceded by Pad characters
+
+ Super_Length (Super_Tail'Result) = Count
+ and then
+ String'(Super_Slice (Super_Tail'Result,
+ 1, Count - Super_Length (Source))) =
+ (1 .. Count - Super_Length (Source) => Pad)
+ and then
+ Super_Slice (Super_Tail'Result,
+ Count - Super_Length (Source) + 1, Count) =
+ Super_To_String (Source),
+ Count >= Source.Max_Length and then Drop = Left
+ =>
+ -- Source is preceded by Pad characters
+
+ Super_Length (Super_Tail'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Tail'Result,
+ 1, Source.Max_Length - Super_Length (Source))) =
+ (1 .. Source.Max_Length - Super_Length (Source) => Pad)
+ and then
+ (if Super_Length (Source) > 0 then
+ Super_Slice (Super_Tail'Result,
+ Source.Max_Length - Super_Length (Source) + 1,
+ Source.Max_Length) =
+ Super_To_String (Source)),
+ Count - Super_Length (Source) >= Source.Max_Length
+ and then Drop /= Left
+ =>
+ -- Source is fully dropped on the right
+
+ Super_To_String (Super_Tail'Result) =
+ (1 .. Source.Max_Length => Pad),
+ others
+ =>
+ -- Source is partly dropped on the right
+
+ Super_Length (Super_Tail'Result) = Source.Max_Length
+ and then
+ String'(Super_Slice (Super_Tail'Result,
+ 1, Count - Super_Length (Source))) =
+ (1 .. Count - Super_Length (Source) => Pad)
+ and then
+ String'(Super_Slice (Super_Tail'Result,
+ Count - Super_Length (Source) + 1, Source.Max_Length)) =
+ Super_Slice (Source,
+ 1, Source.Max_Length - Count + Super_Length (Source))),
+ Global => null;
procedure Super_Tail
(Source : in out Super_String;
Count : Natural;
Pad : Character := Space;
- Drop : Truncation := Error);
+ Drop : Truncation := Error)
+ with
+ Pre => (if Count > Source.Max_Length then Drop /= Error),
+ Contract_Cases =>
+ (Count < Super_Length (Source)
+ =>
+ -- Source is cut
+
+ (if Count > 0 then
+ Super_To_String (Source) =
+ Super_Slice (Source'Old,
+ Super_Length (Source'Old) - Count + 1,
+ Super_Length (Source'Old))
+ else Super_Length (Source) = 0),
+ Count >= Super_Length (Source) and then Count < Source.Max_Length
+ =>
+ -- Source is preceded by Pad characters
+
+ Super_Length (Source) = Count
+ and then
+ String'(Super_Slice (Source,
+ 1, Count - Super_Length (Source'Old))) =
+ (1 .. Count - Super_Length (Source'Old) => Pad)
+ and then
+ Super_Slice (Source,
+ Count - Super_Length (Source'Old) + 1, Count) =
+ Super_To_String (Source'Old),
+ Count >= Source.Max_Length and then Drop = Left
+ =>
+ -- Source is preceded by Pad characters
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source,
+ 1, Source.Max_Length - Super_Length (Source'Old))) =
+ (1 .. Source.Max_Length - Super_Length (Source'Old) => Pad)
+ and then
+ (if Super_Length (Source'Old) > 0 then
+ Super_Slice (Source,
+ Source.Max_Length - Super_Length (Source'Old) + 1,
+ Source.Max_Length) =
+ Super_To_String (Source'Old)),
+ Count - Super_Length (Source) >= Source.Max_Length
+ and then Drop /= Left
+ =>
+ -- Source is fully dropped on the right
+
+ Super_To_String (Source) = (1 .. Source.Max_Length => Pad),
+ others
+ =>
+ -- Source is partly dropped on the right
+
+ Super_Length (Source) = Source.Max_Length
+ and then
+ String'(Super_Slice (Source,
+ 1, Count - Super_Length (Source'Old))) =
+ (1 .. Count - Super_Length (Source'Old) => Pad)
+ and then
+ String'(Super_Slice (Source,
+ Count - Super_Length (Source'Old) + 1, Source.Max_Length)) =
+ Super_Slice (Source'Old,
+ 1, Source.Max_Length - Count + Super_Length (Source'Old))),
+ Global => null;
------------------------------------
-- String Constructor Subprograms --
@@ -439,37 +2562,135 @@ package Ada.Strings.Superbounded is
function Times
(Left : Natural;
Right : Character;
- Max_Length : Positive) return Super_String;
+ Max_Length : Positive) return Super_String
+ with
+ Pre => Left <= Max_Length,
+ Post => Times'Result.Max_Length = Max_Length
+ and then Super_To_String (Times'Result) = (1 .. Left => Right),
+ Global => null;
-- Note the additional parameter Max_Length
function Times
(Left : Natural;
Right : String;
- Max_Length : Positive) return Super_String;
+ Max_Length : Positive) return Super_String
+ with
+ Pre => (if Left /= 0 then Right'Length <= Max_Length / Left),
+ Post => Times'Result.Max_Length = Max_Length
+ and then Super_Length (Times'Result) = Left * Right'Length
+ and then
+ (if Right'Length > 0 then
+ (for all K in 1 .. Left * Right'Length =>
+ Super_Element (Times'Result, K) =
+ Right (Right'First + (K - 1) mod Right'Length))),
+ Global => null;
-- Note the additional parameter Max_Length
function Times
(Left : Natural;
- Right : Super_String) return Super_String;
+ Right : Super_String) return Super_String
+ with
+ Pre =>
+ (if Left /= 0 then Super_Length (Right) <= Right.Max_Length / Left),
+ Post => Times'Result.Max_Length = Right.Max_Length
+ and then Super_Length (Times'Result) = Left * Super_Length (Right)
+ and then
+ (if Super_Length (Right) > 0 then
+ (for all K in 1 .. Left * Super_Length (Right) =>
+ Super_Element (Times'Result, K) =
+ Super_Element (Right, 1 + (K - 1) mod Super_Length (Right)))),
+ Global => null;
function Super_Replicate
(Count : Natural;
Item : Character;
Drop : Truncation := Error;
- Max_Length : Positive) return Super_String;
+ Max_Length : Positive) return Super_String
+ with
+ Pre => (if Count > Max_Length then Drop /= Error),
+ Post => Super_Replicate'Result.Max_Length = Max_Length
+ and then Super_To_String (Super_Replicate'Result) =
+ (1 .. Natural'Min (Max_Length, Count) => Item),
+ Global => null;
-- Note the additional parameter Max_Length
function Super_Replicate
(Count : Natural;
Item : String;
Drop : Truncation := Error;
- Max_Length : Positive) return Super_String;
+ Max_Length : Positive) return Super_String
+ with
+ Pre =>
+ (if Count /= 0 and then Item'Length > Max_Length / Count
+ then Drop /= Error),
+ Post => Super_Replicate'Result.Max_Length = Max_Length,
+ Contract_Cases =>
+ (Count = 0 or else Item'Length <= Max_Length / Count
+ =>
+ Super_Length (Super_Replicate'Result) = Count * Item'Length
+ and then
+ (if Item'Length > 0 then
+ (for all K in 1 .. Count * Item'Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Item (Item'First + (K - 1) mod Item'Length))),
+ Count /= 0
+ and then Item'Length > Max_Length / Count
+ and then Drop = Right
+ =>
+ Super_Length (Super_Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Item (Item'First + (K - 1) mod Item'Length)),
+ others -- Drop = Left
+ =>
+ Super_Length (Super_Replicate'Result) = Max_Length
+ and then
+ (for all K in 1 .. Max_Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Item (Item'Last - (Max_Length - K) mod Item'Length))),
+ Global => null;
-- Note the additional parameter Max_Length
function Super_Replicate
(Count : Natural;
Item : Super_String;
- Drop : Truncation := Error) return Super_String;
+ Drop : Truncation := Error) return Super_String
+ with
+ Pre =>
+ (if Count /= 0
+ and then Super_Length (Item) > Item.Max_Length / Count
+ then Drop /= Error),
+ Post => Super_Replicate'Result.Max_Length = Item.Max_Length,
+ Contract_Cases =>
+ ((if Count /= 0 then Super_Length (Item) <= Item.Max_Length / Count)
+ =>
+ Super_Length (Super_Replicate'Result) = Count * Super_Length (Item)
+ and then
+ (if Super_Length (Item) > 0 then
+ (for all K in 1 .. Count * Super_Length (Item) =>
+ Super_Element (Super_Replicate'Result, K) =
+ Super_Element (Item,
+ 1 + (K - 1) mod Super_Length (Item)))),
+ Count /= 0
+ and then Super_Length (Item) > Item.Max_Length / Count
+ and then Drop = Right
+ =>
+ Super_Length (Super_Replicate'Result) = Item.Max_Length
+ and then
+ (for all K in 1 .. Item.Max_Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Super_Element (Item, 1 + (K - 1) mod Super_Length (Item))),
+ others -- Drop = Left
+ =>
+ Super_Length (Super_Replicate'Result) = Item.Max_Length
+ and then
+ (for all K in 1 .. Item.Max_Length =>
+ Super_Element (Super_Replicate'Result, K) =
+ Super_Element (Item,
+ Super_Length (Item)
+ - (Item.Max_Length - K) mod Super_Length (Item)))),
+ Global => null;
private
-- Pragma Inline declarations
diff --git a/gcc/ada/libgnat/a-strunb.ads b/gcc/ada/libgnat/a-strunb.ads
index 13c7612..b3050fd 100644
--- a/gcc/ada/libgnat/a-strunb.ads
+++ b/gcc/ada/libgnat/a-strunb.ads
@@ -53,11 +53,13 @@ private with Ada.Strings.Text_Buffers;
-- and selector operations are provided.
package Ada.Strings.Unbounded with
+ SPARK_Mode,
Initial_Condition => Length (Null_Unbounded_String) = 0
is
pragma Preelaborate;
- type Unbounded_String is private;
+ type Unbounded_String is private with
+ Default_Initial_Condition => Length (Unbounded_String) = 0;
pragma Preelaborable_Initialization (Unbounded_String);
Null_Unbounded_String : constant Unbounded_String;
@@ -73,7 +75,7 @@ is
-- Provides a (nonprivate) access type for explicit processing of
-- unbounded-length strings.
- procedure Free (X : in out String_Access);
+ procedure Free (X : in out String_Access) with SPARK_Mode => Off;
-- Performs an unchecked deallocation of an object of type String_Access
--------------------------------------------------------
@@ -732,6 +734,8 @@ is
-- strings applied to the string represented by Source's original value.
private
+ pragma SPARK_Mode (Off); -- Controlled types are not in SPARK
+
pragma Inline (Length);
package AF renames Ada.Finalization;
diff --git a/gcc/ada/libgnat/a-strunb__shared.ads b/gcc/ada/libgnat/a-strunb__shared.ads
index 2091bde..2cf6780 100644
--- a/gcc/ada/libgnat/a-strunb__shared.ads
+++ b/gcc/ada/libgnat/a-strunb__shared.ads
@@ -85,7 +85,8 @@ package Ada.Strings.Unbounded with
is
pragma Preelaborate;
- type Unbounded_String is private;
+ type Unbounded_String is private with
+ Default_Initial_Condition => Length (Unbounded_String) = 0;
pragma Preelaborable_Initialization (Unbounded_String);
Null_Unbounded_String : constant Unbounded_String;
diff --git a/gcc/ada/libgnat/a-textio.adb b/gcc/ada/libgnat/a-textio.adb
index 717f529..8667360 100644
--- a/gcc/ada/libgnat/a-textio.adb
+++ b/gcc/ada/libgnat/a-textio.adb
@@ -44,6 +44,7 @@ pragma Elaborate_All (System.File_IO);
-- Needed because of calls to Chain_File in package body elaboration
package body Ada.Text_IO with
+ SPARK_Mode => Off,
Refined_State => (File_System => (Standard_In,
Standard_Out,
Standard_Err,
diff --git a/gcc/ada/libgnat/a-textio.ads b/gcc/ada/libgnat/a-textio.ads
index a06a35c..f94c92d 100644
--- a/gcc/ada/libgnat/a-textio.ads
+++ b/gcc/ada/libgnat/a-textio.ads
@@ -56,8 +56,9 @@ with System.File_Control_Block;
with System.WCh_Con;
package Ada.Text_IO with
- Abstract_State => (File_System),
- Initializes => (File_System),
+ SPARK_Mode,
+ Abstract_State => File_System,
+ Initializes => File_System,
Initial_Condition => Line_Length = 0 and Page_Length = 0
is
pragma Elaborate_Body;
@@ -547,6 +548,7 @@ is
Layout_Error : exception renames IO_Exceptions.Layout_Error;
private
+ pragma SPARK_Mode (Off);
-- The following procedures have a File_Type formal of mode IN OUT because
-- they may close the original file. The Close operation may raise an
diff --git a/gcc/ada/libgnat/a-zchhan.adb b/gcc/ada/libgnat/a-zchhan.adb
index 3f2a91b..61405f7 100644
--- a/gcc/ada/libgnat/a-zchhan.adb
+++ b/gcc/ada/libgnat/a-zchhan.adb
@@ -33,6 +33,15 @@ with Ada.Wide_Wide_Characters.Unicode; use Ada.Wide_Wide_Characters.Unicode;
package body Ada.Wide_Wide_Characters.Handling is
+ ---------------------------
+ -- Character_Set_Version --
+ ---------------------------
+
+ function Character_Set_Version return String is
+ begin
+ return "Unicode 4.0";
+ end Character_Set_Version;
+
---------------------
-- Is_Alphanumeric --
---------------------
@@ -42,6 +51,13 @@ package body Ada.Wide_Wide_Characters.Handling is
return Is_Letter (Item) or else Is_Digit (Item);
end Is_Alphanumeric;
+ --------------
+ -- Is_Basic --
+ --------------
+
+ function Is_Basic (Item : Wide_Wide_Character) return Boolean
+ renames Ada.Wide_Wide_Characters.Unicode.Is_Basic;
+
----------------
-- Is_Control --
----------------
@@ -191,4 +207,22 @@ package body Ada.Wide_Wide_Characters.Handling is
return Result;
end To_Upper;
+ --------------
+ -- To_Basic --
+ --------------
+
+ function To_Basic (Item : Wide_Wide_Character) return Wide_Wide_Character
+ renames Ada.Wide_Wide_Characters.Unicode.To_Basic;
+
+ function To_Basic (Item : Wide_Wide_String) return Wide_Wide_String is
+ Result : Wide_Wide_String (Item'Range);
+
+ begin
+ for J in Result'Range loop
+ Result (J) := To_Basic (Item (J));
+ end loop;
+
+ return Result;
+ end To_Basic;
+
end Ada.Wide_Wide_Characters.Handling;
diff --git a/gcc/ada/libgnat/a-zchhan.ads b/gcc/ada/libgnat/a-zchhan.ads
index 74fab2a..6ebd1a8 100644
--- a/gcc/ada/libgnat/a-zchhan.ads
+++ b/gcc/ada/libgnat/a-zchhan.ads
@@ -15,10 +15,12 @@
package Ada.Wide_Wide_Characters.Handling is
pragma Pure;
- -- This package is clearly intended to be Pure, by analogy with the
- -- base Ada.Characters.Handling package. The version in the RM does
- -- not yet have this pragma, but that is a clear omission. This will
- -- be fixed in a future version of AI05-0266-1.
+
+ function Character_Set_Version return String;
+ pragma Inline (Character_Set_Version);
+ -- Returns an implementation-defined identifier that identifies the version
+ -- of the character set standard that is used for categorizing characters
+ -- by the implementation. For GNAT this is "Unicode v.v".
function Is_Control (Item : Wide_Wide_Character) return Boolean;
pragma Inline (Is_Control);
@@ -42,6 +44,12 @@ package Ada.Wide_Wide_Characters.Handling is
-- Returns True if the Wide_Wide_Character designated by Item is
-- categorized as letter_uppercase, otherwise returns false.
+ function Is_Basic (Item : Wide_Wide_Character) return Boolean;
+ pragma Inline (Is_Basic);
+ -- Returns True if the Wide_Wide_Character designated by Item has no
+ -- Decomposition Mapping in the code charts of ISO/IEC 10646:2017,
+ -- otherwise returns False.
+
function Is_Digit (Item : Wide_Wide_Character) return Boolean;
pragma Inline (Is_Digit);
-- Returns True if the Wide_Wide_Character designated by Item is
@@ -135,4 +143,17 @@ package Ada.Wide_Wide_Characters.Handling is
-- designated by Item. The result is the null Wide_Wide_String if the value
-- of the formal parameter is the null Wide_Wide_String.
+ function To_Basic (Item : Wide_Wide_Character) return Wide_Wide_Character;
+ pragma Inline (To_Basic);
+ -- Returns the Wide_Wide_Character whose code point is given
+ -- by the first value of its Decomposition Mapping in the code charts
+ -- of ISO/IEC 10646:2017 if any, returns Item otherwise.
+
+ function To_Basic (Item : Wide_Wide_String) return Wide_Wide_String;
+ -- Returns the result of applying the To_Basic conversion to each
+ -- Wide_Wide_Character element of the Wide_Wide_String designated by Item.
+ -- The result is the null Wide_Wide_String if the value of the formal
+ -- parameter is the null Wide_Wide_String. The lower bound of the result
+ -- Wide_Wide_String is 1.
+
end Ada.Wide_Wide_Characters.Handling;
diff --git a/gcc/ada/libgnat/a-zchuni.adb b/gcc/ada/libgnat/a-zchuni.adb
index 2bbe584..3c6e720 100644
--- a/gcc/ada/libgnat/a-zchuni.adb
+++ b/gcc/ada/libgnat/a-zchuni.adb
@@ -43,6 +43,15 @@ package body Ada.Wide_Wide_Characters.Unicode is
end Get_Category;
--------------
+ -- Is_Basic --
+ --------------
+
+ function Is_Basic (U : Wide_Wide_Character) return Boolean is
+ begin
+ return G.Is_UTF_32_Basic (Wide_Wide_Character'Pos (U));
+ end Is_Basic;
+
+ --------------
-- Is_Digit --
--------------
@@ -158,6 +167,16 @@ package body Ada.Wide_Wide_Characters.Unicode is
return G.Is_UTF_32_Space (G.Category (C));
end Is_Space;
+ --------------
+ -- To_Basic --
+ --------------
+
+ function To_Basic (U : Wide_Wide_Character) return Wide_Wide_Character is
+ begin
+ return Wide_Wide_Character'Val
+ (G.UTF_32_To_Basic (Wide_Wide_Character'Pos (U)));
+ end To_Basic;
+
-------------------
-- To_Lower_Case --
-------------------
diff --git a/gcc/ada/libgnat/a-zchuni.ads b/gcc/ada/libgnat/a-zchuni.ads
index 51f7c92..0030fd1 100644
--- a/gcc/ada/libgnat/a-zchuni.ads
+++ b/gcc/ada/libgnat/a-zchuni.ads
@@ -177,6 +177,18 @@ package Ada.Wide_Wide_Characters.Unicode is
-- in the list of categories above. This means that these characters can
-- be included in character and string literals.
+ function Is_Basic (U : Wide_Wide_Character) return Boolean;
+ pragma Inline (Is_Basic);
+ -- Returns True if the Wide_Wide_Character designated by Item has no
+ -- Decomposition Mapping in the code charts of ISO/IEC 10646:2017,
+ -- otherwise returns False.
+
+ function To_Basic (U : Wide_Wide_Character) return Wide_Wide_Character;
+ pragma Inline (To_Basic);
+ -- Returns the Wide_Wide_Character whose code point is given by the first
+ -- value of its Decomposition Mapping in the code charts of
+ -- ISO/IEC 10646:2017 if any, returns Item otherwise.
+
-- The following function is used to fold to upper case, as required by
-- the Ada 2005 standard rules for identifier case folding. Two
-- identifiers are equivalent if they are identical after folding all
diff --git a/gcc/ada/libgnat/g-forstr.adb b/gcc/ada/libgnat/g-forstr.adb
index 64c4cb6..04539be 100644
--- a/gcc/ada/libgnat/g-forstr.adb
+++ b/gcc/ada/libgnat/g-forstr.adb
@@ -420,11 +420,11 @@ package body GNAT.Formatted_String is
-- Zero padding if required and possible
- if F_Spec.Left_Justify = False
+ if not F_Spec.Left_Justify
and then F_Spec.Zero_Pad
and then F_Spec.Width > Len + Value'First - S
then
- Append (Res, String'((F_Spec.Width - Len + Value'First - S) * '0'));
+ Append (Res, String'((F_Spec.Width - (Len + Value'First - S)) * '0'));
end if;
-- Add the value now
@@ -519,7 +519,7 @@ package body GNAT.Formatted_String is
J := J + 1;
end loop;
- if F (J) /= '%' or else J = F'Last then
+ if J >= F'Last or else F (J) /= '%' then
raise Format_Error with "no format specifier found for parameter"
& Positive'Image (Format.D.Current);
end if;
diff --git a/gcc/ada/libgnat/i-vxwork.ads b/gcc/ada/libgnat/i-vxwork.ads
index c5686bb..0ba1e6e 100644
--- a/gcc/ada/libgnat/i-vxwork.ads
+++ b/gcc/ada/libgnat/i-vxwork.ads
@@ -133,6 +133,9 @@ package Interfaces.VxWorks is
OK : constant STATUS := 0;
ERROR : constant STATUS := -1;
+ type BOOL is new int;
+ -- Equivalent of the C type BOOL
+
type VOIDFUNCPTR is access procedure (parameter : System.Address);
type Interrupt_Vector is new System.Address;
type Exception_Vector is new System.Address;
@@ -145,9 +148,9 @@ package Interfaces.VxWorks is
-- The routine generates a wrapper around the user handler to save and
-- restore context
- function intContext return int;
- -- Binding to the C routine intContext. This function returns 1 only if the
- -- current execution state is in interrupt context.
+ function intContext return BOOL;
+ -- Binding to the C routine intContext. This function returns 1 (TRUE)
+ -- only if the current execution state is in interrupt context.
function intVecGet
(Vector : Interrupt_Vector) return VOIDFUNCPTR;
diff --git a/gcc/ada/libgnat/i-vxwork__x86.ads b/gcc/ada/libgnat/i-vxwork__x86.ads
index ed9bb42..659167f 100644
--- a/gcc/ada/libgnat/i-vxwork__x86.ads
+++ b/gcc/ada/libgnat/i-vxwork__x86.ads
@@ -128,6 +128,9 @@ package Interfaces.VxWorks is
OK : constant STATUS := 0;
ERROR : constant STATUS := -1;
+ type BOOL is new int;
+ -- Equivalent of the C type BOOL
+
type VOIDFUNCPTR is access procedure (parameter : System.Address);
type Interrupt_Vector is new System.Address;
type Exception_Vector is new System.Address;
@@ -140,9 +143,9 @@ package Interfaces.VxWorks is
-- The routine generates a wrapper around the user handler to save and
-- restore context
- function intContext return int;
- -- Binding to the C routine intContext. This function returns 1 only if the
- -- current execution state is in interrupt context.
+ function intContext return BOOL;
+ -- Binding to the C routine intContext. This function returns 1 (TRUE)
+ -- only if the current execution state is in interrupt context.
function intVecGet
(Vector : Interrupt_Vector) return VOIDFUNCPTR;
diff --git a/gcc/ada/libgnat/memtrack.adb b/gcc/ada/libgnat/memtrack.adb
index e622fec..b34ac04 100644
--- a/gcc/ada/libgnat/memtrack.adb
+++ b/gcc/ada/libgnat/memtrack.adb
@@ -69,10 +69,13 @@
pragma Source_File_Name (System.Memory, Body_File_Name => "memtrack.adb");
with Ada.Exceptions;
+with GNAT.IO;
+
with System.Soft_Links;
with System.Traceback;
with System.Traceback_Entries;
-with GNAT.IO;
+with System.CRTL;
+with System.OS_Lib;
with System.OS_Primitives;
package body System.Memory is
@@ -93,30 +96,14 @@ package body System.Memory is
(Ptr : System.Address; Size : size_t) return System.Address;
pragma Import (C, c_realloc, "realloc");
- subtype File_Ptr is System.Address;
-
- function fopen (Path : String; Mode : String) return File_Ptr;
- pragma Import (C, fopen);
-
- procedure OS_Exit (Status : Integer);
- pragma Import (C, OS_Exit, "__gnat_os_exit");
- pragma No_Return (OS_Exit);
-
In_Child_After_Fork : Integer;
pragma Import (C, In_Child_After_Fork, "__gnat_in_child_after_fork");
- procedure fwrite
- (Ptr : System.Address;
- Size : size_t;
- Nmemb : size_t;
- Stream : File_Ptr);
- pragma Import (C, fwrite);
+ subtype File_Ptr is CRTL.FILEs;
- procedure fputc (C : Integer; Stream : File_Ptr);
- pragma Import (C, fputc);
+ procedure Write (Ptr : System.Address; Size : size_t);
- procedure fclose (Stream : File_Ptr);
- pragma Import (C, fclose);
+ procedure Putc (Char : Character);
procedure Finalize;
pragma Export (C, Finalize, "__gnat_finalize");
@@ -210,20 +197,17 @@ package body System.Memory is
Timestamp := System.OS_Primitives.Clock;
Call_Chain
(Tracebk, Max_Call_Stack, Num_Calls, Skip_Frames => 2);
- fputc (Character'Pos ('A'), Gmemfile);
- fwrite (Result'Address, Address_Size, 1, Gmemfile);
- fwrite (Actual_Size'Address, size_t'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
+ Putc ('A');
+ Write (Result'Address, Address_Size);
+ Write (Actual_Size'Address, size_t'Max_Size_In_Storage_Elements);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
+ Write (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements);
for J in Tracebk'First .. Tracebk'First + Num_Calls - 1 loop
declare
Ptr : System.Address := PC_For (Tracebk (J));
begin
- fwrite (Ptr'Address, Address_Size, 1, Gmemfile);
+ Write (Ptr'Address, Address_Size);
end;
end loop;
@@ -246,8 +230,8 @@ package body System.Memory is
procedure Finalize is
begin
- if not Needs_Init then
- fclose (Gmemfile);
+ if not Needs_Init and then CRTL.fclose (Gmemfile) /= 0 then
+ Put_Line ("gmem close error: " & OS_Lib.Errno_Message);
end if;
end Finalize;
@@ -275,18 +259,16 @@ package body System.Memory is
Call_Chain
(Tracebk, Max_Call_Stack, Num_Calls, Skip_Frames => 2);
Timestamp := System.OS_Primitives.Clock;
- fputc (Character'Pos ('D'), Gmemfile);
- fwrite (Addr'Address, Address_Size, 1, Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
+ Putc ('D');
+ Write (Addr'Address, Address_Size);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
+ Write (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements);
for J in Tracebk'First .. Tracebk'First + Num_Calls - 1 loop
declare
Ptr : System.Address := PC_For (Tracebk (J));
begin
- fwrite (Ptr'Address, Address_Size, 1, Gmemfile);
+ Write (Ptr'Address, Address_Size);
end;
end loop;
@@ -304,29 +286,41 @@ package body System.Memory is
procedure Gmem_Initialize is
Timestamp : aliased Duration;
-
+ File_Mode : constant String := "wb" & ASCII.NUL;
begin
if Needs_Init then
Needs_Init := False;
System.OS_Primitives.Initialize;
Timestamp := System.OS_Primitives.Clock;
- Gmemfile := fopen (Gmemfname, "wb" & ASCII.NUL);
+ Gmemfile := CRTL.fopen (Gmemfname'Address, File_Mode'Address);
if Gmemfile = System.Null_Address then
Put_Line ("Couldn't open gnatmem log file for writing");
- OS_Exit (255);
+ OS_Lib.OS_Exit (255);
end if;
declare
S : constant String := "GMEM DUMP" & ASCII.LF;
begin
- fwrite (S'Address, S'Length, 1, Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements,
- 1, Gmemfile);
+ Write (S'Address, S'Length);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
end;
end if;
end Gmem_Initialize;
+ ----------
+ -- Putc --
+ ----------
+
+ procedure Putc (Char : Character) is
+ C : constant Integer := Character'Pos (Char);
+
+ begin
+ if CRTL.fputc (C, Gmemfile) /= C then
+ Put_Line ("gmem fputc error: " & OS_Lib.Errno_Message);
+ end if;
+ end Putc;
+
-------------
-- Realloc --
-------------
@@ -360,18 +354,16 @@ package body System.Memory is
Call_Chain
(Tracebk, Max_Call_Stack, Num_Calls, Skip_Frames => 2);
Timestamp := System.OS_Primitives.Clock;
- fputc (Character'Pos ('D'), Gmemfile);
- fwrite (Addr'Address, Address_Size, 1, Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
+ Putc ('D');
+ Write (Addr'Address, Address_Size);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
+ Write (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements);
for J in Tracebk'First .. Tracebk'First + Num_Calls - 1 loop
declare
Ptr : System.Address := PC_For (Tracebk (J));
begin
- fwrite (Ptr'Address, Address_Size, 1, Gmemfile);
+ Write (Ptr'Address, Address_Size);
end;
end loop;
@@ -381,20 +373,17 @@ package body System.Memory is
-- Log allocation call using the same backtrace
- fputc (Character'Pos ('A'), Gmemfile);
- fwrite (Result'Address, Address_Size, 1, Gmemfile);
- fwrite (Size'Address, size_t'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Timestamp'Address, Duration'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
- fwrite (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements, 1,
- Gmemfile);
+ Putc ('A');
+ Write (Result'Address, Address_Size);
+ Write (Size'Address, size_t'Max_Size_In_Storage_Elements);
+ Write (Timestamp'Address, Duration'Max_Size_In_Storage_Elements);
+ Write (Num_Calls'Address, Integer'Max_Size_In_Storage_Elements);
for J in Tracebk'First .. Tracebk'First + Num_Calls - 1 loop
declare
Ptr : System.Address := PC_For (Tracebk (J));
begin
- fwrite (Ptr'Address, Address_Size, 1, Gmemfile);
+ Write (Ptr'Address, Address_Size);
end;
end loop;
@@ -411,4 +400,22 @@ package body System.Memory is
return Result;
end Realloc;
+ -----------
+ -- Write --
+ -----------
+
+ procedure Write (Ptr : System.Address; Size : size_t) is
+ function fwrite
+ (buffer : System.Address;
+ size : size_t;
+ count : size_t;
+ stream : File_Ptr) return size_t;
+ pragma Import (C, fwrite);
+
+ begin
+ if fwrite (Ptr, Size, 1, Gmemfile) /= 1 then
+ Put_Line ("gmem fwrite error: " & OS_Lib.Errno_Message);
+ end if;
+ end Write;
+
end System.Memory;
diff --git a/gcc/ada/libgnat/s-arit128.ads b/gcc/ada/libgnat/s-arit128.ads
index 6213cfb..fa6fedc 100644
--- a/gcc/ada/libgnat/s-arit128.ads
+++ b/gcc/ada/libgnat/s-arit128.ads
@@ -81,4 +81,11 @@ package System.Arith_128 is
-- then Q is the rounded quotient. The remainder R is not affected by the
-- setting of the Round flag.
+private
+ -- Make it callable from strub contexts.
+ -- There is a matching setting in trans.c,
+ -- for calls issued by Gigi.
+ pragma Machine_Attribute (Multiply_With_Ovflo_Check128,
+ "strub", "callable");
+
end System.Arith_128;
diff --git a/gcc/ada/libgnat/s-arit64.ads b/gcc/ada/libgnat/s-arit64.ads
index c9141f5..68d2149 100644
--- a/gcc/ada/libgnat/s-arit64.ads
+++ b/gcc/ada/libgnat/s-arit64.ads
@@ -93,4 +93,11 @@ package System.Arith_64 is
Round : Boolean) renames Double_Divide64;
-- Renamed procedure to preserve compatibility with earlier versions
+private
+ -- Make it callable from strub contexts.
+ -- There is a matching setting in trans.c,
+ -- for calls issued by Gigi.
+ pragma Machine_Attribute (Multiply_With_Ovflo_Check64,
+ "strub", "callable");
+
end System.Arith_64;
diff --git a/gcc/ada/libgnat/s-imenne.adb b/gcc/ada/libgnat/s-imenne.adb
deleted file mode 100644
index 4ca7a12..0000000
--- a/gcc/ada/libgnat/s-imenne.adb
+++ /dev/null
@@ -1,170 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M . I M G _ E N U M _ N E W --
--- --
--- B o d y --
--- --
--- Copyright (C) 2000-2021, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
-pragma Compiler_Unit_Warning;
-
-with Ada.Unchecked_Conversion;
-
-package body System.Img_Enum_New is
-
- -------------------------
- -- Image_Enumeration_8 --
- -------------------------
-
- procedure Image_Enumeration_8
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address)
- is
- pragma Assert (S'First = 1);
-
- type Natural_8 is range 0 .. 2 ** 7 - 1;
- subtype Names_Index is
- Natural_8 range Natural_8 (Names'First)
- .. Natural_8 (Names'Last) + 1;
- subtype Index is Natural range Natural'First .. Names'Length;
- type Index_Table is array (Index) of Names_Index;
- type Index_Table_Ptr is access Index_Table;
-
- function To_Index_Table_Ptr is
- new Ada.Unchecked_Conversion (System.Address, Index_Table_Ptr);
-
- IndexesT : constant Index_Table_Ptr := To_Index_Table_Ptr (Indexes);
-
- pragma Assert (Pos in IndexesT'Range);
- pragma Assert (Pos + 1 in IndexesT'Range);
-
- Start : constant Natural := Natural (IndexesT (Pos));
- Next : constant Natural := Natural (IndexesT (Pos + 1));
-
- pragma Assert (Next - 1 >= Start);
- pragma Assert (Start >= Names'First);
- pragma Assert (Next - 1 <= Names'Last);
-
- pragma Assert (Next - Start <= S'Last);
- -- The caller should guarantee that S is large enough to contain the
- -- enumeration image.
- begin
- S (1 .. Next - Start) := Names (Start .. Next - 1);
- P := Next - Start;
- end Image_Enumeration_8;
-
- --------------------------
- -- Image_Enumeration_16 --
- --------------------------
-
- procedure Image_Enumeration_16
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address)
- is
- pragma Assert (S'First = 1);
-
- type Natural_16 is range 0 .. 2 ** 15 - 1;
- subtype Names_Index is
- Natural_16 range Natural_16 (Names'First)
- .. Natural_16 (Names'Last) + 1;
- subtype Index is Natural range Natural'First .. Names'Length;
- type Index_Table is array (Index) of Names_Index;
- type Index_Table_Ptr is access Index_Table;
-
- function To_Index_Table_Ptr is
- new Ada.Unchecked_Conversion (System.Address, Index_Table_Ptr);
-
- IndexesT : constant Index_Table_Ptr := To_Index_Table_Ptr (Indexes);
-
- pragma Assert (Pos in IndexesT'Range);
- pragma Assert (Pos + 1 in IndexesT'Range);
-
- Start : constant Natural := Natural (IndexesT (Pos));
- Next : constant Natural := Natural (IndexesT (Pos + 1));
-
- pragma Assert (Next - 1 >= Start);
- pragma Assert (Start >= Names'First);
- pragma Assert (Next - 1 <= Names'Last);
-
- pragma Assert (Next - Start <= S'Last);
- -- The caller should guarantee that S is large enough to contain the
- -- enumeration image.
- begin
- S (1 .. Next - Start) := Names (Start .. Next - 1);
- P := Next - Start;
- end Image_Enumeration_16;
-
- --------------------------
- -- Image_Enumeration_32 --
- --------------------------
-
- procedure Image_Enumeration_32
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address)
- is
- pragma Assert (S'First = 1);
-
- type Natural_32 is range 0 .. 2 ** 31 - 1;
- subtype Names_Index is
- Natural_32 range Natural_32 (Names'First)
- .. Natural_32 (Names'Last) + 1;
- subtype Index is Natural range Natural'First .. Names'Length;
- type Index_Table is array (Index) of Names_Index;
- type Index_Table_Ptr is access Index_Table;
-
- function To_Index_Table_Ptr is
- new Ada.Unchecked_Conversion (System.Address, Index_Table_Ptr);
-
- IndexesT : constant Index_Table_Ptr := To_Index_Table_Ptr (Indexes);
-
- pragma Assert (Pos in IndexesT'Range);
- pragma Assert (Pos + 1 in IndexesT'Range);
-
- Start : constant Natural := Natural (IndexesT (Pos));
- Next : constant Natural := Natural (IndexesT (Pos + 1));
-
- pragma Assert (Next - 1 >= Start);
- pragma Assert (Start >= Names'First);
- pragma Assert (Next - 1 <= Names'Last);
-
- pragma Assert (Next - Start <= S'Last);
- -- The caller should guarantee that S is large enough to contain the
- -- enumeration image.
- begin
- S (1 .. Next - Start) := Names (Start .. Next - 1);
- P := Next - Start;
- end Image_Enumeration_32;
-
-end System.Img_Enum_New;
diff --git a/gcc/ada/libgnat/s-imenne.ads b/gcc/ada/libgnat/s-imenne.ads
deleted file mode 100644
index eba31c2..0000000
--- a/gcc/ada/libgnat/s-imenne.ads
+++ /dev/null
@@ -1,85 +0,0 @@
-------------------------------------------------------------------------------
--- --
--- GNAT RUN-TIME COMPONENTS --
--- --
--- S Y S T E M . I M G _ E N U M _ N E W --
--- --
--- S p e c --
--- --
--- Copyright (C) 2000-2021, Free Software Foundation, Inc. --
--- --
--- GNAT is free software; you can redistribute it and/or modify it under --
--- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 3, or (at your option) any later ver- --
--- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
--- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
--- or FITNESS FOR A PARTICULAR PURPOSE. --
--- --
--- As a special exception under Section 7 of GPL version 3, you are granted --
--- additional permissions described in the GCC Runtime Library Exception, --
--- version 3.1, as published by the Free Software Foundation. --
--- --
--- You should have received a copy of the GNU General Public License and --
--- a copy of the GCC Runtime Library Exception along with this program; --
--- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
--- <http://www.gnu.org/licenses/>. --
--- --
--- GNAT was originally developed by the GNAT team at New York University. --
--- Extensive contributions were provided by Ada Core Technologies Inc. --
--- --
-------------------------------------------------------------------------------
-
--- Enumeration_Type'Image for all enumeration types except those in package
--- Standard (where we have no opportunity to build image tables), and in
--- package System (where it is too early to start building image tables).
--- Special routines exist for the enumeration types in these packages.
-
--- Note: this is an obsolete package replaced by instantiations of the generic
--- package System.Image_N. The reason we maintain this package is that when
--- bootstrapping with an old compiler, the old compiler will search for this
--- unit, expecting to find these functions. The new compiler will search for
--- procedures in the instances of System.Image_N instead.
-
-pragma Compiler_Unit_Warning;
-
-package System.Img_Enum_New is
- pragma Pure;
-
- procedure Image_Enumeration_8
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address);
- -- Used to compute Enum'Image (Str) where Enum is some enumeration type
- -- other than those defined in package Standard. Names is a string with
- -- a lower bound of 1 containing the characters of all the enumeration
- -- literals concatenated together in sequence. Indexes is the address of
- -- an array of type array (0 .. N) of Natural_8, where N is the number of
- -- enumeration literals in the type. The Indexes values are the starting
- -- subscript of each enumeration literal, indexed by Pos values, with an
- -- extra entry at the end containing Names'Length + 1. The reason that
- -- Indexes is passed by address is that the actual type is created on the
- -- fly by the expander. The desired 'Image value is stored in S (1 .. P)
- -- and P is set on return. The caller guarantees that S is long enough to
- -- hold the result and that the lower bound is 1.
-
- procedure Image_Enumeration_16
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address);
- -- Identical to Set_Image_Enumeration_8 except that it handles types using
- -- array (0 .. Num) of Natural_16 for the Indexes table.
-
- procedure Image_Enumeration_32
- (Pos : Natural;
- S : in out String;
- P : out Natural;
- Names : String;
- Indexes : System.Address);
- -- Identical to Set_Image_Enumeration_8 except that it handles types using
- -- array (0 .. Num) of Natural_32 for the Indexes table.
-
-end System.Img_Enum_New;
diff --git a/gcc/ada/libgnat/s-imglli.ads b/gcc/ada/libgnat/s-imglli.ads
index 2e0b42c..e6e3efc 100644
--- a/gcc/ada/libgnat/s-imglli.ads
+++ b/gcc/ada/libgnat/s-imglli.ads
@@ -30,8 +30,8 @@
------------------------------------------------------------------------------
-- This package contains the routines for supporting the Image attribute for
--- signed integer types larger Integer, and also for conversion operations
--- required in Text_IO.Integer_IO for such types.
+-- signed integer types larger than Integer, and also for conversion
+-- operations required in Text_IO.Integer_IO for such types.
with System.Image_I;
diff --git a/gcc/ada/libgnat/s-parame__vxworks.ads b/gcc/ada/libgnat/s-parame__vxworks.ads
index 11b408b..b22d858 100644
--- a/gcc/ada/libgnat/s-parame__vxworks.ads
+++ b/gcc/ada/libgnat/s-parame__vxworks.ads
@@ -108,11 +108,11 @@ package System.Parameters is
-- Select the appropriate time_t_bits for the VSB in use, then rebuild
-- the runtime using instructions in adainclude/libada.gpr.
- time_t_bits : constant := Long_Integer'Size;
+ -- time_t_bits : constant := Long_Integer'Size;
-- Number of bits in type time_t for SR0650 and before and SR0660 with
-- non-default configuration.
- -- time_t_bits : constant := Long_Long_Integer'Size;
+ time_t_bits : constant := Long_Long_Integer'Size;
-- Number of bits in type time_t for SR0660 with default configuration.
----------------------------------------------
diff --git a/gcc/ada/libgnat/s-regpat.adb b/gcc/ada/libgnat/s-regpat.adb
index 7e33067..b40f682 100644
--- a/gcc/ada/libgnat/s-regpat.adb
+++ b/gcc/ada/libgnat/s-regpat.adb
@@ -3463,18 +3463,58 @@ package body System.Regpat is
end;
elsif Self.First /= ASCII.NUL then
- -- We know what char it must start with
+ -- We know what char (modulo casing) it must start with
- declare
- Next_Try : Natural := Index (First_In_Data, Self.First);
+ if (Self.Flags and Case_Insensitive) = 0
+ or else Self.First not in 'a' .. 'z'
+ then
+ declare
+ Next_Try : Natural := Index (First_In_Data, Self.First);
+ begin
+ while Next_Try /= 0 loop
+ Matched := Try (Next_Try);
+ exit when Matched;
+ Next_Try := Index (Next_Try + 1, Self.First);
+ end loop;
+ end;
+ else
+ declare
+ Uc_First : constant Character := To_Upper (Self.First);
+
+ function Case_Insensitive_Index
+ (Start : Positive) return Natural;
+ -- Search for both Self.First and To_Upper (Self.First).
+ -- If both are nonzero, return the smaller one; if exactly
+ -- one is nonzero, return it; if both are zero, return zero.
+
+ ---------------------------
+ -- Case_Insenstive_Index --
+ ---------------------------
+
+ function Case_Insensitive_Index
+ (Start : Positive) return Natural
+ is
+ Lc_Index : constant Natural := Index (Start, Self.First);
+ Uc_Index : constant Natural := Index (Start, Uc_First);
+ begin
+ if Lc_Index = 0 then
+ return Uc_Index;
+ elsif Uc_Index = 0 then
+ return Lc_Index;
+ else
+ return Natural'Min (Lc_Index, Uc_Index);
+ end if;
+ end Case_Insensitive_Index;
- begin
- while Next_Try /= 0 loop
- Matched := Try (Next_Try);
- exit when Matched;
- Next_Try := Index (Next_Try + 1, Self.First);
- end loop;
- end;
+ Next_Try : Natural := Case_Insensitive_Index (First_In_Data);
+ begin
+ while Next_Try /= 0 loop
+ Matched := Try (Next_Try);
+ exit when Matched;
+ Next_Try := Case_Insensitive_Index (Next_Try + 1);
+ end loop;
+ end;
+ end if;
else
-- Messy cases: try all locations (including for the empty string)
@@ -3634,6 +3674,9 @@ package body System.Regpat is
if Program (Scan) = EXACT then
Self.First := Program (String_Operand (Scan));
+ elsif Program (Scan) = EXACTF then
+ Self.First := To_Lower (Program (String_Operand (Scan)));
+
elsif Program (Scan) = BOL
or else Program (Scan) = SBOL
or else Program (Scan) = MBOL
diff --git a/gcc/ada/libgnat/s-regpat.ads b/gcc/ada/libgnat/s-regpat.ads
index b1a1366f..8fac30a 100644
--- a/gcc/ada/libgnat/s-regpat.ads
+++ b/gcc/ada/libgnat/s-regpat.ads
@@ -482,18 +482,17 @@ package System.Regpat is
-- Data_First is the lower bound for the match, i.e. Data (Data_First)
-- will be the first character to be examined. If Data_First is set to
-- the special value of -1 (the default), then the first character to
- -- be examined is Data (Data_First). However, the regular expression
- -- character ^ (start of string) still refers to the first character
+ -- be examined is Data (Data'First). However, the regular expression
+ -- character ^ (start of string) always refers to the first character
-- of the full string (Data (Data'First)), which is why there is a
-- separate mechanism for specifying Data_First.
-- Data_Last is the upper bound for the match, i.e. Data (Data_Last)
-- will be the last character to be examined. If Data_Last is set to
-- the special value of Positive'Last (the default), then the last
- -- character to be examined is Data (Data_Last). However, the regular
- -- expression character $ (end of string) still refers to the last
- -- character of the full string (Data (Data'Last)), which is why there
- -- is a separate mechanism for specifying Data_Last.
+ -- character to be examined is Data (Data'Last). However, the regular
+ -- expression character $ (end of string) always refers to the last
+ -- character of the full string (Data (Data'Last)).
-- Note: the use of Data_First and Data_Last is not equivalent to
-- simply passing a slice as Expression because of the handling of
diff --git a/gcc/ada/libgnat/s-secsta.ads b/gcc/ada/libgnat/s-secsta.ads
index 7d6b1b9..6648c23 100644
--- a/gcc/ada/libgnat/s-secsta.ads
+++ b/gcc/ada/libgnat/s-secsta.ads
@@ -440,4 +440,9 @@ private
function Get_Stack_Info (Stack : SS_Stack_Ptr) return Stack_Info;
-- Obtain the information attributes of secondary stack Stack
+ pragma Machine_Attribute (SS_Allocate, "strub", "callable");
+ pragma Machine_Attribute (SS_Mark, "strub", "callable");
+ pragma Machine_Attribute (SS_Release, "strub", "callable");
+ -- Enable these to be called from within strub contexts.
+
end System.Secondary_Stack;