]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ada/namet.adb
70f499303b9ab922e5ceae2120eeddc1a384e0c2
[thirdparty/gcc.git] / gcc / ada / namet.adb
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- N A M E T --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2020, 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 ------------------------------------------------------------------------------
31
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.
35
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;
42
43 with Interfaces; use Interfaces;
44
45 package body Namet is
46
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.
55
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.
60
61 Hash_Max : constant Int := Hash_Num - 1;
62 -- Indexes in the hash header table run from 0 to Hash_Num - 1
63
64 subtype Hash_Index_Type is Int range 0 .. Hash_Max;
65 -- Range of hash index values
66
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.
72
73 -----------------------
74 -- Local Subprograms --
75 -----------------------
76
77 function Hash (Buf : Bounded_String) return Hash_Index_Type;
78 pragma Inline (Hash);
79 -- Compute hash code for name stored in Buf
80
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.
85
86 -----------------------------
87 -- Add_Char_To_Name_Buffer --
88 -----------------------------
89
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;
94
95 ----------------------------
96 -- Add_Nat_To_Name_Buffer --
97 ----------------------------
98
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;
103
104 ----------------------------
105 -- Add_Str_To_Name_Buffer --
106 ----------------------------
107
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;
112
113 ------------
114 -- Append --
115 ------------
116
117 procedure Append (Buf : in out Bounded_String; C : Character) is
118 begin
119 Buf.Length := Buf.Length + 1;
120
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;
127
128 Buf.Chars (Buf.Length) := C;
129 end Append;
130
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;
136
137 Append (Buf, Character'Val (Character'Pos ('0') + V rem 10));
138 end Append;
139
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;
144
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;
151
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;
156
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;
161
162 procedure Append (Buf : in out Bounded_String; Id : Valid_Name_Id) is
163 pragma Assert (Is_Valid_Name (Id));
164
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;
172
173 --------------------
174 -- Append_Decoded --
175 --------------------
176
177 procedure Append_Decoded
178 (Buf : in out Bounded_String;
179 Id : Valid_Name_Id)
180 is
181 C : Character;
182 P : Natural;
183 Temp : Bounded_String;
184
185 begin
186 Append (Temp, Id);
187
188 -- Skip scan if we already know there are no encodings
189
190 if Name_Entries.Table (Id).Name_Has_No_Encodings then
191 goto Done;
192 end if;
193
194 -- Quick loop to see if there is anything special to do
195
196 P := 1;
197 loop
198 if P = Temp.Length then
199 Name_Entries.Table (Id).Name_Has_No_Encodings := True;
200 goto Done;
201
202 else
203 C := Temp.Chars (P);
204
205 exit when
206 C = 'U' or else
207 C = 'W' or else
208 C = 'Q' or else
209 C = 'O';
210
211 P := P + 1;
212 end if;
213 end loop;
214
215 -- Here we have at least some encoding that we must decode
216
217 Decode : declare
218 New_Len : Natural;
219 Old : Positive;
220 New_Buf : String (1 .. Temp.Chars'Last);
221
222 procedure Copy_One_Character;
223 -- Copy a character from Temp.Chars to New_Buf. Includes case
224 -- of copying a Uhh,Whhhh,WWhhhhhhhh sequence and decoding it.
225
226 function Hex (N : Natural) return Word;
227 -- Scans past N digits using Old pointer and returns hex value
228
229 procedure Insert_Character (C : Character);
230 -- Insert a new character into output decoded name
231
232 ------------------------
233 -- Copy_One_Character --
234 ------------------------
235
236 procedure Copy_One_Character is
237 C : Character;
238
239 begin
240 C := Temp.Chars (Old);
241
242 -- U (upper half insertion case)
243
244 if C = 'U'
245 and then Old < Temp.Length
246 and then Temp.Chars (Old + 1) not in 'A' .. 'Z'
247 and then Temp.Chars (Old + 1) /= '_'
248 then
249 Old := Old + 1;
250
251 -- If we have upper half encoding, then we have to set an
252 -- appropriate wide character sequence for this character.
253
254 if Upper_Half_Encoding then
255 Widechar.Set_Wide (Char_Code (Hex (2)), New_Buf, New_Len);
256
257 -- For other encoding methods, upper half characters can
258 -- simply use their normal representation.
259
260 else
261 declare
262 W2 : constant Word := Hex (2);
263 begin
264 pragma Assert (W2 <= 255);
265 -- Add assumption to facilitate static analysis. Note
266 -- that we cannot use pragma Assume for bootstrap
267 -- reasons.
268 Insert_Character (Character'Val (W2));
269 end;
270 end if;
271
272 -- WW (wide wide character insertion)
273
274 elsif C = 'W'
275 and then Old < Temp.Length
276 and then Temp.Chars (Old + 1) = 'W'
277 then
278 Old := Old + 2;
279 Widechar.Set_Wide (Char_Code (Hex (8)), New_Buf, New_Len);
280
281 -- W (wide character insertion)
282
283 elsif C = 'W'
284 and then Old < Temp.Length
285 and then Temp.Chars (Old + 1) not in 'A' .. 'Z'
286 and then Temp.Chars (Old + 1) /= '_'
287 then
288 Old := Old + 1;
289 Widechar.Set_Wide (Char_Code (Hex (4)), New_Buf, New_Len);
290
291 -- Any other character is copied unchanged
292
293 else
294 Insert_Character (C);
295 Old := Old + 1;
296 end if;
297 end Copy_One_Character;
298
299 ---------
300 -- Hex --
301 ---------
302
303 function Hex (N : Natural) return Word is
304 T : Word := 0;
305 C : Character;
306
307 begin
308 for J in 1 .. N loop
309 C := Temp.Chars (Old);
310 Old := Old + 1;
311
312 pragma Assert (C in '0' .. '9' or else C in 'a' .. 'f');
313
314 if C <= '9' then
315 T := 16 * T + Character'Pos (C) - Character'Pos ('0');
316 else -- C in 'a' .. 'f'
317 T := 16 * T + Character'Pos (C) - (Character'Pos ('a') - 10);
318 end if;
319 end loop;
320
321 return T;
322 end Hex;
323
324 ----------------------
325 -- Insert_Character --
326 ----------------------
327
328 procedure Insert_Character (C : Character) is
329 begin
330 New_Len := New_Len + 1;
331 New_Buf (New_Len) := C;
332 end Insert_Character;
333
334 -- Start of processing for Decode
335
336 begin
337 New_Len := 0;
338 Old := 1;
339
340 -- Loop through characters of name
341
342 while Old <= Temp.Length loop
343
344 -- Case of character literal, put apostrophes around character
345
346 if Temp.Chars (Old) = 'Q'
347 and then Old < Temp.Length
348 then
349 Old := Old + 1;
350 Insert_Character (''');
351 Copy_One_Character;
352 Insert_Character (''');
353
354 -- Case of operator name
355
356 elsif Temp.Chars (Old) = 'O'
357 and then Old < Temp.Length
358 and then Temp.Chars (Old + 1) not in 'A' .. 'Z'
359 and then Temp.Chars (Old + 1) /= '_'
360 then
361 Old := Old + 1;
362
363 declare
364 -- This table maps the 2nd and 3rd characters of the name
365 -- into the required output. Two blanks means leave the
366 -- name alone
367
368 Map : constant String :=
369 "ab " & -- Oabs => "abs"
370 "ad+ " & -- Oadd => "+"
371 "an " & -- Oand => "and"
372 "co& " & -- Oconcat => "&"
373 "di/ " & -- Odivide => "/"
374 "eq= " & -- Oeq => "="
375 "ex**" & -- Oexpon => "**"
376 "gt> " & -- Ogt => ">"
377 "ge>=" & -- Oge => ">="
378 "le<=" & -- Ole => "<="
379 "lt< " & -- Olt => "<"
380 "mo " & -- Omod => "mod"
381 "mu* " & -- Omutliply => "*"
382 "ne/=" & -- One => "/="
383 "no " & -- Onot => "not"
384 "or " & -- Oor => "or"
385 "re " & -- Orem => "rem"
386 "su- " & -- Osubtract => "-"
387 "xo "; -- Oxor => "xor"
388
389 J : Integer;
390
391 begin
392 Insert_Character ('"');
393
394 -- Search the map. Note that this loop must terminate, if
395 -- not we have some kind of internal error, and a constraint
396 -- error may be raised.
397
398 J := Map'First;
399 loop
400 exit when Temp.Chars (Old) = Map (J)
401 and then Temp.Chars (Old + 1) = Map (J + 1);
402 J := J + 4;
403 end loop;
404
405 -- Special operator name
406
407 if Map (J + 2) /= ' ' then
408 Insert_Character (Map (J + 2));
409
410 if Map (J + 3) /= ' ' then
411 Insert_Character (Map (J + 3));
412 end if;
413
414 Insert_Character ('"');
415
416 -- Skip past original operator name in input
417
418 while Old <= Temp.Length
419 and then Temp.Chars (Old) in 'a' .. 'z'
420 loop
421 Old := Old + 1;
422 end loop;
423
424 -- For other operator names, leave them in lower case,
425 -- surrounded by apostrophes
426
427 else
428 -- Copy original operator name from input to output
429
430 while Old <= Temp.Length
431 and then Temp.Chars (Old) in 'a' .. 'z'
432 loop
433 Copy_One_Character;
434 end loop;
435
436 Insert_Character ('"');
437 end if;
438 end;
439
440 -- Else copy one character and keep going
441
442 else
443 Copy_One_Character;
444 end if;
445 end loop;
446
447 -- Copy new buffer as result
448
449 Temp.Length := New_Len;
450 Temp.Chars (1 .. New_Len) := New_Buf (1 .. New_Len);
451 end Decode;
452
453 <<Done>>
454 Append (Buf, Temp);
455 end Append_Decoded;
456
457 ----------------------------------
458 -- Append_Decoded_With_Brackets --
459 ----------------------------------
460
461 procedure Append_Decoded_With_Brackets
462 (Buf : in out Bounded_String;
463 Id : Valid_Name_Id)
464 is
465 P : Natural;
466
467 begin
468 -- Case of operator name, normal decoding is fine
469
470 if Buf.Chars (1) = 'O' then
471 Append_Decoded (Buf, Id);
472
473 -- For character literals, normal decoding is fine
474
475 elsif Buf.Chars (1) = 'Q' then
476 Append_Decoded (Buf, Id);
477
478 -- Only remaining issue is U/W/WW sequences
479
480 else
481 declare
482 Temp : Bounded_String;
483 begin
484 Append (Temp, Id);
485
486 P := 1;
487 while P < Temp.Length loop
488 if Temp.Chars (P + 1) in 'A' .. 'Z' then
489 P := P + 1;
490
491 -- Uhh encoding
492
493 elsif Temp.Chars (P) = 'U' then
494 for J in reverse P + 3 .. P + Temp.Length loop
495 Temp.Chars (J + 3) := Temp.Chars (J);
496 end loop;
497
498 Temp.Length := Temp.Length + 3;
499 Temp.Chars (P + 3) := Temp.Chars (P + 2);
500 Temp.Chars (P + 2) := Temp.Chars (P + 1);
501 Temp.Chars (P) := '[';
502 Temp.Chars (P + 1) := '"';
503 Temp.Chars (P + 4) := '"';
504 Temp.Chars (P + 5) := ']';
505 P := P + 6;
506
507 -- WWhhhhhhhh encoding
508
509 elsif Temp.Chars (P) = 'W'
510 and then P + 9 <= Temp.Length
511 and then Temp.Chars (P + 1) = 'W'
512 and then Temp.Chars (P + 2) not in 'A' .. 'Z'
513 and then Temp.Chars (P + 2) /= '_'
514 then
515 Temp.Chars (P + 12 .. Temp.Length + 2) :=
516 Temp.Chars (P + 10 .. Temp.Length);
517 Temp.Chars (P) := '[';
518 Temp.Chars (P + 1) := '"';
519 Temp.Chars (P + 10) := '"';
520 Temp.Chars (P + 11) := ']';
521 Temp.Length := Temp.Length + 2;
522 P := P + 12;
523
524 -- Whhhh encoding
525
526 elsif Temp.Chars (P) = 'W'
527 and then P < Temp.Length
528 and then Temp.Chars (P + 1) not in 'A' .. 'Z'
529 and then Temp.Chars (P + 1) /= '_'
530 then
531 Temp.Chars (P + 8 .. P + Temp.Length + 3) :=
532 Temp.Chars (P + 5 .. Temp.Length);
533 Temp.Chars (P + 2 .. P + 5) := Temp.Chars (P + 1 .. P + 4);
534 Temp.Chars (P) := '[';
535 Temp.Chars (P + 1) := '"';
536 Temp.Chars (P + 6) := '"';
537 Temp.Chars (P + 7) := ']';
538 Temp.Length := Temp.Length + 3;
539 P := P + 8;
540
541 else
542 P := P + 1;
543 end if;
544 end loop;
545
546 Append (Buf, Temp);
547 end;
548 end if;
549 end Append_Decoded_With_Brackets;
550
551 --------------------
552 -- Append_Encoded --
553 --------------------
554
555 procedure Append_Encoded (Buf : in out Bounded_String; C : Char_Code) is
556 procedure Set_Hex_Chars (C : Char_Code);
557 -- Stores given value, which is in the range 0 .. 255, as two hex
558 -- digits (using lower case a-f) in Buf.Chars, incrementing Buf.Length.
559
560 -------------------
561 -- Set_Hex_Chars --
562 -------------------
563
564 procedure Set_Hex_Chars (C : Char_Code) is
565 Hexd : constant String := "0123456789abcdef";
566 N : constant Natural := Natural (C);
567 begin
568 Buf.Chars (Buf.Length + 1) := Hexd (N / 16 + 1);
569 Buf.Chars (Buf.Length + 2) := Hexd (N mod 16 + 1);
570 Buf.Length := Buf.Length + 2;
571 end Set_Hex_Chars;
572
573 -- Start of processing for Append_Encoded
574
575 begin
576 Buf.Length := Buf.Length + 1;
577
578 if In_Character_Range (C) then
579 declare
580 CC : constant Character := Get_Character (C);
581 begin
582 if CC in 'a' .. 'z' or else CC in '0' .. '9' then
583 Buf.Chars (Buf.Length) := CC;
584 else
585 Buf.Chars (Buf.Length) := 'U';
586 Set_Hex_Chars (C);
587 end if;
588 end;
589
590 elsif In_Wide_Character_Range (C) then
591 Buf.Chars (Buf.Length) := 'W';
592 Set_Hex_Chars (C / 256);
593 Set_Hex_Chars (C mod 256);
594
595 else
596 Buf.Chars (Buf.Length) := 'W';
597 Buf.Length := Buf.Length + 1;
598 Buf.Chars (Buf.Length) := 'W';
599 Set_Hex_Chars (C / 2 ** 24);
600 Set_Hex_Chars ((C / 2 ** 16) mod 256);
601 Set_Hex_Chars ((C / 256) mod 256);
602 Set_Hex_Chars (C mod 256);
603 end if;
604 end Append_Encoded;
605
606 ------------------------
607 -- Append_Unqualified --
608 ------------------------
609
610 procedure Append_Unqualified
611 (Buf : in out Bounded_String;
612 Id : Valid_Name_Id)
613 is
614 Temp : Bounded_String;
615 begin
616 Append (Temp, Id);
617 Strip_Qualification_And_Suffixes (Temp);
618 Append (Buf, Temp);
619 end Append_Unqualified;
620
621 --------------------------------
622 -- Append_Unqualified_Decoded --
623 --------------------------------
624
625 procedure Append_Unqualified_Decoded
626 (Buf : in out Bounded_String;
627 Id : Valid_Name_Id)
628 is
629 Temp : Bounded_String;
630 begin
631 Append_Decoded (Temp, Id);
632 Strip_Qualification_And_Suffixes (Temp);
633 Append (Buf, Temp);
634 end Append_Unqualified_Decoded;
635
636 --------------
637 -- Finalize --
638 --------------
639
640 procedure Finalize is
641 F : array (Int range 0 .. 50) of Int;
642 -- N'th entry is the number of chains of length N, except last entry,
643 -- which is the number of chains of length F'Last or more.
644
645 Max_Chain_Length : Nat := 0;
646 -- Maximum length of all chains
647
648 Probes : Nat := 0;
649 -- Used to compute average number of probes
650
651 Nsyms : Nat := 0;
652 -- Number of symbols in table
653
654 Verbosity : constant Int range 1 .. 3 := 1;
655 pragma Warnings (Off, Verbosity);
656 -- This constant indicates the level of verbosity in the output from
657 -- this procedure. Currently this can only be changed by editing the
658 -- declaration above and recompiling. That's good enough in practice,
659 -- since we very rarely need to use this debug option. Settings are:
660 --
661 -- 1 => print basic summary information
662 -- 2 => in addition print number of entries per hash chain
663 -- 3 => in addition print content of entries
664
665 Zero : constant Int := Character'Pos ('0');
666
667 begin
668 if not Debug_Flag_H then
669 return;
670 end if;
671
672 for J in F'Range loop
673 F (J) := 0;
674 end loop;
675
676 for J in Hash_Index_Type loop
677 if Hash_Table (J) = No_Name then
678 F (0) := F (0) + 1;
679
680 else
681 declare
682 C : Nat;
683 N : Name_Id;
684 S : Int;
685
686 begin
687 C := 0;
688 N := Hash_Table (J);
689
690 while N /= No_Name loop
691 N := Name_Entries.Table (N).Hash_Link;
692 C := C + 1;
693 end loop;
694
695 Nsyms := Nsyms + 1;
696 Probes := Probes + (1 + C) * 100;
697
698 if C > Max_Chain_Length then
699 Max_Chain_Length := C;
700 end if;
701
702 if Verbosity >= 2 then
703 Write_Str ("Hash_Table (");
704 Write_Int (J);
705 Write_Str (") has ");
706 Write_Int (C);
707 Write_Str (" entries");
708 Write_Eol;
709 end if;
710
711 if C < F'Last then
712 F (C) := F (C) + 1;
713 else
714 F (F'Last) := F (F'Last) + 1;
715 end if;
716
717 if Verbosity >= 3 then
718 N := Hash_Table (J);
719 while N /= No_Name loop
720 S := Name_Entries.Table (N).Name_Chars_Index;
721
722 Write_Str (" ");
723
724 for J in 1 .. Name_Entries.Table (N).Name_Len loop
725 Write_Char (Name_Chars.Table (S + Int (J)));
726 end loop;
727
728 Write_Eol;
729
730 N := Name_Entries.Table (N).Hash_Link;
731 end loop;
732 end if;
733 end;
734 end if;
735 end loop;
736
737 Write_Eol;
738
739 for J in F'Range loop
740 if F (J) /= 0 then
741 Write_Str ("Number of hash chains of length ");
742
743 if J < 10 then
744 Write_Char (' ');
745 end if;
746
747 Write_Int (J);
748
749 if J = F'Last then
750 Write_Str (" or greater");
751 end if;
752
753 Write_Str (" = ");
754 Write_Int (F (J));
755 Write_Eol;
756 end if;
757 end loop;
758
759 -- Print out average number of probes, in the case where Name_Find is
760 -- called for a string that is already in the table.
761
762 Write_Eol;
763 Write_Str ("Average number of probes for lookup = ");
764 pragma Assert (Nsyms /= 0);
765 -- Add assumption to facilitate static analysis. Here Nsyms cannot be
766 -- zero because many symbols are added to the table by default.
767 Probes := Probes / Nsyms;
768 Write_Int (Probes / 200);
769 Write_Char ('.');
770 Probes := (Probes mod 200) / 2;
771 Write_Char (Character'Val (Zero + Probes / 10));
772 Write_Char (Character'Val (Zero + Probes mod 10));
773 Write_Eol;
774
775 Write_Str ("Max_Chain_Length = ");
776 Write_Int (Max_Chain_Length);
777 Write_Eol;
778 Write_Str ("Name_Chars'Length = ");
779 Write_Int (Name_Chars.Last - Name_Chars.First + 1);
780 Write_Eol;
781 Write_Str ("Name_Entries'Length = ");
782 Write_Int (Int (Name_Entries.Last - Name_Entries.First + 1));
783 Write_Eol;
784 Write_Str ("Nsyms = ");
785 Write_Int (Nsyms);
786 Write_Eol;
787 end Finalize;
788
789 -----------------------------
790 -- Get_Decoded_Name_String --
791 -----------------------------
792
793 procedure Get_Decoded_Name_String (Id : Valid_Name_Id) is
794 begin
795 Global_Name_Buffer.Length := 0;
796 Append_Decoded (Global_Name_Buffer, Id);
797 end Get_Decoded_Name_String;
798
799 -------------------------------------------
800 -- Get_Decoded_Name_String_With_Brackets --
801 -------------------------------------------
802
803 procedure Get_Decoded_Name_String_With_Brackets (Id : Valid_Name_Id) is
804 begin
805 Global_Name_Buffer.Length := 0;
806 Append_Decoded_With_Brackets (Global_Name_Buffer, Id);
807 end Get_Decoded_Name_String_With_Brackets;
808
809 ------------------------
810 -- Get_Last_Two_Chars --
811 ------------------------
812
813 procedure Get_Last_Two_Chars
814 (N : Valid_Name_Id;
815 C1 : out Character;
816 C2 : out Character)
817 is
818 NE : Name_Entry renames Name_Entries.Table (N);
819 NEL : constant Int := Int (NE.Name_Len);
820
821 begin
822 if NEL >= 2 then
823 C1 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 1);
824 C2 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 0);
825 else
826 C1 := ASCII.NUL;
827 C2 := ASCII.NUL;
828 end if;
829 end Get_Last_Two_Chars;
830
831 ---------------------
832 -- Get_Name_String --
833 ---------------------
834
835 procedure Get_Name_String (Id : Valid_Name_Id) is
836 begin
837 Global_Name_Buffer.Length := 0;
838 Append (Global_Name_Buffer, Id);
839 end Get_Name_String;
840
841 function Get_Name_String (Id : Valid_Name_Id) return String is
842 Buf : Bounded_String (Max_Length => Natural (Length_Of_Name (Id)));
843 begin
844 Append (Buf, Id);
845 return +Buf;
846 end Get_Name_String;
847
848 --------------------------------
849 -- Get_Name_String_And_Append --
850 --------------------------------
851
852 procedure Get_Name_String_And_Append (Id : Valid_Name_Id) is
853 begin
854 Append (Global_Name_Buffer, Id);
855 end Get_Name_String_And_Append;
856
857 -----------------------------
858 -- Get_Name_Table_Boolean1 --
859 -----------------------------
860
861 function Get_Name_Table_Boolean1 (Id : Valid_Name_Id) return Boolean is
862 begin
863 pragma Assert (Is_Valid_Name (Id));
864 return Name_Entries.Table (Id).Boolean1_Info;
865 end Get_Name_Table_Boolean1;
866
867 -----------------------------
868 -- Get_Name_Table_Boolean2 --
869 -----------------------------
870
871 function Get_Name_Table_Boolean2 (Id : Valid_Name_Id) return Boolean is
872 begin
873 pragma Assert (Is_Valid_Name (Id));
874 return Name_Entries.Table (Id).Boolean2_Info;
875 end Get_Name_Table_Boolean2;
876
877 -----------------------------
878 -- Get_Name_Table_Boolean3 --
879 -----------------------------
880
881 function Get_Name_Table_Boolean3 (Id : Valid_Name_Id) return Boolean is
882 begin
883 pragma Assert (Is_Valid_Name (Id));
884 return Name_Entries.Table (Id).Boolean3_Info;
885 end Get_Name_Table_Boolean3;
886
887 -------------------------
888 -- Get_Name_Table_Byte --
889 -------------------------
890
891 function Get_Name_Table_Byte (Id : Valid_Name_Id) return Byte is
892 begin
893 pragma Assert (Is_Valid_Name (Id));
894 return Name_Entries.Table (Id).Byte_Info;
895 end Get_Name_Table_Byte;
896
897 -------------------------
898 -- Get_Name_Table_Int --
899 -------------------------
900
901 function Get_Name_Table_Int (Id : Valid_Name_Id) return Int is
902 begin
903 pragma Assert (Is_Valid_Name (Id));
904 return Name_Entries.Table (Id).Int_Info;
905 end Get_Name_Table_Int;
906
907 -----------------------------------------
908 -- Get_Unqualified_Decoded_Name_String --
909 -----------------------------------------
910
911 procedure Get_Unqualified_Decoded_Name_String (Id : Valid_Name_Id) is
912 begin
913 Global_Name_Buffer.Length := 0;
914 Append_Unqualified_Decoded (Global_Name_Buffer, Id);
915 end Get_Unqualified_Decoded_Name_String;
916
917 ---------------------------------
918 -- Get_Unqualified_Name_String --
919 ---------------------------------
920
921 procedure Get_Unqualified_Name_String (Id : Valid_Name_Id) is
922 begin
923 Global_Name_Buffer.Length := 0;
924 Append_Unqualified (Global_Name_Buffer, Id);
925 end Get_Unqualified_Name_String;
926
927 ----------
928 -- Hash --
929 ----------
930
931 function Hash (Buf : Bounded_String) return Hash_Index_Type is
932
933 -- This hash function looks at every character, in order to make it
934 -- likely that similar strings get different hash values. The rotate by
935 -- 7 bits has been determined empirically to be good, and it doesn't
936 -- lose bits like a shift would. The final conversion can't overflow,
937 -- because the table is 2**16 in size. This function probably needs to
938 -- be changed if the hash table size is changed.
939
940 -- Note that we could get some speed improvement by aligning the string
941 -- to 32 or 64 bits, and doing word-wise xor's. We could also implement
942 -- a growable table. It doesn't seem worth the trouble to do those
943 -- things, for now.
944
945 Result : Unsigned_16 := 0;
946
947 begin
948 for J in 1 .. Buf.Length loop
949 Result := Rotate_Left (Result, 7) xor Character'Pos (Buf.Chars (J));
950 end loop;
951
952 return Hash_Index_Type (Result);
953 end Hash;
954
955 ----------------
956 -- Initialize --
957 ----------------
958
959 procedure Initialize is
960 begin
961 null;
962 end Initialize;
963
964 ----------------
965 -- Insert_Str --
966 ----------------
967
968 procedure Insert_Str
969 (Buf : in out Bounded_String;
970 S : String;
971 Index : Positive)
972 is
973 SL : constant Natural := S'Length;
974
975 begin
976 Buf.Chars (Index + SL .. Buf.Length + SL) :=
977 Buf.Chars (Index .. Buf.Length);
978 Buf.Chars (Index .. Index + SL - 1) := S;
979 Buf.Length := Buf.Length + SL;
980 end Insert_Str;
981
982 -------------------------------
983 -- Insert_Str_In_Name_Buffer --
984 -------------------------------
985
986 procedure Insert_Str_In_Name_Buffer (S : String; Index : Positive) is
987 begin
988 Insert_Str (Global_Name_Buffer, S, Index);
989 end Insert_Str_In_Name_Buffer;
990
991 ----------------------
992 -- Is_Internal_Name --
993 ----------------------
994
995 function Is_Internal_Name (Buf : Bounded_String) return Boolean is
996 J : Natural;
997
998 begin
999 -- Any name starting or ending with underscore is internal
1000
1001 if Buf.Chars (1) = '_'
1002 or else Buf.Chars (Buf.Length) = '_'
1003 then
1004 return True;
1005
1006 -- Allow quoted character
1007
1008 elsif Buf.Chars (1) = ''' then
1009 return False;
1010
1011 -- All other cases, scan name
1012
1013 else
1014 -- Test backwards, because we only want to test the last entity
1015 -- name if the name we have is qualified with other entities.
1016
1017 J := Buf.Length;
1018 while J /= 0 loop
1019
1020 -- Skip stuff between brackets (A-F OK there)
1021
1022 if Buf.Chars (J) = ']' then
1023 loop
1024 J := J - 1;
1025 exit when J = 1 or else Buf.Chars (J) = '[';
1026 end loop;
1027
1028 -- Test for internal letter
1029
1030 elsif Is_OK_Internal_Letter (Buf.Chars (J)) then
1031 return True;
1032
1033 -- Quit if we come to terminating double underscore (note that
1034 -- if the current character is an underscore, we know that
1035 -- there is a previous character present, since we already
1036 -- filtered out the case of Buf.Chars (1) = '_' above.
1037
1038 elsif Buf.Chars (J) = '_'
1039 and then Buf.Chars (J - 1) = '_'
1040 and then Buf.Chars (J - 2) /= '_'
1041 then
1042 return False;
1043 end if;
1044
1045 J := J - 1;
1046 end loop;
1047 end if;
1048
1049 return False;
1050 end Is_Internal_Name;
1051
1052 function Is_Internal_Name (Id : Valid_Name_Id) return Boolean is
1053 Buf : Bounded_String (Max_Length => Natural (Length_Of_Name (Id)));
1054 begin
1055 Append (Buf, Id);
1056 return Is_Internal_Name (Buf);
1057 end Is_Internal_Name;
1058
1059 function Is_Internal_Name return Boolean is
1060 begin
1061 return Is_Internal_Name (Global_Name_Buffer);
1062 end Is_Internal_Name;
1063
1064 ---------------------------
1065 -- Is_OK_Internal_Letter --
1066 ---------------------------
1067
1068 function Is_OK_Internal_Letter (C : Character) return Boolean is
1069 begin
1070 return C in 'A' .. 'Z'
1071 and then C /= 'O'
1072 and then C /= 'Q'
1073 and then C /= 'U'
1074 and then C /= 'W'
1075 and then C /= 'X';
1076 end Is_OK_Internal_Letter;
1077
1078 ----------------------
1079 -- Is_Operator_Name --
1080 ----------------------
1081
1082 function Is_Operator_Name (Id : Valid_Name_Id) return Boolean is
1083 S : Int;
1084 begin
1085 pragma Assert (Is_Valid_Name (Id));
1086 S := Name_Entries.Table (Id).Name_Chars_Index;
1087 return Name_Chars.Table (S + 1) = 'O';
1088 end Is_Operator_Name;
1089
1090 -------------------
1091 -- Is_Valid_Name --
1092 -------------------
1093
1094 function Is_Valid_Name (Id : Name_Id) return Boolean is
1095 begin
1096 return Id in Name_Entries.First .. Name_Entries.Last;
1097 end Is_Valid_Name;
1098
1099 --------------------
1100 -- Length_Of_Name --
1101 --------------------
1102
1103 function Length_Of_Name (Id : Valid_Name_Id) return Nat is
1104 begin
1105 return Int (Name_Entries.Table (Id).Name_Len);
1106 end Length_Of_Name;
1107
1108 ----------
1109 -- Lock --
1110 ----------
1111
1112 procedure Lock is
1113 begin
1114 Name_Chars.Set_Last (Name_Chars.Last + Name_Chars_Reserve);
1115 Name_Entries.Set_Last (Name_Entries.Last + Name_Entries_Reserve);
1116 Name_Chars.Release;
1117 Name_Chars.Locked := True;
1118 Name_Entries.Release;
1119 Name_Entries.Locked := True;
1120 end Lock;
1121
1122 ----------------
1123 -- Name_Enter --
1124 ----------------
1125
1126 function Name_Enter
1127 (Buf : Bounded_String := Global_Name_Buffer) return Valid_Name_Id
1128 is
1129 begin
1130 Name_Entries.Append
1131 ((Name_Chars_Index => Name_Chars.Last,
1132 Name_Len => Short (Buf.Length),
1133 Byte_Info => 0,
1134 Int_Info => 0,
1135 Boolean1_Info => False,
1136 Boolean2_Info => False,
1137 Boolean3_Info => False,
1138 Name_Has_No_Encodings => False,
1139 Hash_Link => No_Name));
1140
1141 -- Set corresponding string entry in the Name_Chars table
1142
1143 for J in 1 .. Buf.Length loop
1144 Name_Chars.Append (Buf.Chars (J));
1145 end loop;
1146
1147 Name_Chars.Append (ASCII.NUL);
1148
1149 return Name_Entries.Last;
1150 end Name_Enter;
1151
1152 function Name_Enter (S : String) return Valid_Name_Id is
1153 Buf : Bounded_String (Max_Length => S'Length);
1154 begin
1155 Append (Buf, S);
1156 return Name_Enter (Buf);
1157 end Name_Enter;
1158
1159 ------------------------
1160 -- Name_Entries_Count --
1161 ------------------------
1162
1163 function Name_Entries_Count return Nat is
1164 begin
1165 return Int (Name_Entries.Last - Name_Entries.First + 1);
1166 end Name_Entries_Count;
1167
1168 ---------------
1169 -- Name_Find --
1170 ---------------
1171
1172 function Name_Find
1173 (Buf : Bounded_String := Global_Name_Buffer) return Valid_Name_Id
1174 is
1175 New_Id : Name_Id;
1176 -- Id of entry in hash search, and value to be returned
1177
1178 S : Int;
1179 -- Pointer into string table
1180
1181 Hash_Index : Hash_Index_Type;
1182 -- Computed hash index
1183
1184 begin
1185 -- Quick handling for one character names
1186
1187 if Buf.Length = 1 then
1188 return Valid_Name_Id (First_Name_Id + Character'Pos (Buf.Chars (1)));
1189
1190 -- Otherwise search hash table for existing matching entry
1191
1192 else
1193 Hash_Index := Namet.Hash (Buf);
1194 New_Id := Hash_Table (Hash_Index);
1195
1196 if New_Id = No_Name then
1197 Hash_Table (Hash_Index) := Name_Entries.Last + 1;
1198
1199 else
1200 Search : loop
1201 if Buf.Length /=
1202 Integer (Name_Entries.Table (New_Id).Name_Len)
1203 then
1204 goto No_Match;
1205 end if;
1206
1207 S := Name_Entries.Table (New_Id).Name_Chars_Index;
1208
1209 for J in 1 .. Buf.Length loop
1210 if Name_Chars.Table (S + Int (J)) /= Buf.Chars (J) then
1211 goto No_Match;
1212 end if;
1213 end loop;
1214
1215 return New_Id;
1216
1217 -- Current entry in hash chain does not match
1218
1219 <<No_Match>>
1220 if Name_Entries.Table (New_Id).Hash_Link /= No_Name then
1221 New_Id := Name_Entries.Table (New_Id).Hash_Link;
1222 else
1223 Name_Entries.Table (New_Id).Hash_Link :=
1224 Name_Entries.Last + 1;
1225 exit Search;
1226 end if;
1227 end loop Search;
1228 end if;
1229
1230 -- We fall through here only if a matching entry was not found in the
1231 -- hash table. We now create a new entry in the names table. The hash
1232 -- link pointing to the new entry (Name_Entries.Last+1) has been set.
1233
1234 Name_Entries.Append
1235 ((Name_Chars_Index => Name_Chars.Last,
1236 Name_Len => Short (Buf.Length),
1237 Hash_Link => No_Name,
1238 Name_Has_No_Encodings => False,
1239 Int_Info => 0,
1240 Byte_Info => 0,
1241 Boolean1_Info => False,
1242 Boolean2_Info => False,
1243 Boolean3_Info => False));
1244
1245 -- Set corresponding string entry in the Name_Chars table
1246
1247 for J in 1 .. Buf.Length loop
1248 Name_Chars.Append (Buf.Chars (J));
1249 end loop;
1250
1251 Name_Chars.Append (ASCII.NUL);
1252
1253 return Name_Entries.Last;
1254 end if;
1255 end Name_Find;
1256
1257 function Name_Find (S : String) return Valid_Name_Id is
1258 Buf : Bounded_String (Max_Length => S'Length);
1259 begin
1260 Append (Buf, S);
1261 return Name_Find (Buf);
1262 end Name_Find;
1263
1264 -------------
1265 -- Nam_In --
1266 -------------
1267
1268 function Nam_In
1269 (T : Name_Id;
1270 V1 : Name_Id;
1271 V2 : Name_Id) return Boolean
1272 is
1273 begin
1274 return T = V1 or else
1275 T = V2;
1276 end Nam_In;
1277
1278 function Nam_In
1279 (T : Name_Id;
1280 V1 : Name_Id;
1281 V2 : Name_Id;
1282 V3 : Name_Id) return Boolean
1283 is
1284 begin
1285 return T = V1 or else
1286 T = V2 or else
1287 T = V3;
1288 end Nam_In;
1289
1290 function Nam_In
1291 (T : Name_Id;
1292 V1 : Name_Id;
1293 V2 : Name_Id;
1294 V3 : Name_Id;
1295 V4 : Name_Id) return Boolean
1296 is
1297 begin
1298 return T = V1 or else
1299 T = V2 or else
1300 T = V3 or else
1301 T = V4;
1302 end Nam_In;
1303
1304 function Nam_In
1305 (T : Name_Id;
1306 V1 : Name_Id;
1307 V2 : Name_Id;
1308 V3 : Name_Id;
1309 V4 : Name_Id;
1310 V5 : Name_Id) return Boolean
1311 is
1312 begin
1313 return T = V1 or else
1314 T = V2 or else
1315 T = V3 or else
1316 T = V4 or else
1317 T = V5;
1318 end Nam_In;
1319
1320 function Nam_In
1321 (T : Name_Id;
1322 V1 : Name_Id;
1323 V2 : Name_Id;
1324 V3 : Name_Id;
1325 V4 : Name_Id;
1326 V5 : Name_Id;
1327 V6 : Name_Id) return Boolean
1328 is
1329 begin
1330 return T = V1 or else
1331 T = V2 or else
1332 T = V3 or else
1333 T = V4 or else
1334 T = V5 or else
1335 T = V6;
1336 end Nam_In;
1337
1338 function Nam_In
1339 (T : Name_Id;
1340 V1 : Name_Id;
1341 V2 : Name_Id;
1342 V3 : Name_Id;
1343 V4 : Name_Id;
1344 V5 : Name_Id;
1345 V6 : Name_Id;
1346 V7 : Name_Id) return Boolean
1347 is
1348 begin
1349 return T = V1 or else
1350 T = V2 or else
1351 T = V3 or else
1352 T = V4 or else
1353 T = V5 or else
1354 T = V6 or else
1355 T = V7;
1356 end Nam_In;
1357
1358 function Nam_In
1359 (T : Name_Id;
1360 V1 : Name_Id;
1361 V2 : Name_Id;
1362 V3 : Name_Id;
1363 V4 : Name_Id;
1364 V5 : Name_Id;
1365 V6 : Name_Id;
1366 V7 : Name_Id;
1367 V8 : Name_Id) return Boolean
1368 is
1369 begin
1370 return T = V1 or else
1371 T = V2 or else
1372 T = V3 or else
1373 T = V4 or else
1374 T = V5 or else
1375 T = V6 or else
1376 T = V7 or else
1377 T = V8;
1378 end Nam_In;
1379
1380 function Nam_In
1381 (T : Name_Id;
1382 V1 : Name_Id;
1383 V2 : Name_Id;
1384 V3 : Name_Id;
1385 V4 : Name_Id;
1386 V5 : Name_Id;
1387 V6 : Name_Id;
1388 V7 : Name_Id;
1389 V8 : Name_Id;
1390 V9 : Name_Id) return Boolean
1391 is
1392 begin
1393 return T = V1 or else
1394 T = V2 or else
1395 T = V3 or else
1396 T = V4 or else
1397 T = V5 or else
1398 T = V6 or else
1399 T = V7 or else
1400 T = V8 or else
1401 T = V9;
1402 end Nam_In;
1403
1404 function Nam_In
1405 (T : Name_Id;
1406 V1 : Name_Id;
1407 V2 : Name_Id;
1408 V3 : Name_Id;
1409 V4 : Name_Id;
1410 V5 : Name_Id;
1411 V6 : Name_Id;
1412 V7 : Name_Id;
1413 V8 : Name_Id;
1414 V9 : Name_Id;
1415 V10 : Name_Id) return Boolean
1416 is
1417 begin
1418 return T = V1 or else
1419 T = V2 or else
1420 T = V3 or else
1421 T = V4 or else
1422 T = V5 or else
1423 T = V6 or else
1424 T = V7 or else
1425 T = V8 or else
1426 T = V9 or else
1427 T = V10;
1428 end Nam_In;
1429
1430 function Nam_In
1431 (T : Name_Id;
1432 V1 : Name_Id;
1433 V2 : Name_Id;
1434 V3 : Name_Id;
1435 V4 : Name_Id;
1436 V5 : Name_Id;
1437 V6 : Name_Id;
1438 V7 : Name_Id;
1439 V8 : Name_Id;
1440 V9 : Name_Id;
1441 V10 : Name_Id;
1442 V11 : Name_Id) return Boolean
1443 is
1444 begin
1445 return T = V1 or else
1446 T = V2 or else
1447 T = V3 or else
1448 T = V4 or else
1449 T = V5 or else
1450 T = V6 or else
1451 T = V7 or else
1452 T = V8 or else
1453 T = V9 or else
1454 T = V10 or else
1455 T = V11;
1456 end Nam_In;
1457
1458 function Nam_In
1459 (T : Name_Id;
1460 V1 : Name_Id;
1461 V2 : Name_Id;
1462 V3 : Name_Id;
1463 V4 : Name_Id;
1464 V5 : Name_Id;
1465 V6 : Name_Id;
1466 V7 : Name_Id;
1467 V8 : Name_Id;
1468 V9 : Name_Id;
1469 V10 : Name_Id;
1470 V11 : Name_Id;
1471 V12 : Name_Id) return Boolean
1472 is
1473 begin
1474 return T = V1 or else
1475 T = V2 or else
1476 T = V3 or else
1477 T = V4 or else
1478 T = V5 or else
1479 T = V6 or else
1480 T = V7 or else
1481 T = V8 or else
1482 T = V9 or else
1483 T = V10 or else
1484 T = V11 or else
1485 T = V12;
1486 end Nam_In;
1487
1488 -----------------
1489 -- Name_Equals --
1490 -----------------
1491
1492 function Name_Equals
1493 (N1 : Valid_Name_Id;
1494 N2 : Valid_Name_Id) return Boolean
1495 is
1496 begin
1497 return N1 = N2 or else Get_Name_String (N1) = Get_Name_String (N2);
1498 end Name_Equals;
1499
1500 -------------
1501 -- Present --
1502 -------------
1503
1504 function Present (Nam : File_Name_Type) return Boolean is
1505 begin
1506 return Nam /= No_File;
1507 end Present;
1508
1509 -------------
1510 -- Present --
1511 -------------
1512
1513 function Present (Nam : Name_Id) return Boolean is
1514 begin
1515 return Nam /= No_Name;
1516 end Present;
1517
1518 -------------
1519 -- Present --
1520 -------------
1521
1522 function Present (Nam : Unit_Name_Type) return Boolean is
1523 begin
1524 return Nam /= No_Unit_Name;
1525 end Present;
1526
1527 ------------------
1528 -- Reinitialize --
1529 ------------------
1530
1531 procedure Reinitialize is
1532 begin
1533 Name_Chars.Init;
1534 Name_Entries.Init;
1535
1536 -- Initialize entries for one character names
1537
1538 for C in Character loop
1539 Name_Entries.Append
1540 ((Name_Chars_Index => Name_Chars.Last,
1541 Name_Len => 1,
1542 Byte_Info => 0,
1543 Int_Info => 0,
1544 Boolean1_Info => False,
1545 Boolean2_Info => False,
1546 Boolean3_Info => False,
1547 Name_Has_No_Encodings => True,
1548 Hash_Link => No_Name));
1549
1550 Name_Chars.Append (C);
1551 Name_Chars.Append (ASCII.NUL);
1552 end loop;
1553
1554 -- Clear hash table
1555
1556 for J in Hash_Index_Type loop
1557 Hash_Table (J) := No_Name;
1558 end loop;
1559 end Reinitialize;
1560
1561 ----------------------
1562 -- Reset_Name_Table --
1563 ----------------------
1564
1565 procedure Reset_Name_Table is
1566 begin
1567 for J in First_Name_Id .. Name_Entries.Last loop
1568 Name_Entries.Table (J).Int_Info := 0;
1569 Name_Entries.Table (J).Byte_Info := 0;
1570 end loop;
1571 end Reset_Name_Table;
1572
1573 --------------------------------
1574 -- Set_Character_Literal_Name --
1575 --------------------------------
1576
1577 procedure Set_Character_Literal_Name
1578 (Buf : in out Bounded_String;
1579 C : Char_Code)
1580 is
1581 begin
1582 Buf.Length := 0;
1583 Append (Buf, 'Q');
1584 Append_Encoded (Buf, C);
1585 end Set_Character_Literal_Name;
1586
1587 procedure Set_Character_Literal_Name (C : Char_Code) is
1588 begin
1589 Set_Character_Literal_Name (Global_Name_Buffer, C);
1590 end Set_Character_Literal_Name;
1591
1592 -----------------------------
1593 -- Set_Name_Table_Boolean1 --
1594 -----------------------------
1595
1596 procedure Set_Name_Table_Boolean1 (Id : Valid_Name_Id; Val : Boolean) is
1597 begin
1598 pragma Assert (Is_Valid_Name (Id));
1599 Name_Entries.Table (Id).Boolean1_Info := Val;
1600 end Set_Name_Table_Boolean1;
1601
1602 -----------------------------
1603 -- Set_Name_Table_Boolean2 --
1604 -----------------------------
1605
1606 procedure Set_Name_Table_Boolean2 (Id : Valid_Name_Id; Val : Boolean) is
1607 begin
1608 pragma Assert (Is_Valid_Name (Id));
1609 Name_Entries.Table (Id).Boolean2_Info := Val;
1610 end Set_Name_Table_Boolean2;
1611
1612 -----------------------------
1613 -- Set_Name_Table_Boolean3 --
1614 -----------------------------
1615
1616 procedure Set_Name_Table_Boolean3 (Id : Valid_Name_Id; Val : Boolean) is
1617 begin
1618 pragma Assert (Is_Valid_Name (Id));
1619 Name_Entries.Table (Id).Boolean3_Info := Val;
1620 end Set_Name_Table_Boolean3;
1621
1622 -------------------------
1623 -- Set_Name_Table_Byte --
1624 -------------------------
1625
1626 procedure Set_Name_Table_Byte (Id : Valid_Name_Id; Val : Byte) is
1627 begin
1628 pragma Assert (Is_Valid_Name (Id));
1629 Name_Entries.Table (Id).Byte_Info := Val;
1630 end Set_Name_Table_Byte;
1631
1632 -------------------------
1633 -- Set_Name_Table_Int --
1634 -------------------------
1635
1636 procedure Set_Name_Table_Int (Id : Valid_Name_Id; Val : Int) is
1637 begin
1638 pragma Assert (Is_Valid_Name (Id));
1639 Name_Entries.Table (Id).Int_Info := Val;
1640 end Set_Name_Table_Int;
1641
1642 -----------------------------
1643 -- Store_Encoded_Character --
1644 -----------------------------
1645
1646 procedure Store_Encoded_Character (C : Char_Code) is
1647 begin
1648 Append_Encoded (Global_Name_Buffer, C);
1649 end Store_Encoded_Character;
1650
1651 --------------------------------------
1652 -- Strip_Qualification_And_Suffixes --
1653 --------------------------------------
1654
1655 procedure Strip_Qualification_And_Suffixes (Buf : in out Bounded_String) is
1656 J : Integer;
1657
1658 begin
1659 -- Strip package body qualification string off end
1660
1661 for J in reverse 2 .. Buf.Length loop
1662 if Buf.Chars (J) = 'X' then
1663 Buf.Length := J - 1;
1664 exit;
1665 end if;
1666
1667 exit when Buf.Chars (J) /= 'b'
1668 and then Buf.Chars (J) /= 'n'
1669 and then Buf.Chars (J) /= 'p';
1670 end loop;
1671
1672 -- Find rightmost __ or $ separator if one exists. First we position
1673 -- to start the search. If we have a character constant, position
1674 -- just before it, otherwise position to last character but one
1675
1676 if Buf.Chars (Buf.Length) = ''' then
1677 J := Buf.Length - 2;
1678 while J > 0 and then Buf.Chars (J) /= ''' loop
1679 J := J - 1;
1680 end loop;
1681
1682 else
1683 J := Buf.Length - 1;
1684 end if;
1685
1686 -- Loop to search for rightmost __ or $ (homonym) separator
1687
1688 while J > 1 loop
1689
1690 -- If $ separator, homonym separator, so strip it and keep looking
1691
1692 if Buf.Chars (J) = '$' then
1693 Buf.Length := J - 1;
1694 J := Buf.Length - 1;
1695
1696 -- Else check for __ found
1697
1698 elsif Buf.Chars (J) = '_' and then Buf.Chars (J + 1) = '_' then
1699
1700 -- Found __ so see if digit follows, and if so, this is a
1701 -- homonym separator, so strip it and keep looking.
1702
1703 if Buf.Chars (J + 2) in '0' .. '9' then
1704 Buf.Length := J - 1;
1705 J := Buf.Length - 1;
1706
1707 -- If not a homonym separator, then we simply strip the
1708 -- separator and everything that precedes it, and we are done
1709
1710 else
1711 Buf.Chars (1 .. Buf.Length - J - 1) :=
1712 Buf.Chars (J + 2 .. Buf.Length);
1713 Buf.Length := Buf.Length - J - 1;
1714 exit;
1715 end if;
1716
1717 else
1718 J := J - 1;
1719 end if;
1720 end loop;
1721 end Strip_Qualification_And_Suffixes;
1722
1723 ---------------
1724 -- To_String --
1725 ---------------
1726
1727 function To_String (Buf : Bounded_String) return String is
1728 begin
1729 return Buf.Chars (1 .. Buf.Length);
1730 end To_String;
1731
1732 ---------------
1733 -- Tree_Read --
1734 ---------------
1735
1736 procedure Tree_Read is
1737 begin
1738 Name_Chars.Tree_Read;
1739 Name_Entries.Tree_Read;
1740
1741 Tree_Read_Data
1742 (Hash_Table'Address,
1743 Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1744 end Tree_Read;
1745
1746 ----------------
1747 -- Tree_Write --
1748 ----------------
1749
1750 procedure Tree_Write is
1751 begin
1752 Name_Chars.Tree_Write;
1753 Name_Entries.Tree_Write;
1754
1755 Tree_Write_Data
1756 (Hash_Table'Address,
1757 Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1758 end Tree_Write;
1759
1760 ------------
1761 -- Unlock --
1762 ------------
1763
1764 procedure Unlock is
1765 begin
1766 Name_Chars.Locked := False;
1767 Name_Chars.Set_Last (Name_Chars.Last - Name_Chars_Reserve);
1768 Name_Chars.Release;
1769 Name_Entries.Locked := False;
1770 Name_Entries.Set_Last (Name_Entries.Last - Name_Entries_Reserve);
1771 Name_Entries.Release;
1772 end Unlock;
1773
1774 --------
1775 -- wn --
1776 --------
1777
1778 procedure wn (Id : Name_Id) is
1779 begin
1780 if Is_Valid_Name (Id) then
1781 declare
1782 Buf : Bounded_String (Max_Length => Natural (Length_Of_Name (Id)));
1783 begin
1784 Append (Buf, Id);
1785 Write_Str (Buf.Chars (1 .. Buf.Length));
1786 end;
1787
1788 elsif Id = No_Name then
1789 Write_Str ("<No_Name>");
1790
1791 elsif Id = Error_Name then
1792 Write_Str ("<Error_Name>");
1793
1794 else
1795 Write_Str ("<invalid name_id>");
1796 Write_Int (Int (Id));
1797 end if;
1798
1799 Write_Eol;
1800 end wn;
1801
1802 ----------------
1803 -- Write_Name --
1804 ----------------
1805
1806 procedure Write_Name (Id : Valid_Name_Id) is
1807 Buf : Bounded_String (Max_Length => Natural (Length_Of_Name (Id)));
1808 begin
1809 Append (Buf, Id);
1810 Write_Str (Buf.Chars (1 .. Buf.Length));
1811 end Write_Name;
1812
1813 ------------------------
1814 -- Write_Name_Decoded --
1815 ------------------------
1816
1817 procedure Write_Name_Decoded (Id : Valid_Name_Id) is
1818 Buf : Bounded_String;
1819 begin
1820 Append_Decoded (Buf, Id);
1821 Write_Str (Buf.Chars (1 .. Buf.Length));
1822 end Write_Name_Decoded;
1823
1824 -- Package initialization, initialize tables
1825
1826 begin
1827 Reinitialize;
1828 end Namet;