[gcc/testsuite]
[official-gcc.git] / gcc / ada / namet.adb
blobfd458a3085a91f4cd7b0a32ebf284373a0c6d0c1
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- N A M E T --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2017, 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 System; use System;
40 with Tree_IO; use Tree_IO;
41 with Widechar; use Widechar;
43 with Interfaces; use Interfaces;
45 package body Namet is
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;
78 pragma Inline (Hash);
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
91 begin
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
100 begin
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
109 begin
110 Append (Global_Name_Buffer, S);
111 end Add_Str_To_Name_Buffer;
113 ------------
114 -- Append --
115 ------------
117 procedure Append (Buf : in out Bounded_String; C : Character) is
118 begin
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));
124 Write_Line ("");
125 raise Program_Error;
126 end if;
128 Buf.Chars (Buf.Length) := C;
129 end Append;
131 procedure Append (Buf : in out Bounded_String; V : Nat) is
132 begin
133 if V >= 10 then
134 Append (Buf, V / 10);
135 end if;
137 Append (Buf, Character'Val (Character'Pos ('0') + V rem 10));
138 end Append;
140 procedure Append (Buf : in out Bounded_String; S : String) is
141 First : constant Natural := Buf.Length + 1;
142 begin
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));
148 Write_Line ("");
149 raise Program_Error;
150 end if;
152 Buf.Chars (First .. Buf.Length) := S;
153 -- A loop calling Append(Character) would be cleaner, but this slice
154 -- assignment is substantially faster.
155 end Append;
157 procedure Append (Buf : in out Bounded_String; Buf2 : Bounded_String) is
158 begin
159 Append (Buf, Buf2.Chars (1 .. Buf2.Length));
160 end Append;
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));
169 begin
170 Append (Buf, String (Chars));
171 end Append;
173 --------------------
174 -- Append_Decoded --
175 --------------------
177 procedure Append_Decoded (Buf : in out Bounded_String; Id : Name_Id) is
178 C : Character;
179 P : Natural;
180 Temp : Bounded_String;
182 begin
183 Append (Temp, Id);
185 -- Skip scan if we already know there are no encodings
187 if Name_Entries.Table (Id).Name_Has_No_Encodings then
188 goto Done;
189 end if;
191 -- Quick loop to see if there is anything special to do
193 P := 1;
194 loop
195 if P = Temp.Length then
196 Name_Entries.Table (Id).Name_Has_No_Encodings := True;
197 goto Done;
199 else
200 C := Temp.Chars (P);
202 exit when
203 C = 'U' or else
204 C = 'W' or else
205 C = 'Q' or else
206 C = 'O';
208 P := P + 1;
209 end if;
210 end loop;
212 -- Here we have at least some encoding that we must decode
214 Decode : declare
215 New_Len : Natural;
216 Old : Positive;
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
234 C : Character;
236 begin
237 C := Temp.Chars (Old);
239 -- U (upper half insertion case)
241 if C = 'U'
242 and then Old < Temp.Length
243 and then Temp.Chars (Old + 1) not in 'A' .. 'Z'
244 and then Temp.Chars (Old + 1) /= '_'
245 then
246 Old := 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.
257 else
258 Insert_Character (Character'Val (Hex (2)));
259 end if;
261 -- WW (wide wide character insertion)
263 elsif C = 'W'
264 and then Old < Temp.Length
265 and then Temp.Chars (Old + 1) = 'W'
266 then
267 Old := Old + 2;
268 Widechar.Set_Wide (Char_Code (Hex (8)), New_Buf, New_Len);
270 -- W (wide character insertion)
272 elsif C = 'W'
273 and then Old < Temp.Length
274 and then Temp.Chars (Old + 1) not in 'A' .. 'Z'
275 and then Temp.Chars (Old + 1) /= '_'
276 then
277 Old := Old + 1;
278 Widechar.Set_Wide (Char_Code (Hex (4)), New_Buf, New_Len);
280 -- Any other character is copied unchanged
282 else
283 Insert_Character (C);
284 Old := Old + 1;
285 end if;
286 end Copy_One_Character;
288 ---------
289 -- Hex --
290 ---------
292 function Hex (N : Natural) return Word is
293 T : Word := 0;
294 C : Character;
296 begin
297 for J in 1 .. N loop
298 C := Temp.Chars (Old);
299 Old := Old + 1;
301 pragma Assert (C in '0' .. '9' or else C in 'a' .. 'f');
303 if C <= '9' then
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);
307 end if;
308 end loop;
310 return T;
311 end Hex;
313 ----------------------
314 -- Insert_Character --
315 ----------------------
317 procedure Insert_Character (C : Character) is
318 begin
319 New_Len := New_Len + 1;
320 New_Buf (New_Len) := C;
321 end Insert_Character;
323 -- Start of processing for Decode
325 begin
326 New_Len := 0;
327 Old := 1;
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
337 then
338 Old := Old + 1;
339 Insert_Character (''');
340 Copy_One_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) /= '_'
349 then
350 Old := Old + 1;
352 declare
353 -- This table maps the 2nd and 3rd characters of the name
354 -- into the required output. Two blanks means leave the
355 -- name alone
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"
378 J : Integer;
380 begin
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.
387 J := Map'First;
388 loop
389 exit when Temp.Chars (Old) = Map (J)
390 and then Temp.Chars (Old + 1) = Map (J + 1);
391 J := J + 4;
392 end loop;
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));
401 end if;
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'
409 loop
410 Old := Old + 1;
411 end loop;
413 -- For other operator names, leave them in lower case,
414 -- surrounded by apostrophes
416 else
417 -- Copy original operator name from input to output
419 while Old <= Temp.Length
420 and then Temp.Chars (Old) in 'a' .. 'z'
421 loop
422 Copy_One_Character;
423 end loop;
425 Insert_Character ('"');
426 end if;
427 end;
429 -- Else copy one character and keep going
431 else
432 Copy_One_Character;
433 end if;
434 end loop;
436 -- Copy new buffer as result
438 Temp.Length := New_Len;
439 Temp.Chars (1 .. New_Len) := New_Buf (1 .. New_Len);
440 end Decode;
442 <<Done>>
443 Append (Buf, Temp);
444 end Append_Decoded;
446 ----------------------------------
447 -- Append_Decoded_With_Brackets --
448 ----------------------------------
450 procedure Append_Decoded_With_Brackets
451 (Buf : in out Bounded_String;
452 Id : Name_Id)
454 P : Natural;
456 begin
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
469 else
470 declare
471 Temp : Bounded_String;
472 begin
473 Append (Temp, Id);
475 P := 1;
476 while P < Temp.Length loop
477 if Temp.Chars (P + 1) in 'A' .. 'Z' then
478 P := P + 1;
480 -- Uhh encoding
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);
485 end loop;
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) := ']';
494 P := P + 6;
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) /= '_'
503 then
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;
511 P := P + 12;
513 -- Whhhh encoding
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) /= '_'
519 then
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;
528 P := P + 8;
530 else
531 P := P + 1;
532 end if;
533 end loop;
535 Append (Buf, Temp);
536 end;
537 end if;
538 end Append_Decoded_With_Brackets;
540 --------------------
541 -- Append_Encoded --
542 --------------------
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.
549 -------------------
550 -- Set_Hex_Chars --
551 -------------------
553 procedure Set_Hex_Chars (C : Char_Code) is
554 Hexd : constant String := "0123456789abcdef";
555 N : constant Natural := Natural (C);
556 begin
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;
560 end Set_Hex_Chars;
562 -- Start of processing for Append_Encoded
564 begin
565 Buf.Length := Buf.Length + 1;
567 if In_Character_Range (C) then
568 declare
569 CC : constant Character := Get_Character (C);
570 begin
571 if CC in 'a' .. 'z' or else CC in '0' .. '9' then
572 Buf.Chars (Buf.Length) := CC;
573 else
574 Buf.Chars (Buf.Length) := 'U';
575 Set_Hex_Chars (C);
576 end if;
577 end;
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);
584 else
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);
592 end if;
593 end Append_Encoded;
595 ------------------------
596 -- Append_Unqualified --
597 ------------------------
599 procedure Append_Unqualified (Buf : in out Bounded_String; Id : Name_Id) is
600 Temp : Bounded_String;
601 begin
602 Append (Temp, Id);
603 Strip_Qualification_And_Suffixes (Temp);
604 Append (Buf, Temp);
605 end Append_Unqualified;
607 --------------------------------
608 -- Append_Unqualified_Decoded --
609 --------------------------------
611 procedure Append_Unqualified_Decoded
612 (Buf : in out Bounded_String;
613 Id : Name_Id)
615 Temp : Bounded_String;
616 begin
617 Append_Decoded (Temp, Id);
618 Strip_Qualification_And_Suffixes (Temp);
619 Append (Buf, Temp);
620 end Append_Unqualified_Decoded;
622 --------------
623 -- Finalize --
624 --------------
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
634 Probes : Nat := 0;
635 -- Used to compute average number of probes
637 Nsyms : Nat := 0;
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');
653 begin
654 if not Debug_Flag_H then
655 return;
656 end if;
658 for J in F'Range loop
659 F (J) := 0;
660 end loop;
662 for J in Hash_Index_Type loop
663 if Hash_Table (J) = No_Name then
664 F (0) := F (0) + 1;
666 else
667 declare
668 C : Nat;
669 N : Name_Id;
670 S : Int;
672 begin
673 C := 0;
674 N := Hash_Table (J);
676 while N /= No_Name loop
677 N := Name_Entries.Table (N).Hash_Link;
678 C := C + 1;
679 end loop;
681 Nsyms := Nsyms + 1;
682 Probes := Probes + (1 + C) * 100;
684 if C > Max_Chain_Length then
685 Max_Chain_Length := C;
686 end if;
688 if Verbosity >= 2 then
689 Write_Str ("Hash_Table (");
690 Write_Int (J);
691 Write_Str (") has ");
692 Write_Int (C);
693 Write_Str (" entries");
694 Write_Eol;
695 end if;
697 if C < F'Last then
698 F (C) := F (C) + 1;
699 else
700 F (F'Last) := F (F'Last) + 1;
701 end if;
703 if Verbosity >= 3 then
704 N := Hash_Table (J);
705 while N /= No_Name loop
706 S := Name_Entries.Table (N).Name_Chars_Index;
708 Write_Str (" ");
710 for J in 1 .. Name_Entries.Table (N).Name_Len loop
711 Write_Char (Name_Chars.Table (S + Int (J)));
712 end loop;
714 Write_Eol;
716 N := Name_Entries.Table (N).Hash_Link;
717 end loop;
718 end if;
719 end;
720 end if;
721 end loop;
723 Write_Eol;
725 for J in F'Range loop
726 if F (J) /= 0 then
727 Write_Str ("Number of hash chains of length ");
729 if J < 10 then
730 Write_Char (' ');
731 end if;
733 Write_Int (J);
735 if J = F'Last then
736 Write_Str (" or greater");
737 end if;
739 Write_Str (" = ");
740 Write_Int (F (J));
741 Write_Eol;
742 end if;
743 end loop;
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.
748 Write_Eol;
749 Write_Str ("Average number of probes for lookup = ");
750 Probes := Probes / Nsyms;
751 Write_Int (Probes / 200);
752 Write_Char ('.');
753 Probes := (Probes mod 200) / 2;
754 Write_Char (Character'Val (Zero + Probes / 10));
755 Write_Char (Character'Val (Zero + Probes mod 10));
756 Write_Eol;
758 Write_Str ("Max_Chain_Length = ");
759 Write_Int (Max_Chain_Length);
760 Write_Eol;
761 Write_Str ("Name_Chars'Length = ");
762 Write_Int (Name_Chars.Last - Name_Chars.First + 1);
763 Write_Eol;
764 Write_Str ("Name_Entries'Length = ");
765 Write_Int (Int (Name_Entries.Last - Name_Entries.First + 1));
766 Write_Eol;
767 Write_Str ("Nsyms = ");
768 Write_Int (Nsyms);
769 Write_Eol;
770 end Finalize;
772 -----------------------------
773 -- Get_Decoded_Name_String --
774 -----------------------------
776 procedure Get_Decoded_Name_String (Id : Name_Id) is
777 begin
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
787 begin
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
797 (N : Name_Id;
798 C1 : out Character;
799 C2 : out Character)
801 NE : Name_Entry renames Name_Entries.Table (N);
802 NEL : constant Int := Int (NE.Name_Len);
804 begin
805 if NEL >= 2 then
806 C1 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 1);
807 C2 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 0);
808 else
809 C1 := ASCII.NUL;
810 C2 := ASCII.NUL;
811 end if;
812 end Get_Last_Two_Chars;
814 ---------------------
815 -- Get_Name_String --
816 ---------------------
818 procedure Get_Name_String (Id : Name_Id) is
819 begin
820 Global_Name_Buffer.Length := 0;
821 Append (Global_Name_Buffer, Id);
822 end Get_Name_String;
824 function Get_Name_String (Id : Name_Id) return String is
825 Buf : Bounded_String (Max_Length => Natural (Length_Of_Name (Id)));
826 begin
827 Append (Buf, Id);
828 return +Buf;
829 end Get_Name_String;
831 --------------------------------
832 -- Get_Name_String_And_Append --
833 --------------------------------
835 procedure Get_Name_String_And_Append (Id : Name_Id) is
836 begin
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
845 begin
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
855 begin
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
865 begin
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
875 begin
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
885 begin
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
895 begin
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
905 begin
906 Global_Name_Buffer.Length := 0;
907 Append_Unqualified (Global_Name_Buffer, Id);
908 end Get_Unqualified_Name_String;
910 ----------
911 -- Hash --
912 ----------
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
926 -- things, for now.
928 Result : Unsigned_16 := 0;
930 begin
931 for J in 1 .. Buf.Length loop
932 Result := Rotate_Left (Result, 7) xor Character'Pos (Buf.Chars (J));
933 end loop;
935 return Hash_Index_Type (Result);
936 end Hash;
938 ----------------
939 -- Initialize --
940 ----------------
942 procedure Initialize is
943 begin
944 null;
945 end Initialize;
947 ----------------
948 -- Insert_Str --
949 ----------------
951 procedure Insert_Str
952 (Buf : in out Bounded_String;
953 S : String;
954 Index : Positive)
956 SL : constant Natural := S'Length;
958 begin
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;
963 end Insert_Str;
965 -------------------------------
966 -- Insert_Str_In_Name_Buffer --
967 -------------------------------
969 procedure Insert_Str_In_Name_Buffer (S : String; Index : Positive) is
970 begin
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
979 J : Natural;
981 begin
982 -- Any name starting or ending with underscore is internal
984 if Buf.Chars (1) = '_'
985 or else Buf.Chars (Buf.Length) = '_'
986 then
987 return True;
989 -- Allow quoted character
991 elsif Buf.Chars (1) = ''' then
992 return False;
994 -- All other cases, scan name
996 else
997 -- Test backwards, because we only want to test the last entity
998 -- name if the name we have is qualified with other entities.
1000 J := Buf.Length;
1001 while J /= 0 loop
1003 -- Skip stuff between brackets (A-F OK there)
1005 if Buf.Chars (J) = ']' then
1006 loop
1007 J := J - 1;
1008 exit when J = 1 or else Buf.Chars (J) = '[';
1009 end loop;
1011 -- Test for internal letter
1013 elsif Is_OK_Internal_Letter (Buf.Chars (J)) then
1014 return True;
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) /= '_'
1024 then
1025 return False;
1026 end if;
1028 J := J - 1;
1029 end loop;
1030 end if;
1032 return False;
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)));
1037 begin
1038 if Id in Error_Name_Or_No_Name then
1039 return False;
1040 else
1041 Append (Buf, Id);
1042 return Is_Internal_Name (Buf);
1043 end if;
1044 end Is_Internal_Name;
1046 function Is_Internal_Name return Boolean is
1047 begin
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
1056 begin
1057 return C in 'A' .. 'Z'
1058 and then C /= 'O'
1059 and then C /= 'Q'
1060 and then C /= 'U'
1061 and then C /= 'W'
1062 and then C /= 'X';
1063 end Is_OK_Internal_Letter;
1065 ----------------------
1066 -- Is_Operator_Name --
1067 ----------------------
1069 function Is_Operator_Name (Id : Name_Id) return Boolean is
1070 S : Int;
1071 begin
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;
1077 -------------------
1078 -- Is_Valid_Name --
1079 -------------------
1081 function Is_Valid_Name (Id : Name_Id) return Boolean is
1082 begin
1083 return Id in Name_Entries.First .. Name_Entries.Last;
1084 end Is_Valid_Name;
1086 --------------------
1087 -- Length_Of_Name --
1088 --------------------
1090 function Length_Of_Name (Id : Name_Id) return Nat is
1091 begin
1092 return Int (Name_Entries.Table (Id).Name_Len);
1093 end Length_Of_Name;
1095 ----------
1096 -- Lock --
1097 ----------
1099 procedure Lock is
1100 begin
1101 Name_Chars.Set_Last (Name_Chars.Last + Name_Chars_Reserve);
1102 Name_Entries.Set_Last (Name_Entries.Last + Name_Entries_Reserve);
1103 Name_Chars.Release;
1104 Name_Chars.Locked := True;
1105 Name_Entries.Release;
1106 Name_Entries.Locked := True;
1107 end Lock;
1109 ----------------
1110 -- Name_Enter --
1111 ----------------
1113 function Name_Enter
1114 (Buf : Bounded_String := Global_Name_Buffer) return Name_Id
1116 begin
1117 Name_Entries.Append
1118 ((Name_Chars_Index => Name_Chars.Last,
1119 Name_Len => Short (Buf.Length),
1120 Byte_Info => 0,
1121 Int_Info => 0,
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));
1132 end loop;
1134 Name_Chars.Append (ASCII.NUL);
1136 return Name_Entries.Last;
1137 end Name_Enter;
1139 function Name_Enter (S : String) return Name_Id is
1140 Buf : Bounded_String (Max_Length => S'Length);
1141 begin
1142 Append (Buf, S);
1143 return Name_Enter (Buf);
1144 end Name_Enter;
1146 ------------------------
1147 -- Name_Entries_Count --
1148 ------------------------
1150 function Name_Entries_Count return Nat is
1151 begin
1152 return Int (Name_Entries.Last - Name_Entries.First + 1);
1153 end Name_Entries_Count;
1155 ---------------
1156 -- Name_Find --
1157 ---------------
1159 function Name_Find
1160 (Buf : Bounded_String := Global_Name_Buffer) return Name_Id
1162 New_Id : Name_Id;
1163 -- Id of entry in hash search, and value to be returned
1165 S : Int;
1166 -- Pointer into string table
1168 Hash_Index : Hash_Index_Type;
1169 -- Computed hash index
1171 begin
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
1179 else
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;
1186 else
1187 Search : loop
1188 if Buf.Length /=
1189 Integer (Name_Entries.Table (New_Id).Name_Len)
1190 then
1191 goto No_Match;
1192 end if;
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
1198 goto No_Match;
1199 end if;
1200 end loop;
1202 return New_Id;
1204 -- Current entry in hash chain does not match
1206 <<No_Match>>
1207 if Name_Entries.Table (New_Id).Hash_Link /= No_Name then
1208 New_Id := Name_Entries.Table (New_Id).Hash_Link;
1209 else
1210 Name_Entries.Table (New_Id).Hash_Link :=
1211 Name_Entries.Last + 1;
1212 exit Search;
1213 end if;
1214 end loop Search;
1215 end if;
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.
1221 Name_Entries.Append
1222 ((Name_Chars_Index => Name_Chars.Last,
1223 Name_Len => Short (Buf.Length),
1224 Hash_Link => No_Name,
1225 Name_Has_No_Encodings => False,
1226 Int_Info => 0,
1227 Byte_Info => 0,
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));
1236 end loop;
1238 Name_Chars.Append (ASCII.NUL);
1240 return Name_Entries.Last;
1241 end if;
1242 end Name_Find;
1244 function Name_Find (S : String) return Name_Id is
1245 Buf : Bounded_String (Max_Length => S'Length);
1246 begin
1247 Append (Buf, S);
1248 return Name_Find (Buf);
1249 end Name_Find;
1251 -------------
1252 -- Nam_In --
1253 -------------
1255 function Nam_In
1256 (T : Name_Id;
1257 V1 : Name_Id;
1258 V2 : Name_Id) return Boolean
1260 begin
1261 return T = V1 or else
1262 T = V2;
1263 end Nam_In;
1265 function Nam_In
1266 (T : Name_Id;
1267 V1 : Name_Id;
1268 V2 : Name_Id;
1269 V3 : Name_Id) return Boolean
1271 begin
1272 return T = V1 or else
1273 T = V2 or else
1274 T = V3;
1275 end Nam_In;
1277 function Nam_In
1278 (T : Name_Id;
1279 V1 : Name_Id;
1280 V2 : Name_Id;
1281 V3 : Name_Id;
1282 V4 : Name_Id) return Boolean
1284 begin
1285 return T = V1 or else
1286 T = V2 or else
1287 T = V3 or else
1288 T = V4;
1289 end Nam_In;
1291 function Nam_In
1292 (T : Name_Id;
1293 V1 : Name_Id;
1294 V2 : Name_Id;
1295 V3 : Name_Id;
1296 V4 : Name_Id;
1297 V5 : Name_Id) return Boolean
1299 begin
1300 return T = V1 or else
1301 T = V2 or else
1302 T = V3 or else
1303 T = V4 or else
1304 T = V5;
1305 end Nam_In;
1307 function Nam_In
1308 (T : Name_Id;
1309 V1 : Name_Id;
1310 V2 : Name_Id;
1311 V3 : Name_Id;
1312 V4 : Name_Id;
1313 V5 : Name_Id;
1314 V6 : Name_Id) return Boolean
1316 begin
1317 return T = V1 or else
1318 T = V2 or else
1319 T = V3 or else
1320 T = V4 or else
1321 T = V5 or else
1322 T = V6;
1323 end Nam_In;
1325 function Nam_In
1326 (T : Name_Id;
1327 V1 : Name_Id;
1328 V2 : Name_Id;
1329 V3 : Name_Id;
1330 V4 : Name_Id;
1331 V5 : Name_Id;
1332 V6 : Name_Id;
1333 V7 : Name_Id) return Boolean
1335 begin
1336 return T = V1 or else
1337 T = V2 or else
1338 T = V3 or else
1339 T = V4 or else
1340 T = V5 or else
1341 T = V6 or else
1342 T = V7;
1343 end Nam_In;
1345 function Nam_In
1346 (T : Name_Id;
1347 V1 : Name_Id;
1348 V2 : Name_Id;
1349 V3 : Name_Id;
1350 V4 : Name_Id;
1351 V5 : Name_Id;
1352 V6 : Name_Id;
1353 V7 : Name_Id;
1354 V8 : Name_Id) return Boolean
1356 begin
1357 return T = V1 or else
1358 T = V2 or else
1359 T = V3 or else
1360 T = V4 or else
1361 T = V5 or else
1362 T = V6 or else
1363 T = V7 or else
1364 T = V8;
1365 end Nam_In;
1367 function Nam_In
1368 (T : Name_Id;
1369 V1 : Name_Id;
1370 V2 : Name_Id;
1371 V3 : Name_Id;
1372 V4 : Name_Id;
1373 V5 : Name_Id;
1374 V6 : Name_Id;
1375 V7 : Name_Id;
1376 V8 : Name_Id;
1377 V9 : Name_Id) return Boolean
1379 begin
1380 return T = V1 or else
1381 T = V2 or else
1382 T = V3 or else
1383 T = V4 or else
1384 T = V5 or else
1385 T = V6 or else
1386 T = V7 or else
1387 T = V8 or else
1388 T = V9;
1389 end Nam_In;
1391 function Nam_In
1392 (T : Name_Id;
1393 V1 : Name_Id;
1394 V2 : Name_Id;
1395 V3 : Name_Id;
1396 V4 : Name_Id;
1397 V5 : Name_Id;
1398 V6 : Name_Id;
1399 V7 : Name_Id;
1400 V8 : Name_Id;
1401 V9 : Name_Id;
1402 V10 : Name_Id) return Boolean
1404 begin
1405 return T = V1 or else
1406 T = V2 or else
1407 T = V3 or else
1408 T = V4 or else
1409 T = V5 or else
1410 T = V6 or else
1411 T = V7 or else
1412 T = V8 or else
1413 T = V9 or else
1414 T = V10;
1415 end Nam_In;
1417 function Nam_In
1418 (T : Name_Id;
1419 V1 : Name_Id;
1420 V2 : Name_Id;
1421 V3 : Name_Id;
1422 V4 : Name_Id;
1423 V5 : Name_Id;
1424 V6 : Name_Id;
1425 V7 : Name_Id;
1426 V8 : Name_Id;
1427 V9 : Name_Id;
1428 V10 : Name_Id;
1429 V11 : Name_Id) return Boolean
1431 begin
1432 return T = V1 or else
1433 T = V2 or else
1434 T = V3 or else
1435 T = V4 or else
1436 T = V5 or else
1437 T = V6 or else
1438 T = V7 or else
1439 T = V8 or else
1440 T = V9 or else
1441 T = V10 or else
1442 T = V11;
1443 end Nam_In;
1445 function Nam_In
1446 (T : Name_Id;
1447 V1 : Name_Id;
1448 V2 : Name_Id;
1449 V3 : Name_Id;
1450 V4 : Name_Id;
1451 V5 : Name_Id;
1452 V6 : Name_Id;
1453 V7 : Name_Id;
1454 V8 : Name_Id;
1455 V9 : Name_Id;
1456 V10 : Name_Id;
1457 V11 : Name_Id;
1458 V12 : Name_Id) return Boolean
1460 begin
1461 return T = V1 or else
1462 T = V2 or else
1463 T = V3 or else
1464 T = V4 or else
1465 T = V5 or else
1466 T = V6 or else
1467 T = V7 or else
1468 T = V8 or else
1469 T = V9 or else
1470 T = V10 or else
1471 T = V11 or else
1472 T = V12;
1473 end Nam_In;
1475 -----------------
1476 -- Name_Equals --
1477 -----------------
1479 function Name_Equals (N1 : Name_Id; N2 : Name_Id) return Boolean is
1480 begin
1481 return N1 = N2 or else Get_Name_String (N1) = Get_Name_String (N2);
1482 end Name_Equals;
1484 ------------------
1485 -- Reinitialize --
1486 ------------------
1488 procedure Reinitialize is
1489 begin
1490 Name_Chars.Init;
1491 Name_Entries.Init;
1493 -- Initialize entries for one character names
1495 for C in Character loop
1496 Name_Entries.Append
1497 ((Name_Chars_Index => Name_Chars.Last,
1498 Name_Len => 1,
1499 Byte_Info => 0,
1500 Int_Info => 0,
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);
1509 end loop;
1511 -- Clear hash table
1513 for J in Hash_Index_Type loop
1514 Hash_Table (J) := No_Name;
1515 end loop;
1516 end Reinitialize;
1518 ----------------------
1519 -- Reset_Name_Table --
1520 ----------------------
1522 procedure Reset_Name_Table is
1523 begin
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;
1527 end loop;
1528 end Reset_Name_Table;
1530 --------------------------------
1531 -- Set_Character_Literal_Name --
1532 --------------------------------
1534 procedure Set_Character_Literal_Name
1535 (Buf : in out Bounded_String;
1536 C : Char_Code)
1538 begin
1539 Buf.Length := 0;
1540 Append (Buf, 'Q');
1541 Append_Encoded (Buf, C);
1542 end Set_Character_Literal_Name;
1544 procedure Set_Character_Literal_Name (C : Char_Code) is
1545 begin
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
1554 begin
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
1564 begin
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
1574 begin
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
1584 begin
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
1594 begin
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
1604 begin
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
1613 J : Integer;
1615 begin
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;
1621 exit;
1622 end if;
1624 exit when Buf.Chars (J) /= 'b'
1625 and then Buf.Chars (J) /= 'n'
1626 and then Buf.Chars (J) /= 'p';
1627 end loop;
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
1636 J := J - 1;
1637 end loop;
1639 else
1640 J := Buf.Length - 1;
1641 end if;
1643 -- Loop to search for rightmost __ or $ (homonym) separator
1645 while J > 1 loop
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
1667 else
1668 Buf.Chars (1 .. Buf.Length - J - 1) :=
1669 Buf.Chars (J + 2 .. Buf.Length);
1670 Buf.Length := Buf.Length - J - 1;
1671 exit;
1672 end if;
1674 else
1675 J := J - 1;
1676 end if;
1677 end loop;
1678 end Strip_Qualification_And_Suffixes;
1680 ---------------
1681 -- To_String --
1682 ---------------
1684 function To_String (Buf : Bounded_String) return String is
1685 begin
1686 return Buf.Chars (1 .. Buf.Length);
1687 end To_String;
1689 ---------------
1690 -- Tree_Read --
1691 ---------------
1693 procedure Tree_Read is
1694 begin
1695 Name_Chars.Tree_Read;
1696 Name_Entries.Tree_Read;
1698 Tree_Read_Data
1699 (Hash_Table'Address,
1700 Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1701 end Tree_Read;
1703 ----------------
1704 -- Tree_Write --
1705 ----------------
1707 procedure Tree_Write is
1708 begin
1709 Name_Chars.Tree_Write;
1710 Name_Entries.Tree_Write;
1712 Tree_Write_Data
1713 (Hash_Table'Address,
1714 Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1715 end Tree_Write;
1717 ------------
1718 -- Unlock --
1719 ------------
1721 procedure Unlock is
1722 begin
1723 Name_Chars.Locked := False;
1724 Name_Chars.Set_Last (Name_Chars.Last - Name_Chars_Reserve);
1725 Name_Chars.Release;
1726 Name_Entries.Locked := False;
1727 Name_Entries.Set_Last (Name_Entries.Last - Name_Entries_Reserve);
1728 Name_Entries.Release;
1729 end Unlock;
1731 --------
1732 -- wn --
1733 --------
1735 procedure wn (Id : Name_Id) is
1736 begin
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>");
1746 else
1747 declare
1748 Buf : Bounded_String (Max_Length => Natural (Length_Of_Name (Id)));
1749 begin
1750 Append (Buf, Id);
1751 Write_Str (Buf.Chars (1 .. Buf.Length));
1752 end;
1753 end if;
1755 Write_Eol;
1756 end wn;
1758 ----------------
1759 -- Write_Name --
1760 ----------------
1762 procedure Write_Name (Id : Name_Id) is
1763 Buf : Bounded_String (Max_Length => Natural (Length_Of_Name (Id)));
1764 begin
1765 if Id >= First_Name_Id then
1766 Append (Buf, Id);
1767 Write_Str (Buf.Chars (1 .. Buf.Length));
1768 end if;
1769 end Write_Name;
1771 ------------------------
1772 -- Write_Name_Decoded --
1773 ------------------------
1775 procedure Write_Name_Decoded (Id : Name_Id) is
1776 Buf : Bounded_String;
1777 begin
1778 if Id >= First_Name_Id then
1779 Append_Decoded (Buf, Id);
1780 Write_Str (Buf.Chars (1 .. Buf.Length));
1781 end if;
1782 end Write_Name_Decoded;
1784 -- Package initialization, initialize tables
1786 begin
1787 Reinitialize;
1788 end Namet;