aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/libgnat/s-valueu.ads
blob: f7ad677f1237051c02dfea109c1a314614015ace (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
------------------------------------------------------------------------------
--                                                                          --
--                         GNAT COMPILER COMPONENTS                         --
--                                                                          --
--                       S Y S T E M . V A L U E _ U                        --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--          Copyright (C) 1992-2024, 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.      --
--                                                                          --
------------------------------------------------------------------------------

--  This package contains routines for scanning modular Unsigned
--  values for use in Text_IO.Modular_IO, and the Value attribute.

--  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,
                         Subprogram_Variant => Ignore);

with System.Value_U_Spec;
with System.Val_Spec; use System.Val_Spec;

generic

   type Uns is mod <>;

   --  Additional parameters for ghost subprograms used inside contracts

   with package Spec is new System.Value_U_Spec (Uns => Uns) with Ghost;

package System.Value_U is
   pragma Preelaborate;

   procedure Scan_Raw_Unsigned
     (Str : String;
      Ptr : not null access Integer;
      Max : Integer;
      Res : out Uns)
   with Pre => Str'Last /= Positive'Last
     and then Ptr.all in Str'Range
     and then Max in Ptr.all .. Str'Last
     and then Spec.Is_Raw_Unsigned_Format_Ghost (Str (Ptr.all .. Max)),
     Post => Spec.Raw_Unsigned_No_Overflow_Ghost (Str, Ptr.all'Old, Max)
     and Res = Spec.Scan_Raw_Unsigned_Ghost (Str, Ptr.all'Old, Max)
     and Ptr.all = Spec.Raw_Unsigned_Last_Ghost (Str, Ptr.all'Old, Max);

   --  This function scans the string starting at Str (Ptr.all) for a valid
   --  integer according to the syntax described in (RM 3.5(43)). The substring
   --  scanned extends no further than Str (Max).  Note: this does not scan
   --  leading or trailing blanks, nor leading sign.
   --
   --  There are three cases for the return:
   --
   --  If a valid integer is found, then Ptr.all is updated past the last
   --  character of the integer.
   --
   --  If no valid integer is found, then Ptr.all points either to an initial
   --  non-digit character, or to Max + 1 if the field is all spaces and the
   --  exception Constraint_Error is raised.
   --
   --  If a syntactically valid integer is scanned, but the value is out of
   --  range, or, in the based case, the base value is out of range or there
   --  is an out of range digit, then Ptr.all points past the integer, and
   --  Constraint_Error is raised.
   --
   --  Note: these rules correspond to the requirements for leaving the pointer
   --  positioned in Text_IO.Get. Note that the rules as stated in the RM would
   --  seem to imply that for a case like:
   --
   --    8#12345670009#
   --
   --  the pointer should be left at the first # having scanned out the longest
   --  valid integer literal (8), but in fact in this case the pointer points
   --  past the final # and Constraint_Error is raised. This is the behavior
   --  expected for Text_IO and enforced by the ACATS tests.
   --
   --  If a based literal is malformed in that a character other than a valid
   --  hexadecimal digit is encountered during scanning out the digits after
   --  the # (this includes the case of using the wrong terminator, : instead
   --  of # or vice versa) there are two cases. If all the digits before the
   --  non-digit are in range of the base, as in
   --
   --    8#100x00#
   --    8#100:
   --
   --  then in this case, the "base" value before the initial # is returned as
   --  the result, and the pointer points to the initial # character on return.
   --
   --  If an out of range digit has been detected before the invalid character,
   --  as in:
   --
   --   8#900x00#
   --   8#900:
   --
   --  then the pointer is also left at the initial # character, but constraint
   --  error is raised reflecting the encounter of an out of range digit.
   --
   --  Finally if we have an unterminated fixed-point constant where the final
   --  # or : character is missing, Constraint_Error is raised and the pointer
   --  is left pointing past the last digit, as in:
   --
   --   8#22
   --
   --  This string results in a Constraint_Error with the pointer pointing
   --  past the second 2.
   --
   --  Note: if Str is empty, i.e. if Max is less than Ptr, then this is a
   --  special case of an all-blank string, and Ptr is unchanged, and hence
   --  is greater than Max as required in this case.
   --  ??? This is not the case. We will read Str (Ptr.all) without checking
   --  and increase Ptr.all by one.
   --
   --  Note: this routine should not be called with Str'Last = Positive'Last.
   --  If this occurs Program_Error is raised with a message noting that this
   --  case is not supported. Most such cases are eliminated by the caller.

   procedure Scan_Unsigned
     (Str : String;
      Ptr : not null access Integer;
      Max : Integer;
      Res : out Uns)
   with Pre => Str'Last /= Positive'Last
     and then Ptr.all in Str'Range
     and then Max in Ptr.all .. Str'Last
     and then not Only_Space_Ghost (Str, Ptr.all, Max)
     and then
       (declare
          Non_Blank : constant Positive :=
            First_Non_Space_Ghost (Str, Ptr.all, Max);
          Fst_Num   : constant Positive :=
            (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank);
        begin
          Spec.Is_Raw_Unsigned_Format_Ghost (Str (Fst_Num .. Max))),
     Post =>
       (declare
          Non_Blank : constant Positive :=
            First_Non_Space_Ghost (Str, Ptr.all'Old, Max);
          Fst_Num   : constant Positive :=
            (if Str (Non_Blank) = '+' then Non_Blank + 1 else Non_Blank);
        begin
          Spec.Raw_Unsigned_No_Overflow_Ghost (Str, Fst_Num, Max)
          and then Res = Spec.Scan_Raw_Unsigned_Ghost (Str, Fst_Num, Max)
          and then Ptr.all = Spec.Raw_Unsigned_Last_Ghost (Str, Fst_Num, Max));

   --  Same as Scan_Raw_Unsigned, except scans optional leading
   --  blanks, and an optional leading plus sign.
   --
   --  Note: if a minus sign is present, Constraint_Error will be raised.
   --  Note: trailing blanks are not scanned.

   function Value_Unsigned
     (Str : String) return Uns
   with Pre => Str'Length /= Positive'Last
     and then not Only_Space_Ghost (Str, Str'First, Str'Last)
     and then Spec.Is_Unsigned_Ghost (Spec.Slide_If_Necessary (Str)),
     Post =>
         Spec.Is_Value_Unsigned_Ghost
           (Spec.Slide_If_Necessary (Str), Value_Unsigned'Result),
     Subprogram_Variant => (Decreases => Str'First);
   --  Used in computing X'Value (Str) where X is a modular integer type whose
   --  modulus does not exceed the range of System.Unsigned_Types.Unsigned. Str
   --  is the string argument of the attribute. Constraint_Error is raised if
   --  the string is malformed, or if the value is out of range.

end System.Value_U;