1 ------------------------------------------------------------------------------
3 -- GNAAMP COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2012, AdaCore --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 ------------------------------------------------------------------------------
23 with Sem_Aux
; use Sem_Aux
;
24 with Sinput
; use Sinput
;
25 with Stand
; use Stand
;
26 with Stringt
; use Stringt
;
28 with GNAT
.Case_Util
; use GNAT
.Case_Util
;
30 package body AA_Util
is
32 ----------------------
33 -- Is_Global_Entity --
34 ----------------------
36 function Is_Global_Entity
(E
: Entity_Id
) return Boolean is
38 return Enclosing_Dynamic_Scope
(E
) = Standard_Standard
;
45 function New_Name_Id
(Name
: String) return Name_Id
is
47 for J
in 1 .. Name
'Length loop
48 Name_Buffer
(J
) := Name
(Name
'First + (J
- 1));
51 Name_Len
:= Name
'Length;
59 function Name_String
(Name
: Name_Id
) return String is
61 pragma Assert
(Name
/= No_Name
);
62 return Get_Name_String
(Name
);
69 function New_String_Id
(S
: String) return String_Id
is
71 for J
in 1 .. S
'Length loop
72 Name_Buffer
(J
) := S
(S
'First + (J
- 1));
76 return String_From_Name_Buffer
;
83 function String_Value
(Str_Id
: String_Id
) return String is
85 -- ??? pragma Assert (Str_Id /= No_String);
87 if Str_Id
= No_String
then
91 String_To_Name_Buffer
(Str_Id
);
93 return Name_Buffer
(1 .. Name_Len
);
101 (Name_Seq
: not null access Name_Sequencer
;
102 Name_Prefix
: String) return Name_Id
105 Name_Seq
.Sequence_Number
:= Name_Seq
.Sequence_Number
+ 1;
108 Number_Image
: constant String := Name_Seq
.Sequence_Number
'Img;
111 (Name_Prefix
& "__" & Number_Image
(2 .. Number_Image
'Last));
119 function Elab_Spec_Name
(Module_Name
: Name_Id
) return Name_Id
is
121 return New_Name_Id
(Name_String
(Module_Name
) & "___elabs");
128 function Elab_Body_Name
(Module_Name
: Name_Id
) return Name_Id
is
130 return New_Name_Id
(Name_String
(Module_Name
) & "___elabb");
133 --------------------------------
134 -- Source_Name_Without_Suffix --
135 --------------------------------
137 function File_Name_Without_Suffix
(File_Name
: String) return String is
138 Name_Index
: Natural := File_Name
'Last;
141 pragma Assert
(File_Name
'Length > 0);
143 -- We loop in reverse to ensure that file names that follow nonstandard
144 -- naming conventions that include additional dots are handled properly,
145 -- preserving dots in front of the main file suffix (for example,
146 -- main.2.ada => main.2).
148 while Name_Index
>= File_Name
'First
149 and then File_Name
(Name_Index
) /= '.'
151 Name_Index
:= Name_Index
- 1;
154 -- Return the part of the file name up to but not including the last dot
155 -- in the name, or return the whole name as is if no dot character was
158 if Name_Index
>= File_Name
'First then
159 return File_Name
(File_Name
'First .. Name_Index
- 1);
164 end File_Name_Without_Suffix
;
170 function Source_Name
(Sloc
: Source_Ptr
) return File_Name_Type
is
172 if Sloc
= No_Location
or Sloc
= Standard_Location
then
175 return File_Name
(Get_Source_File_Index
(Sloc
));
179 --------------------------------
180 -- Source_Name_Without_Suffix --
181 --------------------------------
183 function Source_Name_Without_Suffix
(Sloc
: Source_Ptr
) return String is
184 Src_Name
: constant String :=
185 Name_String
(Name_Id
(Source_Name
(Sloc
)));
186 Src_Index
: Natural := Src_Name
'Last;
189 pragma Assert
(Src_Name
'Length > 0);
191 -- Treat the presence of a ".dg" suffix specially, stripping it off
192 -- in addition to any suffix preceding it.
194 if Src_Name
'Length >= 4
195 and then Src_Name
(Src_Name
'Last - 2 .. Src_Name
'Last) = ".dg"
197 Src_Index
:= Src_Index
- 3;
200 return File_Name_Without_Suffix
(Src_Name
(Src_Name
'First .. Src_Index
));
201 end Source_Name_Without_Suffix
;
203 ----------------------
204 -- Source_Id_String --
205 ----------------------
207 function Source_Id_String
(Unit_Name
: Name_Id
) return String is
208 Unit_String
: String := Name_String
(Unit_Name
);
209 Name_Last
: Positive := Unit_String
'Last;
210 Name_Index
: Positive := Unit_String
'First;
213 To_Mixed
(Unit_String
);
215 -- Replace any embedded sequences of two or more '_' characters
216 -- with a single '.' character. Note that this will leave any
217 -- leading or trailing single '_' characters untouched, but those
218 -- should normally not occur in compilation unit names (and if
219 -- they do then it's better to leave them as is).
221 while Name_Index
<= Name_Last
loop
222 if Unit_String
(Name_Index
) = '_'
223 and then Name_Index
/= Name_Last
224 and then Unit_String
(Name_Index
+ 1) = '_'
226 Unit_String
(Name_Index
) := '.';
227 Name_Index
:= Name_Index
+ 1;
229 while Unit_String
(Name_Index
) = '_'
230 and then Name_Index
<= Name_Last
232 Unit_String
(Name_Index
.. Name_Last
- 1)
233 := Unit_String
(Name_Index
+ 1 .. Name_Last
);
234 Name_Last
:= Name_Last
- 1;
238 Name_Index
:= Name_Index
+ 1;
242 return Unit_String
(Unit_String
'First .. Name_Last
);
243 end Source_Id_String
;
245 -- This version of Source_Id_String is obsolescent and is being
246 -- replaced with the above function.
248 function Source_Id_String
(Sloc
: Source_Ptr
) return String is
249 File_Index
: Source_File_Index
;
252 -- Use an arbitrary artificial 22-character value for package Standard,
253 -- since Standard doesn't have an associated source file.
255 if Sloc
<= Standard_Location
then
256 return "20010101010101standard";
258 -- Return the concatentation of the source file's timestamp and
259 -- its 8-digit hex checksum.
262 File_Index
:= Get_Source_File_Index
(Sloc
);
264 return String (Time_Stamp
(File_Index
))
265 & Get_Hex_String
(Source_Checksum
(File_Index
));
267 end Source_Id_String
;
273 function Source_Id
(Unit_Name
: Name_Id
) return String_Id
is
275 return New_String_Id
(Source_Id_String
(Unit_Name
));
278 -- This version of Source_Id is obsolescent and is being
279 -- replaced with the above function.
281 function Source_Id
(Sloc
: Source_Ptr
) return String_Id
is
283 return New_String_Id
(Source_Id_String
(Sloc
));
290 function Image
(I
: Int
) return String is
291 Image_String
: constant String := Pos
'Image (I
);
293 if Image_String
(1) = ' ' then
294 return Image_String
(2 .. Image_String
'Last);
304 function UI_Image
(I
: Uint
; Format
: Integer_Image_Format
) return String is
306 if Format
= Decimal
then
307 UI_Image
(I
, Format
=> Decimal
);
308 return UI_Image_Buffer
(1 .. UI_Image_Length
);
310 elsif Format
= Ada_Hex
then
311 UI_Image
(I
, Format
=> Hex
);
312 return UI_Image_Buffer
(1 .. UI_Image_Length
);
315 pragma Assert
(I
>= Uint_0
);
317 UI_Image
(I
, Format
=> Hex
);
319 pragma Assert
(UI_Image_Buffer
(1 .. 3) = "16#"
320 and then UI_Image_Buffer
(UI_Image_Length
) = '#');
322 -- Declare a string where we will copy the digits from the UI_Image,
323 -- interspersing '_' characters as 4-digit group separators. The
324 -- underscores in UI_Image's result are not always at the places
325 -- where we want them, which is why we do the following copy
326 -- (e.g., we map "16#ABCD_EF#" to "^AB_CDEF^").
329 Hex_String
: String (1 .. UI_Image_Max
);
330 Last_Index
: Natural;
331 Digit_Count
: Natural := 0;
332 UI_Image_Index
: Natural := 4; -- Skip past the "16#" bracket
333 Sep_Count
: Natural := 0;
336 -- Count up the number of non-underscore characters in the
337 -- literal value portion of the UI_Image string.
339 while UI_Image_Buffer
(UI_Image_Index
) /= '#' loop
340 if UI_Image_Buffer
(UI_Image_Index
) /= '_' then
341 Digit_Count
:= Digit_Count
+ 1;
344 UI_Image_Index
:= UI_Image_Index
+ 1;
347 UI_Image_Index
:= 4; -- Reset the index past the "16#" bracket
351 Hex_String
(Last_Index
) := '^';
352 Last_Index
:= Last_Index
+ 1;
354 -- Copy digits from UI_Image_Buffer to Hex_String, adding
355 -- underscore separators as appropriate. The initial value
356 -- of Sep_Count accounts for the leading '^' and being one
357 -- character ahead after inserting a digit.
361 while UI_Image_Buffer
(UI_Image_Index
) /= '#' loop
362 if UI_Image_Buffer
(UI_Image_Index
) /= '_' then
363 Hex_String
(Last_Index
) := UI_Image_Buffer
(UI_Image_Index
);
365 Last_Index
:= Last_Index
+ 1;
367 -- Add '_' characters to separate groups of four hex
368 -- digits for readability (grouping from right to left).
370 if (Digit_Count
- (Last_Index
- Sep_Count
)) mod 4 = 0 then
371 Hex_String
(Last_Index
) := '_';
372 Last_Index
:= Last_Index
+ 1;
373 Sep_Count
:= Sep_Count
+ 1;
377 UI_Image_Index
:= UI_Image_Index
+ 1;
380 -- Back up before any trailing underscore
382 if Hex_String
(Last_Index
- 1) = '_' then
383 Last_Index
:= Last_Index
- 1;
386 Hex_String
(Last_Index
) := '^';
388 return Hex_String
(1 .. Last_Index
);
397 -- Shouldn't this be added to Urealp???
399 function UR_Image
(R
: Ureal
) return String is
401 -- The algorithm used here for conversion of Ureal values
402 -- is taken from the JGNAT back end.
404 Num
: Long_Long_Float := 0.0;
405 Den
: Long_Long_Float := 0.0;
406 Sign
: Long_Long_Float := 1.0;
407 Result
: Long_Long_Float;
412 if UR_Is_Negative
(R
) then
416 -- In the following calculus, we consider numbers modulo 2 ** 31,
417 -- so that we don't have problems with signed Int...
419 Tmp
:= abs (Numerator
(R
));
423 + Long_Long_Float (UI_To_Int
(Tmp
mod (Uint_2
** 31)))
425 Tmp
:= Tmp
/ Uint_2
** 31;
429 Tmp
:= abs (Denominator
(R
));
430 if Rbase
(R
) /= 0 then
431 Tmp
:= Rbase
(R
) ** Tmp
;
437 + Long_Long_Float (UI_To_Int
(Tmp
mod (Uint_2
** 31)))
439 Tmp
:= Tmp
/ Uint_2
** 31;
443 -- If the denominator denotes a negative power of Rbase,
444 -- then multiply by the denominator.
446 if Rbase
(R
) /= 0 and then Denominator
(R
) < 0 then
447 Result
:= Sign
* Num
* Den
;
449 -- Otherwise compute the quotient
452 Result
:= Sign
* Num
/ Den
;
455 return Long_Long_Float'Image (Result
);