Merge from the pain train
[official-gcc.git] / gcc / ada / namet.adb
blobd462d1152e533fb22debc7c1f93cd4706e965e86
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- N A M E T --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2005 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 2, 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. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
21 -- --
22 -- As a special exception, if other files instantiate generics from this --
23 -- unit, or you link this unit with other files to produce an executable, --
24 -- this unit does not by itself cause the resulting executable to be --
25 -- covered by the GNU General Public License. This exception does not --
26 -- however invalidate any other reasons why the executable file might be --
27 -- covered by the GNU Public License. --
28 -- --
29 -- GNAT was originally developed by the GNAT team at New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc. --
31 -- --
32 ------------------------------------------------------------------------------
34 -- WARNING: There is a C version of this package. Any changes to this
35 -- source file must be properly reflected in the C header file a-namet.h
36 -- which is created manually from namet.ads and namet.adb.
38 with Debug; use Debug;
39 with Output; use Output;
40 with Tree_IO; use Tree_IO;
41 with Widechar; use Widechar;
43 package body Namet is
45 Name_Chars_Reserve : constant := 5000;
46 Name_Entries_Reserve : constant := 100;
47 -- The names table is locked during gigi processing, since gigi assumes
48 -- that the table does not move. After returning from gigi, the names
49 -- table is unlocked again, since writing library file information needs
50 -- to generate some extra names. To avoid the inefficiency of always
51 -- reallocating during this second unlocked phase, we reserve a bit of
52 -- extra space before doing the release call.
54 Hash_Num : constant Int := 2**12;
55 -- Number of headers in the hash table. Current hash algorithm is closely
56 -- tailored to this choice, so it can only be changed if a corresponding
57 -- change is made to the hash alogorithm.
59 Hash_Max : constant Int := Hash_Num - 1;
60 -- Indexes in the hash header table run from 0 to Hash_Num - 1
62 subtype Hash_Index_Type is Int range 0 .. Hash_Max;
63 -- Range of hash index values
65 Hash_Table : array (Hash_Index_Type) of Name_Id;
66 -- The hash table is used to locate existing entries in the names table.
67 -- The entries point to the first names table entry whose hash value
68 -- matches the hash code. Then subsequent names table entries with the
69 -- same hash code value are linked through the Hash_Link fields.
71 -----------------------
72 -- Local Subprograms --
73 -----------------------
75 function Hash return Hash_Index_Type;
76 pragma Inline (Hash);
77 -- Compute hash code for name stored in Name_Buffer (length in Name_Len)
79 procedure Strip_Qualification_And_Suffixes;
80 -- Given an encoded entity name in Name_Buffer, remove package body
81 -- suffix as described for Strip_Package_Body_Suffix, and also remove
82 -- all qualification, i.e. names followed by two underscores. The
83 -- contents of Name_Buffer is modified by this call, and on return
84 -- Name_Buffer and Name_Len reflect the stripped name.
86 -----------------------------
87 -- Add_Char_To_Name_Buffer --
88 -----------------------------
90 procedure Add_Char_To_Name_Buffer (C : Character) is
91 begin
92 if Name_Len < Name_Buffer'Last then
93 Name_Len := Name_Len + 1;
94 Name_Buffer (Name_Len) := C;
95 end if;
96 end Add_Char_To_Name_Buffer;
98 ----------------------------
99 -- Add_Nat_To_Name_Buffer --
100 ----------------------------
102 procedure Add_Nat_To_Name_Buffer (V : Nat) is
103 begin
104 if V >= 10 then
105 Add_Nat_To_Name_Buffer (V / 10);
106 end if;
108 Add_Char_To_Name_Buffer (Character'Val (Character'Pos ('0') + V rem 10));
109 end Add_Nat_To_Name_Buffer;
111 ----------------------------
112 -- Add_Str_To_Name_Buffer --
113 ----------------------------
115 procedure Add_Str_To_Name_Buffer (S : String) is
116 begin
117 for J in S'Range loop
118 Add_Char_To_Name_Buffer (S (J));
119 end loop;
120 end Add_Str_To_Name_Buffer;
123 --------------
124 -- Finalize --
125 --------------
127 procedure Finalize is
128 Max_Chain_Length : constant := 50;
129 -- Max length of chains for which specific information is output
131 F : array (Int range 0 .. Max_Chain_Length) of Int;
132 -- N'th entry is number of chains of length N
134 Probes : Int := 0;
135 -- Used to compute average number of probes
137 Nsyms : Int := 0;
138 -- Number of symbols in table
140 begin
141 if Debug_Flag_H then
142 for J in F'Range loop
143 F (J) := 0;
144 end loop;
146 for J in Hash_Index_Type loop
147 if Hash_Table (J) = No_Name then
148 F (0) := F (0) + 1;
150 else
151 Write_Str ("Hash_Table (");
152 Write_Int (Int (J));
153 Write_Str (") has ");
155 declare
156 C : Int := 1;
157 N : Name_Id;
158 S : Int;
160 begin
161 C := 0;
162 N := Hash_Table (J);
164 while N /= No_Name loop
165 N := Name_Entries.Table (N).Hash_Link;
166 C := C + 1;
167 end loop;
169 Write_Int (C);
170 Write_Str (" entries");
171 Write_Eol;
173 if C < Max_Chain_Length then
174 F (C) := F (C) + 1;
175 else
176 F (Max_Chain_Length) := F (Max_Chain_Length) + 1;
177 end if;
179 N := Hash_Table (J);
181 while N /= No_Name loop
182 S := Name_Entries.Table (N).Name_Chars_Index;
183 Write_Str (" ");
185 for J in 1 .. Name_Entries.Table (N).Name_Len loop
186 Write_Char (Name_Chars.Table (S + Int (J)));
187 end loop;
189 Write_Eol;
190 N := Name_Entries.Table (N).Hash_Link;
191 end loop;
192 end;
193 end if;
194 end loop;
196 Write_Eol;
198 for J in Int range 0 .. Max_Chain_Length loop
199 if F (J) /= 0 then
200 Write_Str ("Number of hash chains of length ");
202 if J < 10 then
203 Write_Char (' ');
204 end if;
206 Write_Int (J);
208 if J = Max_Chain_Length then
209 Write_Str (" or greater");
210 end if;
212 Write_Str (" = ");
213 Write_Int (F (J));
214 Write_Eol;
216 if J /= 0 then
217 Nsyms := Nsyms + F (J);
218 Probes := Probes + F (J) * (1 + J) * 100;
219 end if;
220 end if;
221 end loop;
223 Write_Eol;
224 Write_Str ("Average number of probes for lookup = ");
225 Probes := Probes / Nsyms;
226 Write_Int (Probes / 200);
227 Write_Char ('.');
228 Probes := (Probes mod 200) / 2;
229 Write_Char (Character'Val (48 + Probes / 10));
230 Write_Char (Character'Val (48 + Probes mod 10));
231 Write_Eol;
232 Write_Eol;
233 end if;
234 end Finalize;
236 -----------------------------
237 -- Get_Decoded_Name_String --
238 -----------------------------
240 procedure Get_Decoded_Name_String (Id : Name_Id) is
241 C : Character;
242 P : Natural;
244 begin
245 Get_Name_String (Id);
247 -- Quick loop to see if there is anything special to do
249 P := 1;
250 loop
251 if P = Name_Len then
252 return;
254 else
255 C := Name_Buffer (P);
257 exit when
258 C = 'U' or else
259 C = 'W' or else
260 C = 'Q' or else
261 C = 'O';
263 P := P + 1;
264 end if;
265 end loop;
267 -- Here we have at least some encoding that we must decode
269 Decode : declare
270 New_Len : Natural;
271 Old : Positive;
272 New_Buf : String (1 .. Name_Buffer'Last);
274 procedure Copy_One_Character;
275 -- Copy a character from Name_Buffer to New_Buf. Includes case
276 -- of copying a Uhh,Whhhh,WWhhhhhhhh sequence and decoding it.
278 function Hex (N : Natural) return Word;
279 -- Scans past N digits using Old pointer and returns hex value
281 procedure Insert_Character (C : Character);
282 -- Insert a new character into output decoded name
284 ------------------------
285 -- Copy_One_Character --
286 ------------------------
288 procedure Copy_One_Character is
289 C : Character;
291 begin
292 C := Name_Buffer (Old);
294 -- U (upper half insertion case)
296 if C = 'U'
297 and then Old < Name_Len
298 and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
299 and then Name_Buffer (Old + 1) /= '_'
300 then
301 Old := Old + 1;
302 Insert_Character (Character'Val (Hex (2)));
304 -- WW (wide wide character insertion)
306 elsif C = 'W'
307 and then Old < Name_Len
308 and then Name_Buffer (Old + 1) = 'W'
309 then
310 Old := Old + 2;
311 Widechar.Set_Wide (Char_Code (Hex (8)), New_Buf, New_Len);
313 -- W (wide character insertion)
315 elsif C = 'W'
316 and then Old < Name_Len
317 and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
318 and then Name_Buffer (Old + 1) /= '_'
319 then
320 Old := Old + 1;
321 Widechar.Set_Wide (Char_Code (Hex (4)), New_Buf, New_Len);
323 -- Any other character is copied unchanged
325 else
326 Insert_Character (C);
327 Old := Old + 1;
328 end if;
329 end Copy_One_Character;
331 ---------
332 -- Hex --
333 ---------
335 function Hex (N : Natural) return Word is
336 T : Word := 0;
337 C : Character;
339 begin
340 for J in 1 .. N loop
341 C := Name_Buffer (Old);
342 Old := Old + 1;
344 pragma Assert (C in '0' .. '9' or else C in 'a' .. 'f');
346 if C <= '9' then
347 T := 16 * T + Character'Pos (C) - Character'Pos ('0');
348 else -- C in 'a' .. 'f'
349 T := 16 * T + Character'Pos (C) - (Character'Pos ('a') - 10);
350 end if;
351 end loop;
353 return T;
354 end Hex;
356 ----------------------
357 -- Insert_Character --
358 ----------------------
360 procedure Insert_Character (C : Character) is
361 begin
362 New_Len := New_Len + 1;
363 New_Buf (New_Len) := C;
364 end Insert_Character;
366 -- Start of processing for Decode
368 begin
369 New_Len := 0;
370 Old := 1;
372 -- Loop through characters of name
374 while Old <= Name_Len loop
376 -- Case of character literal, put apostrophes around character
378 if Name_Buffer (Old) = 'Q'
379 and then Old < Name_Len
380 then
381 Old := Old + 1;
382 Insert_Character (''');
383 Copy_One_Character;
384 Insert_Character (''');
386 -- Case of operator name
388 elsif Name_Buffer (Old) = 'O'
389 and then Old < Name_Len
390 and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
391 and then Name_Buffer (Old + 1) /= '_'
392 then
393 Old := Old + 1;
395 declare
396 -- This table maps the 2nd and 3rd characters of the name
397 -- into the required output. Two blanks means leave the
398 -- name alone
400 Map : constant String :=
401 "ab " & -- Oabs => "abs"
402 "ad+ " & -- Oadd => "+"
403 "an " & -- Oand => "and"
404 "co& " & -- Oconcat => "&"
405 "di/ " & -- Odivide => "/"
406 "eq= " & -- Oeq => "="
407 "ex**" & -- Oexpon => "**"
408 "gt> " & -- Ogt => ">"
409 "ge>=" & -- Oge => ">="
410 "le<=" & -- Ole => "<="
411 "lt< " & -- Olt => "<"
412 "mo " & -- Omod => "mod"
413 "mu* " & -- Omutliply => "*"
414 "ne/=" & -- One => "/="
415 "no " & -- Onot => "not"
416 "or " & -- Oor => "or"
417 "re " & -- Orem => "rem"
418 "su- " & -- Osubtract => "-"
419 "xo "; -- Oxor => "xor"
421 J : Integer;
423 begin
424 Insert_Character ('"');
426 -- Search the map. Note that this loop must terminate, if
427 -- not we have some kind of internal error, and a constraint
428 -- constraint error may be raised.
430 J := Map'First;
431 loop
432 exit when Name_Buffer (Old) = Map (J)
433 and then Name_Buffer (Old + 1) = Map (J + 1);
434 J := J + 4;
435 end loop;
437 -- Special operator name
439 if Map (J + 2) /= ' ' then
440 Insert_Character (Map (J + 2));
442 if Map (J + 3) /= ' ' then
443 Insert_Character (Map (J + 3));
444 end if;
446 Insert_Character ('"');
448 -- Skip past original operator name in input
450 while Old <= Name_Len
451 and then Name_Buffer (Old) in 'a' .. 'z'
452 loop
453 Old := Old + 1;
454 end loop;
456 -- For other operator names, leave them in lower case,
457 -- surrounded by apostrophes
459 else
460 -- Copy original operator name from input to output
462 while Old <= Name_Len
463 and then Name_Buffer (Old) in 'a' .. 'z'
464 loop
465 Copy_One_Character;
466 end loop;
468 Insert_Character ('"');
469 end if;
470 end;
472 -- Else copy one character and keep going
474 else
475 Copy_One_Character;
476 end if;
477 end loop;
479 -- Copy new buffer as result
481 Name_Len := New_Len;
482 Name_Buffer (1 .. New_Len) := New_Buf (1 .. New_Len);
483 end Decode;
484 end Get_Decoded_Name_String;
486 -------------------------------------------
487 -- Get_Decoded_Name_String_With_Brackets --
488 -------------------------------------------
490 procedure Get_Decoded_Name_String_With_Brackets (Id : Name_Id) is
491 P : Natural;
493 begin
494 -- Case of operator name, normal decoding is fine
496 if Name_Buffer (1) = 'O' then
497 Get_Decoded_Name_String (Id);
499 -- For character literals, normal decoding is fine
501 elsif Name_Buffer (1) = 'Q' then
502 Get_Decoded_Name_String (Id);
504 -- Only remaining issue is U/W/WW sequences
506 else
507 Get_Name_String (Id);
509 P := 1;
510 while P < Name_Len loop
511 if Name_Buffer (P + 1) in 'A' .. 'Z' then
512 P := P + 1;
514 -- Uhh encoding
516 elsif Name_Buffer (P) = 'U' then
517 for J in reverse P + 3 .. P + Name_Len loop
518 Name_Buffer (J + 3) := Name_Buffer (J);
519 end loop;
521 Name_Len := Name_Len + 3;
522 Name_Buffer (P + 3) := Name_Buffer (P + 2);
523 Name_Buffer (P + 2) := Name_Buffer (P + 1);
524 Name_Buffer (P) := '[';
525 Name_Buffer (P + 1) := '"';
526 Name_Buffer (P + 4) := '"';
527 Name_Buffer (P + 5) := ']';
528 P := P + 6;
530 -- WWhhhhhhhh encoding
532 elsif Name_Buffer (P) = 'W'
533 and then P + 9 <= Name_Len
534 and then Name_Buffer (P + 1) = 'W'
535 and then Name_Buffer (P + 2) not in 'A' .. 'Z'
536 and then Name_Buffer (P + 2) /= '_'
537 then
538 Name_Buffer (P + 12 .. Name_Len + 2) :=
539 Name_Buffer (P + 10 .. Name_Len);
540 Name_Buffer (P) := '[';
541 Name_Buffer (P + 1) := '"';
542 Name_Buffer (P + 10) := '"';
543 Name_Buffer (P + 11) := ']';
544 Name_Len := Name_Len + 2;
545 P := P + 12;
547 -- Whhhh encoding
549 elsif Name_Buffer (P) = 'W'
550 and then P < Name_Len
551 and then Name_Buffer (P + 1) not in 'A' .. 'Z'
552 and then Name_Buffer (P + 1) /= '_'
553 then
554 Name_Buffer (P + 8 .. P + Name_Len + 3) :=
555 Name_Buffer (P + 5 .. Name_Len);
556 Name_Buffer (P + 2 .. P + 5) := Name_Buffer (P + 1 .. P + 4);
557 Name_Buffer (P) := '[';
558 Name_Buffer (P + 1) := '"';
559 Name_Buffer (P + 6) := '"';
560 Name_Buffer (P + 7) := ']';
561 Name_Len := Name_Len + 3;
562 P := P + 8;
564 else
565 P := P + 1;
566 end if;
567 end loop;
568 end if;
569 end Get_Decoded_Name_String_With_Brackets;
571 ------------------------
572 -- Get_Last_Two_Chars --
573 ------------------------
575 procedure Get_Last_Two_Chars (N : Name_Id; C1, C2 : out Character) is
576 NE : Name_Entry renames Name_Entries.Table (N);
577 NEL : constant Int := Int (NE.Name_Len);
579 begin
580 if NEL >= 2 then
581 C1 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 1);
582 C2 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 0);
583 else
584 C1 := ASCII.NUL;
585 C2 := ASCII.NUL;
586 end if;
587 end Get_Last_Two_Chars;
589 ---------------------
590 -- Get_Name_String --
591 ---------------------
593 -- Procedure version leaving result in Name_Buffer, length in Name_Len
595 procedure Get_Name_String (Id : Name_Id) is
596 S : Int;
598 begin
599 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
601 S := Name_Entries.Table (Id).Name_Chars_Index;
602 Name_Len := Natural (Name_Entries.Table (Id).Name_Len);
604 for J in 1 .. Name_Len loop
605 Name_Buffer (J) := Name_Chars.Table (S + Int (J));
606 end loop;
607 end Get_Name_String;
609 ---------------------
610 -- Get_Name_String --
611 ---------------------
613 -- Function version returning a string
615 function Get_Name_String (Id : Name_Id) return String is
616 S : Int;
618 begin
619 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
620 S := Name_Entries.Table (Id).Name_Chars_Index;
622 declare
623 R : String (1 .. Natural (Name_Entries.Table (Id).Name_Len));
625 begin
626 for J in R'Range loop
627 R (J) := Name_Chars.Table (S + Int (J));
628 end loop;
630 return R;
631 end;
632 end Get_Name_String;
634 --------------------------------
635 -- Get_Name_String_And_Append --
636 --------------------------------
638 procedure Get_Name_String_And_Append (Id : Name_Id) is
639 S : Int;
641 begin
642 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
644 S := Name_Entries.Table (Id).Name_Chars_Index;
646 for J in 1 .. Natural (Name_Entries.Table (Id).Name_Len) loop
647 Name_Len := Name_Len + 1;
648 Name_Buffer (Name_Len) := Name_Chars.Table (S + Int (J));
649 end loop;
650 end Get_Name_String_And_Append;
652 -------------------------
653 -- Get_Name_Table_Byte --
654 -------------------------
656 function Get_Name_Table_Byte (Id : Name_Id) return Byte is
657 begin
658 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
659 return Name_Entries.Table (Id).Byte_Info;
660 end Get_Name_Table_Byte;
662 -------------------------
663 -- Get_Name_Table_Info --
664 -------------------------
666 function Get_Name_Table_Info (Id : Name_Id) return Int is
667 begin
668 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
669 return Name_Entries.Table (Id).Int_Info;
670 end Get_Name_Table_Info;
672 -----------------------------------------
673 -- Get_Unqualified_Decoded_Name_String --
674 -----------------------------------------
676 procedure Get_Unqualified_Decoded_Name_String (Id : Name_Id) is
677 begin
678 Get_Decoded_Name_String (Id);
679 Strip_Qualification_And_Suffixes;
680 end Get_Unqualified_Decoded_Name_String;
682 ---------------------------------
683 -- Get_Unqualified_Name_String --
684 ---------------------------------
686 procedure Get_Unqualified_Name_String (Id : Name_Id) is
687 begin
688 Get_Name_String (Id);
689 Strip_Qualification_And_Suffixes;
690 end Get_Unqualified_Name_String;
692 ----------
693 -- Hash --
694 ----------
696 function Hash return Hash_Index_Type is
697 begin
698 -- For the cases of 1-12 characters, all characters participate in the
699 -- hash. The positioning is randomized, with the bias that characters
700 -- later on participate fully (i.e. are added towards the right side).
702 case Name_Len is
704 when 0 =>
705 return 0;
707 when 1 =>
708 return
709 Character'Pos (Name_Buffer (1));
711 when 2 =>
712 return ((
713 Character'Pos (Name_Buffer (1))) * 64 +
714 Character'Pos (Name_Buffer (2))) mod Hash_Num;
716 when 3 =>
717 return (((
718 Character'Pos (Name_Buffer (1))) * 16 +
719 Character'Pos (Name_Buffer (3))) * 16 +
720 Character'Pos (Name_Buffer (2))) mod Hash_Num;
722 when 4 =>
723 return ((((
724 Character'Pos (Name_Buffer (1))) * 8 +
725 Character'Pos (Name_Buffer (2))) * 8 +
726 Character'Pos (Name_Buffer (3))) * 8 +
727 Character'Pos (Name_Buffer (4))) mod Hash_Num;
729 when 5 =>
730 return (((((
731 Character'Pos (Name_Buffer (4))) * 8 +
732 Character'Pos (Name_Buffer (1))) * 4 +
733 Character'Pos (Name_Buffer (3))) * 4 +
734 Character'Pos (Name_Buffer (5))) * 8 +
735 Character'Pos (Name_Buffer (2))) mod Hash_Num;
737 when 6 =>
738 return ((((((
739 Character'Pos (Name_Buffer (5))) * 4 +
740 Character'Pos (Name_Buffer (1))) * 4 +
741 Character'Pos (Name_Buffer (4))) * 4 +
742 Character'Pos (Name_Buffer (2))) * 4 +
743 Character'Pos (Name_Buffer (6))) * 4 +
744 Character'Pos (Name_Buffer (3))) mod Hash_Num;
746 when 7 =>
747 return (((((((
748 Character'Pos (Name_Buffer (4))) * 4 +
749 Character'Pos (Name_Buffer (3))) * 4 +
750 Character'Pos (Name_Buffer (1))) * 4 +
751 Character'Pos (Name_Buffer (2))) * 2 +
752 Character'Pos (Name_Buffer (5))) * 2 +
753 Character'Pos (Name_Buffer (7))) * 2 +
754 Character'Pos (Name_Buffer (6))) mod Hash_Num;
756 when 8 =>
757 return ((((((((
758 Character'Pos (Name_Buffer (2))) * 4 +
759 Character'Pos (Name_Buffer (1))) * 4 +
760 Character'Pos (Name_Buffer (3))) * 2 +
761 Character'Pos (Name_Buffer (5))) * 2 +
762 Character'Pos (Name_Buffer (7))) * 2 +
763 Character'Pos (Name_Buffer (6))) * 2 +
764 Character'Pos (Name_Buffer (4))) * 2 +
765 Character'Pos (Name_Buffer (8))) mod Hash_Num;
767 when 9 =>
768 return (((((((((
769 Character'Pos (Name_Buffer (2))) * 4 +
770 Character'Pos (Name_Buffer (1))) * 4 +
771 Character'Pos (Name_Buffer (3))) * 4 +
772 Character'Pos (Name_Buffer (4))) * 2 +
773 Character'Pos (Name_Buffer (8))) * 2 +
774 Character'Pos (Name_Buffer (7))) * 2 +
775 Character'Pos (Name_Buffer (5))) * 2 +
776 Character'Pos (Name_Buffer (6))) * 2 +
777 Character'Pos (Name_Buffer (9))) mod Hash_Num;
779 when 10 =>
780 return ((((((((((
781 Character'Pos (Name_Buffer (01))) * 2 +
782 Character'Pos (Name_Buffer (02))) * 2 +
783 Character'Pos (Name_Buffer (08))) * 2 +
784 Character'Pos (Name_Buffer (03))) * 2 +
785 Character'Pos (Name_Buffer (04))) * 2 +
786 Character'Pos (Name_Buffer (09))) * 2 +
787 Character'Pos (Name_Buffer (06))) * 2 +
788 Character'Pos (Name_Buffer (05))) * 2 +
789 Character'Pos (Name_Buffer (07))) * 2 +
790 Character'Pos (Name_Buffer (10))) mod Hash_Num;
792 when 11 =>
793 return (((((((((((
794 Character'Pos (Name_Buffer (05))) * 2 +
795 Character'Pos (Name_Buffer (01))) * 2 +
796 Character'Pos (Name_Buffer (06))) * 2 +
797 Character'Pos (Name_Buffer (09))) * 2 +
798 Character'Pos (Name_Buffer (07))) * 2 +
799 Character'Pos (Name_Buffer (03))) * 2 +
800 Character'Pos (Name_Buffer (08))) * 2 +
801 Character'Pos (Name_Buffer (02))) * 2 +
802 Character'Pos (Name_Buffer (10))) * 2 +
803 Character'Pos (Name_Buffer (04))) * 2 +
804 Character'Pos (Name_Buffer (11))) mod Hash_Num;
806 when 12 =>
807 return ((((((((((((
808 Character'Pos (Name_Buffer (03))) * 2 +
809 Character'Pos (Name_Buffer (02))) * 2 +
810 Character'Pos (Name_Buffer (05))) * 2 +
811 Character'Pos (Name_Buffer (01))) * 2 +
812 Character'Pos (Name_Buffer (06))) * 2 +
813 Character'Pos (Name_Buffer (04))) * 2 +
814 Character'Pos (Name_Buffer (08))) * 2 +
815 Character'Pos (Name_Buffer (11))) * 2 +
816 Character'Pos (Name_Buffer (07))) * 2 +
817 Character'Pos (Name_Buffer (09))) * 2 +
818 Character'Pos (Name_Buffer (10))) * 2 +
819 Character'Pos (Name_Buffer (12))) mod Hash_Num;
821 -- Names longer than 12 characters are handled by taking the first
822 -- 6 odd numbered characters and the last 6 even numbered characters.
824 when others => declare
825 Even_Name_Len : constant Integer := (Name_Len) / 2 * 2;
826 begin
827 return ((((((((((((
828 Character'Pos (Name_Buffer (01))) * 2 +
829 Character'Pos (Name_Buffer (Even_Name_Len - 10))) * 2 +
830 Character'Pos (Name_Buffer (03))) * 2 +
831 Character'Pos (Name_Buffer (Even_Name_Len - 08))) * 2 +
832 Character'Pos (Name_Buffer (05))) * 2 +
833 Character'Pos (Name_Buffer (Even_Name_Len - 06))) * 2 +
834 Character'Pos (Name_Buffer (07))) * 2 +
835 Character'Pos (Name_Buffer (Even_Name_Len - 04))) * 2 +
836 Character'Pos (Name_Buffer (09))) * 2 +
837 Character'Pos (Name_Buffer (Even_Name_Len - 02))) * 2 +
838 Character'Pos (Name_Buffer (11))) * 2 +
839 Character'Pos (Name_Buffer (Even_Name_Len))) mod Hash_Num;
840 end;
841 end case;
842 end Hash;
844 ----------------
845 -- Initialize --
846 ----------------
848 procedure Initialize is
849 begin
850 Name_Chars.Init;
851 Name_Entries.Init;
853 -- Initialize entries for one character names
855 for C in Character loop
856 Name_Entries.Increment_Last;
857 Name_Entries.Table (Name_Entries.Last).Name_Chars_Index :=
858 Name_Chars.Last;
859 Name_Entries.Table (Name_Entries.Last).Name_Len := 1;
860 Name_Entries.Table (Name_Entries.Last).Hash_Link := No_Name;
861 Name_Entries.Table (Name_Entries.Last).Int_Info := 0;
862 Name_Entries.Table (Name_Entries.Last).Byte_Info := 0;
863 Name_Chars.Increment_Last;
864 Name_Chars.Table (Name_Chars.Last) := C;
865 Name_Chars.Increment_Last;
866 Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
867 end loop;
869 -- Clear hash table
871 for J in Hash_Index_Type loop
872 Hash_Table (J) := No_Name;
873 end loop;
874 end Initialize;
876 ----------------------
877 -- Is_Internal_Name --
878 ----------------------
880 -- Version taking an argument
882 function Is_Internal_Name (Id : Name_Id) return Boolean is
883 begin
884 Get_Name_String (Id);
885 return Is_Internal_Name;
886 end Is_Internal_Name;
888 ----------------------
889 -- Is_Internal_Name --
890 ----------------------
892 -- Version taking its input from Name_Buffer
894 function Is_Internal_Name return Boolean is
895 begin
896 if Name_Buffer (1) = '_'
897 or else Name_Buffer (Name_Len) = '_'
898 then
899 return True;
901 else
902 -- Test backwards, because we only want to test the last entity
903 -- name if the name we have is qualified with other entities.
905 for J in reverse 1 .. Name_Len loop
906 if Is_OK_Internal_Letter (Name_Buffer (J)) then
907 return True;
909 -- Quit if we come to terminating double underscore (note that
910 -- if the current character is an underscore, we know that
911 -- there is a previous character present, since we already
912 -- filtered out the case of Name_Buffer (1) = '_' above.
914 elsif Name_Buffer (J) = '_'
915 and then Name_Buffer (J - 1) = '_'
916 and then Name_Buffer (J - 2) /= '_'
917 then
918 return False;
919 end if;
920 end loop;
921 end if;
923 return False;
924 end Is_Internal_Name;
926 ---------------------------
927 -- Is_OK_Internal_Letter --
928 ---------------------------
930 function Is_OK_Internal_Letter (C : Character) return Boolean is
931 begin
932 return C in 'A' .. 'Z'
933 and then C /= 'O'
934 and then C /= 'Q'
935 and then C /= 'U'
936 and then C /= 'W'
937 and then C /= 'X';
938 end Is_OK_Internal_Letter;
940 ----------------------
941 -- Is_Operator_Name --
942 ----------------------
944 function Is_Operator_Name (Id : Name_Id) return Boolean is
945 S : Int;
946 begin
947 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
948 S := Name_Entries.Table (Id).Name_Chars_Index;
949 return Name_Chars.Table (S + 1) = 'O';
950 end Is_Operator_Name;
952 --------------------
953 -- Length_Of_Name --
954 --------------------
956 function Length_Of_Name (Id : Name_Id) return Nat is
957 begin
958 return Int (Name_Entries.Table (Id).Name_Len);
959 end Length_Of_Name;
961 ----------
962 -- Lock --
963 ----------
965 procedure Lock is
966 begin
967 Name_Chars.Set_Last (Name_Chars.Last + Name_Chars_Reserve);
968 Name_Entries.Set_Last (Name_Entries.Last + Name_Entries_Reserve);
969 Name_Chars.Locked := True;
970 Name_Entries.Locked := True;
971 Name_Chars.Release;
972 Name_Entries.Release;
973 end Lock;
975 ------------------------
976 -- Name_Chars_Address --
977 ------------------------
979 function Name_Chars_Address return System.Address is
980 begin
981 return Name_Chars.Table (0)'Address;
982 end Name_Chars_Address;
984 ----------------
985 -- Name_Enter --
986 ----------------
988 function Name_Enter return Name_Id is
989 begin
990 Name_Entries.Increment_Last;
991 Name_Entries.Table (Name_Entries.Last).Name_Chars_Index :=
992 Name_Chars.Last;
993 Name_Entries.Table (Name_Entries.Last).Name_Len := Short (Name_Len);
994 Name_Entries.Table (Name_Entries.Last).Hash_Link := No_Name;
995 Name_Entries.Table (Name_Entries.Last).Int_Info := 0;
996 Name_Entries.Table (Name_Entries.Last).Byte_Info := 0;
998 -- Set corresponding string entry in the Name_Chars table
1000 for J in 1 .. Name_Len loop
1001 Name_Chars.Increment_Last;
1002 Name_Chars.Table (Name_Chars.Last) := Name_Buffer (J);
1003 end loop;
1005 Name_Chars.Increment_Last;
1006 Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
1008 return Name_Entries.Last;
1009 end Name_Enter;
1011 --------------------------
1012 -- Name_Entries_Address --
1013 --------------------------
1015 function Name_Entries_Address return System.Address is
1016 begin
1017 return Name_Entries.Table (First_Name_Id)'Address;
1018 end Name_Entries_Address;
1020 ------------------------
1021 -- Name_Entries_Count --
1022 ------------------------
1024 function Name_Entries_Count return Nat is
1025 begin
1026 return Int (Name_Entries.Last - Name_Entries.First + 1);
1027 end Name_Entries_Count;
1029 ---------------
1030 -- Name_Find --
1031 ---------------
1033 function Name_Find return Name_Id is
1034 New_Id : Name_Id;
1035 -- Id of entry in hash search, and value to be returned
1037 S : Int;
1038 -- Pointer into string table
1040 Hash_Index : Hash_Index_Type;
1041 -- Computed hash index
1043 begin
1044 -- Quick handling for one character names
1046 if Name_Len = 1 then
1047 return Name_Id (First_Name_Id + Character'Pos (Name_Buffer (1)));
1049 -- Otherwise search hash table for existing matching entry
1051 else
1052 Hash_Index := Namet.Hash;
1053 New_Id := Hash_Table (Hash_Index);
1055 if New_Id = No_Name then
1056 Hash_Table (Hash_Index) := Name_Entries.Last + 1;
1058 else
1059 Search : loop
1060 if Name_Len /=
1061 Integer (Name_Entries.Table (New_Id).Name_Len)
1062 then
1063 goto No_Match;
1064 end if;
1066 S := Name_Entries.Table (New_Id).Name_Chars_Index;
1068 for J in 1 .. Name_Len loop
1069 if Name_Chars.Table (S + Int (J)) /= Name_Buffer (J) then
1070 goto No_Match;
1071 end if;
1072 end loop;
1074 return New_Id;
1076 -- Current entry in hash chain does not match
1078 <<No_Match>>
1079 if Name_Entries.Table (New_Id).Hash_Link /= No_Name then
1080 New_Id := Name_Entries.Table (New_Id).Hash_Link;
1081 else
1082 Name_Entries.Table (New_Id).Hash_Link :=
1083 Name_Entries.Last + 1;
1084 exit Search;
1085 end if;
1087 end loop Search;
1088 end if;
1090 -- We fall through here only if a matching entry was not found in the
1091 -- hash table. We now create a new entry in the names table. The hash
1092 -- link pointing to the new entry (Name_Entries.Last+1) has been set.
1094 Name_Entries.Increment_Last;
1095 Name_Entries.Table (Name_Entries.Last).Name_Chars_Index :=
1096 Name_Chars.Last;
1097 Name_Entries.Table (Name_Entries.Last).Name_Len := Short (Name_Len);
1098 Name_Entries.Table (Name_Entries.Last).Hash_Link := No_Name;
1099 Name_Entries.Table (Name_Entries.Last).Int_Info := 0;
1100 Name_Entries.Table (Name_Entries.Last).Byte_Info := 0;
1102 -- Set corresponding string entry in the Name_Chars table
1104 for J in 1 .. Name_Len loop
1105 Name_Chars.Increment_Last;
1106 Name_Chars.Table (Name_Chars.Last) := Name_Buffer (J);
1107 end loop;
1109 Name_Chars.Increment_Last;
1110 Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
1112 return Name_Entries.Last;
1113 end if;
1114 end Name_Find;
1116 ----------------------
1117 -- Reset_Name_Table --
1118 ----------------------
1120 procedure Reset_Name_Table is
1121 begin
1122 for J in First_Name_Id .. Name_Entries.Last loop
1123 Name_Entries.Table (J).Int_Info := 0;
1124 Name_Entries.Table (J).Byte_Info := 0;
1125 end loop;
1126 end Reset_Name_Table;
1128 --------------------------------
1129 -- Set_Character_Literal_Name --
1130 --------------------------------
1132 procedure Set_Character_Literal_Name (C : Char_Code) is
1133 begin
1134 Name_Buffer (1) := 'Q';
1135 Name_Len := 1;
1136 Store_Encoded_Character (C);
1137 end Set_Character_Literal_Name;
1139 -------------------------
1140 -- Set_Name_Table_Byte --
1141 -------------------------
1143 procedure Set_Name_Table_Byte (Id : Name_Id; Val : Byte) is
1144 begin
1145 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
1146 Name_Entries.Table (Id).Byte_Info := Val;
1147 end Set_Name_Table_Byte;
1149 -------------------------
1150 -- Set_Name_Table_Info --
1151 -------------------------
1153 procedure Set_Name_Table_Info (Id : Name_Id; Val : Int) is
1154 begin
1155 pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
1156 Name_Entries.Table (Id).Int_Info := Val;
1157 end Set_Name_Table_Info;
1159 -----------------------------
1160 -- Store_Encoded_Character --
1161 -----------------------------
1163 procedure Store_Encoded_Character (C : Char_Code) is
1165 procedure Set_Hex_Chars (C : Char_Code);
1166 -- Stores given value, which is in the range 0 .. 255, as two hex
1167 -- digits (using lower case a-f) in Name_Buffer, incrementing Name_Len.
1169 -------------------
1170 -- Set_Hex_Chars --
1171 -------------------
1173 procedure Set_Hex_Chars (C : Char_Code) is
1174 Hexd : constant String := "0123456789abcdef";
1175 N : constant Natural := Natural (C);
1176 begin
1177 Name_Buffer (Name_Len + 1) := Hexd (N / 16 + 1);
1178 Name_Buffer (Name_Len + 2) := Hexd (N mod 16 + 1);
1179 Name_Len := Name_Len + 2;
1180 end Set_Hex_Chars;
1182 -- Start of processing for Store_Encoded_Character
1184 begin
1185 Name_Len := Name_Len + 1;
1187 if In_Character_Range (C) then
1188 declare
1189 CC : constant Character := Get_Character (C);
1190 begin
1191 if CC in 'a' .. 'z' or else CC in '0' .. '9' then
1192 Name_Buffer (Name_Len) := CC;
1193 else
1194 Name_Buffer (Name_Len) := 'U';
1195 Set_Hex_Chars (C);
1196 end if;
1197 end;
1199 elsif In_Wide_Character_Range (C) then
1200 Name_Buffer (Name_Len) := 'W';
1201 Set_Hex_Chars (C / 256);
1202 Set_Hex_Chars (C mod 256);
1204 else
1205 Name_Buffer (Name_Len) := 'W';
1206 Name_Len := Name_Len + 1;
1207 Name_Buffer (Name_Len) := 'W';
1208 Set_Hex_Chars (C / 2 ** 24);
1209 Set_Hex_Chars ((C / 2 ** 16) mod 256);
1210 Set_Hex_Chars ((C / 256) mod 256);
1211 Set_Hex_Chars (C mod 256);
1212 end if;
1213 end Store_Encoded_Character;
1215 --------------------------------------
1216 -- Strip_Qualification_And_Suffixes --
1217 --------------------------------------
1219 procedure Strip_Qualification_And_Suffixes is
1220 J : Integer;
1222 begin
1223 -- Strip package body qualification string off end
1225 for J in reverse 2 .. Name_Len loop
1226 if Name_Buffer (J) = 'X' then
1227 Name_Len := J - 1;
1228 exit;
1229 end if;
1231 exit when Name_Buffer (J) /= 'b'
1232 and then Name_Buffer (J) /= 'n'
1233 and then Name_Buffer (J) /= 'p';
1234 end loop;
1236 -- Find rightmost __ or $ separator if one exists. First we position
1237 -- to start the search. If we have a character constant, position
1238 -- just before it, otherwise position to last character but one
1240 if Name_Buffer (Name_Len) = ''' then
1241 J := Name_Len - 2;
1242 while J > 0 and then Name_Buffer (J) /= ''' loop
1243 J := J - 1;
1244 end loop;
1246 else
1247 J := Name_Len - 1;
1248 end if;
1250 -- Loop to search for rightmost __ or $ (homonym) separator
1252 while J > 1 loop
1254 -- If $ separator, homonym separator, so strip it and keep looking
1256 if Name_Buffer (J) = '$' then
1257 Name_Len := J - 1;
1258 J := Name_Len - 1;
1260 -- Else check for __ found
1262 elsif Name_Buffer (J) = '_' and then Name_Buffer (J + 1) = '_' then
1264 -- Found __ so see if digit follows, and if so, this is a
1265 -- homonym separator, so strip it and keep looking.
1267 if Name_Buffer (J + 2) in '0' .. '9' then
1268 Name_Len := J - 1;
1269 J := Name_Len - 1;
1271 -- If not a homonym separator, then we simply strip the
1272 -- separator and everything that precedes it, and we are done
1274 else
1275 Name_Buffer (1 .. Name_Len - J - 1) :=
1276 Name_Buffer (J + 2 .. Name_Len);
1277 Name_Len := Name_Len - J - 1;
1278 exit;
1279 end if;
1281 else
1282 J := J - 1;
1283 end if;
1284 end loop;
1285 end Strip_Qualification_And_Suffixes;
1287 ---------------
1288 -- Tree_Read --
1289 ---------------
1291 procedure Tree_Read is
1292 begin
1293 Name_Chars.Tree_Read;
1294 Name_Entries.Tree_Read;
1296 Tree_Read_Data
1297 (Hash_Table'Address,
1298 Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1299 end Tree_Read;
1301 ----------------
1302 -- Tree_Write --
1303 ----------------
1305 procedure Tree_Write is
1306 begin
1307 Name_Chars.Tree_Write;
1308 Name_Entries.Tree_Write;
1310 Tree_Write_Data
1311 (Hash_Table'Address,
1312 Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1313 end Tree_Write;
1315 ------------
1316 -- Unlock --
1317 ------------
1319 procedure Unlock is
1320 begin
1321 Name_Chars.Set_Last (Name_Chars.Last - Name_Chars_Reserve);
1322 Name_Entries.Set_Last (Name_Entries.Last - Name_Entries_Reserve);
1323 Name_Chars.Locked := False;
1324 Name_Entries.Locked := False;
1325 Name_Chars.Release;
1326 Name_Entries.Release;
1327 end Unlock;
1329 --------
1330 -- wn --
1331 --------
1333 procedure wn (Id : Name_Id) is
1334 begin
1335 Write_Name (Id);
1336 Write_Eol;
1337 end wn;
1339 ----------------
1340 -- Write_Name --
1341 ----------------
1343 procedure Write_Name (Id : Name_Id) is
1344 begin
1345 if Id >= First_Name_Id then
1346 Get_Name_String (Id);
1347 Write_Str (Name_Buffer (1 .. Name_Len));
1348 end if;
1349 end Write_Name;
1351 ------------------------
1352 -- Write_Name_Decoded --
1353 ------------------------
1355 procedure Write_Name_Decoded (Id : Name_Id) is
1356 begin
1357 if Id >= First_Name_Id then
1358 Get_Decoded_Name_String (Id);
1359 Write_Str (Name_Buffer (1 .. Name_Len));
1360 end if;
1361 end Write_Name_Decoded;
1363 end Namet;