------------------------------------------------------------------------------
--                                                                          --
--                         GNAT COMPILER COMPONENTS                         --
--                                                                          --
--                    S Y M B O L S . P R O C E S S I N G                   --
--                                                                          --
--                                 B o d y                                  --
--                                                                          --
--          Copyright (C) 2003-2007, 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- --
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
-- 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 COPYING3.  If not, go to --
-- http://www.gnu.org/licenses for a complete copy of the license.          --
--                                                                          --
-- GNAT was originally developed  by the GNAT team at  New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
--                                                                          --
------------------------------------------------------------------------------

--  This is the VMS Alpha version of this package

separate (Symbols)
package body Processing is

   type Number is mod 2**16;
   --  16 bits unsigned number for number of characters

   GSD : constant Number := 10;
   --  Code for the Global Symbol Definition section

   C_SYM : constant Number := 1;
   --  Code for a Symbol subsection

   V_DEF_Mask  : constant Number := 2**1;
   V_NORM_Mask : constant Number := 2**6;

   B : Byte;

   Number_Of_Characters : Natural := 0;
   --  The number of characters of each section

   --  The following variables are used by procedure Process when reading an
   --  object file.

   Code   : Number := 0;
   Length : Natural := 0;

   Dummy : Number;

   Nchars : Natural := 0;
   Flags  : Number  := 0;

   Symbol : String (1 .. 255);
   LSymb  : Natural;

   procedure Get (N : out Number);
   --  Read two bytes from the object file LSB first as unsigned 16 bit number

   procedure Get (N : out Natural);
   --  Read two bytes from the object file, LSByte first, as a Natural

   ---------
   -- Get --
   ---------

   procedure Get (N : out Number) is
      C : Byte;
      LSByte : Number;
   begin
      Read (File, C);
      LSByte := Byte'Pos (C);
      Read (File, C);
      N := LSByte + (256 * Byte'Pos (C));
   end Get;

   procedure Get (N : out Natural) is
      Result : Number;
   begin
      Get (Result);
      N := Natural (Result);
   end Get;

   -------------
   -- Process --
   -------------

   procedure Process
     (Object_File : String;
      Success     : out Boolean)
   is
      OK : Boolean := True;

   begin
      --  Open the object file with Byte_IO. Return with Success = False if
      --  this fails.

      begin
         Open (File, In_File, Object_File);
      exception
         when others =>
            Put_Line
              ("*** Unable to open object file """ & Object_File & """");
            Success := False;
            return;
      end;

      --  Assume that the object file has a correct format

      Success := True;

      --  Get the different sections one by one from the object file

      while not End_Of_File (File) loop

         Get (Code);
         Get (Number_Of_Characters);
         Number_Of_Characters := Number_Of_Characters - 4;

         --  If this is not a Global Symbol Definition section, skip to the
         --  next section.

         if Code /= GSD then

            for J in 1 .. Number_Of_Characters loop
               Read (File, B);
            end loop;

         else

            --  Skip over the next 4 bytes

            Get (Dummy);
            Get (Dummy);
            Number_Of_Characters := Number_Of_Characters - 4;

            --  Get each subsection in turn

            loop
               Get (Code);
               Get (Nchars);
               Get (Dummy);
               Get (Flags);
               Number_Of_Characters := Number_Of_Characters - 8;
               Nchars := Nchars - 8;

               --  If this is a symbol and the V_DEF flag is set, get the
               --  symbol.

               if Code = C_SYM and then ((Flags and V_DEF_Mask) /= 0) then
                  --  First, reach the symbol length

                  for J in 1 .. 25 loop
                     Read (File, B);
                     Nchars := Nchars - 1;
                     Number_Of_Characters := Number_Of_Characters - 1;
                  end loop;

                  Length := Byte'Pos (B);
                  LSymb := 0;

                  --  Get the symbol characters

                  for J in 1 .. Nchars loop
                     Read (File, B);
                     Number_Of_Characters := Number_Of_Characters - 1;
                     if Length > 0 then
                        LSymb := LSymb + 1;
                        Symbol (LSymb) := B;
                        Length := Length - 1;
                     end if;
                  end loop;

                  --  Check if it is a symbol from a generic body

                  OK := True;

                  for J in 1 .. LSymb - 2 loop
                     if Symbol (J) = 'G' and then Symbol (J + 1) = 'P'
                       and then Symbol (J + 2) in '0' .. '9'
                     then
                        OK := False;
                        exit;
                     end if;
                  end loop;

                  if OK then

                     --  Create the new Symbol

                     declare
                        S_Data : Symbol_Data;

                     begin
                        S_Data.Name := new String'(Symbol (1 .. LSymb));

                        --  The symbol kind (Data or Procedure) depends on the
                        --  V_NORM flag.

                        if (Flags and V_NORM_Mask) = 0 then
                           S_Data.Kind := Data;

                        else
                           S_Data.Kind := Proc;
                        end if;

                        --  Put the new symbol in the table

                        Symbol_Table.Append (Complete_Symbols, S_Data);
                     end;
                  end if;

               else
                  --  As it is not a symbol subsection, skip to the next
                  --  subsection.

                  for J in 1 .. Nchars loop
                     Read (File, B);
                     Number_Of_Characters := Number_Of_Characters - 1;
                  end loop;
               end if;

               --  Exit the GSD section when number of characters reaches 0

               exit when Number_Of_Characters = 0;
            end loop;
         end if;
      end loop;

      --  The object file has been processed, close it

      Close (File);

   exception
      --  For any exception, output an error message, close the object file
      --  and return with Success = False.

      when X : others =>
         Put_Line ("unexpected exception raised while processing """
                   & Object_File & """");
         Put_Line (Exception_Information (X));
         Close (File);
         Success := False;
   end Process;

end Processing;
