1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2015, 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 Tree_IO
; use Tree_IO
;
40 with Widechar
; use Widechar
;
42 with Interfaces
; use Interfaces
;
46 Name_Chars_Reserve
: constant := 5000;
47 Name_Entries_Reserve
: constant := 100;
48 -- The names table is locked during gigi processing, since gigi assumes
49 -- that the table does not move. After returning from gigi, the names
50 -- table is unlocked again, since writing library file information needs
51 -- to generate some extra names. To avoid the inefficiency of always
52 -- reallocating during this second unlocked phase, we reserve a bit of
53 -- extra space before doing the release call.
55 Hash_Num
: constant Int
:= 2**16;
56 -- Number of headers in the hash table. Current hash algorithm is closely
57 -- tailored to this choice, so it can only be changed if a corresponding
58 -- change is made to the hash algorithm.
60 Hash_Max
: constant Int
:= Hash_Num
- 1;
61 -- Indexes in the hash header table run from 0 to Hash_Num - 1
63 subtype Hash_Index_Type
is Int
range 0 .. Hash_Max
;
64 -- Range of hash index values
66 Hash_Table
: array (Hash_Index_Type
) of Name_Id
;
67 -- The hash table is used to locate existing entries in the names table.
68 -- The entries point to the first names table entry whose hash value
69 -- matches the hash code. Then subsequent names table entries with the
70 -- same hash code value are linked through the Hash_Link fields.
72 -----------------------
73 -- Local Subprograms --
74 -----------------------
76 function Hash
(Buf
: Bounded_String
) return Hash_Index_Type
;
78 -- Compute hash code for name stored in Buf
80 procedure Strip_Qualification_And_Suffixes
(Buf
: in out Bounded_String
);
81 -- Given an encoded entity name in Buf, remove package body
82 -- suffix as described for Strip_Package_Body_Suffix, and also remove
83 -- all qualification, i.e. names followed by two underscores.
85 -----------------------------
86 -- Add_Char_To_Name_Buffer --
87 -----------------------------
89 procedure Add_Char_To_Name_Buffer
(C
: Character) is
91 Append
(Global_Name_Buffer
, C
);
92 end Add_Char_To_Name_Buffer
;
94 ----------------------------
95 -- Add_Nat_To_Name_Buffer --
96 ----------------------------
98 procedure Add_Nat_To_Name_Buffer
(V
: Nat
) is
100 Append
(Global_Name_Buffer
, V
);
101 end Add_Nat_To_Name_Buffer
;
103 ----------------------------
104 -- Add_Str_To_Name_Buffer --
105 ----------------------------
107 procedure Add_Str_To_Name_Buffer
(S
: String) is
109 Append
(Global_Name_Buffer
, S
);
110 end Add_Str_To_Name_Buffer
;
116 procedure Append
(Buf
: in out Bounded_String
; C
: Character) is
118 if Buf
.Length
< Buf
.Chars
'Last then
119 Buf
.Length
:= Buf
.Length
+ 1;
120 Buf
.Chars
(Buf
.Length
) := C
;
124 procedure Append
(Buf
: in out Bounded_String
; V
: Nat
) is
127 Append
(Buf
, V
/ 10);
130 Append
(Buf
, Character'Val (Character'Pos ('0') + V
rem 10));
133 procedure Append
(Buf
: in out Bounded_String
; S
: String) is
135 for J
in S
'Range loop
140 procedure Append
(Buf
: in out Bounded_String
; Buf2
: Bounded_String
) is
142 Append
(Buf
, Buf2
.Chars
(1 .. Buf2
.Length
));
145 procedure Append
(Buf
: in out Bounded_String
; Id
: Name_Id
) is
146 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
147 S
: constant Int
:= Name_Entries
.Table
(Id
).Name_Chars_Index
;
150 for J
in 1 .. Natural (Name_Entries
.Table
(Id
).Name_Len
) loop
151 Append
(Buf
, Name_Chars
.Table
(S
+ Int
(J
)));
159 procedure Append_Decoded
(Buf
: in out Bounded_String
; Id
: Name_Id
) is
162 Temp
: Bounded_String
;
167 -- Skip scan if we already know there are no encodings
169 if Name_Entries
.Table
(Id
).Name_Has_No_Encodings
then
173 -- Quick loop to see if there is anything special to do
177 if P
= Temp
.Length
then
178 Name_Entries
.Table
(Id
).Name_Has_No_Encodings
:= True;
194 -- Here we have at least some encoding that we must decode
199 New_Buf
: String (1 .. Temp
.Chars
'Last);
201 procedure Copy_One_Character
;
202 -- Copy a character from Temp.Chars to New_Buf. Includes case
203 -- of copying a Uhh,Whhhh,WWhhhhhhhh sequence and decoding it.
205 function Hex
(N
: Natural) return Word
;
206 -- Scans past N digits using Old pointer and returns hex value
208 procedure Insert_Character
(C
: Character);
209 -- Insert a new character into output decoded name
211 ------------------------
212 -- Copy_One_Character --
213 ------------------------
215 procedure Copy_One_Character
is
219 C
:= Temp
.Chars
(Old
);
221 -- U (upper half insertion case)
224 and then Old
< Temp
.Length
225 and then Temp
.Chars
(Old
+ 1) not in 'A' .. 'Z'
226 and then Temp
.Chars
(Old
+ 1) /= '_'
230 -- If we have upper half encoding, then we have to set an
231 -- appropriate wide character sequence for this character.
233 if Upper_Half_Encoding
then
234 Widechar
.Set_Wide
(Char_Code
(Hex
(2)), New_Buf
, New_Len
);
236 -- For other encoding methods, upper half characters can
237 -- simply use their normal representation.
240 Insert_Character
(Character'Val (Hex
(2)));
243 -- WW (wide wide character insertion)
246 and then Old
< Temp
.Length
247 and then Temp
.Chars
(Old
+ 1) = 'W'
250 Widechar
.Set_Wide
(Char_Code
(Hex
(8)), New_Buf
, New_Len
);
252 -- W (wide character insertion)
255 and then Old
< Temp
.Length
256 and then Temp
.Chars
(Old
+ 1) not in 'A' .. 'Z'
257 and then Temp
.Chars
(Old
+ 1) /= '_'
260 Widechar
.Set_Wide
(Char_Code
(Hex
(4)), New_Buf
, New_Len
);
262 -- Any other character is copied unchanged
265 Insert_Character
(C
);
268 end Copy_One_Character
;
274 function Hex
(N
: Natural) return Word
is
280 C
:= Temp
.Chars
(Old
);
283 pragma Assert
(C
in '0' .. '9' or else C
in 'a' .. 'f');
286 T
:= 16 * T
+ Character'Pos (C
) - Character'Pos ('0');
287 else -- C in 'a' .. 'f'
288 T
:= 16 * T
+ Character'Pos (C
) - (Character'Pos ('a') - 10);
295 ----------------------
296 -- Insert_Character --
297 ----------------------
299 procedure Insert_Character
(C
: Character) is
301 New_Len
:= New_Len
+ 1;
302 New_Buf
(New_Len
) := C
;
303 end Insert_Character
;
305 -- Start of processing for Decode
311 -- Loop through characters of name
313 while Old
<= Temp
.Length
loop
315 -- Case of character literal, put apostrophes around character
317 if Temp
.Chars
(Old
) = 'Q'
318 and then Old
< Temp
.Length
321 Insert_Character
(''');
323 Insert_Character
(''');
325 -- Case of operator name
327 elsif Temp
.Chars
(Old
) = 'O'
328 and then Old
< Temp
.Length
329 and then Temp
.Chars
(Old
+ 1) not in 'A' .. 'Z'
330 and then Temp
.Chars
(Old
+ 1) /= '_'
335 -- This table maps the 2nd and 3rd characters of the name
336 -- into the required output. Two blanks means leave the
339 Map
: constant String :=
340 "ab " & -- Oabs => "abs"
341 "ad+ " & -- Oadd => "+"
342 "an " & -- Oand => "and"
343 "co& " & -- Oconcat => "&"
344 "di/ " & -- Odivide => "/"
345 "eq= " & -- Oeq => "="
346 "ex**" & -- Oexpon => "**"
347 "gt> " & -- Ogt => ">"
348 "ge>=" & -- Oge => ">="
349 "le<=" & -- Ole => "<="
350 "lt< " & -- Olt => "<"
351 "mo " & -- Omod => "mod"
352 "mu* " & -- Omutliply => "*"
353 "ne/=" & -- One => "/="
354 "no " & -- Onot => "not"
355 "or " & -- Oor => "or"
356 "re " & -- Orem => "rem"
357 "su- " & -- Osubtract => "-"
358 "xo "; -- Oxor => "xor"
363 Insert_Character
('"');
365 -- Search the map. Note that this loop must terminate, if
366 -- not we have some kind of internal error, and a constraint
367 -- error may be raised.
371 exit when Temp
.Chars
(Old
) = Map
(J
)
372 and then Temp
.Chars
(Old
+ 1) = Map
(J
+ 1);
376 -- Special operator name
378 if Map
(J
+ 2) /= ' ' then
379 Insert_Character
(Map
(J
+ 2));
381 if Map
(J
+ 3) /= ' ' then
382 Insert_Character
(Map
(J
+ 3));
385 Insert_Character
('"');
387 -- Skip past original operator name in input
389 while Old
<= Temp
.Length
390 and then Temp
.Chars
(Old
) in 'a' .. 'z'
395 -- For other operator names, leave them in lower case,
396 -- surrounded by apostrophes
399 -- Copy original operator name from input to output
401 while Old
<= Temp
.Length
402 and then Temp
.Chars
(Old
) in 'a' .. 'z'
407 Insert_Character
('"');
411 -- Else copy one character and keep going
418 -- Copy new buffer as result
420 Temp
.Length
:= New_Len
;
421 Temp
.Chars
(1 .. New_Len
) := New_Buf
(1 .. New_Len
);
428 ----------------------------------
429 -- Append_Decoded_With_Brackets --
430 ----------------------------------
432 procedure Append_Decoded_With_Brackets
433 (Buf
: in out Bounded_String
;
439 -- Case of operator name, normal decoding is fine
441 if Buf
.Chars
(1) = 'O' then
442 Append_Decoded
(Buf
, Id
);
444 -- For character literals, normal decoding is fine
446 elsif Buf
.Chars
(1) = 'Q' then
447 Append_Decoded
(Buf
, Id
);
449 -- Only remaining issue is U/W/WW sequences
453 Temp
: Bounded_String
;
458 while P
< Temp
.Length
loop
459 if Temp
.Chars
(P
+ 1) in 'A' .. 'Z' then
464 elsif Temp
.Chars
(P
) = 'U' then
465 for J
in reverse P
+ 3 .. P
+ Temp
.Length
loop
466 Temp
.Chars
(J
+ 3) := Temp
.Chars
(J
);
469 Temp
.Length
:= Temp
.Length
+ 3;
470 Temp
.Chars
(P
+ 3) := Temp
.Chars
(P
+ 2);
471 Temp
.Chars
(P
+ 2) := Temp
.Chars
(P
+ 1);
472 Temp
.Chars
(P
) := '[';
473 Temp
.Chars
(P
+ 1) := '"';
474 Temp
.Chars
(P
+ 4) := '"';
475 Temp
.Chars
(P
+ 5) := ']';
478 -- WWhhhhhhhh encoding
480 elsif Temp
.Chars
(P
) = 'W'
481 and then P
+ 9 <= Temp
.Length
482 and then Temp
.Chars
(P
+ 1) = 'W'
483 and then Temp
.Chars
(P
+ 2) not in 'A' .. 'Z'
484 and then Temp
.Chars
(P
+ 2) /= '_'
486 Temp
.Chars
(P
+ 12 .. Temp
.Length
+ 2) :=
487 Temp
.Chars
(P
+ 10 .. Temp
.Length
);
488 Temp
.Chars
(P
) := '[';
489 Temp
.Chars
(P
+ 1) := '"';
490 Temp
.Chars
(P
+ 10) := '"';
491 Temp
.Chars
(P
+ 11) := ']';
492 Temp
.Length
:= Temp
.Length
+ 2;
497 elsif Temp
.Chars
(P
) = 'W'
498 and then P
< Temp
.Length
499 and then Temp
.Chars
(P
+ 1) not in 'A' .. 'Z'
500 and then Temp
.Chars
(P
+ 1) /= '_'
502 Temp
.Chars
(P
+ 8 .. P
+ Temp
.Length
+ 3) :=
503 Temp
.Chars
(P
+ 5 .. Temp
.Length
);
504 Temp
.Chars
(P
+ 2 .. P
+ 5) := Temp
.Chars
(P
+ 1 .. P
+ 4);
505 Temp
.Chars
(P
) := '[';
506 Temp
.Chars
(P
+ 1) := '"';
507 Temp
.Chars
(P
+ 6) := '"';
508 Temp
.Chars
(P
+ 7) := ']';
509 Temp
.Length
:= Temp
.Length
+ 3;
520 end Append_Decoded_With_Brackets
;
526 procedure Append_Encoded
(Buf
: in out Bounded_String
; C
: Char_Code
) is
527 procedure Set_Hex_Chars
(C
: Char_Code
);
528 -- Stores given value, which is in the range 0 .. 255, as two hex
529 -- digits (using lower case a-f) in Buf.Chars, incrementing Buf.Length.
535 procedure Set_Hex_Chars
(C
: Char_Code
) is
536 Hexd
: constant String := "0123456789abcdef";
537 N
: constant Natural := Natural (C
);
539 Buf
.Chars
(Buf
.Length
+ 1) := Hexd
(N
/ 16 + 1);
540 Buf
.Chars
(Buf
.Length
+ 2) := Hexd
(N
mod 16 + 1);
541 Buf
.Length
:= Buf
.Length
+ 2;
544 -- Start of processing for Append_Encoded
547 Buf
.Length
:= Buf
.Length
+ 1;
549 if In_Character_Range
(C
) then
551 CC
: constant Character := Get_Character
(C
);
553 if CC
in 'a' .. 'z' or else CC
in '0' .. '9' then
554 Buf
.Chars
(Buf
.Length
) := CC
;
556 Buf
.Chars
(Buf
.Length
) := 'U';
561 elsif In_Wide_Character_Range
(C
) then
562 Buf
.Chars
(Buf
.Length
) := 'W';
563 Set_Hex_Chars
(C
/ 256);
564 Set_Hex_Chars
(C
mod 256);
567 Buf
.Chars
(Buf
.Length
) := 'W';
568 Buf
.Length
:= Buf
.Length
+ 1;
569 Buf
.Chars
(Buf
.Length
) := 'W';
570 Set_Hex_Chars
(C
/ 2 ** 24);
571 Set_Hex_Chars
((C
/ 2 ** 16) mod 256);
572 Set_Hex_Chars
((C
/ 256) mod 256);
573 Set_Hex_Chars
(C
mod 256);
577 ------------------------
578 -- Append_Unqualified --
579 ------------------------
581 procedure Append_Unqualified
(Buf
: in out Bounded_String
; Id
: Name_Id
) is
582 Temp
: Bounded_String
;
585 Strip_Qualification_And_Suffixes
(Temp
);
587 end Append_Unqualified
;
589 --------------------------------
590 -- Append_Unqualified_Decoded --
591 --------------------------------
593 procedure Append_Unqualified_Decoded
594 (Buf
: in out Bounded_String
;
597 Temp
: Bounded_String
;
599 Append_Decoded
(Temp
, Id
);
600 Strip_Qualification_And_Suffixes
(Temp
);
602 end Append_Unqualified_Decoded
;
608 procedure Finalize
is
609 F
: array (Int
range 0 .. 50) of Int
;
610 -- N'th entry is the number of chains of length N, except last entry,
611 -- which is the number of chains of length F'Last or more.
613 Max_Chain_Length
: Nat
:= 0;
614 -- Maximum length of all chains
617 -- Used to compute average number of probes
620 -- Number of symbols in table
622 Verbosity
: constant Int
range 1 .. 3 := 1;
623 pragma Warnings
(Off
, Verbosity
);
624 -- This constant indicates the level of verbosity in the output from
625 -- this procedure. Currently this can only be changed by editing the
626 -- declaration above and recompiling. That's good enough in practice,
627 -- since we very rarely need to use this debug option. Settings are:
629 -- 1 => print basic summary information
630 -- 2 => in addition print number of entries per hash chain
631 -- 3 => in addition print content of entries
633 Zero
: constant Int
:= Character'Pos ('0');
636 if not Debug_Flag_H
then
640 for J
in F
'Range loop
644 for J
in Hash_Index_Type
loop
645 if Hash_Table
(J
) = No_Name
then
658 while N
/= No_Name
loop
659 N
:= Name_Entries
.Table
(N
).Hash_Link
;
664 Probes
:= Probes
+ (1 + C
) * 100;
666 if C
> Max_Chain_Length
then
667 Max_Chain_Length
:= C
;
670 if Verbosity
>= 2 then
671 Write_Str
("Hash_Table (");
673 Write_Str
(") has ");
675 Write_Str
(" entries");
682 F
(F
'Last) := F
(F
'Last) + 1;
685 if Verbosity
>= 3 then
687 while N
/= No_Name
loop
688 S
:= Name_Entries
.Table
(N
).Name_Chars_Index
;
692 for J
in 1 .. Name_Entries
.Table
(N
).Name_Len
loop
693 Write_Char
(Name_Chars
.Table
(S
+ Int
(J
)));
698 N
:= Name_Entries
.Table
(N
).Hash_Link
;
707 for J
in F
'Range loop
709 Write_Str
("Number of hash chains of length ");
718 Write_Str
(" or greater");
727 -- Print out average number of probes, in the case where Name_Find is
728 -- called for a string that is already in the table.
731 Write_Str
("Average number of probes for lookup = ");
732 Probes
:= Probes
/ Nsyms
;
733 Write_Int
(Probes
/ 200);
735 Probes
:= (Probes
mod 200) / 2;
736 Write_Char
(Character'Val (Zero
+ Probes
/ 10));
737 Write_Char
(Character'Val (Zero
+ Probes
mod 10));
740 Write_Str
("Max_Chain_Length = ");
741 Write_Int
(Max_Chain_Length
);
743 Write_Str
("Name_Chars'Length = ");
744 Write_Int
(Name_Chars
.Last
- Name_Chars
.First
+ 1);
746 Write_Str
("Name_Entries'Length = ");
747 Write_Int
(Int
(Name_Entries
.Last
- Name_Entries
.First
+ 1));
749 Write_Str
("Nsyms = ");
754 -----------------------------
755 -- Get_Decoded_Name_String --
756 -----------------------------
758 procedure Get_Decoded_Name_String
(Id
: Name_Id
) is
760 Global_Name_Buffer
.Length
:= 0;
761 Append_Decoded
(Global_Name_Buffer
, Id
);
762 end Get_Decoded_Name_String
;
764 -------------------------------------------
765 -- Get_Decoded_Name_String_With_Brackets --
766 -------------------------------------------
768 procedure Get_Decoded_Name_String_With_Brackets
(Id
: Name_Id
) is
770 Global_Name_Buffer
.Length
:= 0;
771 Append_Decoded_With_Brackets
(Global_Name_Buffer
, Id
);
772 end Get_Decoded_Name_String_With_Brackets
;
774 ------------------------
775 -- Get_Last_Two_Chars --
776 ------------------------
778 procedure Get_Last_Two_Chars
783 NE
: Name_Entry
renames Name_Entries
.Table
(N
);
784 NEL
: constant Int
:= Int
(NE
.Name_Len
);
788 C1
:= Name_Chars
.Table
(NE
.Name_Chars_Index
+ NEL
- 1);
789 C2
:= Name_Chars
.Table
(NE
.Name_Chars_Index
+ NEL
- 0);
794 end Get_Last_Two_Chars
;
796 ---------------------
797 -- Get_Name_String --
798 ---------------------
800 procedure Get_Name_String
(Id
: Name_Id
) is
802 Global_Name_Buffer
.Length
:= 0;
803 Append
(Global_Name_Buffer
, Id
);
806 function Get_Name_String
(Id
: Name_Id
) return String is
807 Buf
: Bounded_String
;
813 --------------------------------
814 -- Get_Name_String_And_Append --
815 --------------------------------
817 procedure Get_Name_String_And_Append
(Id
: Name_Id
) is
819 Append
(Global_Name_Buffer
, Id
);
820 end Get_Name_String_And_Append
;
822 -----------------------------
823 -- Get_Name_Table_Boolean1 --
824 -----------------------------
826 function Get_Name_Table_Boolean1
(Id
: Name_Id
) return Boolean is
828 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
829 return Name_Entries
.Table
(Id
).Boolean1_Info
;
830 end Get_Name_Table_Boolean1
;
832 -----------------------------
833 -- Get_Name_Table_Boolean2 --
834 -----------------------------
836 function Get_Name_Table_Boolean2
(Id
: Name_Id
) return Boolean is
838 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
839 return Name_Entries
.Table
(Id
).Boolean2_Info
;
840 end Get_Name_Table_Boolean2
;
842 -----------------------------
843 -- Get_Name_Table_Boolean3 --
844 -----------------------------
846 function Get_Name_Table_Boolean3
(Id
: Name_Id
) return Boolean is
848 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
849 return Name_Entries
.Table
(Id
).Boolean3_Info
;
850 end Get_Name_Table_Boolean3
;
852 -------------------------
853 -- Get_Name_Table_Byte --
854 -------------------------
856 function Get_Name_Table_Byte
(Id
: Name_Id
) return Byte
is
858 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
859 return Name_Entries
.Table
(Id
).Byte_Info
;
860 end Get_Name_Table_Byte
;
862 -------------------------
863 -- Get_Name_Table_Int --
864 -------------------------
866 function Get_Name_Table_Int
(Id
: Name_Id
) return Int
is
868 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
869 return Name_Entries
.Table
(Id
).Int_Info
;
870 end Get_Name_Table_Int
;
872 -----------------------------------------
873 -- Get_Unqualified_Decoded_Name_String --
874 -----------------------------------------
876 procedure Get_Unqualified_Decoded_Name_String
(Id
: Name_Id
) is
878 Global_Name_Buffer
.Length
:= 0;
879 Append_Unqualified_Decoded
(Global_Name_Buffer
, Id
);
880 end Get_Unqualified_Decoded_Name_String
;
882 ---------------------------------
883 -- Get_Unqualified_Name_String --
884 ---------------------------------
886 procedure Get_Unqualified_Name_String
(Id
: Name_Id
) is
888 Global_Name_Buffer
.Length
:= 0;
889 Append_Unqualified
(Global_Name_Buffer
, Id
);
890 end Get_Unqualified_Name_String
;
896 function Hash
(Buf
: Bounded_String
) return Hash_Index_Type
is
898 -- This hash function looks at every character, in order to make it
899 -- likely that similar strings get different hash values. The rotate by
900 -- 7 bits has been determined empirically to be good, and it doesn't
901 -- lose bits like a shift would. The final conversion can't overflow,
902 -- because the table is 2**16 in size. This function probably needs to
903 -- be changed if the hash table size is changed.
905 -- Note that we could get some speed improvement by aligning the string
906 -- to 32 or 64 bits, and doing word-wise xor's. We could also implement
907 -- a growable table. It doesn't seem worth the trouble to do those
910 Result
: Unsigned_16
:= 0;
913 for J
in 1 .. Buf
.Length
loop
914 Result
:= Rotate_Left
(Result
, 7) xor Character'Pos (Buf
.Chars
(J
));
917 return Hash_Index_Type
(Result
);
924 procedure Initialize
is
934 (Buf
: in out Bounded_String
;
938 SL
: constant Natural := S
'Length;
941 Buf
.Chars
(Index
+ SL
.. Buf
.Length
+ SL
) :=
942 Buf
.Chars
(Index
.. Buf
.Length
);
943 Buf
.Chars
(Index
.. Index
+ SL
- 1) := S
;
944 Buf
.Length
:= Buf
.Length
+ SL
;
947 -------------------------------
948 -- Insert_Str_In_Name_Buffer --
949 -------------------------------
951 procedure Insert_Str_In_Name_Buffer
(S
: String; Index
: Positive) is
953 Insert_Str
(Global_Name_Buffer
, S
, Index
);
954 end Insert_Str_In_Name_Buffer
;
956 ----------------------
957 -- Is_Internal_Name --
958 ----------------------
960 function Is_Internal_Name
(Buf
: Bounded_String
) return Boolean is
964 -- Any name starting or ending with underscore is internal
966 if Buf
.Chars
(1) = '_'
967 or else Buf
.Chars
(Buf
.Length
) = '_'
971 -- Allow quoted character
973 elsif Buf
.Chars
(1) = ''' then
976 -- All other cases, scan name
979 -- Test backwards, because we only want to test the last entity
980 -- name if the name we have is qualified with other entities.
985 -- Skip stuff between brackets (A-F OK there)
987 if Buf
.Chars
(J
) = ']' then
990 exit when J
= 1 or else Buf
.Chars
(J
) = '[';
993 -- Test for internal letter
995 elsif Is_OK_Internal_Letter
(Buf
.Chars
(J
)) then
998 -- Quit if we come to terminating double underscore (note that
999 -- if the current character is an underscore, we know that
1000 -- there is a previous character present, since we already
1001 -- filtered out the case of Buf.Chars (1) = '_' above.
1003 elsif Buf
.Chars
(J
) = '_'
1004 and then Buf
.Chars
(J
- 1) = '_'
1005 and then Buf
.Chars
(J
- 2) /= '_'
1015 end Is_Internal_Name
;
1017 function Is_Internal_Name
(Id
: Name_Id
) return Boolean is
1018 Buf
: Bounded_String
;
1020 if Id
in Error_Name_Or_No_Name
then
1024 return Is_Internal_Name
(Buf
);
1026 end Is_Internal_Name
;
1028 function Is_Internal_Name
return Boolean is
1030 return Is_Internal_Name
(Global_Name_Buffer
);
1031 end Is_Internal_Name
;
1033 ---------------------------
1034 -- Is_OK_Internal_Letter --
1035 ---------------------------
1037 function Is_OK_Internal_Letter
(C
: Character) return Boolean is
1039 return C
in 'A' .. 'Z'
1045 end Is_OK_Internal_Letter
;
1047 ----------------------
1048 -- Is_Operator_Name --
1049 ----------------------
1051 function Is_Operator_Name
(Id
: Name_Id
) return Boolean is
1054 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
1055 S
:= Name_Entries
.Table
(Id
).Name_Chars_Index
;
1056 return Name_Chars
.Table
(S
+ 1) = 'O';
1057 end Is_Operator_Name
;
1063 function Is_Valid_Name
(Id
: Name_Id
) return Boolean is
1065 return Id
in Name_Entries
.First
.. Name_Entries
.Last
;
1068 --------------------
1069 -- Length_Of_Name --
1070 --------------------
1072 function Length_Of_Name
(Id
: Name_Id
) return Nat
is
1074 return Int
(Name_Entries
.Table
(Id
).Name_Len
);
1083 Name_Chars
.Set_Last
(Name_Chars
.Last
+ Name_Chars_Reserve
);
1084 Name_Entries
.Set_Last
(Name_Entries
.Last
+ Name_Entries_Reserve
);
1085 Name_Chars
.Locked
:= True;
1086 Name_Entries
.Locked
:= True;
1088 Name_Entries
.Release
;
1091 ------------------------
1092 -- Name_Chars_Address --
1093 ------------------------
1095 function Name_Chars_Address
return System
.Address
is
1097 return Name_Chars
.Table
(0)'Address;
1098 end Name_Chars_Address
;
1105 (Buf
: Bounded_String
:= Global_Name_Buffer
) return Name_Id
1109 ((Name_Chars_Index
=> Name_Chars
.Last
,
1110 Name_Len
=> Short
(Buf
.Length
),
1113 Boolean1_Info
=> False,
1114 Boolean2_Info
=> False,
1115 Boolean3_Info
=> False,
1116 Name_Has_No_Encodings
=> False,
1117 Hash_Link
=> No_Name
));
1119 -- Set corresponding string entry in the Name_Chars table
1121 for J
in 1 .. Buf
.Length
loop
1122 Name_Chars
.Append
(Buf
.Chars
(J
));
1125 Name_Chars
.Append
(ASCII
.NUL
);
1127 return Name_Entries
.Last
;
1130 --------------------------
1131 -- Name_Entries_Address --
1132 --------------------------
1134 function Name_Entries_Address
return System
.Address
is
1136 return Name_Entries
.Table
(First_Name_Id
)'Address;
1137 end Name_Entries_Address
;
1139 ------------------------
1140 -- Name_Entries_Count --
1141 ------------------------
1143 function Name_Entries_Count
return Nat
is
1145 return Int
(Name_Entries
.Last
- Name_Entries
.First
+ 1);
1146 end Name_Entries_Count
;
1153 (Buf
: Bounded_String
:= Global_Name_Buffer
) return Name_Id
1156 -- Id of entry in hash search, and value to be returned
1159 -- Pointer into string table
1161 Hash_Index
: Hash_Index_Type
;
1162 -- Computed hash index
1165 -- Quick handling for one character names
1167 if Buf
.Length
= 1 then
1168 return Name_Id
(First_Name_Id
+ Character'Pos (Buf
.Chars
(1)));
1170 -- Otherwise search hash table for existing matching entry
1173 Hash_Index
:= Namet
.Hash
(Buf
);
1174 New_Id
:= Hash_Table
(Hash_Index
);
1176 if New_Id
= No_Name
then
1177 Hash_Table
(Hash_Index
) := Name_Entries
.Last
+ 1;
1182 Integer (Name_Entries
.Table
(New_Id
).Name_Len
)
1187 S
:= Name_Entries
.Table
(New_Id
).Name_Chars_Index
;
1189 for J
in 1 .. Buf
.Length
loop
1190 if Name_Chars
.Table
(S
+ Int
(J
)) /= Buf
.Chars
(J
) then
1197 -- Current entry in hash chain does not match
1200 if Name_Entries
.Table
(New_Id
).Hash_Link
/= No_Name
then
1201 New_Id
:= Name_Entries
.Table
(New_Id
).Hash_Link
;
1203 Name_Entries
.Table
(New_Id
).Hash_Link
:=
1204 Name_Entries
.Last
+ 1;
1210 -- We fall through here only if a matching entry was not found in the
1211 -- hash table. We now create a new entry in the names table. The hash
1212 -- link pointing to the new entry (Name_Entries.Last+1) has been set.
1215 ((Name_Chars_Index
=> Name_Chars
.Last
,
1216 Name_Len
=> Short
(Buf
.Length
),
1217 Hash_Link
=> No_Name
,
1218 Name_Has_No_Encodings
=> False,
1221 Boolean1_Info
=> False,
1222 Boolean2_Info
=> False,
1223 Boolean3_Info
=> False));
1225 -- Set corresponding string entry in the Name_Chars table
1227 for J
in 1 .. Buf
.Length
loop
1228 Name_Chars
.Append
(Buf
.Chars
(J
));
1231 Name_Chars
.Append
(ASCII
.NUL
);
1233 return Name_Entries
.Last
;
1237 function Name_Find
(S
: String) return Name_Id
is
1238 Buf
: Bounded_String
;
1241 return Name_Find
(Buf
);
1251 V2
: Name_Id
) return Boolean
1254 return T
= V1
or else
1262 V3
: Name_Id
) return Boolean
1265 return T
= V1
or else
1275 V4
: Name_Id
) return Boolean
1278 return T
= V1
or else
1290 V5
: Name_Id
) return Boolean
1293 return T
= V1
or else
1307 V6
: Name_Id
) return Boolean
1310 return T
= V1
or else
1326 V7
: Name_Id
) return Boolean
1329 return T
= V1
or else
1347 V8
: Name_Id
) return Boolean
1350 return T
= V1
or else
1370 V9
: Name_Id
) return Boolean
1373 return T
= V1
or else
1395 V10
: Name_Id
) return Boolean
1398 return T
= V1
or else
1422 V11
: Name_Id
) return Boolean
1425 return T
= V1
or else
1442 function Name_Equals
(N1
: Name_Id
; N2
: Name_Id
) return Boolean is
1444 return N1
= N2
or else Get_Name_String
(N1
) = Get_Name_String
(N2
);
1451 procedure Reinitialize
is
1456 -- Initialize entries for one character names
1458 for C
in Character loop
1460 ((Name_Chars_Index
=> Name_Chars
.Last
,
1464 Boolean1_Info
=> False,
1465 Boolean2_Info
=> False,
1466 Boolean3_Info
=> False,
1467 Name_Has_No_Encodings
=> True,
1468 Hash_Link
=> No_Name
));
1470 Name_Chars
.Append
(C
);
1471 Name_Chars
.Append
(ASCII
.NUL
);
1476 for J
in Hash_Index_Type
loop
1477 Hash_Table
(J
) := No_Name
;
1481 ----------------------
1482 -- Reset_Name_Table --
1483 ----------------------
1485 procedure Reset_Name_Table
is
1487 for J
in First_Name_Id
.. Name_Entries
.Last
loop
1488 Name_Entries
.Table
(J
).Int_Info
:= 0;
1489 Name_Entries
.Table
(J
).Byte_Info
:= 0;
1491 end Reset_Name_Table
;
1493 --------------------------------
1494 -- Set_Character_Literal_Name --
1495 --------------------------------
1497 procedure Set_Character_Literal_Name
1498 (Buf
: in out Bounded_String
;
1504 Append_Encoded
(Buf
, C
);
1505 end Set_Character_Literal_Name
;
1507 procedure Set_Character_Literal_Name
(C
: Char_Code
) is
1509 Set_Character_Literal_Name
(Global_Name_Buffer
, C
);
1510 end Set_Character_Literal_Name
;
1512 -----------------------------
1513 -- Set_Name_Table_Boolean1 --
1514 -----------------------------
1516 procedure Set_Name_Table_Boolean1
(Id
: Name_Id
; Val
: Boolean) is
1518 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
1519 Name_Entries
.Table
(Id
).Boolean1_Info
:= Val
;
1520 end Set_Name_Table_Boolean1
;
1522 -----------------------------
1523 -- Set_Name_Table_Boolean2 --
1524 -----------------------------
1526 procedure Set_Name_Table_Boolean2
(Id
: Name_Id
; Val
: Boolean) is
1528 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
1529 Name_Entries
.Table
(Id
).Boolean2_Info
:= Val
;
1530 end Set_Name_Table_Boolean2
;
1532 -----------------------------
1533 -- Set_Name_Table_Boolean3 --
1534 -----------------------------
1536 procedure Set_Name_Table_Boolean3
(Id
: Name_Id
; Val
: Boolean) is
1538 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
1539 Name_Entries
.Table
(Id
).Boolean3_Info
:= Val
;
1540 end Set_Name_Table_Boolean3
;
1542 -------------------------
1543 -- Set_Name_Table_Byte --
1544 -------------------------
1546 procedure Set_Name_Table_Byte
(Id
: Name_Id
; Val
: Byte
) is
1548 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
1549 Name_Entries
.Table
(Id
).Byte_Info
:= Val
;
1550 end Set_Name_Table_Byte
;
1552 -------------------------
1553 -- Set_Name_Table_Int --
1554 -------------------------
1556 procedure Set_Name_Table_Int
(Id
: Name_Id
; Val
: Int
) is
1558 pragma Assert
(Id
in Name_Entries
.First
.. Name_Entries
.Last
);
1559 Name_Entries
.Table
(Id
).Int_Info
:= Val
;
1560 end Set_Name_Table_Int
;
1562 -----------------------------
1563 -- Store_Encoded_Character --
1564 -----------------------------
1566 procedure Store_Encoded_Character
(C
: Char_Code
) is
1568 Append_Encoded
(Global_Name_Buffer
, C
);
1569 end Store_Encoded_Character
;
1571 --------------------------------------
1572 -- Strip_Qualification_And_Suffixes --
1573 --------------------------------------
1575 procedure Strip_Qualification_And_Suffixes
(Buf
: in out Bounded_String
) is
1579 -- Strip package body qualification string off end
1581 for J
in reverse 2 .. Buf
.Length
loop
1582 if Buf
.Chars
(J
) = 'X' then
1583 Buf
.Length
:= J
- 1;
1587 exit when Buf
.Chars
(J
) /= 'b'
1588 and then Buf
.Chars
(J
) /= 'n'
1589 and then Buf
.Chars
(J
) /= 'p';
1592 -- Find rightmost __ or $ separator if one exists. First we position
1593 -- to start the search. If we have a character constant, position
1594 -- just before it, otherwise position to last character but one
1596 if Buf
.Chars
(Buf
.Length
) = ''' then
1597 J
:= Buf
.Length
- 2;
1598 while J
> 0 and then Buf
.Chars
(J
) /= ''' loop
1603 J
:= Buf
.Length
- 1;
1606 -- Loop to search for rightmost __ or $ (homonym) separator
1610 -- If $ separator, homonym separator, so strip it and keep looking
1612 if Buf
.Chars
(J
) = '$' then
1613 Buf
.Length
:= J
- 1;
1614 J
:= Buf
.Length
- 1;
1616 -- Else check for __ found
1618 elsif Buf
.Chars
(J
) = '_' and then Buf
.Chars
(J
+ 1) = '_' then
1620 -- Found __ so see if digit follows, and if so, this is a
1621 -- homonym separator, so strip it and keep looking.
1623 if Buf
.Chars
(J
+ 2) in '0' .. '9' then
1624 Buf
.Length
:= J
- 1;
1625 J
:= Buf
.Length
- 1;
1627 -- If not a homonym separator, then we simply strip the
1628 -- separator and everything that precedes it, and we are done
1631 Buf
.Chars
(1 .. Buf
.Length
- J
- 1) :=
1632 Buf
.Chars
(J
+ 2 .. Buf
.Length
);
1633 Buf
.Length
:= Buf
.Length
- J
- 1;
1641 end Strip_Qualification_And_Suffixes
;
1647 function To_String
(Buf
: Bounded_String
) return String is
1649 return Buf
.Chars
(1 .. Buf
.Length
);
1656 procedure Tree_Read
is
1658 Name_Chars
.Tree_Read
;
1659 Name_Entries
.Tree_Read
;
1662 (Hash_Table
'Address,
1663 Hash_Table
'Length * (Hash_Table
'Component_Size / Storage_Unit
));
1670 procedure Tree_Write
is
1672 Name_Chars
.Tree_Write
;
1673 Name_Entries
.Tree_Write
;
1676 (Hash_Table
'Address,
1677 Hash_Table
'Length * (Hash_Table
'Component_Size / Storage_Unit
));
1686 Name_Chars
.Set_Last
(Name_Chars
.Last
- Name_Chars_Reserve
);
1687 Name_Entries
.Set_Last
(Name_Entries
.Last
- Name_Entries_Reserve
);
1688 Name_Chars
.Locked
:= False;
1689 Name_Entries
.Locked
:= False;
1691 Name_Entries
.Release
;
1698 procedure wn
(Id
: Name_Id
) is
1700 if Id
not in Name_Entries
.First
.. Name_Entries
.Last
then
1701 Write_Str
("<invalid name_id>");
1703 elsif Id
= No_Name
then
1704 Write_Str
("<No_Name>");
1706 elsif Id
= Error_Name
then
1707 Write_Str
("<Error_Name>");
1711 Buf
: Bounded_String
;
1714 Write_Str
(Buf
.Chars
(1 .. Buf
.Length
));
1725 procedure Write_Name
(Id
: Name_Id
) is
1726 Buf
: Bounded_String
;
1728 if Id
>= First_Name_Id
then
1730 Write_Str
(Buf
.Chars
(1 .. Buf
.Length
));
1734 ------------------------
1735 -- Write_Name_Decoded --
1736 ------------------------
1738 procedure Write_Name_Decoded
(Id
: Name_Id
) is
1739 Buf
: Bounded_String
;
1741 if Id
>= First_Name_Id
then
1742 Append_Decoded
(Buf
, Id
);
1743 Write_Str
(Buf
.Chars
(1 .. Buf
.Length
));
1745 end Write_Name_Decoded
;
1747 -- Package initialization, initialize tables