exp_aggr.adb: Minor reformatting.
[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-2013, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
17 -- --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
21 -- --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
26 -- --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
29 -- --
30 ------------------------------------------------------------------------------
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 Tree_IO; use Tree_IO;
40 with Widechar; use Widechar;
41
42 with Interfaces; use Interfaces;
43
44 package body Namet is
45
46 Name_Chars_Reserve : constant := 5000;
47 Name_Entries_Reserve : constant := 100;
48 -- The names table is locked during gigi processing, since gigi assumes
49 -- that the table does not move. After returning from gigi, the names
50 -- table is unlocked again, since writing library file information needs
51 -- to generate some extra names. To avoid the inefficiency of always
52 -- reallocating during this second unlocked phase, we reserve a bit of
53 -- extra space before doing the release call.
54
55 Hash_Num : constant Int := 2**16;
56 -- Number of headers in the hash table. Current hash algorithm is closely
57 -- tailored to this choice, so it can only be changed if a corresponding
58 -- change is made to the hash algorithm.
59
60 Hash_Max : constant Int := Hash_Num - 1;
61 -- Indexes in the hash header table run from 0 to Hash_Num - 1
62
63 subtype Hash_Index_Type is Int range 0 .. Hash_Max;
64 -- Range of hash index values
65
66 Hash_Table : array (Hash_Index_Type) of Name_Id;
67 -- The hash table is used to locate existing entries in the names table.
68 -- The entries point to the first names table entry whose hash value
69 -- matches the hash code. Then subsequent names table entries with the
70 -- same hash code value are linked through the Hash_Link fields.
71
72 -----------------------
73 -- Local Subprograms --
74 -----------------------
75
76 function Hash return Hash_Index_Type;
77 pragma Inline (Hash);
78 -- Compute hash code for name stored in Name_Buffer (length in Name_Len)
79
80 procedure Strip_Qualification_And_Suffixes;
81 -- Given an encoded entity name in Name_Buffer, remove package body
82 -- suffix as described for Strip_Package_Body_Suffix, and also remove
83 -- all qualification, i.e. names followed by two underscores. The
84 -- contents of Name_Buffer is modified by this call, and on return
85 -- Name_Buffer and Name_Len reflect the stripped name.
86
87 -----------------------------
88 -- Add_Char_To_Name_Buffer --
89 -----------------------------
90
91 procedure Add_Char_To_Name_Buffer (C : Character) is
92 begin
93 if Name_Len < Name_Buffer'Last then
94 Name_Len := Name_Len + 1;
95 Name_Buffer (Name_Len) := C;
96 end if;
97 end Add_Char_To_Name_Buffer;
98
99 ----------------------------
100 -- Add_Nat_To_Name_Buffer --
101 ----------------------------
102
103 procedure Add_Nat_To_Name_Buffer (V : Nat) is
104 begin
105 if V >= 10 then
106 Add_Nat_To_Name_Buffer (V / 10);
107 end if;
108
109 Add_Char_To_Name_Buffer (Character'Val (Character'Pos ('0') + V rem 10));
110 end Add_Nat_To_Name_Buffer;
111
112 ----------------------------
113 -- Add_Str_To_Name_Buffer --
114 ----------------------------
115
116 procedure Add_Str_To_Name_Buffer (S : String) is
117 begin
118 for J in S'Range loop
119 Add_Char_To_Name_Buffer (S (J));
120 end loop;
121 end Add_Str_To_Name_Buffer;
122
123 --------------
124 -- Finalize --
125 --------------
126
127 procedure Finalize is
128 F : array (Int range 0 .. 50) of Int;
129 -- N'th entry is the number of chains of length N, except last entry,
130 -- which is the number of chains of length F'Last or more.
131
132 Max_Chain_Length : Int := 0;
133 -- Maximum length of all chains
134
135 Probes : Int := 0;
136 -- Used to compute average number of probes
137
138 Nsyms : Int := 0;
139 -- Number of symbols in table
140
141 Verbosity : constant Int range 1 .. 3 := 1;
142 pragma Warnings (Off, Verbosity);
143 -- This constant indicates the level of verbosity in the output from
144 -- this procedure. Currently this can only be changed by editing the
145 -- declaration above and recompiling. That's good enough in practice,
146 -- since we very rarely need to use this debug option. Settings are:
147 --
148 -- 1 => print basic summary information
149 -- 2 => in addition print number of entries per hash chain
150 -- 3 => in addition print content of entries
151
152 Zero : constant Int := Character'Pos ('0');
153
154 begin
155 if not Debug_Flag_H then
156 return;
157 end if;
158
159 for J in F'Range loop
160 F (J) := 0;
161 end loop;
162
163 for J in Hash_Index_Type loop
164 if Hash_Table (J) = No_Name then
165 F (0) := F (0) + 1;
166
167 else
168 declare
169 C : Int;
170 N : Name_Id;
171 S : Int;
172
173 begin
174 C := 0;
175 N := Hash_Table (J);
176
177 while N /= No_Name loop
178 N := Name_Entries.Table (N).Hash_Link;
179 C := C + 1;
180 end loop;
181
182 Nsyms := Nsyms + 1;
183 Probes := Probes + (1 + C) * 100;
184
185 if C > Max_Chain_Length then
186 Max_Chain_Length := C;
187 end if;
188
189 if Verbosity >= 2 then
190 Write_Str ("Hash_Table (");
191 Write_Int (J);
192 Write_Str (") has ");
193 Write_Int (C);
194 Write_Str (" entries");
195 Write_Eol;
196 end if;
197
198 if C < F'Last then
199 F (C) := F (C) + 1;
200 else
201 F (F'Last) := F (F'Last) + 1;
202 end if;
203
204 if Verbosity >= 3 then
205 N := Hash_Table (J);
206 while N /= No_Name loop
207 S := Name_Entries.Table (N).Name_Chars_Index;
208
209 Write_Str (" ");
210
211 for J in 1 .. Name_Entries.Table (N).Name_Len loop
212 Write_Char (Name_Chars.Table (S + Int (J)));
213 end loop;
214
215 Write_Eol;
216
217 N := Name_Entries.Table (N).Hash_Link;
218 end loop;
219 end if;
220 end;
221 end if;
222 end loop;
223
224 Write_Eol;
225
226 for J in F'Range loop
227 if F (J) /= 0 then
228 Write_Str ("Number of hash chains of length ");
229
230 if J < 10 then
231 Write_Char (' ');
232 end if;
233
234 Write_Int (J);
235
236 if J = F'Last then
237 Write_Str (" or greater");
238 end if;
239
240 Write_Str (" = ");
241 Write_Int (F (J));
242 Write_Eol;
243 end if;
244 end loop;
245
246 -- Print out average number of probes, in the case where Name_Find is
247 -- called for a string that is already in the table.
248
249 Write_Eol;
250 Write_Str ("Average number of probes for lookup = ");
251 Probes := Probes / Nsyms;
252 Write_Int (Probes / 200);
253 Write_Char ('.');
254 Probes := (Probes mod 200) / 2;
255 Write_Char (Character'Val (Zero + Probes / 10));
256 Write_Char (Character'Val (Zero + Probes mod 10));
257 Write_Eol;
258
259 Write_Str ("Max_Chain_Length = ");
260 Write_Int (Max_Chain_Length);
261 Write_Eol;
262 Write_Str ("Name_Chars'Length = ");
263 Write_Int (Name_Chars.Last - Name_Chars.First + 1);
264 Write_Eol;
265 Write_Str ("Name_Entries'Length = ");
266 Write_Int (Int (Name_Entries.Last - Name_Entries.First + 1));
267 Write_Eol;
268 Write_Str ("Nsyms = ");
269 Write_Int (Nsyms);
270 Write_Eol;
271 end Finalize;
272
273 -----------------------------
274 -- Get_Decoded_Name_String --
275 -----------------------------
276
277 procedure Get_Decoded_Name_String (Id : Name_Id) is
278 C : Character;
279 P : Natural;
280
281 begin
282 Get_Name_String (Id);
283
284 -- Skip scan if we already know there are no encodings
285
286 if Name_Entries.Table (Id).Name_Has_No_Encodings then
287 return;
288 end if;
289
290 -- Quick loop to see if there is anything special to do
291
292 P := 1;
293 loop
294 if P = Name_Len then
295 Name_Entries.Table (Id).Name_Has_No_Encodings := True;
296 return;
297
298 else
299 C := Name_Buffer (P);
300
301 exit when
302 C = 'U' or else
303 C = 'W' or else
304 C = 'Q' or else
305 C = 'O';
306
307 P := P + 1;
308 end if;
309 end loop;
310
311 -- Here we have at least some encoding that we must decode
312
313 Decode : declare
314 New_Len : Natural;
315 Old : Positive;
316 New_Buf : String (1 .. Name_Buffer'Last);
317
318 procedure Copy_One_Character;
319 -- Copy a character from Name_Buffer to New_Buf. Includes case
320 -- of copying a Uhh,Whhhh,WWhhhhhhhh sequence and decoding it.
321
322 function Hex (N : Natural) return Word;
323 -- Scans past N digits using Old pointer and returns hex value
324
325 procedure Insert_Character (C : Character);
326 -- Insert a new character into output decoded name
327
328 ------------------------
329 -- Copy_One_Character --
330 ------------------------
331
332 procedure Copy_One_Character is
333 C : Character;
334
335 begin
336 C := Name_Buffer (Old);
337
338 -- U (upper half insertion case)
339
340 if C = 'U'
341 and then Old < Name_Len
342 and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
343 and then Name_Buffer (Old + 1) /= '_'
344 then
345 Old := Old + 1;
346
347 -- If we have upper half encoding, then we have to set an
348 -- appropriate wide character sequence for this character.
349
350 if Upper_Half_Encoding then
351 Widechar.Set_Wide (Char_Code (Hex (2)), New_Buf, New_Len);
352
353 -- For other encoding methods, upper half characters can
354 -- simply use their normal representation.
355
356 else
357 Insert_Character (Character'Val (Hex (2)));
358 end if;
359
360 -- WW (wide wide character insertion)
361
362 elsif C = 'W'
363 and then Old < Name_Len
364 and then Name_Buffer (Old + 1) = 'W'
365 then
366 Old := Old + 2;
367 Widechar.Set_Wide (Char_Code (Hex (8)), New_Buf, New_Len);
368
369 -- W (wide character insertion)
370
371 elsif C = 'W'
372 and then Old < Name_Len
373 and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
374 and then Name_Buffer (Old + 1) /= '_'
375 then
376 Old := Old + 1;
377 Widechar.Set_Wide (Char_Code (Hex (4)), New_Buf, New_Len);
378
379 -- Any other character is copied unchanged
380
381 else
382 Insert_Character (C);
383 Old := Old + 1;
384 end if;
385 end Copy_One_Character;
386
387 ---------
388 -- Hex --
389 ---------
390
391 function Hex (N : Natural) return Word is
392 T : Word := 0;
393 C : Character;
394
395 begin
396 for J in 1 .. N loop
397 C := Name_Buffer (Old);
398 Old := Old + 1;
399
400 pragma Assert (C in '0' .. '9' or else C in 'a' .. 'f');
401
402 if C <= '9' then
403 T := 16 * T + Character'Pos (C) - Character'Pos ('0');
404 else -- C in 'a' .. 'f'
405 T := 16 * T + Character'Pos (C) - (Character'Pos ('a') - 10);
406 end if;
407 end loop;
408
409 return T;
410 end Hex;
411
412 ----------------------
413 -- Insert_Character --
414 ----------------------
415
416 procedure Insert_Character (C : Character) is
417 begin
418 New_Len := New_Len + 1;
419 New_Buf (New_Len) := C;
420 end Insert_Character;
421
422 -- Start of processing for Decode
423
424 begin
425 New_Len := 0;
426 Old := 1;
427
428 -- Loop through characters of name
429
430 while Old <= Name_Len loop
431
432 -- Case of character literal, put apostrophes around character
433
434 if Name_Buffer (Old) = 'Q'
435 and then Old < Name_Len
436 then
437 Old := Old + 1;
438 Insert_Character (''');
439 Copy_One_Character;
440 Insert_Character (''');
441
442 -- Case of operator name
443
444 elsif Name_Buffer (Old) = 'O'
445 and then Old < Name_Len
446 and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
447 and then Name_Buffer (Old + 1) /= '_'
448 then
449 Old := Old + 1;
450
451 declare
452 -- This table maps the 2nd and 3rd characters of the name
453 -- into the required output. Two blanks means leave the
454 -- name alone
455
456 Map : constant String :=
457 "ab " & -- Oabs => "abs"
458 "ad+ " & -- Oadd => "+"
459 "an " & -- Oand => "and"
460 "co& " & -- Oconcat => "&"
461 "di/ " & -- Odivide => "/"
462 "eq= " & -- Oeq => "="
463 "ex**" & -- Oexpon => "**"
464 "gt> " & -- Ogt => ">"
465 "ge>=" & -- Oge => ">="
466 "le<=" & -- Ole => "<="
467 "lt< " & -- Olt => "<"
468 "mo " & -- Omod => "mod"
469 "mu* " & -- Omutliply => "*"
470 "ne/=" & -- One => "/="
471 "no " & -- Onot => "not"
472 "or " & -- Oor => "or"
473 "re " & -- Orem => "rem"
474 "su- " & -- Osubtract => "-"
475 "xo "; -- Oxor => "xor"
476
477 J : Integer;
478
479 begin
480 Insert_Character ('"');
481
482 -- Search the map. Note that this loop must terminate, if
483 -- not we have some kind of internal error, and a constraint
484 -- error may be raised.
485
486 J := Map'First;
487 loop
488 exit when Name_Buffer (Old) = Map (J)
489 and then Name_Buffer (Old + 1) = Map (J + 1);
490 J := J + 4;
491 end loop;
492
493 -- Special operator name
494
495 if Map (J + 2) /= ' ' then
496 Insert_Character (Map (J + 2));
497
498 if Map (J + 3) /= ' ' then
499 Insert_Character (Map (J + 3));
500 end if;
501
502 Insert_Character ('"');
503
504 -- Skip past original operator name in input
505
506 while Old <= Name_Len
507 and then Name_Buffer (Old) in 'a' .. 'z'
508 loop
509 Old := Old + 1;
510 end loop;
511
512 -- For other operator names, leave them in lower case,
513 -- surrounded by apostrophes
514
515 else
516 -- Copy original operator name from input to output
517
518 while Old <= Name_Len
519 and then Name_Buffer (Old) in 'a' .. 'z'
520 loop
521 Copy_One_Character;
522 end loop;
523
524 Insert_Character ('"');
525 end if;
526 end;
527
528 -- Else copy one character and keep going
529
530 else
531 Copy_One_Character;
532 end if;
533 end loop;
534
535 -- Copy new buffer as result
536
537 Name_Len := New_Len;
538 Name_Buffer (1 .. New_Len) := New_Buf (1 .. New_Len);
539 end Decode;
540 end Get_Decoded_Name_String;
541
542 -------------------------------------------
543 -- Get_Decoded_Name_String_With_Brackets --
544 -------------------------------------------
545
546 procedure Get_Decoded_Name_String_With_Brackets (Id : Name_Id) is
547 P : Natural;
548
549 begin
550 -- Case of operator name, normal decoding is fine
551
552 if Name_Buffer (1) = 'O' then
553 Get_Decoded_Name_String (Id);
554
555 -- For character literals, normal decoding is fine
556
557 elsif Name_Buffer (1) = 'Q' then
558 Get_Decoded_Name_String (Id);
559
560 -- Only remaining issue is U/W/WW sequences
561
562 else
563 Get_Name_String (Id);
564
565 P := 1;
566 while P < Name_Len loop
567 if Name_Buffer (P + 1) in 'A' .. 'Z' then
568 P := P + 1;
569
570 -- Uhh encoding
571
572 elsif Name_Buffer (P) = 'U' then
573 for J in reverse P + 3 .. P + Name_Len loop
574 Name_Buffer (J + 3) := Name_Buffer (J);
575 end loop;
576
577 Name_Len := Name_Len + 3;
578 Name_Buffer (P + 3) := Name_Buffer (P + 2);
579 Name_Buffer (P + 2) := Name_Buffer (P + 1);
580 Name_Buffer (P) := '[';
581 Name_Buffer (P + 1) := '"';
582 Name_Buffer (P + 4) := '"';
583 Name_Buffer (P + 5) := ']';
584 P := P + 6;
585
586 -- WWhhhhhhhh encoding
587
588 elsif Name_Buffer (P) = 'W'
589 and then P + 9 <= Name_Len
590 and then Name_Buffer (P + 1) = 'W'
591 and then Name_Buffer (P + 2) not in 'A' .. 'Z'
592 and then Name_Buffer (P + 2) /= '_'
593 then
594 Name_Buffer (P + 12 .. Name_Len + 2) :=
595 Name_Buffer (P + 10 .. Name_Len);
596 Name_Buffer (P) := '[';
597 Name_Buffer (P + 1) := '"';
598 Name_Buffer (P + 10) := '"';
599 Name_Buffer (P + 11) := ']';
600 Name_Len := Name_Len + 2;
601 P := P + 12;
602
603 -- Whhhh encoding
604
605 elsif Name_Buffer (P) = 'W'
606 and then P < Name_Len
607 and then Name_Buffer (P + 1) not in 'A' .. 'Z'
608 and then Name_Buffer (P + 1) /= '_'
609 then
610 Name_Buffer (P + 8 .. P + Name_Len + 3) :=
611 Name_Buffer (P + 5 .. Name_Len);
612 Name_Buffer (P + 2 .. P + 5) := Name_Buffer (P + 1 .. P + 4);
613 Name_Buffer (P) := '[';
614 Name_Buffer (P + 1) := '"';
615 Name_Buffer (P + 6) := '"';
616 Name_Buffer (P + 7) := ']';
617 Name_Len := Name_Len + 3;
618 P := P + 8;
619
620 else
621 P := P + 1;
622 end if;
623 end loop;
624 end if;
625 end Get_Decoded_Name_String_With_Brackets;
626
627 ------------------------
628 -- Get_Last_Two_Chars --
629 ------------------------
630
631 procedure Get_Last_Two_Chars (N : Name_Id; C1, C2 : out Character) is
632 NE : Name_Entry renames Name_Entries.Table (N);
633 NEL : constant Int := Int (NE.Name_Len);
634
635 begin
636 if NEL >= 2 then
637 C1 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 1);
638 C2 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 0);
639 else
640 C1 := ASCII.NUL;
641 C2 := ASCII.NUL;
642 end if;
643 end Get_Last_Two_Chars;
644
645 ---------------------
646 -- Get_Name_String --
647 ---------------------
648
649 -- Procedure version leaving result in Name_Buffer, length in Name_Len
650
651 procedure Get_Name_String (Id : Name_Id) is
652 S : Int;
653
654 begin
655 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
656
657 S := Name_Entries.Table (Id).Name_Chars_Index;
658 Name_Len := Natural (Name_Entries.Table (Id).Name_Len);
659
660 for J in 1 .. Name_Len loop
661 Name_Buffer (J) := Name_Chars.Table (S + Int (J));
662 end loop;
663 end Get_Name_String;
664
665 ---------------------
666 -- Get_Name_String --
667 ---------------------
668
669 -- Function version returning a string
670
671 function Get_Name_String (Id : Name_Id) return String is
672 S : Int;
673
674 begin
675 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
676 S := Name_Entries.Table (Id).Name_Chars_Index;
677
678 declare
679 R : String (1 .. Natural (Name_Entries.Table (Id).Name_Len));
680
681 begin
682 for J in R'Range loop
683 R (J) := Name_Chars.Table (S + Int (J));
684 end loop;
685
686 return R;
687 end;
688 end Get_Name_String;
689
690 --------------------------------
691 -- Get_Name_String_And_Append --
692 --------------------------------
693
694 procedure Get_Name_String_And_Append (Id : Name_Id) is
695 S : Int;
696
697 begin
698 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
699
700 S := Name_Entries.Table (Id).Name_Chars_Index;
701
702 for J in 1 .. Natural (Name_Entries.Table (Id).Name_Len) loop
703 Name_Len := Name_Len + 1;
704 Name_Buffer (Name_Len) := Name_Chars.Table (S + Int (J));
705 end loop;
706 end Get_Name_String_And_Append;
707
708 -------------------------
709 -- Get_Name_Table_Byte --
710 -------------------------
711
712 function Get_Name_Table_Byte (Id : Name_Id) return Byte is
713 begin
714 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
715 return Name_Entries.Table (Id).Byte_Info;
716 end Get_Name_Table_Byte;
717
718 -------------------------
719 -- Get_Name_Table_Info --
720 -------------------------
721
722 function Get_Name_Table_Info (Id : Name_Id) return Int is
723 begin
724 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
725 return Name_Entries.Table (Id).Int_Info;
726 end Get_Name_Table_Info;
727
728 -----------------------------------------
729 -- Get_Unqualified_Decoded_Name_String --
730 -----------------------------------------
731
732 procedure Get_Unqualified_Decoded_Name_String (Id : Name_Id) is
733 begin
734 Get_Decoded_Name_String (Id);
735 Strip_Qualification_And_Suffixes;
736 end Get_Unqualified_Decoded_Name_String;
737
738 ---------------------------------
739 -- Get_Unqualified_Name_String --
740 ---------------------------------
741
742 procedure Get_Unqualified_Name_String (Id : Name_Id) is
743 begin
744 Get_Name_String (Id);
745 Strip_Qualification_And_Suffixes;
746 end Get_Unqualified_Name_String;
747
748 ----------
749 -- Hash --
750 ----------
751
752 function Hash return Hash_Index_Type is
753
754 -- This hash function looks at every character, in order to make it
755 -- likely that similar strings get different hash values. The rotate by
756 -- 7 bits has been determined empirically to be good, and it doesn't
757 -- lose bits like a shift would. The final conversion can't overflow,
758 -- because the table is 2**16 in size. This function probably needs to
759 -- be changed if the hash table size is changed.
760
761 -- Note that we could get some speed improvement by aligning the string
762 -- to 32 or 64 bits, and doing word-wise xor's. We could also implement
763 -- a growable table. It doesn't seem worth the trouble to do those
764 -- things, for now.
765
766 Result : Unsigned_16 := 0;
767
768 begin
769 for J in 1 .. Name_Len loop
770 Result := Rotate_Left (Result, 7) xor Character'Pos (Name_Buffer (J));
771 end loop;
772
773 return Hash_Index_Type (Result);
774 end Hash;
775
776 ----------------
777 -- Initialize --
778 ----------------
779
780 procedure Initialize is
781 begin
782 null;
783 end Initialize;
784
785 -------------------------------
786 -- Insert_Str_In_Name_Buffer --
787 -------------------------------
788
789 procedure Insert_Str_In_Name_Buffer (S : String; Index : Positive) is
790 SL : constant Natural := S'Length;
791 begin
792 Name_Buffer (Index + SL .. Name_Len + SL) :=
793 Name_Buffer (Index .. Name_Len);
794 Name_Buffer (Index .. Index + SL - 1) := S;
795 Name_Len := Name_Len + SL;
796 end Insert_Str_In_Name_Buffer;
797
798 ----------------------
799 -- Is_Internal_Name --
800 ----------------------
801
802 -- Version taking an argument
803
804 function Is_Internal_Name (Id : Name_Id) return Boolean is
805 begin
806 Get_Name_String (Id);
807 return Is_Internal_Name;
808 end Is_Internal_Name;
809
810 ----------------------
811 -- Is_Internal_Name --
812 ----------------------
813
814 -- Version taking its input from Name_Buffer
815
816 function Is_Internal_Name return Boolean is
817 begin
818 if Name_Buffer (1) = '_'
819 or else Name_Buffer (Name_Len) = '_'
820 then
821 return True;
822
823 else
824 -- Test backwards, because we only want to test the last entity
825 -- name if the name we have is qualified with other entities.
826
827 for J in reverse 1 .. Name_Len loop
828 if Is_OK_Internal_Letter (Name_Buffer (J)) then
829 return True;
830
831 -- Quit if we come to terminating double underscore (note that
832 -- if the current character is an underscore, we know that
833 -- there is a previous character present, since we already
834 -- filtered out the case of Name_Buffer (1) = '_' above.
835
836 elsif Name_Buffer (J) = '_'
837 and then Name_Buffer (J - 1) = '_'
838 and then Name_Buffer (J - 2) /= '_'
839 then
840 return False;
841 end if;
842 end loop;
843 end if;
844
845 return False;
846 end Is_Internal_Name;
847
848 ---------------------------
849 -- Is_OK_Internal_Letter --
850 ---------------------------
851
852 function Is_OK_Internal_Letter (C : Character) return Boolean is
853 begin
854 return C in 'A' .. 'Z'
855 and then C /= 'O'
856 and then C /= 'Q'
857 and then C /= 'U'
858 and then C /= 'W'
859 and then C /= 'X';
860 end Is_OK_Internal_Letter;
861
862 ----------------------
863 -- Is_Operator_Name --
864 ----------------------
865
866 function Is_Operator_Name (Id : Name_Id) return Boolean is
867 S : Int;
868 begin
869 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
870 S := Name_Entries.Table (Id).Name_Chars_Index;
871 return Name_Chars.Table (S + 1) = 'O';
872 end Is_Operator_Name;
873
874 -------------------
875 -- Is_Valid_Name --
876 -------------------
877
878 function Is_Valid_Name (Id : Name_Id) return Boolean is
879 begin
880 return Id in Name_Entries.First .. Name_Entries.Last;
881 end Is_Valid_Name;
882
883 --------------------
884 -- Length_Of_Name --
885 --------------------
886
887 function Length_Of_Name (Id : Name_Id) return Nat is
888 begin
889 return Int (Name_Entries.Table (Id).Name_Len);
890 end Length_Of_Name;
891
892 ----------
893 -- Lock --
894 ----------
895
896 procedure Lock is
897 begin
898 Name_Chars.Set_Last (Name_Chars.Last + Name_Chars_Reserve);
899 Name_Entries.Set_Last (Name_Entries.Last + Name_Entries_Reserve);
900 Name_Chars.Locked := True;
901 Name_Entries.Locked := True;
902 Name_Chars.Release;
903 Name_Entries.Release;
904 end Lock;
905
906 ------------------------
907 -- Name_Chars_Address --
908 ------------------------
909
910 function Name_Chars_Address return System.Address is
911 begin
912 return Name_Chars.Table (0)'Address;
913 end Name_Chars_Address;
914
915 ----------------
916 -- Name_Enter --
917 ----------------
918
919 function Name_Enter return Name_Id is
920 begin
921 Name_Entries.Append
922 ((Name_Chars_Index => Name_Chars.Last,
923 Name_Len => Short (Name_Len),
924 Byte_Info => 0,
925 Int_Info => 0,
926 Name_Has_No_Encodings => False,
927 Hash_Link => No_Name));
928
929 -- Set corresponding string entry in the Name_Chars table
930
931 for J in 1 .. Name_Len loop
932 Name_Chars.Append (Name_Buffer (J));
933 end loop;
934
935 Name_Chars.Append (ASCII.NUL);
936
937 return Name_Entries.Last;
938 end Name_Enter;
939
940 --------------------------
941 -- Name_Entries_Address --
942 --------------------------
943
944 function Name_Entries_Address return System.Address is
945 begin
946 return Name_Entries.Table (First_Name_Id)'Address;
947 end Name_Entries_Address;
948
949 ------------------------
950 -- Name_Entries_Count --
951 ------------------------
952
953 function Name_Entries_Count return Nat is
954 begin
955 return Int (Name_Entries.Last - Name_Entries.First + 1);
956 end Name_Entries_Count;
957
958 ---------------
959 -- Name_Find --
960 ---------------
961
962 function Name_Find return Name_Id is
963 New_Id : Name_Id;
964 -- Id of entry in hash search, and value to be returned
965
966 S : Int;
967 -- Pointer into string table
968
969 Hash_Index : Hash_Index_Type;
970 -- Computed hash index
971
972 begin
973 -- Quick handling for one character names
974
975 if Name_Len = 1 then
976 return Name_Id (First_Name_Id + Character'Pos (Name_Buffer (1)));
977
978 -- Otherwise search hash table for existing matching entry
979
980 else
981 Hash_Index := Namet.Hash;
982 New_Id := Hash_Table (Hash_Index);
983
984 if New_Id = No_Name then
985 Hash_Table (Hash_Index) := Name_Entries.Last + 1;
986
987 else
988 Search : loop
989 if Name_Len /=
990 Integer (Name_Entries.Table (New_Id).Name_Len)
991 then
992 goto No_Match;
993 end if;
994
995 S := Name_Entries.Table (New_Id).Name_Chars_Index;
996
997 for J in 1 .. Name_Len loop
998 if Name_Chars.Table (S + Int (J)) /= Name_Buffer (J) then
999 goto No_Match;
1000 end if;
1001 end loop;
1002
1003 return New_Id;
1004
1005 -- Current entry in hash chain does not match
1006
1007 <<No_Match>>
1008 if Name_Entries.Table (New_Id).Hash_Link /= No_Name then
1009 New_Id := Name_Entries.Table (New_Id).Hash_Link;
1010 else
1011 Name_Entries.Table (New_Id).Hash_Link :=
1012 Name_Entries.Last + 1;
1013 exit Search;
1014 end if;
1015 end loop Search;
1016 end if;
1017
1018 -- We fall through here only if a matching entry was not found in the
1019 -- hash table. We now create a new entry in the names table. The hash
1020 -- link pointing to the new entry (Name_Entries.Last+1) has been set.
1021
1022 Name_Entries.Append
1023 ((Name_Chars_Index => Name_Chars.Last,
1024 Name_Len => Short (Name_Len),
1025 Hash_Link => No_Name,
1026 Name_Has_No_Encodings => False,
1027 Int_Info => 0,
1028 Byte_Info => 0));
1029
1030 -- Set corresponding string entry in the Name_Chars table
1031
1032 for J in 1 .. Name_Len loop
1033 Name_Chars.Append (Name_Buffer (J));
1034 end loop;
1035
1036 Name_Chars.Append (ASCII.NUL);
1037
1038 return Name_Entries.Last;
1039 end if;
1040 end Name_Find;
1041
1042 -------------
1043 -- Nam_In --
1044 -------------
1045
1046 function Nam_In
1047 (T : Name_Id;
1048 V1 : Name_Id;
1049 V2 : Name_Id) return Boolean
1050 is
1051 begin
1052 return T = V1 or else
1053 T = V2;
1054 end Nam_In;
1055
1056 function Nam_In
1057 (T : Name_Id;
1058 V1 : Name_Id;
1059 V2 : Name_Id;
1060 V3 : Name_Id) return Boolean
1061 is
1062 begin
1063 return T = V1 or else
1064 T = V2 or else
1065 T = V3;
1066 end Nam_In;
1067
1068 function Nam_In
1069 (T : Name_Id;
1070 V1 : Name_Id;
1071 V2 : Name_Id;
1072 V3 : Name_Id;
1073 V4 : Name_Id) return Boolean
1074 is
1075 begin
1076 return T = V1 or else
1077 T = V2 or else
1078 T = V3 or else
1079 T = V4;
1080 end Nam_In;
1081
1082 function Nam_In
1083 (T : Name_Id;
1084 V1 : Name_Id;
1085 V2 : Name_Id;
1086 V3 : Name_Id;
1087 V4 : Name_Id;
1088 V5 : Name_Id) return Boolean
1089 is
1090 begin
1091 return T = V1 or else
1092 T = V2 or else
1093 T = V3 or else
1094 T = V4 or else
1095 T = V5;
1096 end Nam_In;
1097
1098 function Nam_In
1099 (T : Name_Id;
1100 V1 : Name_Id;
1101 V2 : Name_Id;
1102 V3 : Name_Id;
1103 V4 : Name_Id;
1104 V5 : Name_Id;
1105 V6 : Name_Id) return Boolean
1106 is
1107 begin
1108 return T = V1 or else
1109 T = V2 or else
1110 T = V3 or else
1111 T = V4 or else
1112 T = V5 or else
1113 T = V6;
1114 end Nam_In;
1115
1116 ------------------
1117 -- Reinitialize --
1118 ------------------
1119
1120 procedure Reinitialize is
1121 begin
1122 Name_Chars.Init;
1123 Name_Entries.Init;
1124
1125 -- Initialize entries for one character names
1126
1127 for C in Character loop
1128 Name_Entries.Append
1129 ((Name_Chars_Index => Name_Chars.Last,
1130 Name_Len => 1,
1131 Byte_Info => 0,
1132 Int_Info => 0,
1133 Name_Has_No_Encodings => True,
1134 Hash_Link => No_Name));
1135
1136 Name_Chars.Append (C);
1137 Name_Chars.Append (ASCII.NUL);
1138 end loop;
1139
1140 -- Clear hash table
1141
1142 for J in Hash_Index_Type loop
1143 Hash_Table (J) := No_Name;
1144 end loop;
1145 end Reinitialize;
1146
1147 ----------------------
1148 -- Reset_Name_Table --
1149 ----------------------
1150
1151 procedure Reset_Name_Table is
1152 begin
1153 for J in First_Name_Id .. Name_Entries.Last loop
1154 Name_Entries.Table (J).Int_Info := 0;
1155 Name_Entries.Table (J).Byte_Info := 0;
1156 end loop;
1157 end Reset_Name_Table;
1158
1159 --------------------------------
1160 -- Set_Character_Literal_Name --
1161 --------------------------------
1162
1163 procedure Set_Character_Literal_Name (C : Char_Code) is
1164 begin
1165 Name_Buffer (1) := 'Q';
1166 Name_Len := 1;
1167 Store_Encoded_Character (C);
1168 end Set_Character_Literal_Name;
1169
1170 -------------------------
1171 -- Set_Name_Table_Byte --
1172 -------------------------
1173
1174 procedure Set_Name_Table_Byte (Id : Name_Id; Val : Byte) is
1175 begin
1176 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
1177 Name_Entries.Table (Id).Byte_Info := Val;
1178 end Set_Name_Table_Byte;
1179
1180 -------------------------
1181 -- Set_Name_Table_Info --
1182 -------------------------
1183
1184 procedure Set_Name_Table_Info (Id : Name_Id; Val : Int) is
1185 begin
1186 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
1187 Name_Entries.Table (Id).Int_Info := Val;
1188 end Set_Name_Table_Info;
1189
1190 -----------------------------
1191 -- Store_Encoded_Character --
1192 -----------------------------
1193
1194 procedure Store_Encoded_Character (C : Char_Code) is
1195
1196 procedure Set_Hex_Chars (C : Char_Code);
1197 -- Stores given value, which is in the range 0 .. 255, as two hex
1198 -- digits (using lower case a-f) in Name_Buffer, incrementing Name_Len.
1199
1200 -------------------
1201 -- Set_Hex_Chars --
1202 -------------------
1203
1204 procedure Set_Hex_Chars (C : Char_Code) is
1205 Hexd : constant String := "0123456789abcdef";
1206 N : constant Natural := Natural (C);
1207 begin
1208 Name_Buffer (Name_Len + 1) := Hexd (N / 16 + 1);
1209 Name_Buffer (Name_Len + 2) := Hexd (N mod 16 + 1);
1210 Name_Len := Name_Len + 2;
1211 end Set_Hex_Chars;
1212
1213 -- Start of processing for Store_Encoded_Character
1214
1215 begin
1216 Name_Len := Name_Len + 1;
1217
1218 if In_Character_Range (C) then
1219 declare
1220 CC : constant Character := Get_Character (C);
1221 begin
1222 if CC in 'a' .. 'z' or else CC in '0' .. '9' then
1223 Name_Buffer (Name_Len) := CC;
1224 else
1225 Name_Buffer (Name_Len) := 'U';
1226 Set_Hex_Chars (C);
1227 end if;
1228 end;
1229
1230 elsif In_Wide_Character_Range (C) then
1231 Name_Buffer (Name_Len) := 'W';
1232 Set_Hex_Chars (C / 256);
1233 Set_Hex_Chars (C mod 256);
1234
1235 else
1236 Name_Buffer (Name_Len) := 'W';
1237 Name_Len := Name_Len + 1;
1238 Name_Buffer (Name_Len) := 'W';
1239 Set_Hex_Chars (C / 2 ** 24);
1240 Set_Hex_Chars ((C / 2 ** 16) mod 256);
1241 Set_Hex_Chars ((C / 256) mod 256);
1242 Set_Hex_Chars (C mod 256);
1243 end if;
1244 end Store_Encoded_Character;
1245
1246 --------------------------------------
1247 -- Strip_Qualification_And_Suffixes --
1248 --------------------------------------
1249
1250 procedure Strip_Qualification_And_Suffixes is
1251 J : Integer;
1252
1253 begin
1254 -- Strip package body qualification string off end
1255
1256 for J in reverse 2 .. Name_Len loop
1257 if Name_Buffer (J) = 'X' then
1258 Name_Len := J - 1;
1259 exit;
1260 end if;
1261
1262 exit when Name_Buffer (J) /= 'b'
1263 and then Name_Buffer (J) /= 'n'
1264 and then Name_Buffer (J) /= 'p';
1265 end loop;
1266
1267 -- Find rightmost __ or $ separator if one exists. First we position
1268 -- to start the search. If we have a character constant, position
1269 -- just before it, otherwise position to last character but one
1270
1271 if Name_Buffer (Name_Len) = ''' then
1272 J := Name_Len - 2;
1273 while J > 0 and then Name_Buffer (J) /= ''' loop
1274 J := J - 1;
1275 end loop;
1276
1277 else
1278 J := Name_Len - 1;
1279 end if;
1280
1281 -- Loop to search for rightmost __ or $ (homonym) separator
1282
1283 while J > 1 loop
1284
1285 -- If $ separator, homonym separator, so strip it and keep looking
1286
1287 if Name_Buffer (J) = '$' then
1288 Name_Len := J - 1;
1289 J := Name_Len - 1;
1290
1291 -- Else check for __ found
1292
1293 elsif Name_Buffer (J) = '_' and then Name_Buffer (J + 1) = '_' then
1294
1295 -- Found __ so see if digit follows, and if so, this is a
1296 -- homonym separator, so strip it and keep looking.
1297
1298 if Name_Buffer (J + 2) in '0' .. '9' then
1299 Name_Len := J - 1;
1300 J := Name_Len - 1;
1301
1302 -- If not a homonym separator, then we simply strip the
1303 -- separator and everything that precedes it, and we are done
1304
1305 else
1306 Name_Buffer (1 .. Name_Len - J - 1) :=
1307 Name_Buffer (J + 2 .. Name_Len);
1308 Name_Len := Name_Len - J - 1;
1309 exit;
1310 end if;
1311
1312 else
1313 J := J - 1;
1314 end if;
1315 end loop;
1316 end Strip_Qualification_And_Suffixes;
1317
1318 ---------------
1319 -- Tree_Read --
1320 ---------------
1321
1322 procedure Tree_Read is
1323 begin
1324 Name_Chars.Tree_Read;
1325 Name_Entries.Tree_Read;
1326
1327 Tree_Read_Data
1328 (Hash_Table'Address,
1329 Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1330 end Tree_Read;
1331
1332 ----------------
1333 -- Tree_Write --
1334 ----------------
1335
1336 procedure Tree_Write is
1337 begin
1338 Name_Chars.Tree_Write;
1339 Name_Entries.Tree_Write;
1340
1341 Tree_Write_Data
1342 (Hash_Table'Address,
1343 Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1344 end Tree_Write;
1345
1346 ------------
1347 -- Unlock --
1348 ------------
1349
1350 procedure Unlock is
1351 begin
1352 Name_Chars.Set_Last (Name_Chars.Last - Name_Chars_Reserve);
1353 Name_Entries.Set_Last (Name_Entries.Last - Name_Entries_Reserve);
1354 Name_Chars.Locked := False;
1355 Name_Entries.Locked := False;
1356 Name_Chars.Release;
1357 Name_Entries.Release;
1358 end Unlock;
1359
1360 --------
1361 -- wn --
1362 --------
1363
1364 procedure wn (Id : Name_Id) is
1365 S : Int;
1366
1367 begin
1368 if not Id'Valid then
1369 Write_Str ("<invalid name_id>");
1370
1371 elsif Id = No_Name then
1372 Write_Str ("<No_Name>");
1373
1374 elsif Id = Error_Name then
1375 Write_Str ("<Error_Name>");
1376
1377 else
1378 S := Name_Entries.Table (Id).Name_Chars_Index;
1379 Name_Len := Natural (Name_Entries.Table (Id).Name_Len);
1380
1381 for J in 1 .. Name_Len loop
1382 Write_Char (Name_Chars.Table (S + Int (J)));
1383 end loop;
1384 end if;
1385
1386 Write_Eol;
1387 end wn;
1388
1389 ----------------
1390 -- Write_Name --
1391 ----------------
1392
1393 procedure Write_Name (Id : Name_Id) is
1394 begin
1395 if Id >= First_Name_Id then
1396 Get_Name_String (Id);
1397 Write_Str (Name_Buffer (1 .. Name_Len));
1398 end if;
1399 end Write_Name;
1400
1401 ------------------------
1402 -- Write_Name_Decoded --
1403 ------------------------
1404
1405 procedure Write_Name_Decoded (Id : Name_Id) is
1406 begin
1407 if Id >= First_Name_Id then
1408 Get_Decoded_Name_String (Id);
1409 Write_Str (Name_Buffer (1 .. Name_Len));
1410 end if;
1411 end Write_Name_Decoded;
1412
1413 -- Package initialization, initialize tables
1414
1415 begin
1416 Reinitialize;
1417 end Namet;