OSDN Git Service

2005-03-08 Geert Bosch <bosch@adacore.com>
[pf3gnuchains/gcc-fork.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-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 ------------------------------------------------------------------------------
33
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.
37
38 with Debug;    use Debug;
39 with Output;   use Output;
40 with Tree_IO;  use Tree_IO;
41 with Widechar; use Widechar;
42
43 package body Namet is
44
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.
53
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.
58
59    Hash_Max : constant Int := Hash_Num - 1;
60    --  Indexes in the hash header table run from 0 to Hash_Num - 1
61
62    subtype Hash_Index_Type is Int range 0 .. Hash_Max;
63    --  Range of hash index values
64
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.
70
71    -----------------------
72    -- Local Subprograms --
73    -----------------------
74
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)
78
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.
85
86    -----------------------------
87    -- Add_Char_To_Name_Buffer --
88    -----------------------------
89
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;
97
98    ----------------------------
99    -- Add_Nat_To_Name_Buffer --
100    ----------------------------
101
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;
107
108       Add_Char_To_Name_Buffer (Character'Val (Character'Pos ('0') + V rem 10));
109    end Add_Nat_To_Name_Buffer;
110
111    ----------------------------
112    -- Add_Str_To_Name_Buffer --
113    ----------------------------
114
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;
121
122
123    --------------
124    -- Finalize --
125    --------------
126
127    procedure Finalize is
128       Max_Chain_Length : constant := 50;
129       --  Max length of chains for which specific information is output
130
131       F : array (Int range 0 .. Max_Chain_Length) of Int;
132       --  N'th entry is number of chains of length N
133
134       Probes : Int := 0;
135       --  Used to compute average number of probes
136
137       Nsyms : Int := 0;
138       --  Number of symbols in table
139
140    begin
141       if Debug_Flag_H then
142          for J in F'Range loop
143             F (J) := 0;
144          end loop;
145
146          for J in Hash_Index_Type loop
147             if Hash_Table (J) = No_Name then
148                F (0) := F (0) + 1;
149
150             else
151                Write_Str ("Hash_Table (");
152                Write_Int (Int (J));
153                Write_Str (") has ");
154
155                declare
156                   C : Int := 1;
157                   N : Name_Id;
158                   S : Int;
159
160                begin
161                   C := 0;
162                   N := Hash_Table (J);
163
164                   while N /= No_Name loop
165                      N := Name_Entries.Table (N).Hash_Link;
166                      C := C + 1;
167                   end loop;
168
169                   Write_Int (C);
170                   Write_Str (" entries");
171                   Write_Eol;
172
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;
178
179                   N := Hash_Table (J);
180
181                   while N /= No_Name loop
182                      S := Name_Entries.Table (N).Name_Chars_Index;
183                      Write_Str ("      ");
184
185                      for J in 1 .. Name_Entries.Table (N).Name_Len loop
186                         Write_Char (Name_Chars.Table (S + Int (J)));
187                      end loop;
188
189                      Write_Eol;
190                      N := Name_Entries.Table (N).Hash_Link;
191                   end loop;
192                end;
193             end if;
194          end loop;
195
196          Write_Eol;
197
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 ");
201
202                if J < 10 then
203                   Write_Char (' ');
204                end if;
205
206                Write_Int (J);
207
208                if J = Max_Chain_Length then
209                   Write_Str (" or greater");
210                end if;
211
212                Write_Str (" = ");
213                Write_Int (F (J));
214                Write_Eol;
215
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;
222
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;
235
236    -----------------------------
237    -- Get_Decoded_Name_String --
238    -----------------------------
239
240    procedure Get_Decoded_Name_String (Id : Name_Id) is
241       C : Character;
242       P : Natural;
243
244    begin
245       Get_Name_String (Id);
246
247       --  Quick loop to see if there is anything special to do
248
249       P := 1;
250       loop
251          if P = Name_Len then
252             return;
253
254          else
255             C := Name_Buffer (P);
256
257             exit when
258               C = 'U' or else
259               C = 'W' or else
260               C = 'Q' or else
261               C = 'O';
262
263             P := P + 1;
264          end if;
265       end loop;
266
267       --  Here we have at least some encoding that we must decode
268
269       Decode : declare
270          New_Len : Natural;
271          Old     : Positive;
272          New_Buf : String (1 .. Name_Buffer'Last);
273
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.
277
278          function Hex (N : Natural) return Word;
279          --  Scans past N digits using Old pointer and returns hex value
280
281          procedure Insert_Character (C : Character);
282          --  Insert a new character into output decoded name
283
284          ------------------------
285          -- Copy_One_Character --
286          ------------------------
287
288          procedure Copy_One_Character is
289             C : Character;
290
291          begin
292             C := Name_Buffer (Old);
293
294             --  U (upper half insertion case)
295
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)));
303
304             --  WW (wide wide character insertion)
305
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);
312
313             --  W (wide character insertion)
314
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);
322
323             --  Any other character is copied unchanged
324
325             else
326                Insert_Character (C);
327                Old := Old + 1;
328             end if;
329          end Copy_One_Character;
330
331          ---------
332          -- Hex --
333          ---------
334
335          function Hex (N : Natural) return Word is
336             T : Word := 0;
337             C : Character;
338
339          begin
340             for J in 1 .. N loop
341                C := Name_Buffer (Old);
342                Old := Old + 1;
343
344                pragma Assert (C in '0' .. '9' or else C in 'a' .. 'f');
345
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;
352
353             return T;
354          end Hex;
355
356          ----------------------
357          -- Insert_Character --
358          ----------------------
359
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;
365
366       --  Start of processing for Decode
367
368       begin
369          New_Len := 0;
370          Old := 1;
371
372          --  Loop through characters of name
373
374          while Old <= Name_Len loop
375
376             --  Case of character literal, put apostrophes around character
377
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 (''');
385
386             --  Case of operator name
387
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;
394
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
399
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"
420
421                   J : Integer;
422
423                begin
424                   Insert_Character ('"');
425
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.
429
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;
436
437                   --  Special operator name
438
439                   if Map (J + 2) /= ' ' then
440                      Insert_Character (Map (J + 2));
441
442                      if Map (J + 3) /= ' ' then
443                         Insert_Character (Map (J + 3));
444                      end if;
445
446                      Insert_Character ('"');
447
448                      --  Skip past original operator name in input
449
450                      while Old <= Name_Len
451                        and then Name_Buffer (Old) in 'a' .. 'z'
452                      loop
453                         Old := Old + 1;
454                      end loop;
455
456                   --  For other operator names, leave them in lower case,
457                   --  surrounded by apostrophes
458
459                   else
460                      --  Copy original operator name from input to output
461
462                      while Old <= Name_Len
463                         and then Name_Buffer (Old) in 'a' .. 'z'
464                      loop
465                         Copy_One_Character;
466                      end loop;
467
468                      Insert_Character ('"');
469                   end if;
470                end;
471
472             --  Else copy one character and keep going
473
474             else
475                Copy_One_Character;
476             end if;
477          end loop;
478
479          --  Copy new buffer as result
480
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;
485
486    -------------------------------------------
487    -- Get_Decoded_Name_String_With_Brackets --
488    -------------------------------------------
489
490    procedure Get_Decoded_Name_String_With_Brackets (Id : Name_Id) is
491       P : Natural;
492
493    begin
494       --  Case of operator name, normal decoding is fine
495
496       if Name_Buffer (1) = 'O' then
497          Get_Decoded_Name_String (Id);
498
499       --  For character literals, normal decoding is fine
500
501       elsif Name_Buffer (1) = 'Q' then
502          Get_Decoded_Name_String (Id);
503
504       --  Only remaining issue is U/W/WW sequences
505
506       else
507          Get_Name_String (Id);
508
509          P := 1;
510          while P < Name_Len loop
511             if Name_Buffer (P + 1) in 'A' .. 'Z' then
512                P := P + 1;
513
514             --  Uhh encoding
515
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;
520
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;
529
530             --  WWhhhhhhhh encoding
531
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;
546
547             --  Whhhh encoding
548
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;
563
564             else
565                P := P + 1;
566             end if;
567          end loop;
568       end if;
569    end Get_Decoded_Name_String_With_Brackets;
570
571    ------------------------
572    -- Get_Last_Two_Chars --
573    ------------------------
574
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);
578
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;
588
589    ---------------------
590    -- Get_Name_String --
591    ---------------------
592
593    --  Procedure version leaving result in Name_Buffer, length in Name_Len
594
595    procedure Get_Name_String (Id : Name_Id) is
596       S : Int;
597
598    begin
599       pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
600
601       S := Name_Entries.Table (Id).Name_Chars_Index;
602       Name_Len := Natural (Name_Entries.Table (Id).Name_Len);
603
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;
608
609    ---------------------
610    -- Get_Name_String --
611    ---------------------
612
613    --  Function version returning a string
614
615    function Get_Name_String (Id : Name_Id) return String is
616       S : Int;
617
618    begin
619       pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
620       S := Name_Entries.Table (Id).Name_Chars_Index;
621
622       declare
623          R : String (1 .. Natural (Name_Entries.Table (Id).Name_Len));
624
625       begin
626          for J in R'Range loop
627             R (J) := Name_Chars.Table (S + Int (J));
628          end loop;
629
630          return R;
631       end;
632    end Get_Name_String;
633
634    --------------------------------
635    -- Get_Name_String_And_Append --
636    --------------------------------
637
638    procedure Get_Name_String_And_Append (Id : Name_Id) is
639       S : Int;
640
641    begin
642       pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
643
644       S := Name_Entries.Table (Id).Name_Chars_Index;
645
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;
651
652    -------------------------
653    -- Get_Name_Table_Byte --
654    -------------------------
655
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;
661
662    -------------------------
663    -- Get_Name_Table_Info --
664    -------------------------
665
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;
671
672    -----------------------------------------
673    -- Get_Unqualified_Decoded_Name_String --
674    -----------------------------------------
675
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;
681
682    ---------------------------------
683    -- Get_Unqualified_Name_String --
684    ---------------------------------
685
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;
691
692    ----------
693    -- Hash --
694    ----------
695
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).
701
702       case Name_Len is
703
704          when 0 =>
705             return 0;
706
707          when 1 =>
708             return
709                Character'Pos (Name_Buffer (1));
710
711          when 2 =>
712             return ((
713               Character'Pos (Name_Buffer (1))) * 64 +
714               Character'Pos (Name_Buffer (2))) mod Hash_Num;
715
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;
721
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;
728
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;
736
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;
745
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;
755
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;
766
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;
778
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;
791
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;
805
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;
820
821          --  Names longer than 12 characters are handled by taking the first
822          --  6 odd numbered characters and the last 6 even numbered characters.
823
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;
843
844    ----------------
845    -- Initialize --
846    ----------------
847
848    procedure Initialize is
849    begin
850       Name_Chars.Init;
851       Name_Entries.Init;
852
853       --  Initialize entries for one character names
854
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;
868
869       --  Clear hash table
870
871       for J in Hash_Index_Type loop
872          Hash_Table (J) := No_Name;
873       end loop;
874    end Initialize;
875
876    ----------------------
877    -- Is_Internal_Name --
878    ----------------------
879
880    --  Version taking an argument
881
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;
887
888    ----------------------
889    -- Is_Internal_Name --
890    ----------------------
891
892    --  Version taking its input from Name_Buffer
893
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;
900
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.
904
905          for J in reverse 1 .. Name_Len loop
906             if Is_OK_Internal_Letter (Name_Buffer (J)) then
907                return True;
908
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.
913
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;
922
923       return False;
924    end Is_Internal_Name;
925
926    ---------------------------
927    -- Is_OK_Internal_Letter --
928    ---------------------------
929
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;
939
940    ----------------------
941    -- Is_Operator_Name --
942    ----------------------
943
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;
951
952    --------------------
953    -- Length_Of_Name --
954    --------------------
955
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;
960
961    ----------
962    -- Lock --
963    ----------
964
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;
974
975    ------------------------
976    -- Name_Chars_Address --
977    ------------------------
978
979    function Name_Chars_Address return System.Address is
980    begin
981       return Name_Chars.Table (0)'Address;
982    end Name_Chars_Address;
983
984    ----------------
985    -- Name_Enter --
986    ----------------
987
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;
997
998       --  Set corresponding string entry in the Name_Chars table
999
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;
1004
1005       Name_Chars.Increment_Last;
1006       Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
1007
1008       return Name_Entries.Last;
1009    end Name_Enter;
1010
1011    --------------------------
1012    -- Name_Entries_Address --
1013    --------------------------
1014
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;
1019
1020    ------------------------
1021    -- Name_Entries_Count --
1022    ------------------------
1023
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;
1028
1029    ---------------
1030    -- Name_Find --
1031    ---------------
1032
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
1036
1037       S : Int;
1038       --  Pointer into string table
1039
1040       Hash_Index : Hash_Index_Type;
1041       --  Computed hash index
1042
1043    begin
1044       --  Quick handling for one character names
1045
1046       if Name_Len = 1 then
1047          return Name_Id (First_Name_Id + Character'Pos (Name_Buffer (1)));
1048
1049       --  Otherwise search hash table for existing matching entry
1050
1051       else
1052          Hash_Index := Namet.Hash;
1053          New_Id := Hash_Table (Hash_Index);
1054
1055          if New_Id = No_Name then
1056             Hash_Table (Hash_Index) := Name_Entries.Last + 1;
1057
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;
1065
1066                S := Name_Entries.Table (New_Id).Name_Chars_Index;
1067
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;
1073
1074                return New_Id;
1075
1076                --  Current entry in hash chain does not match
1077
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;
1086
1087             end loop Search;
1088          end if;
1089
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.
1093
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;
1101
1102          --  Set corresponding string entry in the Name_Chars table
1103
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;
1108
1109          Name_Chars.Increment_Last;
1110          Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
1111
1112          return Name_Entries.Last;
1113       end if;
1114    end Name_Find;
1115
1116    ----------------------
1117    -- Reset_Name_Table --
1118    ----------------------
1119
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;
1127
1128    --------------------------------
1129    -- Set_Character_Literal_Name --
1130    --------------------------------
1131
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;
1138
1139    -------------------------
1140    -- Set_Name_Table_Byte --
1141    -------------------------
1142
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;
1148
1149    -------------------------
1150    -- Set_Name_Table_Info --
1151    -------------------------
1152
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;
1158
1159    -----------------------------
1160    -- Store_Encoded_Character --
1161    -----------------------------
1162
1163    procedure Store_Encoded_Character (C : Char_Code) is
1164
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.
1168
1169       -------------------
1170       -- Set_Hex_Chars --
1171       -------------------
1172
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;
1181
1182    --  Start of processing for Store_Encoded_Character
1183
1184    begin
1185       Name_Len := Name_Len + 1;
1186
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;
1198
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);
1203
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;
1214
1215    --------------------------------------
1216    -- Strip_Qualification_And_Suffixes --
1217    --------------------------------------
1218
1219    procedure Strip_Qualification_And_Suffixes is
1220       J : Integer;
1221
1222    begin
1223       --  Strip package body qualification string off end
1224
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;
1230
1231          exit when Name_Buffer (J) /= 'b'
1232            and then Name_Buffer (J) /= 'n'
1233            and then Name_Buffer (J) /= 'p';
1234       end loop;
1235
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
1239
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;
1245
1246       else
1247          J := Name_Len - 1;
1248       end if;
1249
1250       --  Loop to search for rightmost __ or $ (homonym) separator
1251
1252       while J > 1 loop
1253
1254          --  If $ separator, homonym separator, so strip it and keep looking
1255
1256          if Name_Buffer (J) = '$' then
1257             Name_Len := J - 1;
1258             J := Name_Len - 1;
1259
1260          --  Else check for __ found
1261
1262          elsif Name_Buffer (J) = '_' and then Name_Buffer (J + 1) = '_' then
1263
1264             --  Found __ so see if digit follows, and if so, this is a
1265             --  homonym separator, so strip it and keep looking.
1266
1267             if Name_Buffer (J + 2) in '0' .. '9' then
1268                Name_Len := J - 1;
1269                J := Name_Len - 1;
1270
1271             --  If not a homonym separator, then we simply strip the
1272             --  separator and everything that precedes it, and we are done
1273
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;
1280
1281          else
1282             J := J - 1;
1283          end if;
1284       end loop;
1285    end Strip_Qualification_And_Suffixes;
1286
1287    ---------------
1288    -- Tree_Read --
1289    ---------------
1290
1291    procedure Tree_Read is
1292    begin
1293       Name_Chars.Tree_Read;
1294       Name_Entries.Tree_Read;
1295
1296       Tree_Read_Data
1297         (Hash_Table'Address,
1298          Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1299    end Tree_Read;
1300
1301    ----------------
1302    -- Tree_Write --
1303    ----------------
1304
1305    procedure Tree_Write is
1306    begin
1307       Name_Chars.Tree_Write;
1308       Name_Entries.Tree_Write;
1309
1310       Tree_Write_Data
1311         (Hash_Table'Address,
1312          Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1313    end Tree_Write;
1314
1315    ------------
1316    -- Unlock --
1317    ------------
1318
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;
1328
1329    --------
1330    -- wn --
1331    --------
1332
1333    procedure wn (Id : Name_Id) is
1334    begin
1335       Write_Name (Id);
1336       Write_Eol;
1337    end wn;
1338
1339    ----------------
1340    -- Write_Name --
1341    ----------------
1342
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;
1350
1351    ------------------------
1352    -- Write_Name_Decoded --
1353    ------------------------
1354
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;
1362
1363 end Namet;