1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2017, Free Software Foundation, Inc. --
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. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 -- WARNING: There is a C version of this package. Any changes to this
33 -- source file must be properly reflected in the C header file namet.h
34 -- which is created manually from namet.ads and namet.adb.
36 with Debug
; use Debug
;
38 with Output
; use Output
;
39 with System
; use System
;
40 with Tree_IO
; use Tree_IO
;
41 with Widechar
; use Widechar
;
43 with Interfaces
; use Interfaces
;
47 Name_Chars_Reserve
: constant := 5000;
48 Name_Entries_Reserve
: constant := 100;
49 -- The names table is locked during gigi processing, since gigi assumes
50 -- that the table does not move. After returning from gigi, the names
51 -- table is unlocked again, since writing library file information needs
52 -- to generate some extra names. To avoid the inefficiency of always
53 -- reallocating during this second unlocked phase, we reserve a bit of
54 -- extra space before doing the release call.
56 Hash_Num
: constant Int
:= 2**16;
57 -- Number of headers in the hash table. Current hash algorithm is closely
58 -- tailored to this choice, so it can only be changed if a corresponding
59 -- change is made to the hash algorithm.
61 Hash_Max
: constant Int
:= Hash_Num
- 1;
62 -- Indexes in the hash header table run from 0 to Hash_Num - 1
64 subtype Hash_Index_Type
is Int
range 0 .. Hash_Max
;
65 -- Range of hash index values
67 Hash_Table
: array (Hash_Index_Type
) of Name_Id
;
68 -- The hash table is used to locate existing entries in the names table.
69 -- The entries point to the first names table entry whose hash value
70 -- matches the hash code. Then subsequent names table entries with the
71 -- same hash code value are linked through the Hash_Link fields.
73 -----------------------
74 -- Local Subprograms --
75 -----------------------
77 function Hash
(Buf
: Bounded_String
) return Hash_Index_Type
;
79 -- Compute hash code for name stored in Buf
81 procedure Strip_Qualification_And_Suffixes
(Buf
: in out Bounded_String
);
82 -- Given an encoded entity name in Buf, remove package body
83 -- suffix as described for Strip_Package_Body_Suffix, and also remove
84 -- all qualification, i.e. names followed by two underscores.
86 -----------------------------
87 -- Add_Char_To_Name_Buffer --
88 -----------------------------
90 procedure Add_Char_To_Name_Buffer
(C
: Character) is
92 Append
(Global_Name_Buffer
, C
);
93 end Add_Char_To_Name_Buffer
;
95 ----------------------------
96 -- Add_Nat_To_Name_Buffer --
97 ----------------------------
99 procedure Add_Nat_To_Name_Buffer
(V
: Nat
) is
101 Append
(Global_Name_Buffer
, V
);
102 end Add_Nat_To_Name_Buffer
;
104 ----------------------------
105 -- Add_Str_To_Name_Buffer --
106 ----------------------------
108 procedure Add_Str_To_Name_Buffer
(S
: String) is
110 Append
(Global_Name_Buffer
, S
);
111 end Add_Str_To_Name_Buffer
;
117 procedure Append
(Buf
: in out Bounded_String
; C
: Character) is
119 Buf
.Length
:= Buf
.Length
+ 1;
121 if Buf
.Length
> Buf
.Chars
'Last then
122 Write_Str
("Name buffer overflow; Max_Length = ");
123 Write_Int
(Int
(Buf
.Max_Length
));
128 Buf
.Chars
(Buf
.Length
) := C
;
131 procedure Append
(Buf
: in out Bounded_String
; V
: Nat
) is
134 Append
(Buf
, V
/ 10);
137 Append
(Buf
, Character'Val (Character'Pos ('0') + V
rem 10));
140 procedure Append
(Buf
: in out Bounded_String
; S
: String) is
141 First
: constant Natural := Buf
.Length
+ 1;
143 Buf
.Length
:= Buf
.Length
+ S
'Length;
145 if Buf
.Length
> Buf
.Chars
'Last then
146 Write_Str
("Name buffer overflow; Max_Length = ");
147 Write_Int
(Int
(Buf
.Max_Length
));
152 Buf
.Chars
(First
.. Buf
.Length
) := S
;
153 -- A loop calling Append(Character) would be cleaner, but this slice
154 -- assignment is substantially faster.
157 procedure Append
(Buf
: in out Bounded_String
; Buf2
: Bounded_String
) is
159 Append
(Buf
, Buf2
.Chars
(1 .. Buf2
.Length
));
162 procedure Append
(Buf
: in out Bounded_String
; Id
: Name_Id
) is
163 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
165 Index
: constant Int
:= Name_Entries
.Table
(Id
).Name_Chars_Index
;
166 Len
: constant Short
:= Name_Entries
.Table
(Id
).Name_Len
;
167 Chars
: Name_Chars
.Table_Type
renames
168 Name_Chars
.Table
(Index
+ 1 .. Index
+ Int
(Len
));
170 Append
(Buf
, String (Chars
));
177 procedure Append_Decoded
(Buf
: in out Bounded_String
; Id
: Name_Id
) is
180 Temp
: Bounded_String
;
185 -- Skip scan if we already know there are no encodings
187 if Name_Entries
.Table
(Id
).Name_Has_No_Encodings
then
191 -- Quick loop to see if there is anything special to do
195 if P
= Temp
.Length
then
196 Name_Entries
.Table
(Id
).Name_Has_No_Encodings
:= True;
212 -- Here we have at least some encoding that we must decode
217 New_Buf
: String (1 .. Temp
.Chars
'Last);
219 procedure Copy_One_Character
;
220 -- Copy a character from Temp.Chars to New_Buf. Includes case
221 -- of copying a Uhh,Whhhh,WWhhhhhhhh sequence and decoding it.
223 function Hex
(N
: Natural) return Word
;
224 -- Scans past N digits using Old pointer and returns hex value
226 procedure Insert_Character
(C
: Character);
227 -- Insert a new character into output decoded name
229 ------------------------
230 -- Copy_One_Character --
231 ------------------------
233 procedure Copy_One_Character
is
237 C
:= Temp
.Chars
(Old
);
239 -- U (upper half insertion case)
242 and then Old
< Temp
.Length
243 and then Temp
.Chars
(Old
+ 1) not in 'A' .. 'Z'
244 and then Temp
.Chars
(Old
+ 1) /= '_'
248 -- If we have upper half encoding, then we have to set an
249 -- appropriate wide character sequence for this character.
251 if Upper_Half_Encoding
then
252 Widechar
.Set_Wide
(Char_Code
(Hex
(2)), New_Buf
, New_Len
);
254 -- For other encoding methods, upper half characters can
255 -- simply use their normal representation.
258 Insert_Character
(Character'Val (Hex
(2)));
261 -- WW (wide wide character insertion)
264 and then Old
< Temp
.Length
265 and then Temp
.Chars
(Old
+ 1) = 'W'
268 Widechar
.Set_Wide
(Char_Code
(Hex
(8)), New_Buf
, New_Len
);
270 -- W (wide character insertion)
273 and then Old
< Temp
.Length
274 and then Temp
.Chars
(Old
+ 1) not in 'A' .. 'Z'
275 and then Temp
.Chars
(Old
+ 1) /= '_'
278 Widechar
.Set_Wide
(Char_Code
(Hex
(4)), New_Buf
, New_Len
);
280 -- Any other character is copied unchanged
283 Insert_Character
(C
);
286 end Copy_One_Character
;
292 function Hex
(N
: Natural) return Word
is
298 C
:= Temp
.Chars
(Old
);
301 pragma Assert
(C
in '0' .. '9' or else C
in 'a' .. 'f');
304 T
:= 16 * T
+ Character'Pos (C
) - Character'Pos ('0');
305 else -- C in 'a' .. 'f'
306 T
:= 16 * T
+ Character'Pos (C
) - (Character'Pos ('a') - 10);
313 ----------------------
314 -- Insert_Character --
315 ----------------------
317 procedure Insert_Character
(C
: Character) is
319 New_Len
:= New_Len
+ 1;
320 New_Buf
(New_Len
) := C
;
321 end Insert_Character
;
323 -- Start of processing for Decode
329 -- Loop through characters of name
331 while Old
<= Temp
.Length
loop
333 -- Case of character literal, put apostrophes around character
335 if Temp
.Chars
(Old
) = 'Q'
336 and then Old
< Temp
.Length
339 Insert_Character
(''');
341 Insert_Character
(''');
343 -- Case of operator name
345 elsif Temp
.Chars
(Old
) = 'O'
346 and then Old
< Temp
.Length
347 and then Temp
.Chars
(Old
+ 1) not in 'A' .. 'Z'
348 and then Temp
.Chars
(Old
+ 1) /= '_'
353 -- This table maps the 2nd and 3rd characters of the name
354 -- into the required output. Two blanks means leave the
357 Map
: constant String :=
358 "ab " & -- Oabs => "abs"
359 "ad+ " & -- Oadd => "+"
360 "an " & -- Oand => "and"
361 "co& " & -- Oconcat => "&"
362 "di/ " & -- Odivide => "/"
363 "eq= " & -- Oeq => "="
364 "ex**" & -- Oexpon => "**"
365 "gt> " & -- Ogt => ">"
366 "ge>=" & -- Oge => ">="
367 "le<=" & -- Ole => "<="
368 "lt< " & -- Olt => "<"
369 "mo " & -- Omod => "mod"
370 "mu* " & -- Omutliply => "*"
371 "ne/=" & -- One => "/="
372 "no " & -- Onot => "not"
373 "or " & -- Oor => "or"
374 "re " & -- Orem => "rem"
375 "su- " & -- Osubtract => "-"
376 "xo "; -- Oxor => "xor"
381 Insert_Character
('"');
383 -- Search the map. Note that this loop must terminate, if
384 -- not we have some kind of internal error, and a constraint
385 -- error may be raised.
389 exit when Temp
.Chars
(Old
) = Map
(J
)
390 and then Temp
.Chars
(Old
+ 1) = Map
(J
+ 1);
394 -- Special operator name
396 if Map
(J
+ 2) /= ' ' then
397 Insert_Character
(Map
(J
+ 2));
399 if Map
(J
+ 3) /= ' ' then
400 Insert_Character
(Map
(J
+ 3));
403 Insert_Character
('"');
405 -- Skip past original operator name in input
407 while Old
<= Temp
.Length
408 and then Temp
.Chars
(Old
) in 'a' .. 'z'
413 -- For other operator names, leave them in lower case,
414 -- surrounded by apostrophes
417 -- Copy original operator name from input to output
419 while Old
<= Temp
.Length
420 and then Temp
.Chars
(Old
) in 'a' .. 'z'
425 Insert_Character
('"');
429 -- Else copy one character and keep going
436 -- Copy new buffer as result
438 Temp
.Length
:= New_Len
;
439 Temp
.Chars
(1 .. New_Len
) := New_Buf
(1 .. New_Len
);
446 ----------------------------------
447 -- Append_Decoded_With_Brackets --
448 ----------------------------------
450 procedure Append_Decoded_With_Brackets
451 (Buf
: in out Bounded_String
;
457 -- Case of operator name, normal decoding is fine
459 if Buf
.Chars
(1) = 'O' then
460 Append_Decoded
(Buf
, Id
);
462 -- For character literals, normal decoding is fine
464 elsif Buf
.Chars
(1) = 'Q' then
465 Append_Decoded
(Buf
, Id
);
467 -- Only remaining issue is U/W/WW sequences
471 Temp
: Bounded_String
;
476 while P
< Temp
.Length
loop
477 if Temp
.Chars
(P
+ 1) in 'A' .. 'Z' then
482 elsif Temp
.Chars
(P
) = 'U' then
483 for J
in reverse P
+ 3 .. P
+ Temp
.Length
loop
484 Temp
.Chars
(J
+ 3) := Temp
.Chars
(J
);
487 Temp
.Length
:= Temp
.Length
+ 3;
488 Temp
.Chars
(P
+ 3) := Temp
.Chars
(P
+ 2);
489 Temp
.Chars
(P
+ 2) := Temp
.Chars
(P
+ 1);
490 Temp
.Chars
(P
) := '[';
491 Temp
.Chars
(P
+ 1) := '"';
492 Temp
.Chars
(P
+ 4) := '"';
493 Temp
.Chars
(P
+ 5) := ']';
496 -- WWhhhhhhhh encoding
498 elsif Temp
.Chars
(P
) = 'W'
499 and then P
+ 9 <= Temp
.Length
500 and then Temp
.Chars
(P
+ 1) = 'W'
501 and then Temp
.Chars
(P
+ 2) not in 'A' .. 'Z'
502 and then Temp
.Chars
(P
+ 2) /= '_'
504 Temp
.Chars
(P
+ 12 .. Temp
.Length
+ 2) :=
505 Temp
.Chars
(P
+ 10 .. Temp
.Length
);
506 Temp
.Chars
(P
) := '[';
507 Temp
.Chars
(P
+ 1) := '"';
508 Temp
.Chars
(P
+ 10) := '"';
509 Temp
.Chars
(P
+ 11) := ']';
510 Temp
.Length
:= Temp
.Length
+ 2;
515 elsif Temp
.Chars
(P
) = 'W'
516 and then P
< Temp
.Length
517 and then Temp
.Chars
(P
+ 1) not in 'A' .. 'Z'
518 and then Temp
.Chars
(P
+ 1) /= '_'
520 Temp
.Chars
(P
+ 8 .. P
+ Temp
.Length
+ 3) :=
521 Temp
.Chars
(P
+ 5 .. Temp
.Length
);
522 Temp
.Chars
(P
+ 2 .. P
+ 5) := Temp
.Chars
(P
+ 1 .. P
+ 4);
523 Temp
.Chars
(P
) := '[';
524 Temp
.Chars
(P
+ 1) := '"';
525 Temp
.Chars
(P
+ 6) := '"';
526 Temp
.Chars
(P
+ 7) := ']';
527 Temp
.Length
:= Temp
.Length
+ 3;
538 end Append_Decoded_With_Brackets
;
544 procedure Append_Encoded
(Buf
: in out Bounded_String
; C
: Char_Code
) is
545 procedure Set_Hex_Chars
(C
: Char_Code
);
546 -- Stores given value, which is in the range 0 .. 255, as two hex
547 -- digits (using lower case a-f) in Buf.Chars, incrementing Buf.Length.
553 procedure Set_Hex_Chars
(C
: Char_Code
) is
554 Hexd
: constant String := "0123456789abcdef";
555 N
: constant Natural := Natural (C
);
557 Buf
.Chars
(Buf
.Length
+ 1) := Hexd
(N
/ 16 + 1);
558 Buf
.Chars
(Buf
.Length
+ 2) := Hexd
(N
mod 16 + 1);
559 Buf
.Length
:= Buf
.Length
+ 2;
562 -- Start of processing for Append_Encoded
565 Buf
.Length
:= Buf
.Length
+ 1;
567 if In_Character_Range
(C
) then
569 CC
: constant Character := Get_Character
(C
);
571 if CC
in 'a' .. 'z' or else CC
in '0' .. '9' then
572 Buf
.Chars
(Buf
.Length
) := CC
;
574 Buf
.Chars
(Buf
.Length
) := 'U';
579 elsif In_Wide_Character_Range
(C
) then
580 Buf
.Chars
(Buf
.Length
) := 'W';
581 Set_Hex_Chars
(C
/ 256);
582 Set_Hex_Chars
(C
mod 256);
585 Buf
.Chars
(Buf
.Length
) := 'W';
586 Buf
.Length
:= Buf
.Length
+ 1;
587 Buf
.Chars
(Buf
.Length
) := 'W';
588 Set_Hex_Chars
(C
/ 2 ** 24);
589 Set_Hex_Chars
((C
/ 2 ** 16) mod 256);
590 Set_Hex_Chars
((C
/ 256) mod 256);
591 Set_Hex_Chars
(C
mod 256);
595 ------------------------
596 -- Append_Unqualified --
597 ------------------------
599 procedure Append_Unqualified
(Buf
: in out Bounded_String
; Id
: Name_Id
) is
600 Temp
: Bounded_String
;
603 Strip_Qualification_And_Suffixes
(Temp
);
605 end Append_Unqualified
;
607 --------------------------------
608 -- Append_Unqualified_Decoded --
609 --------------------------------
611 procedure Append_Unqualified_Decoded
612 (Buf
: in out Bounded_String
;
615 Temp
: Bounded_String
;
617 Append_Decoded
(Temp
, Id
);
618 Strip_Qualification_And_Suffixes
(Temp
);
620 end Append_Unqualified_Decoded
;
626 procedure Finalize
is
627 F
: array (Int
range 0 .. 50) of Int
;
628 -- N'th entry is the number of chains of length N, except last entry,
629 -- which is the number of chains of length F'Last or more.
631 Max_Chain_Length
: Nat
:= 0;
632 -- Maximum length of all chains
635 -- Used to compute average number of probes
638 -- Number of symbols in table
640 Verbosity
: constant Int
range 1 .. 3 := 1;
641 pragma Warnings
(Off
, Verbosity
);
642 -- This constant indicates the level of verbosity in the output from
643 -- this procedure. Currently this can only be changed by editing the
644 -- declaration above and recompiling. That's good enough in practice,
645 -- since we very rarely need to use this debug option. Settings are:
647 -- 1 => print basic summary information
648 -- 2 => in addition print number of entries per hash chain
649 -- 3 => in addition print content of entries
651 Zero
: constant Int
:= Character'Pos ('0');
654 if not Debug_Flag_H
then
658 for J
in F
'Range loop
662 for J
in Hash_Index_Type
loop
663 if Hash_Table
(J
) = No_Name
then
676 while N
/= No_Name
loop
677 N
:= Name_Entries
.Table
(N
).Hash_Link
;
682 Probes
:= Probes
+ (1 + C
) * 100;
684 if C
> Max_Chain_Length
then
685 Max_Chain_Length
:= C
;
688 if Verbosity
>= 2 then
689 Write_Str
("Hash_Table (");
691 Write_Str
(") has ");
693 Write_Str
(" entries");
700 F
(F
'Last) := F
(F
'Last) + 1;
703 if Verbosity
>= 3 then
705 while N
/= No_Name
loop
706 S
:= Name_Entries
.Table
(N
).Name_Chars_Index
;
710 for J
in 1 .. Name_Entries
.Table
(N
).Name_Len
loop
711 Write_Char
(Name_Chars
.Table
(S
+ Int
(J
)));
716 N
:= Name_Entries
.Table
(N
).Hash_Link
;
725 for J
in F
'Range loop
727 Write_Str
("Number of hash chains of length ");
736 Write_Str
(" or greater");
745 -- Print out average number of probes, in the case where Name_Find is
746 -- called for a string that is already in the table.
749 Write_Str
("Average number of probes for lookup = ");
750 Probes
:= Probes
/ Nsyms
;
751 Write_Int
(Probes
/ 200);
753 Probes
:= (Probes
mod 200) / 2;
754 Write_Char
(Character'Val (Zero
+ Probes
/ 10));
755 Write_Char
(Character'Val (Zero
+ Probes
mod 10));
758 Write_Str
("Max_Chain_Length = ");
759 Write_Int
(Max_Chain_Length
);
761 Write_Str
("Name_Chars'Length = ");
762 Write_Int
(Name_Chars
.Last
- Name_Chars
.First
+ 1);
764 Write_Str
("Name_Entries'Length = ");
765 Write_Int
(Int
(Name_Entries
.Last
- Name_Entries
.First
+ 1));
767 Write_Str
("Nsyms = ");
772 -----------------------------
773 -- Get_Decoded_Name_String --
774 -----------------------------
776 procedure Get_Decoded_Name_String
(Id
: Name_Id
) is
778 Global_Name_Buffer
.Length
:= 0;
779 Append_Decoded
(Global_Name_Buffer
, Id
);
780 end Get_Decoded_Name_String
;
782 -------------------------------------------
783 -- Get_Decoded_Name_String_With_Brackets --
784 -------------------------------------------
786 procedure Get_Decoded_Name_String_With_Brackets
(Id
: Name_Id
) is
788 Global_Name_Buffer
.Length
:= 0;
789 Append_Decoded_With_Brackets
(Global_Name_Buffer
, Id
);
790 end Get_Decoded_Name_String_With_Brackets
;
792 ------------------------
793 -- Get_Last_Two_Chars --
794 ------------------------
796 procedure Get_Last_Two_Chars
801 NE
: Name_Entry
renames Name_Entries
.Table
(N
);
802 NEL
: constant Int
:= Int
(NE
.Name_Len
);
806 C1
:= Name_Chars
.Table
(NE
.Name_Chars_Index
+ NEL
- 1);
807 C2
:= Name_Chars
.Table
(NE
.Name_Chars_Index
+ NEL
- 0);
812 end Get_Last_Two_Chars
;
814 ---------------------
815 -- Get_Name_String --
816 ---------------------
818 procedure Get_Name_String
(Id
: Name_Id
) is
820 Global_Name_Buffer
.Length
:= 0;
821 Append
(Global_Name_Buffer
, Id
);
824 function Get_Name_String
(Id
: Name_Id
) return String is
825 Buf
: Bounded_String
(Max_Length
=> Natural (Length_Of_Name
(Id
)));
831 --------------------------------
832 -- Get_Name_String_And_Append --
833 --------------------------------
835 procedure Get_Name_String_And_Append
(Id
: Name_Id
) is
837 Append
(Global_Name_Buffer
, Id
);
838 end Get_Name_String_And_Append
;
840 -----------------------------
841 -- Get_Name_Table_Boolean1 --
842 -----------------------------
844 function Get_Name_Table_Boolean1
(Id
: Name_Id
) return Boolean is
846 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
847 return Name_Entries
.Table
(Id
).Boolean1_Info
;
848 end Get_Name_Table_Boolean1
;
850 -----------------------------
851 -- Get_Name_Table_Boolean2 --
852 -----------------------------
854 function Get_Name_Table_Boolean2
(Id
: Name_Id
) return Boolean is
856 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
857 return Name_Entries
.Table
(Id
).Boolean2_Info
;
858 end Get_Name_Table_Boolean2
;
860 -----------------------------
861 -- Get_Name_Table_Boolean3 --
862 -----------------------------
864 function Get_Name_Table_Boolean3
(Id
: Name_Id
) return Boolean is
866 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
867 return Name_Entries
.Table
(Id
).Boolean3_Info
;
868 end Get_Name_Table_Boolean3
;
870 -------------------------
871 -- Get_Name_Table_Byte --
872 -------------------------
874 function Get_Name_Table_Byte
(Id
: Name_Id
) return Byte
is
876 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
877 return Name_Entries
.Table
(Id
).Byte_Info
;
878 end Get_Name_Table_Byte
;
880 -------------------------
881 -- Get_Name_Table_Int --
882 -------------------------
884 function Get_Name_Table_Int
(Id
: Name_Id
) return Int
is
886 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
887 return Name_Entries
.Table
(Id
).Int_Info
;
888 end Get_Name_Table_Int
;
890 -----------------------------------------
891 -- Get_Unqualified_Decoded_Name_String --
892 -----------------------------------------
894 procedure Get_Unqualified_Decoded_Name_String
(Id
: Name_Id
) is
896 Global_Name_Buffer
.Length
:= 0;
897 Append_Unqualified_Decoded
(Global_Name_Buffer
, Id
);
898 end Get_Unqualified_Decoded_Name_String
;
900 ---------------------------------
901 -- Get_Unqualified_Name_String --
902 ---------------------------------
904 procedure Get_Unqualified_Name_String
(Id
: Name_Id
) is
906 Global_Name_Buffer
.Length
:= 0;
907 Append_Unqualified
(Global_Name_Buffer
, Id
);
908 end Get_Unqualified_Name_String
;
914 function Hash
(Buf
: Bounded_String
) return Hash_Index_Type
is
916 -- This hash function looks at every character, in order to make it
917 -- likely that similar strings get different hash values. The rotate by
918 -- 7 bits has been determined empirically to be good, and it doesn't
919 -- lose bits like a shift would. The final conversion can't overflow,
920 -- because the table is 2**16 in size. This function probably needs to
921 -- be changed if the hash table size is changed.
923 -- Note that we could get some speed improvement by aligning the string
924 -- to 32 or 64 bits, and doing word-wise xor's. We could also implement
925 -- a growable table. It doesn't seem worth the trouble to do those
928 Result
: Unsigned_16
:= 0;
931 for J
in 1 .. Buf
.Length
loop
932 Result
:= Rotate_Left
(Result
, 7) xor Character'Pos (Buf
.Chars
(J
));
935 return Hash_Index_Type
(Result
);
942 procedure Initialize
is
952 (Buf
: in out Bounded_String
;
956 SL
: constant Natural := S
'Length;
959 Buf
.Chars
(Index
+ SL
.. Buf
.Length
+ SL
) :=
960 Buf
.Chars
(Index
.. Buf
.Length
);
961 Buf
.Chars
(Index
.. Index
+ SL
- 1) := S
;
962 Buf
.Length
:= Buf
.Length
+ SL
;
965 -------------------------------
966 -- Insert_Str_In_Name_Buffer --
967 -------------------------------
969 procedure Insert_Str_In_Name_Buffer
(S
: String; Index
: Positive) is
971 Insert_Str
(Global_Name_Buffer
, S
, Index
);
972 end Insert_Str_In_Name_Buffer
;
974 ----------------------
975 -- Is_Internal_Name --
976 ----------------------
978 function Is_Internal_Name
(Buf
: Bounded_String
) return Boolean is
982 -- Any name starting or ending with underscore is internal
984 if Buf
.Chars
(1) = '_'
985 or else Buf
.Chars
(Buf
.Length
) = '_'
989 -- Allow quoted character
991 elsif Buf
.Chars
(1) = ''' then
994 -- All other cases, scan name
997 -- Test backwards, because we only want to test the last entity
998 -- name if the name we have is qualified with other entities.
1003 -- Skip stuff between brackets (A-F OK there)
1005 if Buf
.Chars
(J
) = ']' then
1008 exit when J
= 1 or else Buf
.Chars
(J
) = '[';
1011 -- Test for internal letter
1013 elsif Is_OK_Internal_Letter
(Buf
.Chars
(J
)) then
1016 -- Quit if we come to terminating double underscore (note that
1017 -- if the current character is an underscore, we know that
1018 -- there is a previous character present, since we already
1019 -- filtered out the case of Buf.Chars (1) = '_' above.
1021 elsif Buf
.Chars
(J
) = '_'
1022 and then Buf
.Chars
(J
- 1) = '_'
1023 and then Buf
.Chars
(J
- 2) /= '_'
1033 end Is_Internal_Name
;
1035 function Is_Internal_Name
(Id
: Name_Id
) return Boolean is
1036 Buf
: Bounded_String
(Max_Length
=> Natural (Length_Of_Name
(Id
)));
1038 if Id
in Error_Name_Or_No_Name
then
1042 return Is_Internal_Name
(Buf
);
1044 end Is_Internal_Name
;
1046 function Is_Internal_Name
return Boolean is
1048 return Is_Internal_Name
(Global_Name_Buffer
);
1049 end Is_Internal_Name
;
1051 ---------------------------
1052 -- Is_OK_Internal_Letter --
1053 ---------------------------
1055 function Is_OK_Internal_Letter
(C
: Character) return Boolean is
1057 return C
in 'A' .. 'Z'
1063 end Is_OK_Internal_Letter
;
1065 ----------------------
1066 -- Is_Operator_Name --
1067 ----------------------
1069 function Is_Operator_Name
(Id
: Name_Id
) return Boolean is
1072 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
1073 S
:= Name_Entries
.Table
(Id
).Name_Chars_Index
;
1074 return Name_Chars
.Table
(S
+ 1) = 'O';
1075 end Is_Operator_Name
;
1081 function Is_Valid_Name
(Id
: Name_Id
) return Boolean is
1083 return Id
in Name_Entries
.First
.. Name_Entries
.Last
;
1086 --------------------
1087 -- Length_Of_Name --
1088 --------------------
1090 function Length_Of_Name
(Id
: Name_Id
) return Nat
is
1092 return Int
(Name_Entries
.Table
(Id
).Name_Len
);
1101 Name_Chars
.Set_Last
(Name_Chars
.Last
+ Name_Chars_Reserve
);
1102 Name_Entries
.Set_Last
(Name_Entries
.Last
+ Name_Entries_Reserve
);
1104 Name_Chars
.Locked
:= True;
1105 Name_Entries
.Release
;
1106 Name_Entries
.Locked
:= True;
1114 (Buf
: Bounded_String
:= Global_Name_Buffer
) return Name_Id
1118 ((Name_Chars_Index
=> Name_Chars
.Last
,
1119 Name_Len
=> Short
(Buf
.Length
),
1122 Boolean1_Info
=> False,
1123 Boolean2_Info
=> False,
1124 Boolean3_Info
=> False,
1125 Name_Has_No_Encodings
=> False,
1126 Hash_Link
=> No_Name
));
1128 -- Set corresponding string entry in the Name_Chars table
1130 for J
in 1 .. Buf
.Length
loop
1131 Name_Chars
.Append
(Buf
.Chars
(J
));
1134 Name_Chars
.Append
(ASCII
.NUL
);
1136 return Name_Entries
.Last
;
1139 function Name_Enter
(S
: String) return Name_Id
is
1140 Buf
: Bounded_String
(Max_Length
=> S
'Length);
1143 return Name_Enter
(Buf
);
1146 ------------------------
1147 -- Name_Entries_Count --
1148 ------------------------
1150 function Name_Entries_Count
return Nat
is
1152 return Int
(Name_Entries
.Last
- Name_Entries
.First
+ 1);
1153 end Name_Entries_Count
;
1160 (Buf
: Bounded_String
:= Global_Name_Buffer
) return Name_Id
1163 -- Id of entry in hash search, and value to be returned
1166 -- Pointer into string table
1168 Hash_Index
: Hash_Index_Type
;
1169 -- Computed hash index
1172 -- Quick handling for one character names
1174 if Buf
.Length
= 1 then
1175 return Name_Id
(First_Name_Id
+ Character'Pos (Buf
.Chars
(1)));
1177 -- Otherwise search hash table for existing matching entry
1180 Hash_Index
:= Namet
.Hash
(Buf
);
1181 New_Id
:= Hash_Table
(Hash_Index
);
1183 if New_Id
= No_Name
then
1184 Hash_Table
(Hash_Index
) := Name_Entries
.Last
+ 1;
1189 Integer (Name_Entries
.Table
(New_Id
).Name_Len
)
1194 S
:= Name_Entries
.Table
(New_Id
).Name_Chars_Index
;
1196 for J
in 1 .. Buf
.Length
loop
1197 if Name_Chars
.Table
(S
+ Int
(J
)) /= Buf
.Chars
(J
) then
1204 -- Current entry in hash chain does not match
1207 if Name_Entries
.Table
(New_Id
).Hash_Link
/= No_Name
then
1208 New_Id
:= Name_Entries
.Table
(New_Id
).Hash_Link
;
1210 Name_Entries
.Table
(New_Id
).Hash_Link
:=
1211 Name_Entries
.Last
+ 1;
1217 -- We fall through here only if a matching entry was not found in the
1218 -- hash table. We now create a new entry in the names table. The hash
1219 -- link pointing to the new entry (Name_Entries.Last+1) has been set.
1222 ((Name_Chars_Index
=> Name_Chars
.Last
,
1223 Name_Len
=> Short
(Buf
.Length
),
1224 Hash_Link
=> No_Name
,
1225 Name_Has_No_Encodings
=> False,
1228 Boolean1_Info
=> False,
1229 Boolean2_Info
=> False,
1230 Boolean3_Info
=> False));
1232 -- Set corresponding string entry in the Name_Chars table
1234 for J
in 1 .. Buf
.Length
loop
1235 Name_Chars
.Append
(Buf
.Chars
(J
));
1238 Name_Chars
.Append
(ASCII
.NUL
);
1240 return Name_Entries
.Last
;
1244 function Name_Find
(S
: String) return Name_Id
is
1245 Buf
: Bounded_String
(Max_Length
=> S
'Length);
1248 return Name_Find
(Buf
);
1258 V2
: Name_Id
) return Boolean
1261 return T
= V1
or else
1269 V3
: Name_Id
) return Boolean
1272 return T
= V1
or else
1282 V4
: Name_Id
) return Boolean
1285 return T
= V1
or else
1297 V5
: Name_Id
) return Boolean
1300 return T
= V1
or else
1314 V6
: Name_Id
) return Boolean
1317 return T
= V1
or else
1333 V7
: Name_Id
) return Boolean
1336 return T
= V1
or else
1354 V8
: Name_Id
) return Boolean
1357 return T
= V1
or else
1377 V9
: Name_Id
) return Boolean
1380 return T
= V1
or else
1402 V10
: Name_Id
) return Boolean
1405 return T
= V1
or else
1429 V11
: Name_Id
) return Boolean
1432 return T
= V1
or else
1458 V12
: Name_Id
) return Boolean
1461 return T
= V1
or else
1479 function Name_Equals
(N1
: Name_Id
; N2
: Name_Id
) return Boolean is
1481 return N1
= N2
or else Get_Name_String
(N1
) = Get_Name_String
(N2
);
1488 procedure Reinitialize
is
1493 -- Initialize entries for one character names
1495 for C
in Character loop
1497 ((Name_Chars_Index
=> Name_Chars
.Last
,
1501 Boolean1_Info
=> False,
1502 Boolean2_Info
=> False,
1503 Boolean3_Info
=> False,
1504 Name_Has_No_Encodings
=> True,
1505 Hash_Link
=> No_Name
));
1507 Name_Chars
.Append
(C
);
1508 Name_Chars
.Append
(ASCII
.NUL
);
1513 for J
in Hash_Index_Type
loop
1514 Hash_Table
(J
) := No_Name
;
1518 ----------------------
1519 -- Reset_Name_Table --
1520 ----------------------
1522 procedure Reset_Name_Table
is
1524 for J
in First_Name_Id
.. Name_Entries
.Last
loop
1525 Name_Entries
.Table
(J
).Int_Info
:= 0;
1526 Name_Entries
.Table
(J
).Byte_Info
:= 0;
1528 end Reset_Name_Table
;
1530 --------------------------------
1531 -- Set_Character_Literal_Name --
1532 --------------------------------
1534 procedure Set_Character_Literal_Name
1535 (Buf
: in out Bounded_String
;
1541 Append_Encoded
(Buf
, C
);
1542 end Set_Character_Literal_Name
;
1544 procedure Set_Character_Literal_Name
(C
: Char_Code
) is
1546 Set_Character_Literal_Name
(Global_Name_Buffer
, C
);
1547 end Set_Character_Literal_Name
;
1549 -----------------------------
1550 -- Set_Name_Table_Boolean1 --
1551 -----------------------------
1553 procedure Set_Name_Table_Boolean1
(Id
: Name_Id
; Val
: Boolean) is
1555 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
1556 Name_Entries
.Table
(Id
).Boolean1_Info
:= Val
;
1557 end Set_Name_Table_Boolean1
;
1559 -----------------------------
1560 -- Set_Name_Table_Boolean2 --
1561 -----------------------------
1563 procedure Set_Name_Table_Boolean2
(Id
: Name_Id
; Val
: Boolean) is
1565 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
1566 Name_Entries
.Table
(Id
).Boolean2_Info
:= Val
;
1567 end Set_Name_Table_Boolean2
;
1569 -----------------------------
1570 -- Set_Name_Table_Boolean3 --
1571 -----------------------------
1573 procedure Set_Name_Table_Boolean3
(Id
: Name_Id
; Val
: Boolean) is
1575 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
1576 Name_Entries
.Table
(Id
).Boolean3_Info
:= Val
;
1577 end Set_Name_Table_Boolean3
;
1579 -------------------------
1580 -- Set_Name_Table_Byte --
1581 -------------------------
1583 procedure Set_Name_Table_Byte
(Id
: Name_Id
; Val
: Byte
) is
1585 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
1586 Name_Entries
.Table
(Id
).Byte_Info
:= Val
;
1587 end Set_Name_Table_Byte
;
1589 -------------------------
1590 -- Set_Name_Table_Int --
1591 -------------------------
1593 procedure Set_Name_Table_Int
(Id
: Name_Id
; Val
: Int
) is
1595 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
1596 Name_Entries
.Table
(Id
).Int_Info
:= Val
;
1597 end Set_Name_Table_Int
;
1599 -----------------------------
1600 -- Store_Encoded_Character --
1601 -----------------------------
1603 procedure Store_Encoded_Character
(C
: Char_Code
) is
1605 Append_Encoded
(Global_Name_Buffer
, C
);
1606 end Store_Encoded_Character
;
1608 --------------------------------------
1609 -- Strip_Qualification_And_Suffixes --
1610 --------------------------------------
1612 procedure Strip_Qualification_And_Suffixes
(Buf
: in out Bounded_String
) is
1616 -- Strip package body qualification string off end
1618 for J
in reverse 2 .. Buf
.Length
loop
1619 if Buf
.Chars
(J
) = 'X' then
1620 Buf
.Length
:= J
- 1;
1624 exit when Buf
.Chars
(J
) /= 'b'
1625 and then Buf
.Chars
(J
) /= 'n'
1626 and then Buf
.Chars
(J
) /= 'p';
1629 -- Find rightmost __ or $ separator if one exists. First we position
1630 -- to start the search. If we have a character constant, position
1631 -- just before it, otherwise position to last character but one
1633 if Buf
.Chars
(Buf
.Length
) = ''' then
1634 J
:= Buf
.Length
- 2;
1635 while J
> 0 and then Buf
.Chars
(J
) /= ''' loop
1640 J
:= Buf
.Length
- 1;
1643 -- Loop to search for rightmost __ or $ (homonym) separator
1647 -- If $ separator, homonym separator, so strip it and keep looking
1649 if Buf
.Chars
(J
) = '$' then
1650 Buf
.Length
:= J
- 1;
1651 J
:= Buf
.Length
- 1;
1653 -- Else check for __ found
1655 elsif Buf
.Chars
(J
) = '_' and then Buf
.Chars
(J
+ 1) = '_' then
1657 -- Found __ so see if digit follows, and if so, this is a
1658 -- homonym separator, so strip it and keep looking.
1660 if Buf
.Chars
(J
+ 2) in '0' .. '9' then
1661 Buf
.Length
:= J
- 1;
1662 J
:= Buf
.Length
- 1;
1664 -- If not a homonym separator, then we simply strip the
1665 -- separator and everything that precedes it, and we are done
1668 Buf
.Chars
(1 .. Buf
.Length
- J
- 1) :=
1669 Buf
.Chars
(J
+ 2 .. Buf
.Length
);
1670 Buf
.Length
:= Buf
.Length
- J
- 1;
1678 end Strip_Qualification_And_Suffixes
;
1684 function To_String
(Buf
: Bounded_String
) return String is
1686 return Buf
.Chars
(1 .. Buf
.Length
);
1693 procedure Tree_Read
is
1695 Name_Chars
.Tree_Read
;
1696 Name_Entries
.Tree_Read
;
1699 (Hash_Table
'Address,
1700 Hash_Table
'Length * (Hash_Table
'Component_Size / Storage_Unit
));
1707 procedure Tree_Write
is
1709 Name_Chars
.Tree_Write
;
1710 Name_Entries
.Tree_Write
;
1713 (Hash_Table
'Address,
1714 Hash_Table
'Length * (Hash_Table
'Component_Size / Storage_Unit
));
1723 Name_Chars
.Locked
:= False;
1724 Name_Chars
.Set_Last
(Name_Chars
.Last
- Name_Chars_Reserve
);
1726 Name_Entries
.Locked
:= False;
1727 Name_Entries
.Set_Last
(Name_Entries
.Last
- Name_Entries_Reserve
);
1728 Name_Entries
.Release
;
1735 procedure wn
(Id
: Name_Id
) is
1737 if Id
not in Name_Entries
.First
.. Name_Entries
.Last
then
1738 Write_Str
("<invalid name_id>");
1740 elsif Id
= No_Name
then
1741 Write_Str
("<No_Name>");
1743 elsif Id
= Error_Name
then
1744 Write_Str
("<Error_Name>");
1748 Buf
: Bounded_String
(Max_Length
=> Natural (Length_Of_Name
(Id
)));
1751 Write_Str
(Buf
.Chars
(1 .. Buf
.Length
));
1762 procedure Write_Name
(Id
: Name_Id
) is
1763 Buf
: Bounded_String
(Max_Length
=> Natural (Length_Of_Name
(Id
)));
1765 if Id
>= First_Name_Id
then
1767 Write_Str
(Buf
.Chars
(1 .. Buf
.Length
));
1771 ------------------------
1772 -- Write_Name_Decoded --
1773 ------------------------
1775 procedure Write_Name_Decoded
(Id
: Name_Id
) is
1776 Buf
: Bounded_String
;
1778 if Id
>= First_Name_Id
then
1779 Append_Decoded
(Buf
, Id
);
1780 Write_Str
(Buf
.Chars
(1 .. Buf
.Length
));
1782 end Write_Name_Decoded
;
1784 -- Package initialization, initialize tables