2014-03-21 Paolo Carlini <paolo.carlini@oracle.com>
[official-gcc.git] / gcc / ada / namet.adb
blob1cebb464b8e28d65673773d8a6b50ffbcebd3f7a
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- N A M E T --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
10 -- --
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. --
17 -- --
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. --
21 -- --
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/>. --
26 -- --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
29 -- --
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;
37 with Opt; use Opt;
38 with Output; use Output;
39 with Tree_IO; use Tree_IO;
40 with Widechar; use Widechar;
42 with Interfaces; use Interfaces;
44 package body Namet is
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 return Hash_Index_Type;
77 pragma Inline (Hash);
78 -- Compute hash code for name stored in Name_Buffer (length in Name_Len)
80 procedure Strip_Qualification_And_Suffixes;
81 -- Given an encoded entity name in Name_Buffer, 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. The
84 -- contents of Name_Buffer is modified by this call, and on return
85 -- Name_Buffer and Name_Len reflect the stripped name.
87 -----------------------------
88 -- Add_Char_To_Name_Buffer --
89 -----------------------------
91 procedure Add_Char_To_Name_Buffer (C : Character) is
92 begin
93 if Name_Len < Name_Buffer'Last then
94 Name_Len := Name_Len + 1;
95 Name_Buffer (Name_Len) := C;
96 end if;
97 end Add_Char_To_Name_Buffer;
99 ----------------------------
100 -- Add_Nat_To_Name_Buffer --
101 ----------------------------
103 procedure Add_Nat_To_Name_Buffer (V : Nat) is
104 begin
105 if V >= 10 then
106 Add_Nat_To_Name_Buffer (V / 10);
107 end if;
109 Add_Char_To_Name_Buffer (Character'Val (Character'Pos ('0') + V rem 10));
110 end Add_Nat_To_Name_Buffer;
112 ----------------------------
113 -- Add_Str_To_Name_Buffer --
114 ----------------------------
116 procedure Add_Str_To_Name_Buffer (S : String) is
117 begin
118 for J in S'Range loop
119 Add_Char_To_Name_Buffer (S (J));
120 end loop;
121 end Add_Str_To_Name_Buffer;
123 --------------
124 -- Finalize --
125 --------------
127 procedure Finalize is
128 F : array (Int range 0 .. 50) of Int;
129 -- N'th entry is the number of chains of length N, except last entry,
130 -- which is the number of chains of length F'Last or more.
132 Max_Chain_Length : Int := 0;
133 -- Maximum length of all chains
135 Probes : Int := 0;
136 -- Used to compute average number of probes
138 Nsyms : Int := 0;
139 -- Number of symbols in table
141 Verbosity : constant Int range 1 .. 3 := 1;
142 pragma Warnings (Off, Verbosity);
143 -- This constant indicates the level of verbosity in the output from
144 -- this procedure. Currently this can only be changed by editing the
145 -- declaration above and recompiling. That's good enough in practice,
146 -- since we very rarely need to use this debug option. Settings are:
148 -- 1 => print basic summary information
149 -- 2 => in addition print number of entries per hash chain
150 -- 3 => in addition print content of entries
152 Zero : constant Int := Character'Pos ('0');
154 begin
155 if not Debug_Flag_H then
156 return;
157 end if;
159 for J in F'Range loop
160 F (J) := 0;
161 end loop;
163 for J in Hash_Index_Type loop
164 if Hash_Table (J) = No_Name then
165 F (0) := F (0) + 1;
167 else
168 declare
169 C : Int;
170 N : Name_Id;
171 S : Int;
173 begin
174 C := 0;
175 N := Hash_Table (J);
177 while N /= No_Name loop
178 N := Name_Entries.Table (N).Hash_Link;
179 C := C + 1;
180 end loop;
182 Nsyms := Nsyms + 1;
183 Probes := Probes + (1 + C) * 100;
185 if C > Max_Chain_Length then
186 Max_Chain_Length := C;
187 end if;
189 if Verbosity >= 2 then
190 Write_Str ("Hash_Table (");
191 Write_Int (J);
192 Write_Str (") has ");
193 Write_Int (C);
194 Write_Str (" entries");
195 Write_Eol;
196 end if;
198 if C < F'Last then
199 F (C) := F (C) + 1;
200 else
201 F (F'Last) := F (F'Last) + 1;
202 end if;
204 if Verbosity >= 3 then
205 N := Hash_Table (J);
206 while N /= No_Name loop
207 S := Name_Entries.Table (N).Name_Chars_Index;
209 Write_Str (" ");
211 for J in 1 .. Name_Entries.Table (N).Name_Len loop
212 Write_Char (Name_Chars.Table (S + Int (J)));
213 end loop;
215 Write_Eol;
217 N := Name_Entries.Table (N).Hash_Link;
218 end loop;
219 end if;
220 end;
221 end if;
222 end loop;
224 Write_Eol;
226 for J in F'Range loop
227 if F (J) /= 0 then
228 Write_Str ("Number of hash chains of length ");
230 if J < 10 then
231 Write_Char (' ');
232 end if;
234 Write_Int (J);
236 if J = F'Last then
237 Write_Str (" or greater");
238 end if;
240 Write_Str (" = ");
241 Write_Int (F (J));
242 Write_Eol;
243 end if;
244 end loop;
246 -- Print out average number of probes, in the case where Name_Find is
247 -- called for a string that is already in the table.
249 Write_Eol;
250 Write_Str ("Average number of probes for lookup = ");
251 Probes := Probes / Nsyms;
252 Write_Int (Probes / 200);
253 Write_Char ('.');
254 Probes := (Probes mod 200) / 2;
255 Write_Char (Character'Val (Zero + Probes / 10));
256 Write_Char (Character'Val (Zero + Probes mod 10));
257 Write_Eol;
259 Write_Str ("Max_Chain_Length = ");
260 Write_Int (Max_Chain_Length);
261 Write_Eol;
262 Write_Str ("Name_Chars'Length = ");
263 Write_Int (Name_Chars.Last - Name_Chars.First + 1);
264 Write_Eol;
265 Write_Str ("Name_Entries'Length = ");
266 Write_Int (Int (Name_Entries.Last - Name_Entries.First + 1));
267 Write_Eol;
268 Write_Str ("Nsyms = ");
269 Write_Int (Nsyms);
270 Write_Eol;
271 end Finalize;
273 -----------------------------
274 -- Get_Decoded_Name_String --
275 -----------------------------
277 procedure Get_Decoded_Name_String (Id : Name_Id) is
278 C : Character;
279 P : Natural;
281 begin
282 Get_Name_String (Id);
284 -- Skip scan if we already know there are no encodings
286 if Name_Entries.Table (Id).Name_Has_No_Encodings then
287 return;
288 end if;
290 -- Quick loop to see if there is anything special to do
292 P := 1;
293 loop
294 if P = Name_Len then
295 Name_Entries.Table (Id).Name_Has_No_Encodings := True;
296 return;
298 else
299 C := Name_Buffer (P);
301 exit when
302 C = 'U' or else
303 C = 'W' or else
304 C = 'Q' or else
305 C = 'O';
307 P := P + 1;
308 end if;
309 end loop;
311 -- Here we have at least some encoding that we must decode
313 Decode : declare
314 New_Len : Natural;
315 Old : Positive;
316 New_Buf : String (1 .. Name_Buffer'Last);
318 procedure Copy_One_Character;
319 -- Copy a character from Name_Buffer to New_Buf. Includes case
320 -- of copying a Uhh,Whhhh,WWhhhhhhhh sequence and decoding it.
322 function Hex (N : Natural) return Word;
323 -- Scans past N digits using Old pointer and returns hex value
325 procedure Insert_Character (C : Character);
326 -- Insert a new character into output decoded name
328 ------------------------
329 -- Copy_One_Character --
330 ------------------------
332 procedure Copy_One_Character is
333 C : Character;
335 begin
336 C := Name_Buffer (Old);
338 -- U (upper half insertion case)
340 if C = 'U'
341 and then Old < Name_Len
342 and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
343 and then Name_Buffer (Old + 1) /= '_'
344 then
345 Old := Old + 1;
347 -- If we have upper half encoding, then we have to set an
348 -- appropriate wide character sequence for this character.
350 if Upper_Half_Encoding then
351 Widechar.Set_Wide (Char_Code (Hex (2)), New_Buf, New_Len);
353 -- For other encoding methods, upper half characters can
354 -- simply use their normal representation.
356 else
357 Insert_Character (Character'Val (Hex (2)));
358 end if;
360 -- WW (wide wide character insertion)
362 elsif C = 'W'
363 and then Old < Name_Len
364 and then Name_Buffer (Old + 1) = 'W'
365 then
366 Old := Old + 2;
367 Widechar.Set_Wide (Char_Code (Hex (8)), New_Buf, New_Len);
369 -- W (wide character insertion)
371 elsif C = 'W'
372 and then Old < Name_Len
373 and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
374 and then Name_Buffer (Old + 1) /= '_'
375 then
376 Old := Old + 1;
377 Widechar.Set_Wide (Char_Code (Hex (4)), New_Buf, New_Len);
379 -- Any other character is copied unchanged
381 else
382 Insert_Character (C);
383 Old := Old + 1;
384 end if;
385 end Copy_One_Character;
387 ---------
388 -- Hex --
389 ---------
391 function Hex (N : Natural) return Word is
392 T : Word := 0;
393 C : Character;
395 begin
396 for J in 1 .. N loop
397 C := Name_Buffer (Old);
398 Old := Old + 1;
400 pragma Assert (C in '0' .. '9' or else C in 'a' .. 'f');
402 if C <= '9' then
403 T := 16 * T + Character'Pos (C) - Character'Pos ('0');
404 else -- C in 'a' .. 'f'
405 T := 16 * T + Character'Pos (C) - (Character'Pos ('a') - 10);
406 end if;
407 end loop;
409 return T;
410 end Hex;
412 ----------------------
413 -- Insert_Character --
414 ----------------------
416 procedure Insert_Character (C : Character) is
417 begin
418 New_Len := New_Len + 1;
419 New_Buf (New_Len) := C;
420 end Insert_Character;
422 -- Start of processing for Decode
424 begin
425 New_Len := 0;
426 Old := 1;
428 -- Loop through characters of name
430 while Old <= Name_Len loop
432 -- Case of character literal, put apostrophes around character
434 if Name_Buffer (Old) = 'Q'
435 and then Old < Name_Len
436 then
437 Old := Old + 1;
438 Insert_Character (''');
439 Copy_One_Character;
440 Insert_Character (''');
442 -- Case of operator name
444 elsif Name_Buffer (Old) = 'O'
445 and then Old < Name_Len
446 and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
447 and then Name_Buffer (Old + 1) /= '_'
448 then
449 Old := Old + 1;
451 declare
452 -- This table maps the 2nd and 3rd characters of the name
453 -- into the required output. Two blanks means leave the
454 -- name alone
456 Map : constant String :=
457 "ab " & -- Oabs => "abs"
458 "ad+ " & -- Oadd => "+"
459 "an " & -- Oand => "and"
460 "co& " & -- Oconcat => "&"
461 "di/ " & -- Odivide => "/"
462 "eq= " & -- Oeq => "="
463 "ex**" & -- Oexpon => "**"
464 "gt> " & -- Ogt => ">"
465 "ge>=" & -- Oge => ">="
466 "le<=" & -- Ole => "<="
467 "lt< " & -- Olt => "<"
468 "mo " & -- Omod => "mod"
469 "mu* " & -- Omutliply => "*"
470 "ne/=" & -- One => "/="
471 "no " & -- Onot => "not"
472 "or " & -- Oor => "or"
473 "re " & -- Orem => "rem"
474 "su- " & -- Osubtract => "-"
475 "xo "; -- Oxor => "xor"
477 J : Integer;
479 begin
480 Insert_Character ('"');
482 -- Search the map. Note that this loop must terminate, if
483 -- not we have some kind of internal error, and a constraint
484 -- error may be raised.
486 J := Map'First;
487 loop
488 exit when Name_Buffer (Old) = Map (J)
489 and then Name_Buffer (Old + 1) = Map (J + 1);
490 J := J + 4;
491 end loop;
493 -- Special operator name
495 if Map (J + 2) /= ' ' then
496 Insert_Character (Map (J + 2));
498 if Map (J + 3) /= ' ' then
499 Insert_Character (Map (J + 3));
500 end if;
502 Insert_Character ('"');
504 -- Skip past original operator name in input
506 while Old <= Name_Len
507 and then Name_Buffer (Old) in 'a' .. 'z'
508 loop
509 Old := Old + 1;
510 end loop;
512 -- For other operator names, leave them in lower case,
513 -- surrounded by apostrophes
515 else
516 -- Copy original operator name from input to output
518 while Old <= Name_Len
519 and then Name_Buffer (Old) in 'a' .. 'z'
520 loop
521 Copy_One_Character;
522 end loop;
524 Insert_Character ('"');
525 end if;
526 end;
528 -- Else copy one character and keep going
530 else
531 Copy_One_Character;
532 end if;
533 end loop;
535 -- Copy new buffer as result
537 Name_Len := New_Len;
538 Name_Buffer (1 .. New_Len) := New_Buf (1 .. New_Len);
539 end Decode;
540 end Get_Decoded_Name_String;
542 -------------------------------------------
543 -- Get_Decoded_Name_String_With_Brackets --
544 -------------------------------------------
546 procedure Get_Decoded_Name_String_With_Brackets (Id : Name_Id) is
547 P : Natural;
549 begin
550 -- Case of operator name, normal decoding is fine
552 if Name_Buffer (1) = 'O' then
553 Get_Decoded_Name_String (Id);
555 -- For character literals, normal decoding is fine
557 elsif Name_Buffer (1) = 'Q' then
558 Get_Decoded_Name_String (Id);
560 -- Only remaining issue is U/W/WW sequences
562 else
563 Get_Name_String (Id);
565 P := 1;
566 while P < Name_Len loop
567 if Name_Buffer (P + 1) in 'A' .. 'Z' then
568 P := P + 1;
570 -- Uhh encoding
572 elsif Name_Buffer (P) = 'U' then
573 for J in reverse P + 3 .. P + Name_Len loop
574 Name_Buffer (J + 3) := Name_Buffer (J);
575 end loop;
577 Name_Len := Name_Len + 3;
578 Name_Buffer (P + 3) := Name_Buffer (P + 2);
579 Name_Buffer (P + 2) := Name_Buffer (P + 1);
580 Name_Buffer (P) := '[';
581 Name_Buffer (P + 1) := '"';
582 Name_Buffer (P + 4) := '"';
583 Name_Buffer (P + 5) := ']';
584 P := P + 6;
586 -- WWhhhhhhhh encoding
588 elsif Name_Buffer (P) = 'W'
589 and then P + 9 <= Name_Len
590 and then Name_Buffer (P + 1) = 'W'
591 and then Name_Buffer (P + 2) not in 'A' .. 'Z'
592 and then Name_Buffer (P + 2) /= '_'
593 then
594 Name_Buffer (P + 12 .. Name_Len + 2) :=
595 Name_Buffer (P + 10 .. Name_Len);
596 Name_Buffer (P) := '[';
597 Name_Buffer (P + 1) := '"';
598 Name_Buffer (P + 10) := '"';
599 Name_Buffer (P + 11) := ']';
600 Name_Len := Name_Len + 2;
601 P := P + 12;
603 -- Whhhh encoding
605 elsif Name_Buffer (P) = 'W'
606 and then P < Name_Len
607 and then Name_Buffer (P + 1) not in 'A' .. 'Z'
608 and then Name_Buffer (P + 1) /= '_'
609 then
610 Name_Buffer (P + 8 .. P + Name_Len + 3) :=
611 Name_Buffer (P + 5 .. Name_Len);
612 Name_Buffer (P + 2 .. P + 5) := Name_Buffer (P + 1 .. P + 4);
613 Name_Buffer (P) := '[';
614 Name_Buffer (P + 1) := '"';
615 Name_Buffer (P + 6) := '"';
616 Name_Buffer (P + 7) := ']';
617 Name_Len := Name_Len + 3;
618 P := P + 8;
620 else
621 P := P + 1;
622 end if;
623 end loop;
624 end if;
625 end Get_Decoded_Name_String_With_Brackets;
627 ------------------------
628 -- Get_Last_Two_Chars --
629 ------------------------
631 procedure Get_Last_Two_Chars (N : Name_Id; C1, C2 : out Character) is
632 NE : Name_Entry renames Name_Entries.Table (N);
633 NEL : constant Int := Int (NE.Name_Len);
635 begin
636 if NEL >= 2 then
637 C1 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 1);
638 C2 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 0);
639 else
640 C1 := ASCII.NUL;
641 C2 := ASCII.NUL;
642 end if;
643 end Get_Last_Two_Chars;
645 ---------------------
646 -- Get_Name_String --
647 ---------------------
649 -- Procedure version leaving result in Name_Buffer, length in Name_Len
651 procedure Get_Name_String (Id : Name_Id) is
652 S : Int;
654 begin
655 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
657 S := Name_Entries.Table (Id).Name_Chars_Index;
658 Name_Len := Natural (Name_Entries.Table (Id).Name_Len);
660 for J in 1 .. Name_Len loop
661 Name_Buffer (J) := Name_Chars.Table (S + Int (J));
662 end loop;
663 end Get_Name_String;
665 ---------------------
666 -- Get_Name_String --
667 ---------------------
669 -- Function version returning a string
671 function Get_Name_String (Id : Name_Id) return String is
672 S : Int;
674 begin
675 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
676 S := Name_Entries.Table (Id).Name_Chars_Index;
678 declare
679 R : String (1 .. Natural (Name_Entries.Table (Id).Name_Len));
681 begin
682 for J in R'Range loop
683 R (J) := Name_Chars.Table (S + Int (J));
684 end loop;
686 return R;
687 end;
688 end Get_Name_String;
690 --------------------------------
691 -- Get_Name_String_And_Append --
692 --------------------------------
694 procedure Get_Name_String_And_Append (Id : Name_Id) is
695 S : Int;
697 begin
698 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
700 S := Name_Entries.Table (Id).Name_Chars_Index;
702 for J in 1 .. Natural (Name_Entries.Table (Id).Name_Len) loop
703 Name_Len := Name_Len + 1;
704 Name_Buffer (Name_Len) := Name_Chars.Table (S + Int (J));
705 end loop;
706 end Get_Name_String_And_Append;
708 -------------------------
709 -- Get_Name_Table_Byte --
710 -------------------------
712 function Get_Name_Table_Byte (Id : Name_Id) return Byte is
713 begin
714 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
715 return Name_Entries.Table (Id).Byte_Info;
716 end Get_Name_Table_Byte;
718 -------------------------
719 -- Get_Name_Table_Info --
720 -------------------------
722 function Get_Name_Table_Info (Id : Name_Id) return Int is
723 begin
724 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
725 return Name_Entries.Table (Id).Int_Info;
726 end Get_Name_Table_Info;
728 -----------------------------------------
729 -- Get_Unqualified_Decoded_Name_String --
730 -----------------------------------------
732 procedure Get_Unqualified_Decoded_Name_String (Id : Name_Id) is
733 begin
734 Get_Decoded_Name_String (Id);
735 Strip_Qualification_And_Suffixes;
736 end Get_Unqualified_Decoded_Name_String;
738 ---------------------------------
739 -- Get_Unqualified_Name_String --
740 ---------------------------------
742 procedure Get_Unqualified_Name_String (Id : Name_Id) is
743 begin
744 Get_Name_String (Id);
745 Strip_Qualification_And_Suffixes;
746 end Get_Unqualified_Name_String;
748 ----------
749 -- Hash --
750 ----------
752 function Hash return Hash_Index_Type is
754 -- This hash function looks at every character, in order to make it
755 -- likely that similar strings get different hash values. The rotate by
756 -- 7 bits has been determined empirically to be good, and it doesn't
757 -- lose bits like a shift would. The final conversion can't overflow,
758 -- because the table is 2**16 in size. This function probably needs to
759 -- be changed if the hash table size is changed.
761 -- Note that we could get some speed improvement by aligning the string
762 -- to 32 or 64 bits, and doing word-wise xor's. We could also implement
763 -- a growable table. It doesn't seem worth the trouble to do those
764 -- things, for now.
766 Result : Unsigned_16 := 0;
768 begin
769 for J in 1 .. Name_Len loop
770 Result := Rotate_Left (Result, 7) xor Character'Pos (Name_Buffer (J));
771 end loop;
773 return Hash_Index_Type (Result);
774 end Hash;
776 ----------------
777 -- Initialize --
778 ----------------
780 procedure Initialize is
781 begin
782 null;
783 end Initialize;
785 -------------------------------
786 -- Insert_Str_In_Name_Buffer --
787 -------------------------------
789 procedure Insert_Str_In_Name_Buffer (S : String; Index : Positive) is
790 SL : constant Natural := S'Length;
791 begin
792 Name_Buffer (Index + SL .. Name_Len + SL) :=
793 Name_Buffer (Index .. Name_Len);
794 Name_Buffer (Index .. Index + SL - 1) := S;
795 Name_Len := Name_Len + SL;
796 end Insert_Str_In_Name_Buffer;
798 ----------------------
799 -- Is_Internal_Name --
800 ----------------------
802 -- Version taking an argument
804 function Is_Internal_Name (Id : Name_Id) return Boolean is
805 begin
806 Get_Name_String (Id);
807 return Is_Internal_Name;
808 end Is_Internal_Name;
810 ----------------------
811 -- Is_Internal_Name --
812 ----------------------
814 -- Version taking its input from Name_Buffer
816 function Is_Internal_Name return Boolean is
817 begin
818 if Name_Buffer (1) = '_'
819 or else Name_Buffer (Name_Len) = '_'
820 then
821 return True;
823 else
824 -- Test backwards, because we only want to test the last entity
825 -- name if the name we have is qualified with other entities.
827 for J in reverse 1 .. Name_Len loop
828 if Is_OK_Internal_Letter (Name_Buffer (J)) then
829 return True;
831 -- Quit if we come to terminating double underscore (note that
832 -- if the current character is an underscore, we know that
833 -- there is a previous character present, since we already
834 -- filtered out the case of Name_Buffer (1) = '_' above.
836 elsif Name_Buffer (J) = '_'
837 and then Name_Buffer (J - 1) = '_'
838 and then Name_Buffer (J - 2) /= '_'
839 then
840 return False;
841 end if;
842 end loop;
843 end if;
845 return False;
846 end Is_Internal_Name;
848 ---------------------------
849 -- Is_OK_Internal_Letter --
850 ---------------------------
852 function Is_OK_Internal_Letter (C : Character) return Boolean is
853 begin
854 return C in 'A' .. 'Z'
855 and then C /= 'O'
856 and then C /= 'Q'
857 and then C /= 'U'
858 and then C /= 'W'
859 and then C /= 'X';
860 end Is_OK_Internal_Letter;
862 ----------------------
863 -- Is_Operator_Name --
864 ----------------------
866 function Is_Operator_Name (Id : Name_Id) return Boolean is
867 S : Int;
868 begin
869 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
870 S := Name_Entries.Table (Id).Name_Chars_Index;
871 return Name_Chars.Table (S + 1) = 'O';
872 end Is_Operator_Name;
874 -------------------
875 -- Is_Valid_Name --
876 -------------------
878 function Is_Valid_Name (Id : Name_Id) return Boolean is
879 begin
880 return Id in Name_Entries.First .. Name_Entries.Last;
881 end Is_Valid_Name;
883 --------------------
884 -- Length_Of_Name --
885 --------------------
887 function Length_Of_Name (Id : Name_Id) return Nat is
888 begin
889 return Int (Name_Entries.Table (Id).Name_Len);
890 end Length_Of_Name;
892 ----------
893 -- Lock --
894 ----------
896 procedure Lock is
897 begin
898 Name_Chars.Set_Last (Name_Chars.Last + Name_Chars_Reserve);
899 Name_Entries.Set_Last (Name_Entries.Last + Name_Entries_Reserve);
900 Name_Chars.Locked := True;
901 Name_Entries.Locked := True;
902 Name_Chars.Release;
903 Name_Entries.Release;
904 end Lock;
906 ------------------------
907 -- Name_Chars_Address --
908 ------------------------
910 function Name_Chars_Address return System.Address is
911 begin
912 return Name_Chars.Table (0)'Address;
913 end Name_Chars_Address;
915 ----------------
916 -- Name_Enter --
917 ----------------
919 function Name_Enter return Name_Id is
920 begin
921 Name_Entries.Append
922 ((Name_Chars_Index => Name_Chars.Last,
923 Name_Len => Short (Name_Len),
924 Byte_Info => 0,
925 Int_Info => 0,
926 Name_Has_No_Encodings => False,
927 Hash_Link => No_Name));
929 -- Set corresponding string entry in the Name_Chars table
931 for J in 1 .. Name_Len loop
932 Name_Chars.Append (Name_Buffer (J));
933 end loop;
935 Name_Chars.Append (ASCII.NUL);
937 return Name_Entries.Last;
938 end Name_Enter;
940 --------------------------
941 -- Name_Entries_Address --
942 --------------------------
944 function Name_Entries_Address return System.Address is
945 begin
946 return Name_Entries.Table (First_Name_Id)'Address;
947 end Name_Entries_Address;
949 ------------------------
950 -- Name_Entries_Count --
951 ------------------------
953 function Name_Entries_Count return Nat is
954 begin
955 return Int (Name_Entries.Last - Name_Entries.First + 1);
956 end Name_Entries_Count;
958 ---------------
959 -- Name_Find --
960 ---------------
962 function Name_Find return Name_Id is
963 New_Id : Name_Id;
964 -- Id of entry in hash search, and value to be returned
966 S : Int;
967 -- Pointer into string table
969 Hash_Index : Hash_Index_Type;
970 -- Computed hash index
972 begin
973 -- Quick handling for one character names
975 if Name_Len = 1 then
976 return Name_Id (First_Name_Id + Character'Pos (Name_Buffer (1)));
978 -- Otherwise search hash table for existing matching entry
980 else
981 Hash_Index := Namet.Hash;
982 New_Id := Hash_Table (Hash_Index);
984 if New_Id = No_Name then
985 Hash_Table (Hash_Index) := Name_Entries.Last + 1;
987 else
988 Search : loop
989 if Name_Len /=
990 Integer (Name_Entries.Table (New_Id).Name_Len)
991 then
992 goto No_Match;
993 end if;
995 S := Name_Entries.Table (New_Id).Name_Chars_Index;
997 for J in 1 .. Name_Len loop
998 if Name_Chars.Table (S + Int (J)) /= Name_Buffer (J) then
999 goto No_Match;
1000 end if;
1001 end loop;
1003 return New_Id;
1005 -- Current entry in hash chain does not match
1007 <<No_Match>>
1008 if Name_Entries.Table (New_Id).Hash_Link /= No_Name then
1009 New_Id := Name_Entries.Table (New_Id).Hash_Link;
1010 else
1011 Name_Entries.Table (New_Id).Hash_Link :=
1012 Name_Entries.Last + 1;
1013 exit Search;
1014 end if;
1015 end loop Search;
1016 end if;
1018 -- We fall through here only if a matching entry was not found in the
1019 -- hash table. We now create a new entry in the names table. The hash
1020 -- link pointing to the new entry (Name_Entries.Last+1) has been set.
1022 Name_Entries.Append
1023 ((Name_Chars_Index => Name_Chars.Last,
1024 Name_Len => Short (Name_Len),
1025 Hash_Link => No_Name,
1026 Name_Has_No_Encodings => False,
1027 Int_Info => 0,
1028 Byte_Info => 0));
1030 -- Set corresponding string entry in the Name_Chars table
1032 for J in 1 .. Name_Len loop
1033 Name_Chars.Append (Name_Buffer (J));
1034 end loop;
1036 Name_Chars.Append (ASCII.NUL);
1038 return Name_Entries.Last;
1039 end if;
1040 end Name_Find;
1042 -------------
1043 -- Nam_In --
1044 -------------
1046 function Nam_In
1047 (T : Name_Id;
1048 V1 : Name_Id;
1049 V2 : Name_Id) return Boolean
1051 begin
1052 return T = V1 or else
1053 T = V2;
1054 end Nam_In;
1056 function Nam_In
1057 (T : Name_Id;
1058 V1 : Name_Id;
1059 V2 : Name_Id;
1060 V3 : Name_Id) return Boolean
1062 begin
1063 return T = V1 or else
1064 T = V2 or else
1065 T = V3;
1066 end Nam_In;
1068 function Nam_In
1069 (T : Name_Id;
1070 V1 : Name_Id;
1071 V2 : Name_Id;
1072 V3 : Name_Id;
1073 V4 : Name_Id) return Boolean
1075 begin
1076 return T = V1 or else
1077 T = V2 or else
1078 T = V3 or else
1079 T = V4;
1080 end Nam_In;
1082 function Nam_In
1083 (T : Name_Id;
1084 V1 : Name_Id;
1085 V2 : Name_Id;
1086 V3 : Name_Id;
1087 V4 : Name_Id;
1088 V5 : Name_Id) return Boolean
1090 begin
1091 return T = V1 or else
1092 T = V2 or else
1093 T = V3 or else
1094 T = V4 or else
1095 T = V5;
1096 end Nam_In;
1098 function Nam_In
1099 (T : Name_Id;
1100 V1 : Name_Id;
1101 V2 : Name_Id;
1102 V3 : Name_Id;
1103 V4 : Name_Id;
1104 V5 : Name_Id;
1105 V6 : Name_Id) return Boolean
1107 begin
1108 return T = V1 or else
1109 T = V2 or else
1110 T = V3 or else
1111 T = V4 or else
1112 T = V5 or else
1113 T = V6;
1114 end Nam_In;
1116 function Nam_In
1117 (T : Name_Id;
1118 V1 : Name_Id;
1119 V2 : Name_Id;
1120 V3 : Name_Id;
1121 V4 : Name_Id;
1122 V5 : Name_Id;
1123 V6 : Name_Id;
1124 V7 : Name_Id) return Boolean
1126 begin
1127 return T = V1 or else
1128 T = V2 or else
1129 T = V3 or else
1130 T = V4 or else
1131 T = V5 or else
1132 T = V6 or else
1133 T = V7;
1134 end Nam_In;
1136 ------------------
1137 -- Reinitialize --
1138 ------------------
1140 procedure Reinitialize is
1141 begin
1142 Name_Chars.Init;
1143 Name_Entries.Init;
1145 -- Initialize entries for one character names
1147 for C in Character loop
1148 Name_Entries.Append
1149 ((Name_Chars_Index => Name_Chars.Last,
1150 Name_Len => 1,
1151 Byte_Info => 0,
1152 Int_Info => 0,
1153 Name_Has_No_Encodings => True,
1154 Hash_Link => No_Name));
1156 Name_Chars.Append (C);
1157 Name_Chars.Append (ASCII.NUL);
1158 end loop;
1160 -- Clear hash table
1162 for J in Hash_Index_Type loop
1163 Hash_Table (J) := No_Name;
1164 end loop;
1165 end Reinitialize;
1167 ----------------------
1168 -- Reset_Name_Table --
1169 ----------------------
1171 procedure Reset_Name_Table is
1172 begin
1173 for J in First_Name_Id .. Name_Entries.Last loop
1174 Name_Entries.Table (J).Int_Info := 0;
1175 Name_Entries.Table (J).Byte_Info := 0;
1176 end loop;
1177 end Reset_Name_Table;
1179 --------------------------------
1180 -- Set_Character_Literal_Name --
1181 --------------------------------
1183 procedure Set_Character_Literal_Name (C : Char_Code) is
1184 begin
1185 Name_Buffer (1) := 'Q';
1186 Name_Len := 1;
1187 Store_Encoded_Character (C);
1188 end Set_Character_Literal_Name;
1190 -------------------------
1191 -- Set_Name_Table_Byte --
1192 -------------------------
1194 procedure Set_Name_Table_Byte (Id : Name_Id; Val : Byte) is
1195 begin
1196 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
1197 Name_Entries.Table (Id).Byte_Info := Val;
1198 end Set_Name_Table_Byte;
1200 -------------------------
1201 -- Set_Name_Table_Info --
1202 -------------------------
1204 procedure Set_Name_Table_Info (Id : Name_Id; Val : Int) is
1205 begin
1206 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
1207 Name_Entries.Table (Id).Int_Info := Val;
1208 end Set_Name_Table_Info;
1210 -----------------------------
1211 -- Store_Encoded_Character --
1212 -----------------------------
1214 procedure Store_Encoded_Character (C : Char_Code) is
1216 procedure Set_Hex_Chars (C : Char_Code);
1217 -- Stores given value, which is in the range 0 .. 255, as two hex
1218 -- digits (using lower case a-f) in Name_Buffer, incrementing Name_Len.
1220 -------------------
1221 -- Set_Hex_Chars --
1222 -------------------
1224 procedure Set_Hex_Chars (C : Char_Code) is
1225 Hexd : constant String := "0123456789abcdef";
1226 N : constant Natural := Natural (C);
1227 begin
1228 Name_Buffer (Name_Len + 1) := Hexd (N / 16 + 1);
1229 Name_Buffer (Name_Len + 2) := Hexd (N mod 16 + 1);
1230 Name_Len := Name_Len + 2;
1231 end Set_Hex_Chars;
1233 -- Start of processing for Store_Encoded_Character
1235 begin
1236 Name_Len := Name_Len + 1;
1238 if In_Character_Range (C) then
1239 declare
1240 CC : constant Character := Get_Character (C);
1241 begin
1242 if CC in 'a' .. 'z' or else CC in '0' .. '9' then
1243 Name_Buffer (Name_Len) := CC;
1244 else
1245 Name_Buffer (Name_Len) := 'U';
1246 Set_Hex_Chars (C);
1247 end if;
1248 end;
1250 elsif In_Wide_Character_Range (C) then
1251 Name_Buffer (Name_Len) := 'W';
1252 Set_Hex_Chars (C / 256);
1253 Set_Hex_Chars (C mod 256);
1255 else
1256 Name_Buffer (Name_Len) := 'W';
1257 Name_Len := Name_Len + 1;
1258 Name_Buffer (Name_Len) := 'W';
1259 Set_Hex_Chars (C / 2 ** 24);
1260 Set_Hex_Chars ((C / 2 ** 16) mod 256);
1261 Set_Hex_Chars ((C / 256) mod 256);
1262 Set_Hex_Chars (C mod 256);
1263 end if;
1264 end Store_Encoded_Character;
1266 --------------------------------------
1267 -- Strip_Qualification_And_Suffixes --
1268 --------------------------------------
1270 procedure Strip_Qualification_And_Suffixes is
1271 J : Integer;
1273 begin
1274 -- Strip package body qualification string off end
1276 for J in reverse 2 .. Name_Len loop
1277 if Name_Buffer (J) = 'X' then
1278 Name_Len := J - 1;
1279 exit;
1280 end if;
1282 exit when Name_Buffer (J) /= 'b'
1283 and then Name_Buffer (J) /= 'n'
1284 and then Name_Buffer (J) /= 'p';
1285 end loop;
1287 -- Find rightmost __ or $ separator if one exists. First we position
1288 -- to start the search. If we have a character constant, position
1289 -- just before it, otherwise position to last character but one
1291 if Name_Buffer (Name_Len) = ''' then
1292 J := Name_Len - 2;
1293 while J > 0 and then Name_Buffer (J) /= ''' loop
1294 J := J - 1;
1295 end loop;
1297 else
1298 J := Name_Len - 1;
1299 end if;
1301 -- Loop to search for rightmost __ or $ (homonym) separator
1303 while J > 1 loop
1305 -- If $ separator, homonym separator, so strip it and keep looking
1307 if Name_Buffer (J) = '$' then
1308 Name_Len := J - 1;
1309 J := Name_Len - 1;
1311 -- Else check for __ found
1313 elsif Name_Buffer (J) = '_' and then Name_Buffer (J + 1) = '_' then
1315 -- Found __ so see if digit follows, and if so, this is a
1316 -- homonym separator, so strip it and keep looking.
1318 if Name_Buffer (J + 2) in '0' .. '9' then
1319 Name_Len := J - 1;
1320 J := Name_Len - 1;
1322 -- If not a homonym separator, then we simply strip the
1323 -- separator and everything that precedes it, and we are done
1325 else
1326 Name_Buffer (1 .. Name_Len - J - 1) :=
1327 Name_Buffer (J + 2 .. Name_Len);
1328 Name_Len := Name_Len - J - 1;
1329 exit;
1330 end if;
1332 else
1333 J := J - 1;
1334 end if;
1335 end loop;
1336 end Strip_Qualification_And_Suffixes;
1338 ---------------
1339 -- Tree_Read --
1340 ---------------
1342 procedure Tree_Read is
1343 begin
1344 Name_Chars.Tree_Read;
1345 Name_Entries.Tree_Read;
1347 Tree_Read_Data
1348 (Hash_Table'Address,
1349 Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1350 end Tree_Read;
1352 ----------------
1353 -- Tree_Write --
1354 ----------------
1356 procedure Tree_Write is
1357 begin
1358 Name_Chars.Tree_Write;
1359 Name_Entries.Tree_Write;
1361 Tree_Write_Data
1362 (Hash_Table'Address,
1363 Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1364 end Tree_Write;
1366 ------------
1367 -- Unlock --
1368 ------------
1370 procedure Unlock is
1371 begin
1372 Name_Chars.Set_Last (Name_Chars.Last - Name_Chars_Reserve);
1373 Name_Entries.Set_Last (Name_Entries.Last - Name_Entries_Reserve);
1374 Name_Chars.Locked := False;
1375 Name_Entries.Locked := False;
1376 Name_Chars.Release;
1377 Name_Entries.Release;
1378 end Unlock;
1380 --------
1381 -- wn --
1382 --------
1384 procedure wn (Id : Name_Id) is
1385 S : Int;
1387 begin
1388 if not Id'Valid then
1389 Write_Str ("<invalid name_id>");
1391 elsif Id = No_Name then
1392 Write_Str ("<No_Name>");
1394 elsif Id = Error_Name then
1395 Write_Str ("<Error_Name>");
1397 else
1398 S := Name_Entries.Table (Id).Name_Chars_Index;
1399 Name_Len := Natural (Name_Entries.Table (Id).Name_Len);
1401 for J in 1 .. Name_Len loop
1402 Write_Char (Name_Chars.Table (S + Int (J)));
1403 end loop;
1404 end if;
1406 Write_Eol;
1407 end wn;
1409 ----------------
1410 -- Write_Name --
1411 ----------------
1413 procedure Write_Name (Id : Name_Id) is
1414 begin
1415 if Id >= First_Name_Id then
1416 Get_Name_String (Id);
1417 Write_Str (Name_Buffer (1 .. Name_Len));
1418 end if;
1419 end Write_Name;
1421 ------------------------
1422 -- Write_Name_Decoded --
1423 ------------------------
1425 procedure Write_Name_Decoded (Id : Name_Id) is
1426 begin
1427 if Id >= First_Name_Id then
1428 Get_Decoded_Name_String (Id);
1429 Write_Str (Name_Buffer (1 .. Name_Len));
1430 end if;
1431 end Write_Name_Decoded;
1433 -- Package initialization, initialize tables
1435 begin
1436 Reinitialize;
1437 end Namet;