OSDN Git Service

optimize
[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-2004 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 or Whhhh sequence and decoding it.
277
278          function Hex (N : Natural) return Natural;
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             --  W (wide character insertion)
305
306             elsif C = 'W'
307               and then Old < Name_Len
308               and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
309               and then Name_Buffer (Old + 1) /= '_'
310             then
311                Old := Old + 1;
312                Widechar.Set_Wide (Char_Code (Hex (4)), New_Buf, New_Len);
313
314             --  Any other character is copied unchanged
315
316             else
317                Insert_Character (C);
318                Old := Old + 1;
319             end if;
320          end Copy_One_Character;
321
322          ---------
323          -- Hex --
324          ---------
325
326          function Hex (N : Natural) return Natural is
327             T : Natural := 0;
328             C : Character;
329
330          begin
331             for J in 1 .. N loop
332                C := Name_Buffer (Old);
333                Old := Old + 1;
334
335                pragma Assert (C in '0' .. '9' or else C in 'a' .. 'f');
336
337                if C <= '9' then
338                   T := 16 * T + Character'Pos (C) - Character'Pos ('0');
339                else -- C in 'a' .. 'f'
340                   T := 16 * T + Character'Pos (C) - (Character'Pos ('a') - 10);
341                end if;
342             end loop;
343
344             return T;
345          end Hex;
346
347          ----------------------
348          -- Insert_Character --
349          ----------------------
350
351          procedure Insert_Character (C : Character) is
352          begin
353             New_Len := New_Len + 1;
354             New_Buf (New_Len) := C;
355          end Insert_Character;
356
357       --  Start of processing for Decode
358
359       begin
360          New_Len := 0;
361          Old := 1;
362
363          --  Loop through characters of name
364
365          while Old <= Name_Len loop
366
367             --  Case of character literal, put apostrophes around character
368
369             if Name_Buffer (Old) = 'Q'
370               and then Old < Name_Len
371             then
372                Old := Old + 1;
373                Insert_Character (''');
374                Copy_One_Character;
375                Insert_Character (''');
376
377             --  Case of operator name
378
379             elsif Name_Buffer (Old) = 'O'
380               and then Old < Name_Len
381               and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
382               and then Name_Buffer (Old + 1) /= '_'
383             then
384                Old := Old + 1;
385
386                declare
387                   --  This table maps the 2nd and 3rd characters of the name
388                   --  into the required output. Two blanks means leave the
389                   --  name alone
390
391                   Map : constant String :=
392                      "ab  " &               --  Oabs         => "abs"
393                      "ad+ " &               --  Oadd         => "+"
394                      "an  " &               --  Oand         => "and"
395                      "co& " &               --  Oconcat      => "&"
396                      "di/ " &               --  Odivide      => "/"
397                      "eq= " &               --  Oeq          => "="
398                      "ex**" &               --  Oexpon       => "**"
399                      "gt> " &               --  Ogt          => ">"
400                      "ge>=" &               --  Oge          => ">="
401                      "le<=" &               --  Ole          => "<="
402                      "lt< " &               --  Olt          => "<"
403                      "mo  " &               --  Omod         => "mod"
404                      "mu* " &               --  Omutliply    => "*"
405                      "ne/=" &               --  One          => "/="
406                      "no  " &               --  Onot         => "not"
407                      "or  " &               --  Oor          => "or"
408                      "re  " &               --  Orem         => "rem"
409                      "su- " &               --  Osubtract    => "-"
410                      "xo  ";                --  Oxor         => "xor"
411
412                   J : Integer;
413
414                begin
415                   Insert_Character ('"');
416
417                   --  Search the map. Note that this loop must terminate, if
418                   --  not we have some kind of internal error, and a constraint
419                   --  constraint error may be raised.
420
421                   J := Map'First;
422                   loop
423                      exit when Name_Buffer (Old) = Map (J)
424                        and then Name_Buffer (Old + 1) = Map (J + 1);
425                      J := J + 4;
426                   end loop;
427
428                   --  Special operator name
429
430                   if Map (J + 2) /= ' ' then
431                      Insert_Character (Map (J + 2));
432
433                      if Map (J + 3) /= ' ' then
434                         Insert_Character (Map (J + 3));
435                      end if;
436
437                      Insert_Character ('"');
438
439                      --  Skip past original operator name in input
440
441                      while Old <= Name_Len
442                        and then Name_Buffer (Old) in 'a' .. 'z'
443                      loop
444                         Old := Old + 1;
445                      end loop;
446
447                   --  For other operator names, leave them in lower case,
448                   --  surrounded by apostrophes
449
450                   else
451                      --  Copy original operator name from input to output
452
453                      while Old <= Name_Len
454                         and then Name_Buffer (Old) in 'a' .. 'z'
455                      loop
456                         Copy_One_Character;
457                      end loop;
458
459                      Insert_Character ('"');
460                   end if;
461                end;
462
463             --  Else copy one character and keep going
464
465             else
466                Copy_One_Character;
467             end if;
468          end loop;
469
470          --  Copy new buffer as result
471
472          Name_Len := New_Len;
473          Name_Buffer (1 .. New_Len) := New_Buf (1 .. New_Len);
474       end Decode;
475    end Get_Decoded_Name_String;
476
477    -------------------------------------------
478    -- Get_Decoded_Name_String_With_Brackets --
479    -------------------------------------------
480
481    procedure Get_Decoded_Name_String_With_Brackets (Id : Name_Id) is
482       P : Natural;
483
484    begin
485       --  Case of operator name, normal decoding is fine
486
487       if Name_Buffer (1) = 'O' then
488          Get_Decoded_Name_String (Id);
489
490       --  For character literals, normal decoding is fine
491
492       elsif Name_Buffer (1) = 'Q' then
493          Get_Decoded_Name_String (Id);
494
495       --  Only remaining issue is U/W sequences
496
497       else
498          Get_Name_String (Id);
499
500          P := 1;
501          while P < Name_Len loop
502             if Name_Buffer (P + 1) in 'A' .. 'Z' then
503                P := P + 1;
504
505             elsif Name_Buffer (P) = 'U' then
506                for J in reverse P + 3 .. P + Name_Len loop
507                   Name_Buffer (J + 3) := Name_Buffer (J);
508                end loop;
509
510                Name_Len := Name_Len + 3;
511                Name_Buffer (P + 3) := Name_Buffer (P + 2);
512                Name_Buffer (P + 2) := Name_Buffer (P + 1);
513                Name_Buffer (P)     := '[';
514                Name_Buffer (P + 1) := '"';
515                Name_Buffer (P + 4) := '"';
516                Name_Buffer (P + 5) := ']';
517                P := P + 6;
518
519             elsif Name_Buffer (P) = 'W' then
520                Name_Buffer (P + 8 .. P + Name_Len + 5) :=
521                  Name_Buffer (P + 5 .. Name_Len);
522                Name_Buffer (P + 5) := Name_Buffer (P + 4);
523                Name_Buffer (P + 4) := Name_Buffer (P + 3);
524                Name_Buffer (P + 3) := Name_Buffer (P + 2);
525                Name_Buffer (P + 2) := Name_Buffer (P + 1);
526                Name_Buffer (P)     := '[';
527                Name_Buffer (P + 1) := '"';
528                Name_Buffer (P + 6) := '"';
529                Name_Buffer (P + 7) := ']';
530                Name_Len := Name_Len + 5;
531                P := P + 8;
532
533             else
534                P := P + 1;
535             end if;
536          end loop;
537       end if;
538    end Get_Decoded_Name_String_With_Brackets;
539
540    ------------------------
541    -- Get_Last_Two_Chars --
542    ------------------------
543
544    procedure Get_Last_Two_Chars (N : Name_Id; C1, C2 : out Character) is
545       NE  : Name_Entry renames Name_Entries.Table (N);
546       NEL : constant Int := Int (NE.Name_Len);
547
548    begin
549       if NEL >= 2 then
550          C1 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 1);
551          C2 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 0);
552       else
553          C1 := ASCII.NUL;
554          C2 := ASCII.NUL;
555       end if;
556    end Get_Last_Two_Chars;
557
558    ---------------------
559    -- Get_Name_String --
560    ---------------------
561
562    --  Procedure version leaving result in Name_Buffer, length in Name_Len
563
564    procedure Get_Name_String (Id : Name_Id) is
565       S : Int;
566
567    begin
568       pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
569
570       S := Name_Entries.Table (Id).Name_Chars_Index;
571       Name_Len := Natural (Name_Entries.Table (Id).Name_Len);
572
573       for J in 1 .. Name_Len loop
574          Name_Buffer (J) := Name_Chars.Table (S + Int (J));
575       end loop;
576    end Get_Name_String;
577
578    ---------------------
579    -- Get_Name_String --
580    ---------------------
581
582    --  Function version returning a string
583
584    function Get_Name_String (Id : Name_Id) return String is
585       S : Int;
586
587    begin
588       pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
589       S := Name_Entries.Table (Id).Name_Chars_Index;
590
591       declare
592          R : String (1 .. Natural (Name_Entries.Table (Id).Name_Len));
593
594       begin
595          for J in R'Range loop
596             R (J) := Name_Chars.Table (S + Int (J));
597          end loop;
598
599          return R;
600       end;
601    end Get_Name_String;
602
603    --------------------------------
604    -- Get_Name_String_And_Append --
605    --------------------------------
606
607    procedure Get_Name_String_And_Append (Id : Name_Id) is
608       S : Int;
609
610    begin
611       pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
612
613       S := Name_Entries.Table (Id).Name_Chars_Index;
614
615       for J in 1 .. Natural (Name_Entries.Table (Id).Name_Len) loop
616          Name_Len := Name_Len + 1;
617          Name_Buffer (Name_Len) := Name_Chars.Table (S + Int (J));
618       end loop;
619    end Get_Name_String_And_Append;
620
621    -------------------------
622    -- Get_Name_Table_Byte --
623    -------------------------
624
625    function Get_Name_Table_Byte (Id : Name_Id) return Byte is
626    begin
627       pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
628       return Name_Entries.Table (Id).Byte_Info;
629    end Get_Name_Table_Byte;
630
631    -------------------------
632    -- Get_Name_Table_Info --
633    -------------------------
634
635    function Get_Name_Table_Info (Id : Name_Id) return Int is
636    begin
637       pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
638       return Name_Entries.Table (Id).Int_Info;
639    end Get_Name_Table_Info;
640
641    -----------------------------------------
642    -- Get_Unqualified_Decoded_Name_String --
643    -----------------------------------------
644
645    procedure Get_Unqualified_Decoded_Name_String (Id : Name_Id) is
646    begin
647       Get_Decoded_Name_String (Id);
648       Strip_Qualification_And_Suffixes;
649    end Get_Unqualified_Decoded_Name_String;
650
651    ---------------------------------
652    -- Get_Unqualified_Name_String --
653    ---------------------------------
654
655    procedure Get_Unqualified_Name_String (Id : Name_Id) is
656    begin
657       Get_Name_String (Id);
658       Strip_Qualification_And_Suffixes;
659    end Get_Unqualified_Name_String;
660
661    ----------
662    -- Hash --
663    ----------
664
665    function Hash return Hash_Index_Type is
666    begin
667       --  For the cases of 1-12 characters, all characters participate in the
668       --  hash. The positioning is randomized, with the bias that characters
669       --  later on participate fully (i.e. are added towards the right side).
670
671       case Name_Len is
672
673          when 0 =>
674             return 0;
675
676          when 1 =>
677             return
678                Character'Pos (Name_Buffer (1));
679
680          when 2 =>
681             return ((
682               Character'Pos (Name_Buffer (1))) * 64 +
683               Character'Pos (Name_Buffer (2))) mod Hash_Num;
684
685          when 3 =>
686             return (((
687               Character'Pos (Name_Buffer (1))) * 16 +
688               Character'Pos (Name_Buffer (3))) * 16 +
689               Character'Pos (Name_Buffer (2))) mod Hash_Num;
690
691          when 4 =>
692             return ((((
693               Character'Pos (Name_Buffer (1))) * 8 +
694               Character'Pos (Name_Buffer (2))) * 8 +
695               Character'Pos (Name_Buffer (3))) * 8 +
696               Character'Pos (Name_Buffer (4))) mod Hash_Num;
697
698          when 5 =>
699             return (((((
700               Character'Pos (Name_Buffer (4))) * 8 +
701               Character'Pos (Name_Buffer (1))) * 4 +
702               Character'Pos (Name_Buffer (3))) * 4 +
703               Character'Pos (Name_Buffer (5))) * 8 +
704               Character'Pos (Name_Buffer (2))) mod Hash_Num;
705
706          when 6 =>
707             return ((((((
708               Character'Pos (Name_Buffer (5))) * 4 +
709               Character'Pos (Name_Buffer (1))) * 4 +
710               Character'Pos (Name_Buffer (4))) * 4 +
711               Character'Pos (Name_Buffer (2))) * 4 +
712               Character'Pos (Name_Buffer (6))) * 4 +
713               Character'Pos (Name_Buffer (3))) mod Hash_Num;
714
715          when 7 =>
716             return (((((((
717               Character'Pos (Name_Buffer (4))) * 4 +
718               Character'Pos (Name_Buffer (3))) * 4 +
719               Character'Pos (Name_Buffer (1))) * 4 +
720               Character'Pos (Name_Buffer (2))) * 2 +
721               Character'Pos (Name_Buffer (5))) * 2 +
722               Character'Pos (Name_Buffer (7))) * 2 +
723               Character'Pos (Name_Buffer (6))) mod Hash_Num;
724
725          when 8 =>
726             return ((((((((
727               Character'Pos (Name_Buffer (2))) * 4 +
728               Character'Pos (Name_Buffer (1))) * 4 +
729               Character'Pos (Name_Buffer (3))) * 2 +
730               Character'Pos (Name_Buffer (5))) * 2 +
731               Character'Pos (Name_Buffer (7))) * 2 +
732               Character'Pos (Name_Buffer (6))) * 2 +
733               Character'Pos (Name_Buffer (4))) * 2 +
734               Character'Pos (Name_Buffer (8))) mod Hash_Num;
735
736          when 9 =>
737             return (((((((((
738               Character'Pos (Name_Buffer (2))) * 4 +
739               Character'Pos (Name_Buffer (1))) * 4 +
740               Character'Pos (Name_Buffer (3))) * 4 +
741               Character'Pos (Name_Buffer (4))) * 2 +
742               Character'Pos (Name_Buffer (8))) * 2 +
743               Character'Pos (Name_Buffer (7))) * 2 +
744               Character'Pos (Name_Buffer (5))) * 2 +
745               Character'Pos (Name_Buffer (6))) * 2 +
746               Character'Pos (Name_Buffer (9))) mod Hash_Num;
747
748          when 10 =>
749             return ((((((((((
750               Character'Pos (Name_Buffer (01))) * 2 +
751               Character'Pos (Name_Buffer (02))) * 2 +
752               Character'Pos (Name_Buffer (08))) * 2 +
753               Character'Pos (Name_Buffer (03))) * 2 +
754               Character'Pos (Name_Buffer (04))) * 2 +
755               Character'Pos (Name_Buffer (09))) * 2 +
756               Character'Pos (Name_Buffer (06))) * 2 +
757               Character'Pos (Name_Buffer (05))) * 2 +
758               Character'Pos (Name_Buffer (07))) * 2 +
759               Character'Pos (Name_Buffer (10))) mod Hash_Num;
760
761          when 11 =>
762             return (((((((((((
763               Character'Pos (Name_Buffer (05))) * 2 +
764               Character'Pos (Name_Buffer (01))) * 2 +
765               Character'Pos (Name_Buffer (06))) * 2 +
766               Character'Pos (Name_Buffer (09))) * 2 +
767               Character'Pos (Name_Buffer (07))) * 2 +
768               Character'Pos (Name_Buffer (03))) * 2 +
769               Character'Pos (Name_Buffer (08))) * 2 +
770               Character'Pos (Name_Buffer (02))) * 2 +
771               Character'Pos (Name_Buffer (10))) * 2 +
772               Character'Pos (Name_Buffer (04))) * 2 +
773               Character'Pos (Name_Buffer (11))) mod Hash_Num;
774
775          when 12 =>
776             return ((((((((((((
777               Character'Pos (Name_Buffer (03))) * 2 +
778               Character'Pos (Name_Buffer (02))) * 2 +
779               Character'Pos (Name_Buffer (05))) * 2 +
780               Character'Pos (Name_Buffer (01))) * 2 +
781               Character'Pos (Name_Buffer (06))) * 2 +
782               Character'Pos (Name_Buffer (04))) * 2 +
783               Character'Pos (Name_Buffer (08))) * 2 +
784               Character'Pos (Name_Buffer (11))) * 2 +
785               Character'Pos (Name_Buffer (07))) * 2 +
786               Character'Pos (Name_Buffer (09))) * 2 +
787               Character'Pos (Name_Buffer (10))) * 2 +
788               Character'Pos (Name_Buffer (12))) mod Hash_Num;
789
790          --  Names longer than 12 characters are handled by taking the first
791          --  6 odd numbered characters and the last 6 even numbered characters.
792
793          when others => declare
794                Even_Name_Len : constant Integer := (Name_Len) / 2 * 2;
795          begin
796             return ((((((((((((
797               Character'Pos (Name_Buffer (01))) * 2 +
798               Character'Pos (Name_Buffer (Even_Name_Len - 10))) * 2 +
799               Character'Pos (Name_Buffer (03))) * 2 +
800               Character'Pos (Name_Buffer (Even_Name_Len - 08))) * 2 +
801               Character'Pos (Name_Buffer (05))) * 2 +
802               Character'Pos (Name_Buffer (Even_Name_Len - 06))) * 2 +
803               Character'Pos (Name_Buffer (07))) * 2 +
804               Character'Pos (Name_Buffer (Even_Name_Len - 04))) * 2 +
805               Character'Pos (Name_Buffer (09))) * 2 +
806               Character'Pos (Name_Buffer (Even_Name_Len - 02))) * 2 +
807               Character'Pos (Name_Buffer (11))) * 2 +
808               Character'Pos (Name_Buffer (Even_Name_Len))) mod Hash_Num;
809          end;
810       end case;
811    end Hash;
812
813    ----------------
814    -- Initialize --
815    ----------------
816
817    procedure Initialize is
818    begin
819       Name_Chars.Init;
820       Name_Entries.Init;
821
822       --  Initialize entries for one character names
823
824       for C in Character loop
825          Name_Entries.Increment_Last;
826          Name_Entries.Table (Name_Entries.Last).Name_Chars_Index :=
827            Name_Chars.Last;
828          Name_Entries.Table (Name_Entries.Last).Name_Len  := 1;
829          Name_Entries.Table (Name_Entries.Last).Hash_Link := No_Name;
830          Name_Entries.Table (Name_Entries.Last).Int_Info  := 0;
831          Name_Entries.Table (Name_Entries.Last).Byte_Info := 0;
832          Name_Chars.Increment_Last;
833          Name_Chars.Table (Name_Chars.Last) := C;
834          Name_Chars.Increment_Last;
835          Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
836       end loop;
837
838       --  Clear hash table
839
840       for J in Hash_Index_Type loop
841          Hash_Table (J) := No_Name;
842       end loop;
843    end Initialize;
844
845    ----------------------
846    -- Is_Internal_Name --
847    ----------------------
848
849    --  Version taking an argument
850
851    function Is_Internal_Name (Id : Name_Id) return Boolean is
852    begin
853       Get_Name_String (Id);
854       return Is_Internal_Name;
855    end Is_Internal_Name;
856
857    ----------------------
858    -- Is_Internal_Name --
859    ----------------------
860
861    --  Version taking its input from Name_Buffer
862
863    function Is_Internal_Name return Boolean is
864    begin
865       if Name_Buffer (1) = '_'
866         or else Name_Buffer (Name_Len) = '_'
867       then
868          return True;
869
870       else
871          --  Test backwards, because we only want to test the last entity
872          --  name if the name we have is qualified with other entities.
873
874          for J in reverse 1 .. Name_Len loop
875             if Is_OK_Internal_Letter (Name_Buffer (J)) then
876                return True;
877
878             --  Quit if we come to terminating double underscore (note that
879             --  if the current character is an underscore, we know that
880             --  there is a previous character present, since we already
881             --  filtered out the case of Name_Buffer (1) = '_' above.
882
883             elsif Name_Buffer (J) = '_'
884               and then Name_Buffer (J - 1) = '_'
885               and then Name_Buffer (J - 2) /= '_'
886             then
887                return False;
888             end if;
889          end loop;
890       end if;
891
892       return False;
893    end Is_Internal_Name;
894
895    ---------------------------
896    -- Is_OK_Internal_Letter --
897    ---------------------------
898
899    function Is_OK_Internal_Letter (C : Character) return Boolean is
900    begin
901       return C in 'A' .. 'Z'
902         and then C /= 'O'
903         and then C /= 'Q'
904         and then C /= 'U'
905         and then C /= 'W'
906         and then C /= 'X';
907    end Is_OK_Internal_Letter;
908
909    ----------------------
910    -- Is_Operator_Name --
911    ----------------------
912
913    function Is_Operator_Name (Id : Name_Id) return Boolean is
914       S : Int;
915    begin
916       pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
917       S := Name_Entries.Table (Id).Name_Chars_Index;
918       return Name_Chars.Table (S + 1) = 'O';
919    end Is_Operator_Name;
920
921    --------------------
922    -- Length_Of_Name --
923    --------------------
924
925    function Length_Of_Name (Id : Name_Id) return Nat is
926    begin
927       return Int (Name_Entries.Table (Id).Name_Len);
928    end Length_Of_Name;
929
930    ----------
931    -- Lock --
932    ----------
933
934    procedure Lock is
935    begin
936       Name_Chars.Set_Last (Name_Chars.Last + Name_Chars_Reserve);
937       Name_Entries.Set_Last (Name_Entries.Last + Name_Entries_Reserve);
938       Name_Chars.Locked := True;
939       Name_Entries.Locked := True;
940       Name_Chars.Release;
941       Name_Entries.Release;
942    end Lock;
943
944    ------------------------
945    -- Name_Chars_Address --
946    ------------------------
947
948    function Name_Chars_Address return System.Address is
949    begin
950       return Name_Chars.Table (0)'Address;
951    end Name_Chars_Address;
952
953    ----------------
954    -- Name_Enter --
955    ----------------
956
957    function Name_Enter return Name_Id is
958    begin
959       Name_Entries.Increment_Last;
960       Name_Entries.Table (Name_Entries.Last).Name_Chars_Index :=
961         Name_Chars.Last;
962       Name_Entries.Table (Name_Entries.Last).Name_Len  := Short (Name_Len);
963       Name_Entries.Table (Name_Entries.Last).Hash_Link := No_Name;
964       Name_Entries.Table (Name_Entries.Last).Int_Info  := 0;
965       Name_Entries.Table (Name_Entries.Last).Byte_Info := 0;
966
967       --  Set corresponding string entry in the Name_Chars table
968
969       for J in 1 .. Name_Len loop
970          Name_Chars.Increment_Last;
971          Name_Chars.Table (Name_Chars.Last) := Name_Buffer (J);
972       end loop;
973
974       Name_Chars.Increment_Last;
975       Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
976
977       return Name_Entries.Last;
978    end Name_Enter;
979
980    --------------------------
981    -- Name_Entries_Address --
982    --------------------------
983
984    function Name_Entries_Address return System.Address is
985    begin
986       return Name_Entries.Table (First_Name_Id)'Address;
987    end Name_Entries_Address;
988
989    ------------------------
990    -- Name_Entries_Count --
991    ------------------------
992
993    function Name_Entries_Count return Nat is
994    begin
995       return Int (Name_Entries.Last - Name_Entries.First + 1);
996    end Name_Entries_Count;
997
998    ---------------
999    -- Name_Find --
1000    ---------------
1001
1002    function Name_Find return Name_Id is
1003       New_Id : Name_Id;
1004       --  Id of entry in hash search, and value to be returned
1005
1006       S : Int;
1007       --  Pointer into string table
1008
1009       Hash_Index : Hash_Index_Type;
1010       --  Computed hash index
1011
1012    begin
1013       --  Quick handling for one character names
1014
1015       if Name_Len = 1 then
1016          return Name_Id (First_Name_Id + Character'Pos (Name_Buffer (1)));
1017
1018       --  Otherwise search hash table for existing matching entry
1019
1020       else
1021          Hash_Index := Namet.Hash;
1022          New_Id := Hash_Table (Hash_Index);
1023
1024          if New_Id = No_Name then
1025             Hash_Table (Hash_Index) := Name_Entries.Last + 1;
1026
1027          else
1028             Search : loop
1029                if Name_Len /=
1030                  Integer (Name_Entries.Table (New_Id).Name_Len)
1031                then
1032                   goto No_Match;
1033                end if;
1034
1035                S := Name_Entries.Table (New_Id).Name_Chars_Index;
1036
1037                for J in 1 .. Name_Len loop
1038                   if Name_Chars.Table (S + Int (J)) /= Name_Buffer (J) then
1039                      goto No_Match;
1040                   end if;
1041                end loop;
1042
1043                return New_Id;
1044
1045                --  Current entry in hash chain does not match
1046
1047                <<No_Match>>
1048                   if Name_Entries.Table (New_Id).Hash_Link /= No_Name then
1049                      New_Id := Name_Entries.Table (New_Id).Hash_Link;
1050                   else
1051                      Name_Entries.Table (New_Id).Hash_Link :=
1052                        Name_Entries.Last + 1;
1053                      exit Search;
1054                   end if;
1055
1056             end loop Search;
1057          end if;
1058
1059          --  We fall through here only if a matching entry was not found in the
1060          --  hash table. We now create a new entry in the names table. The hash
1061          --  link pointing to the new entry (Name_Entries.Last+1) has been set.
1062
1063          Name_Entries.Increment_Last;
1064          Name_Entries.Table (Name_Entries.Last).Name_Chars_Index :=
1065            Name_Chars.Last;
1066          Name_Entries.Table (Name_Entries.Last).Name_Len  := Short (Name_Len);
1067          Name_Entries.Table (Name_Entries.Last).Hash_Link := No_Name;
1068          Name_Entries.Table (Name_Entries.Last).Int_Info  := 0;
1069          Name_Entries.Table (Name_Entries.Last).Byte_Info := 0;
1070
1071          --  Set corresponding string entry in the Name_Chars table
1072
1073          for J in 1 .. Name_Len loop
1074             Name_Chars.Increment_Last;
1075             Name_Chars.Table (Name_Chars.Last) := Name_Buffer (J);
1076          end loop;
1077
1078          Name_Chars.Increment_Last;
1079          Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
1080
1081          return Name_Entries.Last;
1082       end if;
1083    end Name_Find;
1084
1085    ----------------------
1086    -- Reset_Name_Table --
1087    ----------------------
1088
1089    procedure Reset_Name_Table is
1090    begin
1091       for J in First_Name_Id .. Name_Entries.Last loop
1092          Name_Entries.Table (J).Int_Info  := 0;
1093          Name_Entries.Table (J).Byte_Info := 0;
1094       end loop;
1095    end Reset_Name_Table;
1096
1097    --------------------------------
1098    -- Set_Character_Literal_Name --
1099    --------------------------------
1100
1101    procedure Set_Character_Literal_Name (C : Char_Code) is
1102    begin
1103       Name_Buffer (1) := 'Q';
1104       Name_Len := 1;
1105       Store_Encoded_Character (C);
1106    end Set_Character_Literal_Name;
1107
1108    -------------------------
1109    -- Set_Name_Table_Byte --
1110    -------------------------
1111
1112    procedure Set_Name_Table_Byte (Id : Name_Id; Val : Byte) is
1113    begin
1114       pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
1115       Name_Entries.Table (Id).Byte_Info := Val;
1116    end Set_Name_Table_Byte;
1117
1118    -------------------------
1119    -- Set_Name_Table_Info --
1120    -------------------------
1121
1122    procedure Set_Name_Table_Info (Id : Name_Id; Val : Int) is
1123    begin
1124       pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
1125       Name_Entries.Table (Id).Int_Info := Val;
1126    end Set_Name_Table_Info;
1127
1128    -----------------------------
1129    -- Store_Encoded_Character --
1130    -----------------------------
1131
1132    procedure Store_Encoded_Character (C : Char_Code) is
1133
1134       procedure Set_Hex_Chars (N : Natural);
1135       --  Stores given value, which is in the range 0 .. 255, as two hex
1136       --  digits (using lower case a-f) in Name_Buffer, incrementing Name_Len
1137
1138       procedure Set_Hex_Chars (N : Natural) is
1139          Hexd : constant String := "0123456789abcdef";
1140
1141       begin
1142          Name_Buffer (Name_Len + 1) := Hexd (N / 16 + 1);
1143          Name_Buffer (Name_Len + 2) := Hexd (N mod 16 + 1);
1144          Name_Len := Name_Len + 2;
1145       end Set_Hex_Chars;
1146
1147    begin
1148       Name_Len := Name_Len + 1;
1149
1150       if In_Character_Range (C) then
1151          declare
1152             CC : constant Character := Get_Character (C);
1153          begin
1154             if CC in 'a' .. 'z' or else CC in '0' .. '9' then
1155                Name_Buffer (Name_Len) := CC;
1156             else
1157                Name_Buffer (Name_Len) := 'U';
1158                Set_Hex_Chars (Natural (C));
1159             end if;
1160          end;
1161
1162       else
1163          Name_Buffer (Name_Len) := 'W';
1164          Set_Hex_Chars (Natural (C) / 256);
1165          Set_Hex_Chars (Natural (C) mod 256);
1166       end if;
1167
1168    end Store_Encoded_Character;
1169
1170    --------------------------------------
1171    -- Strip_Qualification_And_Suffixes --
1172    --------------------------------------
1173
1174    procedure Strip_Qualification_And_Suffixes is
1175       J : Integer;
1176
1177    begin
1178       --  Strip package body qualification string off end
1179
1180       for J in reverse 2 .. Name_Len loop
1181          if Name_Buffer (J) = 'X' then
1182             Name_Len := J - 1;
1183             exit;
1184          end if;
1185
1186          exit when Name_Buffer (J) /= 'b'
1187            and then Name_Buffer (J) /= 'n'
1188            and then Name_Buffer (J) /= 'p';
1189       end loop;
1190
1191       --  Find rightmost __ or $ separator if one exists. First we position
1192       --  to start the search. If we have a character constant, position
1193       --  just before it, otherwise position to last character but one
1194
1195       if Name_Buffer (Name_Len) = ''' then
1196          J := Name_Len - 2;
1197          while J > 0 and then Name_Buffer (J) /= ''' loop
1198             J := J - 1;
1199          end loop;
1200
1201       else
1202          J := Name_Len - 1;
1203       end if;
1204
1205       --  Loop to search for rightmost __ or $ (homonym) separator
1206
1207       while J > 1 loop
1208
1209          --  If $ separator, homonym separator, so strip it and keep looking
1210
1211          if Name_Buffer (J) = '$' then
1212             Name_Len := J - 1;
1213             J := Name_Len - 1;
1214
1215          --  Else check for __ found
1216
1217          elsif Name_Buffer (J) = '_' and then Name_Buffer (J + 1) = '_' then
1218
1219             --  Found __ so see if digit follows, and if so, this is a
1220             --  homonym separator, so strip it and keep looking.
1221
1222             if Name_Buffer (J + 2) in '0' .. '9' then
1223                Name_Len := J - 1;
1224                J := Name_Len - 1;
1225
1226             --  If not a homonym separator, then we simply strip the
1227             --  separator and everything that precedes it, and we are done
1228
1229             else
1230                Name_Buffer (1 .. Name_Len - J - 1) :=
1231                  Name_Buffer (J + 2 .. Name_Len);
1232                Name_Len := Name_Len - J - 1;
1233                exit;
1234             end if;
1235
1236          else
1237             J := J - 1;
1238          end if;
1239       end loop;
1240    end Strip_Qualification_And_Suffixes;
1241
1242    ---------------
1243    -- Tree_Read --
1244    ---------------
1245
1246    procedure Tree_Read is
1247    begin
1248       Name_Chars.Tree_Read;
1249       Name_Entries.Tree_Read;
1250
1251       Tree_Read_Data
1252         (Hash_Table'Address,
1253          Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1254    end Tree_Read;
1255
1256    ----------------
1257    -- Tree_Write --
1258    ----------------
1259
1260    procedure Tree_Write is
1261    begin
1262       Name_Chars.Tree_Write;
1263       Name_Entries.Tree_Write;
1264
1265       Tree_Write_Data
1266         (Hash_Table'Address,
1267          Hash_Table'Length * (Hash_Table'Component_Size / Storage_Unit));
1268    end Tree_Write;
1269
1270    ------------
1271    -- Unlock --
1272    ------------
1273
1274    procedure Unlock is
1275    begin
1276       Name_Chars.Set_Last (Name_Chars.Last - Name_Chars_Reserve);
1277       Name_Entries.Set_Last (Name_Entries.Last - Name_Entries_Reserve);
1278       Name_Chars.Locked := False;
1279       Name_Entries.Locked := False;
1280       Name_Chars.Release;
1281       Name_Entries.Release;
1282    end Unlock;
1283
1284    --------
1285    -- wn --
1286    --------
1287
1288    procedure wn (Id : Name_Id) is
1289    begin
1290       Write_Name (Id);
1291       Write_Eol;
1292    end wn;
1293
1294    ----------------
1295    -- Write_Name --
1296    ----------------
1297
1298    procedure Write_Name (Id : Name_Id) is
1299    begin
1300       if Id >= First_Name_Id then
1301          Get_Name_String (Id);
1302          Write_Str (Name_Buffer (1 .. Name_Len));
1303       end if;
1304    end Write_Name;
1305
1306    ------------------------
1307    -- Write_Name_Decoded --
1308    ------------------------
1309
1310    procedure Write_Name_Decoded (Id : Name_Id) is
1311    begin
1312       if Id >= First_Name_Id then
1313          Get_Decoded_Name_String (Id);
1314          Write_Str (Name_Buffer (1 .. Name_Len));
1315       end if;
1316    end Write_Name_Decoded;
1317
1318 end Namet;