OSDN Git Service

2007-04-20 Robert Dewar <dewar@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / namet.adb
index 4fe8c1a..0f4074c 100644 (file)
@@ -6,9 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---                            $Revision: 1.86 $
---                                                                          --
---          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
+--          Copyright (C) 1992-2006, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -18,8 +16,8 @@
 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
 -- for  more details.  You should have  received  a copy of the GNU General --
 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
--- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
--- MA 02111-1307, USA.                                                      --
+-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
+-- Boston, MA 02110-1301, USA.                                              --
 --                                                                          --
 -- As a special exception,  if other files  instantiate  generics from this --
 -- unit, or you link  this unit with other files  to produce an executable, --
@@ -29,7 +27,7 @@
 -- covered by the  GNU Public License.                                      --
 --                                                                          --
 -- GNAT was originally developed  by the GNAT team at  New York University. --
--- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
+-- Extensive contributions were provided by Ada Core Technologies Inc.      --
 --                                                                          --
 ------------------------------------------------------------------------------
 
@@ -38,6 +36,7 @@
 --  which is created manually from namet.ads and namet.adb.
 
 with Debug;    use Debug;
+with Opt;      use Opt;
 with Output;   use Output;
 with Tree_IO;  use Tree_IO;
 with Widechar; use Widechar;
@@ -78,7 +77,7 @@ package body Namet is
    pragma Inline (Hash);
    --  Compute hash code for name stored in Name_Buffer (length in Name_Len)
 
-   procedure Strip_Qualification_And_Package_Body_Suffix;
+   procedure Strip_Qualification_And_Suffixes;
    --  Given an encoded entity name in Name_Buffer, remove package body
    --  suffix as described for Strip_Package_Body_Suffix, and also remove
    --  all qualification, i.e. names followed by two underscores. The
@@ -140,18 +139,17 @@ package body Namet is
 
    begin
       if Debug_Flag_H then
-
          for J in F'Range loop
             F (J) := 0;
          end loop;
 
-         for I in Hash_Index_Type loop
-            if Hash_Table (I) = No_Name then
+         for J in Hash_Index_Type loop
+            if Hash_Table (J) = No_Name then
                F (0) := F (0) + 1;
 
             else
                Write_Str ("Hash_Table (");
-               Write_Int (Int (I));
+               Write_Int (Int (J));
                Write_Str (") has ");
 
                declare
@@ -161,7 +159,7 @@ package body Namet is
 
                begin
                   C := 0;
-                  N := Hash_Table (I);
+                  N := Hash_Table (J);
 
                   while N /= No_Name loop
                      N := Name_Entries.Table (N).Hash_Link;
@@ -178,7 +176,7 @@ package body Namet is
                      F (Max_Chain_Length) := F (Max_Chain_Length) + 1;
                   end if;
 
-                  N := Hash_Table (I);
+                  N := Hash_Table (J);
 
                   while N /= No_Name loop
                      S := Name_Entries.Table (N).Name_Chars_Index;
@@ -197,27 +195,27 @@ package body Namet is
 
          Write_Eol;
 
-         for I in Int range 0 .. Max_Chain_Length loop
-            if F (I) /= 0 then
+         for J in Int range 0 .. Max_Chain_Length loop
+            if F (J) /= 0 then
                Write_Str ("Number of hash chains of length ");
 
-               if I < 10 then
+               if J < 10 then
                   Write_Char (' ');
                end if;
 
-               Write_Int (I);
+               Write_Int (J);
 
-               if I = Max_Chain_Length then
+               if J = Max_Chain_Length then
                   Write_Str (" or greater");
                end if;
 
                Write_Str (" = ");
-               Write_Int (F (I));
+               Write_Int (F (J));
                Write_Eol;
 
-               if I /= 0 then
-                  Nsyms := Nsyms + F (I);
-                  Probes := Probes + F (I) * (1 + I) * 100;
+               if J /= 0 then
+                  Nsyms := Nsyms + F (J);
+                  Probes := Probes + F (J) * (1 + J) * 100;
                end if;
             end if;
          end loop;
@@ -246,11 +244,18 @@ package body Namet is
    begin
       Get_Name_String (Id);
 
+      --  Skip scan if we already know there are no encodings
+
+      if Name_Entries.Table (Id).Name_Has_No_Encodings then
+         return;
+      end if;
+
       --  Quick loop to see if there is anything special to do
 
       P := 1;
       loop
          if P = Name_Len then
+            Name_Entries.Table (Id).Name_Has_No_Encodings := True;
             return;
 
          else
@@ -268,45 +273,86 @@ package body Namet is
 
       --  Here we have at least some encoding that we must decode
 
-      --  Here we have to decode one or more Uhh or Whhhh sequences
-
-      declare
+      Decode : declare
          New_Len : Natural;
          Old     : Positive;
          New_Buf : String (1 .. Name_Buffer'Last);
 
-         procedure Insert_Character (C : Character);
-         --  Insert a new character into output decoded name
-
          procedure Copy_One_Character;
          --  Copy a character from Name_Buffer to New_Buf. Includes case
-         --  of copying a Uhh or Whhhh sequence and decoding it.
+         --  of copying a Uhh,Whhhh,WWhhhhhhhh sequence and decoding it.
 
-         function Hex (N : Natural) return Natural;
+         function Hex (N : Natural) return Word;
          --  Scans past N digits using Old pointer and returns hex value
 
+         procedure Insert_Character (C : Character);
+         --  Insert a new character into output decoded name
+
+         ------------------------
+         -- Copy_One_Character --
+         ------------------------
+
          procedure Copy_One_Character is
             C : Character;
 
          begin
             C := Name_Buffer (Old);
 
-            if C = 'U' then
+            --  U (upper half insertion case)
+
+            if C = 'U'
+              and then Old < Name_Len
+              and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
+              and then Name_Buffer (Old + 1) /= '_'
+            then
                Old := Old + 1;
-               Insert_Character (Character'Val (Hex (2)));
 
-            elsif C = 'W' then
+               --  If we have upper half encoding, then we have to set an
+               --  appropriate wide character sequence for this character.
+
+               if Upper_Half_Encoding then
+                  Widechar.Set_Wide (Char_Code (Hex (2)), New_Buf, New_Len);
+
+                  --  For other encoding methods, upper half characters can
+                  --  simply use their normal representation.
+
+               else
+                  Insert_Character (Character'Val (Hex (2)));
+               end if;
+
+            --  WW (wide wide character insertion)
+
+            elsif C = 'W'
+              and then Old < Name_Len
+              and then Name_Buffer (Old + 1) = 'W'
+            then
+               Old := Old + 2;
+               Widechar.Set_Wide (Char_Code (Hex (8)), New_Buf, New_Len);
+
+            --  W (wide character insertion)
+
+            elsif C = 'W'
+              and then Old < Name_Len
+              and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
+              and then Name_Buffer (Old + 1) /= '_'
+            then
                Old := Old + 1;
                Widechar.Set_Wide (Char_Code (Hex (4)), New_Buf, New_Len);
 
+            --  Any other character is copied unchanged
+
             else
-               Insert_Character (Name_Buffer (Old));
+               Insert_Character (C);
                Old := Old + 1;
             end if;
          end Copy_One_Character;
 
-         function Hex (N : Natural) return Natural is
-            T : Natural := 0;
+         ---------
+         -- Hex --
+         ---------
+
+         function Hex (N : Natural) return Word is
+            T : Word := 0;
             C : Character;
 
          begin
@@ -326,13 +372,17 @@ package body Namet is
             return T;
          end Hex;
 
+         ----------------------
+         -- Insert_Character --
+         ----------------------
+
          procedure Insert_Character (C : Character) is
          begin
             New_Len := New_Len + 1;
             New_Buf (New_Len) := C;
          end Insert_Character;
 
-      --  Actual decoding processing
+      --  Start of processing for Decode
 
       begin
          New_Len := 0;
@@ -344,7 +394,9 @@ package body Namet is
 
             --  Case of character literal, put apostrophes around character
 
-            if Name_Buffer (Old) = 'Q' then
+            if Name_Buffer (Old) = 'Q'
+              and then Old < Name_Len
+            then
                Old := Old + 1;
                Insert_Character (''');
                Copy_One_Character;
@@ -352,7 +404,11 @@ package body Namet is
 
             --  Case of operator name
 
-            elsif Name_Buffer (Old) = 'O' then
+            elsif Name_Buffer (Old) = 'O'
+              and then Old < Name_Len
+              and then Name_Buffer (Old + 1) not in 'A' .. 'Z'
+              and then Name_Buffer (Old + 1) /= '_'
+            then
                Old := Old + 1;
 
                declare
@@ -443,8 +499,7 @@ package body Namet is
 
          Name_Len := New_Len;
          Name_Buffer (1 .. New_Len) := New_Buf (1 .. New_Len);
-      end;
-
+      end Decode;
    end Get_Decoded_Name_String;
 
    -------------------------------------------
@@ -465,14 +520,19 @@ package body Namet is
       elsif Name_Buffer (1) = 'Q' then
          Get_Decoded_Name_String (Id);
 
-      --  Only remaining issue is U/W sequences
+      --  Only remaining issue is U/W/WW sequences
 
       else
          Get_Name_String (Id);
 
          P := 1;
          while P < Name_Len loop
-            if Name_Buffer (P) = 'U' then
+            if Name_Buffer (P + 1) in 'A' .. 'Z' then
+               P := P + 1;
+
+            --  Uhh encoding
+
+            elsif Name_Buffer (P) = 'U' then
                for J in reverse P + 3 .. P + Name_Len loop
                   Name_Buffer (J + 3) := Name_Buffer (J);
                end loop;
@@ -486,18 +546,38 @@ package body Namet is
                Name_Buffer (P + 5) := ']';
                P := P + 6;
 
-            elsif Name_Buffer (P) = 'W' then
-               Name_Buffer (P + 8 .. P + Name_Len + 5) :=
+            --  WWhhhhhhhh encoding
+
+            elsif Name_Buffer (P) = 'W'
+              and then P + 9 <= Name_Len
+              and then Name_Buffer (P + 1) = 'W'
+              and then Name_Buffer (P + 2) not in 'A' .. 'Z'
+              and then Name_Buffer (P + 2) /= '_'
+            then
+               Name_Buffer (P + 12 .. Name_Len + 2) :=
+                 Name_Buffer (P + 10 .. Name_Len);
+               Name_Buffer (P)     := '[';
+               Name_Buffer (P + 1) := '"';
+               Name_Buffer (P + 10) := '"';
+               Name_Buffer (P + 11) := ']';
+               Name_Len := Name_Len + 2;
+               P := P + 12;
+
+            --  Whhhh encoding
+
+            elsif Name_Buffer (P) = 'W'
+              and then P < Name_Len
+              and then Name_Buffer (P + 1) not in 'A' .. 'Z'
+              and then Name_Buffer (P + 1) /= '_'
+            then
+               Name_Buffer (P + 8 .. P + Name_Len + 3) :=
                  Name_Buffer (P + 5 .. Name_Len);
-               Name_Buffer (P + 5) := Name_Buffer (P + 4);
-               Name_Buffer (P + 4) := Name_Buffer (P + 3);
-               Name_Buffer (P + 3) := Name_Buffer (P + 2);
-               Name_Buffer (P + 2) := Name_Buffer (P + 1);
+               Name_Buffer (P + 2 .. P + 5) := Name_Buffer (P + 1 .. P + 4);
                Name_Buffer (P)     := '[';
                Name_Buffer (P + 1) := '"';
                Name_Buffer (P + 6) := '"';
                Name_Buffer (P + 7) := ']';
-               Name_Len := Name_Len + 5;
+               Name_Len := Name_Len + 3;
                P := P + 8;
 
             else
@@ -507,10 +587,30 @@ package body Namet is
       end if;
    end Get_Decoded_Name_String_With_Brackets;
 
+   ------------------------
+   -- Get_Last_Two_Chars --
+   ------------------------
+
+   procedure Get_Last_Two_Chars (N : Name_Id; C1, C2 : out Character) is
+      NE  : Name_Entry renames Name_Entries.Table (N);
+      NEL : constant Int := Int (NE.Name_Len);
+
+   begin
+      if NEL >= 2 then
+         C1 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 1);
+         C2 := Name_Chars.Table (NE.Name_Chars_Index + NEL - 0);
+      else
+         C1 := ASCII.NUL;
+         C2 := ASCII.NUL;
+      end if;
+   end Get_Last_Two_Chars;
+
    ---------------------
    -- Get_Name_String --
    ---------------------
 
+   --  Procedure version leaving result in Name_Buffer, length in Name_Len
+
    procedure Get_Name_String (Id : Name_Id) is
       S : Int;
 
@@ -525,6 +625,12 @@ package body Namet is
       end loop;
    end Get_Name_String;
 
+   ---------------------
+   -- Get_Name_String --
+   ---------------------
+
+   --  Function version returning a string
+
    function Get_Name_String (Id : Name_Id) return String is
       S : Int;
 
@@ -589,7 +695,7 @@ package body Namet is
    procedure Get_Unqualified_Decoded_Name_String (Id : Name_Id) is
    begin
       Get_Decoded_Name_String (Id);
-      Strip_Qualification_And_Package_Body_Suffix;
+      Strip_Qualification_And_Suffixes;
    end Get_Unqualified_Decoded_Name_String;
 
    ---------------------------------
@@ -599,7 +705,7 @@ package body Namet is
    procedure Get_Unqualified_Name_String (Id : Name_Id) is
    begin
       Get_Name_String (Id);
-      Strip_Qualification_And_Package_Body_Suffix;
+      Strip_Qualification_And_Suffixes;
    end Get_Unqualified_Name_String;
 
    ----------
@@ -607,45 +713,15 @@ package body Namet is
    ----------
 
    function Hash return Hash_Index_Type is
-      subtype Int_1_12 is Int range 1 .. 12;
-      --  Used to avoid when others on case jump below
-
-      Even_Name_Len : Integer;
-      --  Last even numbered position (used for >12 case)
-
    begin
-
-      --  Special test for 12 (rather than counting on a when others for the
-      --  case statement below) avoids some Ada compilers converting the case
-      --  statement into successive jumps.
-
-      --  The case of a name longer than 12 characters is handled by taking
-      --  the first 6 odd numbered characters and the last 6 even numbered
-      --  characters
-
-      if Name_Len > 12 then
-         Even_Name_Len := (Name_Len) / 2 * 2;
-
-         return ((((((((((((
-           Character'Pos (Name_Buffer (01))) * 2 +
-           Character'Pos (Name_Buffer (Even_Name_Len - 10))) * 2 +
-           Character'Pos (Name_Buffer (03))) * 2 +
-           Character'Pos (Name_Buffer (Even_Name_Len - 08))) * 2 +
-           Character'Pos (Name_Buffer (05))) * 2 +
-           Character'Pos (Name_Buffer (Even_Name_Len - 06))) * 2 +
-           Character'Pos (Name_Buffer (07))) * 2 +
-           Character'Pos (Name_Buffer (Even_Name_Len - 04))) * 2 +
-           Character'Pos (Name_Buffer (09))) * 2 +
-           Character'Pos (Name_Buffer (Even_Name_Len - 02))) * 2 +
-           Character'Pos (Name_Buffer (11))) * 2 +
-           Character'Pos (Name_Buffer (Even_Name_Len))) mod Hash_Num;
-      end if;
-
       --  For the cases of 1-12 characters, all characters participate in the
       --  hash. The positioning is randomized, with the bias that characters
       --  later on participate fully (i.e. are added towards the right side).
 
-      case Int_1_12 (Name_Len) is
+      case Name_Len is
+
+         when 0 =>
+            return 0;
 
          when 1 =>
             return
@@ -761,6 +837,26 @@ package body Namet is
               Character'Pos (Name_Buffer (10))) * 2 +
               Character'Pos (Name_Buffer (12))) mod Hash_Num;
 
+         --  Names longer than 12 characters are handled by taking the first
+         --  6 odd numbered characters and the last 6 even numbered characters.
+
+         when others => declare
+               Even_Name_Len : constant Integer := (Name_Len) / 2 * 2;
+         begin
+            return ((((((((((((
+              Character'Pos (Name_Buffer (01))) * 2 +
+              Character'Pos (Name_Buffer (Even_Name_Len - 10))) * 2 +
+              Character'Pos (Name_Buffer (03))) * 2 +
+              Character'Pos (Name_Buffer (Even_Name_Len - 08))) * 2 +
+              Character'Pos (Name_Buffer (05))) * 2 +
+              Character'Pos (Name_Buffer (Even_Name_Len - 06))) * 2 +
+              Character'Pos (Name_Buffer (07))) * 2 +
+              Character'Pos (Name_Buffer (Even_Name_Len - 04))) * 2 +
+              Character'Pos (Name_Buffer (09))) * 2 +
+              Character'Pos (Name_Buffer (Even_Name_Len - 02))) * 2 +
+              Character'Pos (Name_Buffer (11))) * 2 +
+              Character'Pos (Name_Buffer (Even_Name_Len))) mod Hash_Num;
+         end;
       end case;
    end Hash;
 
@@ -769,7 +865,6 @@ package body Namet is
    ----------------
 
    procedure Initialize is
-
    begin
       Name_Chars.Init;
       Name_Entries.Init;
@@ -777,17 +872,16 @@ package body Namet is
       --  Initialize entries for one character names
 
       for C in Character loop
-         Name_Entries.Increment_Last;
-         Name_Entries.Table (Name_Entries.Last).Name_Chars_Index :=
-           Name_Chars.Last;
-         Name_Entries.Table (Name_Entries.Last).Name_Len  := 1;
-         Name_Entries.Table (Name_Entries.Last).Hash_Link := No_Name;
-         Name_Entries.Table (Name_Entries.Last).Int_Info  := 0;
-         Name_Entries.Table (Name_Entries.Last).Byte_Info := 0;
-         Name_Chars.Increment_Last;
-         Name_Chars.Table (Name_Chars.Last) := C;
-         Name_Chars.Increment_Last;
-         Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
+         Name_Entries.Append
+           ((Name_Chars_Index      => Name_Chars.Last,
+             Name_Len              => 1,
+             Byte_Info             => 0,
+             Int_Info              => 0,
+             Name_Has_No_Encodings => True,
+             Hash_Link             => No_Name));
+
+         Name_Chars.Append (C);
+         Name_Chars.Append (ASCII.NUL);
       end loop;
 
       --  Clear hash table
@@ -801,12 +895,20 @@ package body Namet is
    -- Is_Internal_Name --
    ----------------------
 
+   --  Version taking an argument
+
    function Is_Internal_Name (Id : Name_Id) return Boolean is
    begin
       Get_Name_String (Id);
       return Is_Internal_Name;
    end Is_Internal_Name;
 
+   ----------------------
+   -- Is_Internal_Name --
+   ----------------------
+
+   --  Version taking its input from Name_Buffer
+
    function Is_Internal_Name return Boolean is
    begin
       if Name_Buffer (1) = '_'
@@ -853,6 +955,27 @@ package body Namet is
         and then C /= 'X';
    end Is_OK_Internal_Letter;
 
+   ----------------------
+   -- Is_Operator_Name --
+   ----------------------
+
+   function Is_Operator_Name (Id : Name_Id) return Boolean is
+      S : Int;
+   begin
+      pragma Assert (Id in Name_Entries.First .. Name_Entries.Last);
+      S := Name_Entries.Table (Id).Name_Chars_Index;
+      return Name_Chars.Table (S + 1) = 'O';
+   end Is_Operator_Name;
+
+   -------------------
+   -- Is_Valid_Name --
+   -------------------
+
+   function Is_Valid_Name (Id : Name_Id) return Boolean is
+   begin
+      return Id in Name_Entries.First .. Name_Entries.Last;
+   end Is_Valid_Name;
+
    --------------------
    -- Length_Of_Name --
    --------------------
@@ -891,24 +1014,21 @@ package body Namet is
 
    function Name_Enter return Name_Id is
    begin
-
-      Name_Entries.Increment_Last;
-      Name_Entries.Table (Name_Entries.Last).Name_Chars_Index :=
-        Name_Chars.Last;
-      Name_Entries.Table (Name_Entries.Last).Name_Len  := Short (Name_Len);
-      Name_Entries.Table (Name_Entries.Last).Hash_Link := No_Name;
-      Name_Entries.Table (Name_Entries.Last).Int_Info  := 0;
-      Name_Entries.Table (Name_Entries.Last).Byte_Info := 0;
+      Name_Entries.Append
+        ((Name_Chars_Index      => Name_Chars.Last,
+          Name_Len              => Short (Name_Len),
+          Byte_Info             => 0,
+          Int_Info              => 0,
+          Name_Has_No_Encodings => False,
+          Hash_Link             => No_Name));
 
       --  Set corresponding string entry in the Name_Chars table
 
       for J in 1 .. Name_Len loop
-         Name_Chars.Increment_Last;
-         Name_Chars.Table (Name_Chars.Last) := Name_Buffer (J);
+         Name_Chars.Append (Name_Buffer (J));
       end loop;
 
-      Name_Chars.Increment_Last;
-      Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
+      Name_Chars.Append (ASCII.NUL);
 
       return Name_Entries.Last;
    end Name_Enter;
@@ -970,8 +1090,8 @@ package body Namet is
 
                S := Name_Entries.Table (New_Id).Name_Chars_Index;
 
-               for I in 1 .. Name_Len loop
-                  if Name_Chars.Table (S + Int (I)) /= Name_Buffer (I) then
+               for J in 1 .. Name_Len loop
+                  if Name_Chars.Table (S + Int (J)) /= Name_Buffer (J) then
                      goto No_Match;
                   end if;
                end loop;
@@ -988,7 +1108,6 @@ package body Namet is
                        Name_Entries.Last + 1;
                      exit Search;
                   end if;
-
             end loop Search;
          end if;
 
@@ -996,23 +1115,21 @@ package body Namet is
          --  hash table. We now create a new entry in the names table. The hash
          --  link pointing to the new entry (Name_Entries.Last+1) has been set.
 
-         Name_Entries.Increment_Last;
-         Name_Entries.Table (Name_Entries.Last).Name_Chars_Index :=
-           Name_Chars.Last;
-         Name_Entries.Table (Name_Entries.Last).Name_Len  := Short (Name_Len);
-         Name_Entries.Table (Name_Entries.Last).Hash_Link := No_Name;
-         Name_Entries.Table (Name_Entries.Last).Int_Info  := 0;
-         Name_Entries.Table (Name_Entries.Last).Byte_Info := 0;
+         Name_Entries.Append
+           ((Name_Chars_Index      => Name_Chars.Last,
+             Name_Len              => Short (Name_Len),
+             Hash_Link             => No_Name,
+             Name_Has_No_Encodings => False,
+             Int_Info              => 0,
+             Byte_Info             => 0));
 
          --  Set corresponding string entry in the Name_Chars table
 
-         for I in 1 .. Name_Len loop
-            Name_Chars.Increment_Last;
-            Name_Chars.Table (Name_Chars.Last) := Name_Buffer (I);
+         for J in 1 .. Name_Len loop
+            Name_Chars.Append (Name_Buffer (J));
          end loop;
 
-         Name_Chars.Increment_Last;
-         Name_Chars.Table (Name_Chars.Last) := ASCII.NUL;
+         Name_Chars.Append (ASCII.NUL);
 
          return Name_Entries.Last;
       end if;
@@ -1067,49 +1184,63 @@ package body Namet is
 
    procedure Store_Encoded_Character (C : Char_Code) is
 
-      procedure Set_Hex_Chars (N : Natural);
+      procedure Set_Hex_Chars (C : Char_Code);
       --  Stores given value, which is in the range 0 .. 255, as two hex
-      --  digits (using lower case a-f) in Name_Buffer, incrementing Name_Len
+      --  digits (using lower case a-f) in Name_Buffer, incrementing Name_Len.
 
-      procedure Set_Hex_Chars (N : Natural) is
-         Hexd : constant String := "0123456789abcdef";
+      -------------------
+      -- Set_Hex_Chars --
+      -------------------
 
+      procedure Set_Hex_Chars (C : Char_Code) is
+         Hexd : constant String := "0123456789abcdef";
+         N    : constant Natural := Natural (C);
       begin
          Name_Buffer (Name_Len + 1) := Hexd (N / 16 + 1);
          Name_Buffer (Name_Len + 2) := Hexd (N mod 16 + 1);
          Name_Len := Name_Len + 2;
       end Set_Hex_Chars;
 
+   --  Start of processing for Store_Encoded_Character
+
    begin
       Name_Len := Name_Len + 1;
 
       if In_Character_Range (C) then
          declare
             CC : constant Character := Get_Character (C);
-
          begin
             if CC in 'a' .. 'z' or else CC in '0' .. '9' then
                Name_Buffer (Name_Len) := CC;
-
             else
                Name_Buffer (Name_Len) := 'U';
-               Set_Hex_Chars (Natural (C));
+               Set_Hex_Chars (C);
             end if;
          end;
 
+      elsif In_Wide_Character_Range (C) then
+         Name_Buffer (Name_Len) := 'W';
+         Set_Hex_Chars (C / 256);
+         Set_Hex_Chars (C mod 256);
+
       else
          Name_Buffer (Name_Len) := 'W';
-         Set_Hex_Chars (Natural (C) / 256);
-         Set_Hex_Chars (Natural (C) mod 256);
+         Name_Len := Name_Len + 1;
+         Name_Buffer (Name_Len) := 'W';
+         Set_Hex_Chars (C / 2 ** 24);
+         Set_Hex_Chars ((C / 2 ** 16) mod 256);
+         Set_Hex_Chars ((C / 256) mod 256);
+         Set_Hex_Chars (C mod 256);
       end if;
-
    end Store_Encoded_Character;
 
-   -------------------------------------------------
-   -- Strip_Qualification_And_Package_Body_Suffix --
-   -------------------------------------------------
+   --------------------------------------
+   -- Strip_Qualification_And_Suffixes --
+   --------------------------------------
+
+   procedure Strip_Qualification_And_Suffixes is
+      J : Integer;
 
-   procedure Strip_Qualification_And_Package_Body_Suffix is
    begin
       --  Strip package body qualification string off end
 
@@ -1124,18 +1255,56 @@ package body Namet is
            and then Name_Buffer (J) /= 'p';
       end loop;
 
-      --  Find rightmost __ separator if one exists and strip it
-      --  and everything that precedes it from the name.
+      --  Find rightmost __ or $ separator if one exists. First we position
+      --  to start the search. If we have a character constant, position
+      --  just before it, otherwise position to last character but one
 
-      for J in reverse 2 .. Name_Len - 2 loop
-         if Name_Buffer (J) = '_' and then Name_Buffer (J + 1) = '_' then
-            Name_Buffer (1 .. Name_Len - J - 1) :=
-              Name_Buffer (J + 2 .. Name_Len);
-            Name_Len := Name_Len - J - 1;
-            exit;
+      if Name_Buffer (Name_Len) = ''' then
+         J := Name_Len - 2;
+         while J > 0 and then Name_Buffer (J) /= ''' loop
+            J := J - 1;
+         end loop;
+
+      else
+         J := Name_Len - 1;
+      end if;
+
+      --  Loop to search for rightmost __ or $ (homonym) separator
+
+      while J > 1 loop
+
+         --  If $ separator, homonym separator, so strip it and keep looking
+
+         if Name_Buffer (J) = '$' then
+            Name_Len := J - 1;
+            J := Name_Len - 1;
+
+         --  Else check for __ found
+
+         elsif Name_Buffer (J) = '_' and then Name_Buffer (J + 1) = '_' then
+
+            --  Found __ so see if digit follows, and if so, this is a
+            --  homonym separator, so strip it and keep looking.
+
+            if Name_Buffer (J + 2) in '0' .. '9' then
+               Name_Len := J - 1;
+               J := Name_Len - 1;
+
+            --  If not a homonym separator, then we simply strip the
+            --  separator and everything that precedes it, and we are done
+
+            else
+               Name_Buffer (1 .. Name_Len - J - 1) :=
+                 Name_Buffer (J + 2 .. Name_Len);
+               Name_Len := Name_Len - J - 1;
+               exit;
+            end if;
+
+         else
+            J := J - 1;
          end if;
       end loop;
-   end Strip_Qualification_And_Package_Body_Suffix;
+   end Strip_Qualification_And_Suffixes;
 
    ---------------
    -- Tree_Read --
@@ -1184,8 +1353,27 @@ package body Namet is
    --------
 
    procedure wn (Id : Name_Id) is
+      S : Int;
+
    begin
-      Write_Name (Id);
+      if not Id'Valid then
+         Write_Str ("<invalid name_id>");
+
+      elsif Id = No_Name then
+         Write_Str ("<No_Name>");
+
+      elsif Id = Error_Name then
+         Write_Str ("<Error_Name>");
+
+      else
+         S := Name_Entries.Table (Id).Name_Chars_Index;
+         Name_Len := Natural (Name_Entries.Table (Id).Name_Len);
+
+         for J in 1 .. Name_Len loop
+            Write_Char (Name_Chars.Table (S + Int (J)));
+         end loop;
+      end if;
+
       Write_Eol;
    end wn;