-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset is free software; you can redistribute it and/or modify it
-- under terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 3, or (at your option) any later
-- version. The SPARK toolset is distributed in the hope that it will be
-- useful, but WITHOUT 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 the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

-- Options for handling generic units are marked with -- GenOption --
-- With the code commented out, generic declarations are indexed as "specification"
-- With the code included, they are indicated by "generic_declaration"
-- The former is probably better because if a package body is found, there is no way
-- of knowing whether a generic spec or normal spec is required.  We know this for a
-- generic subprgoram body because any subprogram body that is not a main program must
-- be generic.  It seems uneccesarily complicated to change the language of index files
-- so as to say something about generic suprgorams that we can't say about generic
-- packages.  Therefore overloading "specification" seems the best option.

with Ada.Characters.Latin_1;
with CommandLineData;
with FileSystem;
with IndexManager.Cache;
with IndexManager.Index_Table_P;
with SystemErrors;

package body IndexManager
--# own State is IndexManager.Cache.The_Unit_Hash,
--#              IndexManager.Index_Table_P.Fatal_Error,
--#              IndexManager.Index_Table_P.Index_Table;
is

   procedure Look_In_File
     (Lookup_Components   : in     Boolean;
      Required_Unit       : in     LexTokenLists.Lists;
      Possible_Unit_Types : in     ContextManager.UnitTypeSets;
      Top_Filename        : in     LexTokenManager.Lex_String;
      Returned_Filename   :    out LexTokenManager.Lex_String;
      Actual_Unit_Type    :    out ContextManager.UnitTypes;
      Components          :    out Component_Lists;
      Found               :    out Boolean)
   --# global in     CommandLineData.Content;
   --#        in out Cache.The_Unit_Hash;
   --#        in out ErrorHandler.Error_Context;
   --#        in out Index_Table_P.Fatal_Error;
   --#        in out Index_Table_P.Index_Table;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Actual_Unit_Type,
   --#         Cache.The_Unit_Hash,
   --#         Components,
   --#         ErrorHandler.Error_Context,
   --#         Found,
   --#         Index_Table_P.Index_Table,
   --#         LexTokenManager.State,
   --#         Returned_Filename,
   --#         SPARK_IO.File_Sys          from Cache.The_Unit_Hash,
   --#                                         CommandLineData.Content,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Index_Table_P.Index_Table,
   --#                                         LexTokenManager.State,
   --#                                         Lookup_Components,
   --#                                         Possible_Unit_Types,
   --#                                         Required_Unit,
   --#                                         SPARK_IO.File_Sys,
   --#                                         Top_Filename &
   --#         Index_Table_P.Fatal_Error  from *,
   --#                                         Cache.The_Unit_Hash,
   --#                                         CommandLineData.Content,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Index_Table_P.Index_Table,
   --#                                         LexTokenManager.State,
   --#                                         Lookup_Components,
   --#                                         Possible_Unit_Types,
   --#                                         Required_Unit,
   --#                                         SPARK_IO.File_Sys,
   --#                                         Top_Filename;
   is
      L_Returned_Filename    : E_Strings.T;
      L_Actual_Unit_Type     : ContextManager.UnitTypes;
      L_Components           : Component_Lists;
      L_Found                : Boolean;
      Entry_Unit             : LexTokenLists.Lists;
      Entry_Type             : Entry_Types;
      Entry_Filename         : E_Strings.T;
      Entry_Components       : Component_Lists;
      Valid_Entry            : Boolean;
      First_In_File          : Boolean;
      Position               : File_Position;
      Last_Filename          : LexTokenManager.Lex_String;
      Poss_Error_Type        : Library_Manager_Errors;
      In_Aux_Index           : Boolean;
      Done                   : Boolean;
      File_Spec_Status       : FileSystem.Typ_File_Spec_Status;
      Index_File             : SPARK_IO.File_Type;
      File_Status            : SPARK_IO.File_Status;
      Aux_Index_Unit         : LexTokenLists.Lists;
      Super_Index_Found      : Boolean;
      Index_Filename         : E_Strings.T;
      Current_Index_Filename : LexTokenManager.Lex_String;
      Source_Position        : File_Position;
      Last_Char              : Character;

      SPARK_Library_Unit      : LexTokenLists.Lists;
      Interfaces_Library_Unit : LexTokenLists.Lists;
      Ada_Library_Unit        : LexTokenLists.Lists;

      function Is_End_Of_Buffered_Line (File      : SPARK_IO.File_Type;
                                        Last_Char : Character) return Boolean
      --# global in SPARK_IO.File_Sys;
      is
         Answer : Boolean;
      begin
         Answer := False;
         if SPARK_IO.End_Of_Line (File) and then Last_Char = Ada.Characters.Latin_1.NUL then
            Answer := True;
         end if;
         return Answer;
      end Is_End_Of_Buffered_Line;

      function Is_End_Of_Buffered_File (File      : SPARK_IO.File_Type;
                                        Last_Char : Character) return Boolean
      --# global in SPARK_IO.File_Sys;
      is
         Answer : Boolean;
      begin
         Answer := False;
         if SPARK_IO.End_Of_File (File) and then Last_Char = Ada.Characters.Latin_1.NUL then
            Answer := True;
         end if;
         return Answer;
      end Is_End_Of_Buffered_File;

      procedure Read_Buffered_Char
        (File           : in     SPARK_IO.File_Type;
         Index_Filename : in     LexTokenManager.Lex_String;
         Last_Char      : in out Character;
         Ch             :    out Character)
      --# global in     CommandLineData.Content;
      --#        in     LexTokenManager.State;
      --#        in out ErrorHandler.Error_Context;
      --#        in out Index_Table_P.Fatal_Error;
      --#        in out SPARK_IO.File_Sys;
      --# derives Ch,
      --#         Last_Char                  from File,
      --#                                         Last_Char,
      --#                                         SPARK_IO.File_Sys &
      --#         ErrorHandler.Error_Context,
      --#         Index_Table_P.Fatal_Error  from *,
      --#                                         File,
      --#                                         Last_Char,
      --#                                         SPARK_IO.File_Sys &
      --#         SPARK_IO.File_Sys          from *,
      --#                                         CommandLineData.Content,
      --#                                         ErrorHandler.Error_Context,
      --#                                         File,
      --#                                         Index_Filename,
      --#                                         Last_Char,
      --#                                         LexTokenManager.State;
      is
         Token_Position : File_Position;
      begin
         if Last_Char = Ada.Characters.Latin_1.NUL then
            -- No buffered character
            SPARK_IO.Get_Char (File, Ch);
            if Ch = Ada.Characters.Latin_1.HT or else Ch = Ada.Characters.Latin_1.CR then
               Ch := ' ';
            end if;
         else
            -- Read the buffered character
            Ch        := Last_Char;
            Last_Char := Ada.Characters.Latin_1.NUL;
         end if;

         -- Check for comments; skip line if found
         if Ch = '-' then
            if not Is_End_Of_Buffered_File (File      => File,
                                            Last_Char => Last_Char) then
               SPARK_IO.Get_Char (File, Ch);
               if Ch = '-' then
                  -- it is a comment so skip to end of line
                  SPARK_IO.Skip_Line (File, 1);
                  Ch := ' ';
               else
                  -- only one '-' so its not a comment
                  Last_Char := Ch;
                  Ch        := '-';
               end if;
            else
               -- A single dash then EOF - nonsense
               -- error reading; assume no file can end with '-'

               -- In priciple calls to Line and Col may cause a run-time exception
               -- if Line or Col > Count'Last defined in the TEXT_IO package
               -- but in practice this is exception will not be raised because, for
               -- instance, in gnat Count'Last = Natural'Last
               Token_Position := File_Position'(Line => SPARK_IO.Line (File),
                                                Col  => SPARK_IO.Col (File));
               Index_Table_P.Output_Error
                 (E              => ES_Comment,
                  Source_File    => Index_Filename,
                  Token_Position => Token_Position,
                  Token_String   => E_Strings.Empty_String);
            end if;
         end if;
      end Read_Buffered_Char;

      -- Get all the contiguous whitespace (including newlines)
      -- up to end of file or a non-whitespace char.  Unget
      -- non-whitespace.
      procedure Skip_White_Space
        (File           : in     SPARK_IO.File_Type;
         Index_Filename : in     LexTokenManager.Lex_String;
         Last_Char      : in out Character)
      --# global in     CommandLineData.Content;
      --#        in     LexTokenManager.State;
      --#        in out ErrorHandler.Error_Context;
      --#        in out Index_Table_P.Fatal_Error;
      --#        in out SPARK_IO.File_Sys;
      --# derives ErrorHandler.Error_Context,
      --#         Index_Table_P.Fatal_Error,
      --#         Last_Char,
      --#         SPARK_IO.File_Sys          from *,
      --#                                         CommandLineData.Content,
      --#                                         ErrorHandler.Error_Context,
      --#                                         File,
      --#                                         Index_Filename,
      --#                                         Last_Char,
      --#                                         LexTokenManager.State,
      --#                                         SPARK_IO.File_Sys;
      is
         My_Char : Character;
      begin
         while Is_End_Of_Buffered_Line (File      => File,
                                        Last_Char => Last_Char)
           and then (not Is_End_Of_Buffered_File (File      => File,
                                                  Last_Char => Last_Char)) loop
            SPARK_IO.Skip_Line (File, 1);
         end loop;
         if not Is_End_Of_Buffered_File (File      => File,
                                         Last_Char => Last_Char) then
            Read_Buffered_Char (File           => File,
                                Index_Filename => Index_Filename,
                                Last_Char      => Last_Char,
                                Ch             => My_Char);
            if (My_Char /= ' ') then
               Last_Char := My_Char;
            end if;
            while My_Char = ' ' and then (not Is_End_Of_Buffered_File (File      => File,
                                                                       Last_Char => Last_Char)) loop
               if Is_End_Of_Buffered_Line (File      => File,
                                           Last_Char => Last_Char) then
                  SPARK_IO.Skip_Line (File, 1);
               else
                  -- Read the next char, as long as it's whitespace
                  Read_Buffered_Char (File           => File,
                                      Index_Filename => Index_Filename,
                                      Last_Char      => Last_Char,
                                      Ch             => My_Char);
                  if (My_Char /= ' ') then
                     Last_Char := My_Char;
                  end if;
               end if;
            end loop;
         end if;
      end Skip_White_Space;

      procedure Get_Token_Position
        (Index_File     : in     SPARK_IO.File_Type;
         Index_Filename : in     LexTokenManager.Lex_String;
         Last_Char      : in out Character;
         Position       :    out File_Position)
      --# global in     CommandLineData.Content;
      --#        in     LexTokenManager.State;
      --#        in out ErrorHandler.Error_Context;
      --#        in out Index_Table_P.Fatal_Error;
      --#        in out SPARK_IO.File_Sys;
      --# derives ErrorHandler.Error_Context,
      --#         Index_Table_P.Fatal_Error,
      --#         Last_Char,
      --#         SPARK_IO.File_Sys          from *,
      --#                                         CommandLineData.Content,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Index_File,
      --#                                         Index_Filename,
      --#                                         Last_Char,
      --#                                         LexTokenManager.State,
      --#                                         SPARK_IO.File_Sys &
      --#         Position                   from CommandLineData.Content,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Index_File,
      --#                                         Index_Filename,
      --#                                         Last_Char,
      --#                                         LexTokenManager.State,
      --#                                         SPARK_IO.File_Sys;
      is
      begin
         Skip_White_Space (File           => Index_File,
                           Index_Filename => Index_Filename,
                           Last_Char      => Last_Char);
         Position := File_Position'(Line => SPARK_IO.Line (Index_File),
                                    Col  => SPARK_IO.Col (Index_File));
      end Get_Token_Position;

      procedure Read_Entry
        (Index_File        : in     SPARK_IO.File_Type;
         Index_Filename    : in     LexTokenManager.Lex_String;
         Last_Char         : in out Character;
         Entry_Unit_Export :    out LexTokenLists.Lists;
         Entry_Type        :    out Entry_Types;
         Entry_Filename    :    out E_Strings.T;
         Entry_Components  :    out Component_Lists;
         Valid_Entry       :    out Boolean)
      --# global in     CommandLineData.Content;
      --#        in out ErrorHandler.Error_Context;
      --#        in out Index_Table_P.Fatal_Error;
      --#        in out LexTokenManager.State;
      --#        in out SPARK_IO.File_Sys;
      --# derives Entry_Components,
      --#         Entry_Filename,
      --#         Entry_Type,
      --#         Entry_Unit_Export,
      --#         ErrorHandler.Error_Context,
      --#         Last_Char,
      --#         LexTokenManager.State,
      --#         SPARK_IO.File_Sys,
      --#         Valid_Entry                from CommandLineData.Content,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Index_File,
      --#                                         Index_Filename,
      --#                                         Last_Char,
      --#                                         LexTokenManager.State,
      --#                                         SPARK_IO.File_Sys &
      --#         Index_Table_P.Fatal_Error  from *,
      --#                                         CommandLineData.Content,
      --#                                         ErrorHandler.Error_Context,
      --#                                         Index_File,
      --#                                         Index_Filename,
      --#                                         Last_Char,
      --#                                         LexTokenManager.State,
      --#                                         SPARK_IO.File_Sys;
      is
         Entry_Name_Valid, Is_In_Valid, Components_Valid, File_Location_Valid : Boolean;
         Entry_Type_Loc                                                       : Entry_Types;
         Current_Position                                                     : File_Position;

         -- Get the next single character; unget any whitespace
         procedure Get_Single_Char
           (File             : in     SPARK_IO.File_Type;
            Index_Filename   : in     LexTokenManager.Lex_String;
            In_Quoted_String : in     Boolean;
            Last_Char        : in out Character;
            Ch               :    out Character;
            OK               :    out Boolean)
         --# global in     CommandLineData.Content;
         --#        in     LexTokenManager.State;
         --#        in out ErrorHandler.Error_Context;
         --#        in out Index_Table_P.Fatal_Error;
         --#        in out SPARK_IO.File_Sys;
         --# derives Ch,
         --#         OK                         from File,
         --#                                         Last_Char,
         --#                                         SPARK_IO.File_Sys &
         --#         ErrorHandler.Error_Context,
         --#         Index_Table_P.Fatal_Error  from *,
         --#                                         File,
         --#                                         Last_Char,
         --#                                         SPARK_IO.File_Sys &
         --#         Last_Char                  from *,
         --#                                         File,
         --#                                         In_Quoted_String,
         --#                                         SPARK_IO.File_Sys &
         --#         SPARK_IO.File_Sys          from *,
         --#                                         CommandLineData.Content,
         --#                                         ErrorHandler.Error_Context,
         --#                                         File,
         --#                                         Index_Filename,
         --#                                         Last_Char,
         --#                                         LexTokenManager.State;
         is
         begin
            if Is_End_Of_Buffered_File (File      => File,
                                        Last_Char => Last_Char) then
               Ch := ' ';
               OK := False;
            elsif Is_End_Of_Buffered_Line (File      => File,
                                           Last_Char => Last_Char) then
               Ch := ' ';
               OK := True;
            else
               Read_Buffered_Char (File           => File,
                                   Index_Filename => Index_Filename,
                                   Last_Char      => Last_Char,
                                   Ch             => Ch);

               -- Allow for quoted strings containing spaces
               if Ch = ' ' and then not In_Quoted_String then
                  Last_Char := Ch;
               end if;

               OK := True;
            end if;
         end Get_Single_Char;

         procedure Read_An_Identifier
           (Index_File     : in     SPARK_IO.File_Type;
            Index_Filename : in     LexTokenManager.Lex_String;
            Identifier     : in out E_Strings.T;
            Last_Char      : in out Character;
            Valid          :    out Boolean;
            Follower       :    out Character)
         --# global in     CommandLineData.Content;
         --#        in     LexTokenManager.State;
         --#        in out ErrorHandler.Error_Context;
         --#        in out Index_Table_P.Fatal_Error;
         --#        in out SPARK_IO.File_Sys;
         --# derives ErrorHandler.Error_Context,
         --#         Identifier,
         --#         Index_Table_P.Fatal_Error,
         --#         Last_Char,
         --#         SPARK_IO.File_Sys          from *,
         --#                                         CommandLineData.Content,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Index_File,
         --#                                         Index_Filename,
         --#                                         Last_Char,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys &
         --#         Follower,
         --#         Valid                      from CommandLineData.Content,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Index_File,
         --#                                         Index_Filename,
         --#                                         Last_Char,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys;
         is
            Ch      : Character;
            Read_OK : Boolean;
         begin
            Skip_White_Space (File           => Index_File,
                              Index_Filename => Index_Filename,
                              Last_Char      => Last_Char);
            Get_Single_Char
              (File             => Index_File,
               Index_Filename   => Index_Filename,
               In_Quoted_String => False,
               Last_Char        => Last_Char,
               Ch               => Ch,
               OK               => Read_OK);
            if Read_OK and then (Ch in 'a' .. 'z' or else Ch in 'A' .. 'Z') then
               Identifier := E_Strings.Empty_String;
               loop
                  E_Strings.Append_Char (E_Str => Identifier,
                                         Ch    => Ch);
                  Get_Single_Char
                    (File             => Index_File,
                     Index_Filename   => Index_Filename,
                     In_Quoted_String => False,
                     Last_Char        => Last_Char,
                     Ch               => Ch,
                     OK               => Read_OK);
                  exit when not Read_OK
                    or else (Ch not  in 'A' .. 'Z'
                               and then Ch not  in 'a' .. 'z'
                               and then Ch not  in '0' .. '9'
                               and then Ch /= '_');
               end loop;
               Valid    := Is_End_Of_Buffered_File (File      => Index_File,
                                                    Last_Char => Last_Char) or else Read_OK;
               Follower := Ch;
            else
               Valid    := False;
               Follower := ' ';
            end if;
         end Read_An_Identifier;

         procedure Read_An_Entry_Name
           (Index_File        : in     SPARK_IO.File_Type;
            Index_Filename    : in     LexTokenManager.Lex_String;
            Last_Char         : in out Character;
            Entry_Unit_Export :    out LexTokenLists.Lists;
            Entry_Type        :    out Entry_Types;
            Entry_Name_Valid  :    out Boolean)
         --# global in     CommandLineData.Content;
         --#        in out ErrorHandler.Error_Context;
         --#        in out Index_Table_P.Fatal_Error;
         --#        in out LexTokenManager.State;
         --#        in out SPARK_IO.File_Sys;
         --# derives Entry_Name_Valid,
         --#         Entry_Type,
         --#         Entry_Unit_Export,
         --#         ErrorHandler.Error_Context,
         --#         Last_Char,
         --#         LexTokenManager.State,
         --#         SPARK_IO.File_Sys          from CommandLineData.Content,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Index_File,
         --#                                         Index_Filename,
         --#                                         Last_Char,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys &
         --#         Index_Table_P.Fatal_Error  from *,
         --#                                         CommandLineData.Content,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Index_File,
         --#                                         Index_Filename,
         --#                                         Last_Char,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys;
         is
            Unit_Valid   : Boolean;
            A_String     : E_Strings.T;
            String_Valid : Boolean;
            Next_Ch      : Character;
            Position     : File_Position;

            procedure Read_A_Unit_Name
              (Index_File     : in     SPARK_IO.File_Type;
               Index_Filename : in     LexTokenManager.Lex_String;
               Last_Char      : in out Character;
               Unit_Name      :    out LexTokenLists.Lists;
               Valid          :    out Boolean)
            --# global in     CommandLineData.Content;
            --#        in out ErrorHandler.Error_Context;
            --#        in out Index_Table_P.Fatal_Error;
            --#        in out LexTokenManager.State;
            --#        in out SPARK_IO.File_Sys;
            --# derives ErrorHandler.Error_Context,
            --#         Last_Char,
            --#         LexTokenManager.State,
            --#         SPARK_IO.File_Sys,
            --#         Unit_Name,
            --#         Valid                      from CommandLineData.Content,
            --#                                         ErrorHandler.Error_Context,
            --#                                         Index_File,
            --#                                         Index_Filename,
            --#                                         Last_Char,
            --#                                         LexTokenManager.State,
            --#                                         SPARK_IO.File_Sys &
            --#         Index_Table_P.Fatal_Error  from *,
            --#                                         CommandLineData.Content,
            --#                                         ErrorHandler.Error_Context,
            --#                                         Index_File,
            --#                                         Index_Filename,
            --#                                         Last_Char,
            --#                                         LexTokenManager.State,
            --#                                         SPARK_IO.File_Sys;
            is
               Id               : E_Strings.T;
               Valid_Identifier : Boolean;
               Next_Ch          : Character;
               Token            : LexTokenManager.Lex_String;
            begin
               Id        := E_Strings.Empty_String;
               Unit_Name := LexTokenLists.Null_List;
               loop
                  Read_An_Identifier
                    (Index_File     => Index_File,
                     Index_Filename => Index_Filename,
                     Identifier     => Id,
                     Last_Char      => Last_Char,
                     Valid          => Valid_Identifier,
                     Follower       => Next_Ch);
                  exit when not Valid_Identifier;
                  LexTokenManager.Insert_Examiner_String (Str     => Id,
                                                          Lex_Str => Token);
                  LexTokenLists.Append (List => Unit_Name,
                                        Item => Token);
                  exit when Next_Ch /= '.';
               end loop;
               Valid := Valid_Identifier and then Next_Ch = ' ';
            end Read_A_Unit_Name;

         begin
            Entry_Type := Invalid_Entry_Type;
            A_String   := E_Strings.Empty_String;
            -- Get position of start of entry
            Get_Token_Position
              (Index_File     => Index_File,
               Index_Filename => Index_Filename,
               Last_Char      => Last_Char,
               Position       => Position);
            Read_A_Unit_Name
              (Index_File     => Index_File,
               Index_Filename => Index_Filename,
               Last_Char      => Last_Char,
               Unit_Name      => Entry_Unit_Export,
               Valid          => Unit_Valid);
            if Unit_Valid then
               if LexTokenLists.Get_Length (List => Entry_Unit_Export) = 1
                 and then LexTokenManager.Lex_String_Case_Insensitive_Compare
                 (Lex_Str1 => LexTokenLists.Get_Element (List => Entry_Unit_Export,
                                                         Pos  => 1),
                  Lex_Str2 => LexTokenManager.Super_Index_Token) =
                 LexTokenManager.Str_Eq then
                  Entry_Type       := Super_Index;
                  Entry_Name_Valid := True;
               else
                  -- Get the position of the start of the unit type
                  Get_Token_Position
                    (Index_File     => Index_File,
                     Index_Filename => Index_Filename,
                     Last_Char      => Last_Char,
                     Position       => Position);
                  Read_An_Identifier
                    (Index_File     => Index_File,
                     Index_Filename => Index_Filename,
                     Identifier     => A_String,
                     Last_Char      => Last_Char,
                     Valid          => String_Valid,
                     Follower       => Next_Ch);
                  if String_Valid and then Next_Ch = ' ' then
                     if E_Strings.Eq1_String (E_Str => A_String,
                                              Str   => "auxindex") then
                        Entry_Type       := Aux_Index;
                        Entry_Name_Valid := True;
                     elsif E_Strings.Eq1_String (E_Str => A_String,
                                                 Str   => "main_program") then
                        Entry_Type       := Main_P;
                        Entry_Name_Valid := True;
                     elsif E_Strings.Eq1_String (E_Str => A_String,
                                                 Str   => "specification")
                       or else E_Strings.Eq1_String (E_Str => A_String,
                                                     Str   => "spec") then
                        Entry_Type       := P_Spec;
                        Entry_Name_Valid := True;
                     elsif E_Strings.Eq1_String (E_Str => A_String,
                                                 Str   => "body") then
                        Entry_Type       := P_Bodi;
                        Entry_Name_Valid := True;
                     elsif E_Strings.Eq1_String (E_Str => A_String,
                                                 Str   => "subunit") then
                        Entry_Type       := Subunit;
                        Entry_Name_Valid := True;
                     elsif E_Strings.Eq1_String (E_Str => A_String,
                                                 Str   => "components") then
                        Entry_Type       := Component_List;
                        Entry_Name_Valid := True;
                     else
                        Entry_Name_Valid := False;
                        Index_Table_P.Output_Error
                          (E              => ES_UnitEntry,
                           Source_File    => Index_Filename,
                           Token_Position => Position,
                           Token_String   => A_String);
                     end if;
                  else
                     Entry_Name_Valid := False;
                     Index_Table_P.Output_Error
                       (E              => ES_UnitEntry,
                        Source_File    => Index_Filename,
                        Token_Position => Position,
                        Token_String   => E_Strings.Empty_String);
                  end if;
               end if;
            else
               Entry_Name_Valid := False;
               Index_Table_P.Output_Error
                 (E              => EW_IllegalUnitName,
                  Source_File    => Index_Filename,
                  Token_Position => Position,
                  Token_String   => E_Strings.Empty_String);
            end if;
         end Read_An_Entry_Name;

         procedure Skip_Is_In
           (Index_File     : in     SPARK_IO.File_Type;
            Index_Filename : in     LexTokenManager.Lex_String;
            Last_Char      : in out Character;
            Is_In_Valid    :    out Boolean)
         --# global in     CommandLineData.Content;
         --#        in     LexTokenManager.State;
         --#        in out ErrorHandler.Error_Context;
         --#        in out Index_Table_P.Fatal_Error;
         --#        in out SPARK_IO.File_Sys;
         --# derives ErrorHandler.Error_Context,
         --#         Index_Table_P.Fatal_Error,
         --#         Last_Char,
         --#         SPARK_IO.File_Sys          from *,
         --#                                         CommandLineData.Content,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Index_File,
         --#                                         Index_Filename,
         --#                                         Last_Char,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys &
         --#         Is_In_Valid                from CommandLineData.Content,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Index_File,
         --#                                         Index_Filename,
         --#                                         Last_Char,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys;
         is
            Id       : E_Strings.T;
            Id_Valid : Boolean;
            Is_Valid : Boolean;
            In_Valid : Boolean;
            Next_Ch  : Character;
         begin
            Id := E_Strings.Empty_String;
            Read_An_Identifier
              (Index_File     => Index_File,
               Index_Filename => Index_Filename,
               Identifier     => Id,
               Last_Char      => Last_Char,
               Valid          => Id_Valid,
               Follower       => Next_Ch);
            if Id_Valid and then Next_Ch = ' ' then
               Is_Valid := E_Strings.Eq1_String (E_Str => Id,
                                                 Str   => "is");
            else
               Is_Valid := False;
            end if;

            if Is_Valid then
               Read_An_Identifier
                 (Index_File     => Index_File,
                  Index_Filename => Index_Filename,
                  Identifier     => Id,
                  Last_Char      => Last_Char,
                  Valid          => Id_Valid,
                  Follower       => Next_Ch);

               if Id_Valid and then Next_Ch = ' ' then
                  In_Valid := E_Strings.Eq1_String (E_Str => Id,
                                                    Str   => "in");
               else
                  In_Valid := False;
               end if;

               if In_Valid then
                  Is_In_Valid := True;
               else
                  Is_In_Valid := False;
               end if;
            else
               Is_In_Valid := False;
            end if;
         end Skip_Is_In;

         procedure Read_A_File_Location
           (Index_File          : in     SPARK_IO.File_Type;
            Index_Filename      : in     LexTokenManager.Lex_String;
            Last_Char           : in out Character;
            Entry_Filename      :    out E_Strings.T;
            File_Location_Valid :    out Boolean)
         --# global in     CommandLineData.Content;
         --#        in     LexTokenManager.State;
         --#        in out ErrorHandler.Error_Context;
         --#        in out Index_Table_P.Fatal_Error;
         --#        in out SPARK_IO.File_Sys;
         --# derives Entry_Filename,
         --#         ErrorHandler.Error_Context,
         --#         File_Location_Valid,
         --#         Last_Char,
         --#         SPARK_IO.File_Sys          from CommandLineData.Content,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Index_File,
         --#                                         Index_Filename,
         --#                                         Last_Char,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys &
         --#         Index_Table_P.Fatal_Error  from *,
         --#                                         CommandLineData.Content,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Index_File,
         --#                                         Index_Filename,
         --#                                         Last_Char,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys;
         is
            Ch               : Character;
            Read_OK          : Boolean;
            E_Str            : E_Strings.T;
            In_Quoted_String : Boolean;
         begin
            In_Quoted_String := False;

            E_Str := E_Strings.Empty_String;

            Skip_White_Space (File           => Index_File,
                              Index_Filename => Index_Filename,
                              Last_Char      => Last_Char);
            Get_Single_Char
              (File             => Index_File,
               Index_Filename   => Index_Filename,
               In_Quoted_String => False,
               Last_Char        => Last_Char,
               Ch               => Ch,
               OK               => Read_OK);
            loop
               -- Allow for quoted strings containing spaces
               exit when not Read_OK or else (Ch = ' ' and then not In_Quoted_String);

               if Ch = Ada.Characters.Latin_1.Quotation then
                  In_Quoted_String := not In_Quoted_String;
               else
                  E_Strings.Append_Char (E_Str => E_Str,
                                         Ch    => Ch);
               end if;

               Get_Single_Char
                 (File             => Index_File,
                  Index_Filename   => Index_Filename,
                  In_Quoted_String => In_Quoted_String,
                  Last_Char        => Last_Char,
                  Ch               => Ch,
                  OK               => Read_OK);
            end loop;
            Skip_White_Space (File           => Index_File,
                              Index_Filename => Index_Filename,
                              Last_Char      => Last_Char);
            Entry_Filename      := E_Str;
            File_Location_Valid := E_Strings.Get_Length (E_Str => E_Str) > 0;

         end Read_A_File_Location;

         procedure Read_Components
           (Index_File     : in     SPARK_IO.File_Type;
            Index_Filename : in     LexTokenManager.Lex_String;
            Last_Char      : in out Character;
            The_Components :    out Component_Lists;
            Entry_Valid    :    out Boolean)
         --# global in     CommandLineData.Content;
         --#        in out ErrorHandler.Error_Context;
         --#        in out Index_Table_P.Fatal_Error;
         --#        in out LexTokenManager.State;
         --#        in out SPARK_IO.File_Sys;
         --# derives Entry_Valid,
         --#         ErrorHandler.Error_Context,
         --#         Last_Char,
         --#         LexTokenManager.State,
         --#         SPARK_IO.File_Sys,
         --#         The_Components             from CommandLineData.Content,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Index_File,
         --#                                         Index_Filename,
         --#                                         Last_Char,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys &
         --#         Index_Table_P.Fatal_Error  from *,
         --#                                         CommandLineData.Content,
         --#                                         ErrorHandler.Error_Context,
         --#                                         Index_File,
         --#                                         Index_Filename,
         --#                                         Last_Char,
         --#                                         LexTokenManager.State,
         --#                                         SPARK_IO.File_Sys;
         is
            Id               : E_Strings.T;
            Token            : LexTokenManager.Lex_String;
            Index            : Component_Index;
            Component        : LexTokenLists.Lists;
            Valid            : Boolean;
            Next_Ch          : Character;
            Current_Position : File_Position;
         begin
            The_Components := Component_Lists'(others => LexTokenLists.Null_List);
            Index          := Component_Index'First;
            Id             := E_Strings.Empty_String;

            -- Locate the position of the "are"
            Get_Token_Position
              (Index_File     => Index_File,
               Index_Filename => Index_Filename,
               Last_Char      => Last_Char,
               Position       => Current_Position);
            Read_An_Identifier
              (Index_File     => Index_File,
               Index_Filename => Index_Filename,
               Identifier     => Id,
               Last_Char      => Last_Char,
               Valid          => Valid,
               Follower       => Next_Ch);

            Valid := Valid and then Next_Ch = ' ' and then E_Strings.Eq1_String (E_Str => Id,
                                                                                 Str   => "are");

            if Valid then
               loop -- over components
                  Id        := E_Strings.Empty_String;
                  Component := LexTokenLists.Null_List;
                  loop -- over component identifiers

                     -- Locate the position of the next identifier
                     Get_Token_Position
                       (Index_File     => Index_File,
                        Index_Filename => Index_Filename,
                        Last_Char      => Last_Char,
                        Position       => Current_Position);

                     Read_An_Identifier
                       (Index_File     => Index_File,
                        Index_Filename => Index_Filename,
                        Identifier     => Id,
                        Last_Char      => Last_Char,
                        Valid          => Valid,
                        Follower       => Next_Ch);
                     exit when not Valid;
                     LexTokenManager.Insert_Examiner_String (Str     => Id,
                                                             Lex_Str => Token);
                     LexTokenLists.Append (List => Component,
                                           Item => Token);
                     exit when Next_Ch /= '.';
                  end loop;
                  exit when not Valid;
                  The_Components (Index) := Component;
                  if Index < Component_Index'Last then
                     Index := Component_Index'Succ (Index);
                  else
                     SystemErrors.Fatal_Error (Sys_Err => SystemErrors.Index_Component_List_Full,
                                               Msg     => "");
                  end if;
                  exit when Next_Ch /= ',';
               end loop;
               Valid := Valid and then Next_Ch = ' ';
               if not Valid then
                  Index_Table_P.Output_Error
                    (E              => ES_Components,
                     Source_File    => Index_Filename,
                     Token_Position => Current_Position,
                     Token_String   => E_Strings.Empty_String);
               end if;
            else
               Index_Table_P.Output_Error
                 (E              => ES_Are,
                  Source_File    => Index_Filename,
                  Token_Position => Current_Position,
                  Token_String   => E_Strings.Empty_String);
            end if;
            The_Components (Index) := LexTokenLists.Null_List; -- list terminator
            Entry_Valid            := Valid;
         end Read_Components;

      begin -- Read_Entry
         Entry_Components := Component_Lists'(others => LexTokenLists.Null_List);

         Read_An_Entry_Name
           (Index_File        => Index_File,
            Index_Filename    => Index_Filename,
            Last_Char         => Last_Char,
            Entry_Unit_Export => Entry_Unit_Export,
            Entry_Type        => Entry_Type_Loc,
            Entry_Name_Valid  => Entry_Name_Valid);
         Entry_Type := Entry_Type_Loc;

         if Entry_Name_Valid then
            if Entry_Type_Loc = Component_List then
               Entry_Filename := E_Strings.Empty_String;
               Read_Components
                 (Index_File     => Index_File,
                  Index_Filename => Index_Filename,
                  Last_Char      => Last_Char,
                  The_Components => Entry_Components,
                  Entry_Valid    => Components_Valid);
               if Components_Valid then
                  Valid_Entry := True;
               else
                  Valid_Entry := False;
                  -- Errors are reported by Read_Components
                  SPARK_IO.Skip_Line (Index_File, 1);
               end if;
            else
               -- Locate the start of "is in"
               Get_Token_Position
                 (Index_File     => Index_File,
                  Index_Filename => Index_Filename,
                  Last_Char      => Last_Char,
                  Position       => Current_Position);

               Skip_Is_In
                 (Index_File     => Index_File,
                  Index_Filename => Index_Filename,
                  Last_Char      => Last_Char,
                  Is_In_Valid    => Is_In_Valid);
               if Is_In_Valid then
                  -- Locate the start of file location
                  Get_Token_Position
                    (Index_File     => Index_File,
                     Index_Filename => Index_Filename,
                     Last_Char      => Last_Char,
                     Position       => Current_Position);

                  Read_A_File_Location
                    (Index_File          => Index_File,
                     Index_Filename      => Index_Filename,
                     Last_Char           => Last_Char,
                     Entry_Filename      => Entry_Filename,
                     File_Location_Valid => File_Location_Valid);
                  if File_Location_Valid then
                     Valid_Entry := True;
                  else
                     Valid_Entry    := False;
                     Entry_Filename := E_Strings.Empty_String;
                     Index_Table_P.Output_Error
                       (E              => ES_FileLocation,
                        Source_File    => Index_Filename,
                        Token_Position => Current_Position,
                        Token_String   => E_Strings.Empty_String);
                  end if;
               else
                  Valid_Entry    := False;
                  Entry_Filename := E_Strings.Empty_String;
                  Index_Table_P.Output_Error
                    (E              => ES_IsIn,
                     Source_File    => Index_Filename,
                     Token_Position => Current_Position,
                     Token_String   => E_Strings.Empty_String);
                  SPARK_IO.Skip_Line (Index_File, 1);
               end if;
            end if;
         else
            Valid_Entry    := False;
            Entry_Filename := E_Strings.Empty_String;
            -- Error reported in call to ReadAnEntry
            SPARK_IO.Skip_Line (Index_File, 1);
         end if;
      end Read_Entry;

      procedure Handle_Main_P
        (Entry_Unit          : in     LexTokenLists.Lists;
         Required_Unit       : in     LexTokenLists.Lists;
         Entry_Filename      : in     E_Strings.T;
         Possible_Unit_Types : in     ContextManager.UnitTypeSets;
         Found               : in out Boolean;
         Returned_Filename   :    out E_Strings.T;
         Actual_Unit_Type    :    out ContextManager.UnitTypes)
      --# global in LexTokenManager.State;
      --# derives Actual_Unit_Type  from Entry_Unit,
      --#                                LexTokenManager.State,
      --#                                Possible_Unit_Types,
      --#                                Required_Unit &
      --#         Found             from *,
      --#                                Entry_Unit,
      --#                                LexTokenManager.State,
      --#                                Possible_Unit_Types,
      --#                                Required_Unit &
      --#         Returned_Filename from Entry_Filename,
      --#                                Entry_Unit,
      --#                                LexTokenManager.State,
      --#                                Possible_Unit_Types,
      --#                                Required_Unit;
      is
      begin
         if Possible_Unit_Types (ContextManager.MainProgram)
           and then LexTokenLists.Eq_Unit (First_Item => Entry_Unit,
                                           Second     => Required_Unit) then
            Found             := True;
            Returned_Filename := Entry_Filename;
            Actual_Unit_Type  := ContextManager.MainProgram;
         else
            Returned_Filename := E_Strings.Empty_String;
            Actual_Unit_Type  := ContextManager.InvalidUnit;
         end if;
      end Handle_Main_P;

      procedure Handle_P_Spec
        (Entry_Unit          : in     LexTokenLists.Lists;
         Required_Unit       : in     LexTokenLists.Lists;
         Entry_Filename      : in     E_Strings.T;
         Possible_Unit_Types : in     ContextManager.UnitTypeSets;
         Found               : in out Boolean;
         Returned_Filename   :    out E_Strings.T;
         Actual_Unit_Type    :    out ContextManager.UnitTypes)
      --# global in LexTokenManager.State;
      --# derives Actual_Unit_Type  from Entry_Unit,
      --#                                LexTokenManager.State,
      --#                                Possible_Unit_Types,
      --#                                Required_Unit &
      --#         Found             from *,
      --#                                Entry_Unit,
      --#                                LexTokenManager.State,
      --#                                Possible_Unit_Types,
      --#                                Required_Unit &
      --#         Returned_Filename from Entry_Filename,
      --#                                Entry_Unit,
      --#                                LexTokenManager.State,
      --#                                Possible_Unit_Types,
      --#                                Required_Unit;
      is
      begin
         if Possible_Unit_Types (ContextManager.PackageSpecification)
           and then LexTokenLists.Eq_Unit (First_Item => Entry_Unit,
                                           Second     => Required_Unit) then
            Found             := True;
            Returned_Filename := Entry_Filename;
            Actual_Unit_Type  := ContextManager.PackageSpecification;
         elsif Possible_Unit_Types (ContextManager.GenericSubprogramDeclaration)
           and then LexTokenLists.Eq_Unit (First_Item => Entry_Unit,
                                           Second     => Required_Unit) then
            Found             := True;
            Returned_Filename := Entry_Filename;
            Actual_Unit_Type  := ContextManager.GenericSubprogramDeclaration;
         else
            Returned_Filename := E_Strings.Empty_String;
            Actual_Unit_Type  := ContextManager.InvalidUnit;
         end if;
      end Handle_P_Spec;

      procedure Handle_P_Bodi
        (Entry_Unit          : in     LexTokenLists.Lists;
         Required_Unit       : in     LexTokenLists.Lists;
         Entry_Filename      : in     E_Strings.T;
         Possible_Unit_Types : in     ContextManager.UnitTypeSets;
         Found               : in out Boolean;
         Returned_Filename   :    out E_Strings.T;
         Actual_Unit_Type    :    out ContextManager.UnitTypes)
      --# global in LexTokenManager.State;
      --# derives Actual_Unit_Type  from Entry_Unit,
      --#                                LexTokenManager.State,
      --#                                Possible_Unit_Types,
      --#                                Required_Unit &
      --#         Found             from *,
      --#                                Entry_Unit,
      --#                                LexTokenManager.State,
      --#                                Possible_Unit_Types,
      --#                                Required_Unit &
      --#         Returned_Filename from Entry_Filename,
      --#                                Entry_Unit,
      --#                                LexTokenManager.State,
      --#                                Possible_Unit_Types,
      --#                                Required_Unit;
      is
      begin
         if Possible_Unit_Types (ContextManager.PackageBody)
           and then LexTokenLists.Eq_Unit (First_Item => Entry_Unit,
                                           Second     => Required_Unit) then
            Found             := True;
            Returned_Filename := Entry_Filename;
            Actual_Unit_Type  := ContextManager.PackageBody;
         else
            Returned_Filename := E_Strings.Empty_String;
            Actual_Unit_Type  := ContextManager.InvalidUnit;
         end if;
      end Handle_P_Bodi;

      procedure Handle_Subunit
        (Entry_Unit          : in     LexTokenLists.Lists;
         Required_Unit       : in     LexTokenLists.Lists;
         Entry_Filename      : in     E_Strings.T;
         Possible_Unit_Types : in     ContextManager.UnitTypeSets;
         Found               : in out Boolean;
         Returned_Filename   :    out E_Strings.T;
         Actual_Unit_Type    :    out ContextManager.UnitTypes)
      --# global in LexTokenManager.State;
      --# derives Actual_Unit_Type  from Entry_Unit,
      --#                                LexTokenManager.State,
      --#                                Possible_Unit_Types,
      --#                                Required_Unit &
      --#         Found             from *,
      --#                                Entry_Unit,
      --#                                LexTokenManager.State,
      --#                                Possible_Unit_Types,
      --#                                Required_Unit &
      --#         Returned_Filename from Entry_Filename,
      --#                                Entry_Unit,
      --#                                LexTokenManager.State,
      --#                                Possible_Unit_Types,
      --#                                Required_Unit;
      is
      begin
         if Possible_Unit_Types (ContextManager.SubUnit)
           and then LexTokenLists.Eq_Unit (First_Item => Entry_Unit,
                                           Second     => Required_Unit) then
            Found             := True;
            Returned_Filename := Entry_Filename;
            Actual_Unit_Type  := ContextManager.SubUnit;
         else
            Returned_Filename := E_Strings.Empty_String;
            Actual_Unit_Type  := ContextManager.InvalidUnit;
         end if;
      end Handle_Subunit;

      procedure Handle_Components
        (Entry_Unit       : in     LexTokenLists.Lists;
         Required_Unit    : in     LexTokenLists.Lists;
         Entry_Components : in     Component_Lists;
         Components       : in out Component_Lists;
         Found            : in out Boolean)
      --# global in LexTokenManager.State;
      --# derives Components from *,
      --#                         Entry_Components,
      --#                         Entry_Unit,
      --#                         LexTokenManager.State,
      --#                         Required_Unit &
      --#         Found      from *,
      --#                         Entry_Unit,
      --#                         LexTokenManager.State,
      --#                         Required_Unit;
      is
      begin
         if LexTokenLists.Eq_Unit (First_Item => Entry_Unit,
                                   Second     => Required_Unit) then
            Found      := True;
            Components := Entry_Components;
         end if;
      end Handle_Components;

      function Get_SPARK_Lib_Index_Filename (Index_Base_Name : in String) return E_Strings.T
      --# global in SPARK_IO.File_Sys;
      is
         Index_Filename : E_Strings.T;
      begin
         Index_Filename := FileSystem.Examiner_SPARK_Lib_Directory;
         E_Strings.Append_Examiner_String (E_Str1 => Index_Filename,
                                           E_Str2 => FileSystem.Directory_Separator);
         E_Strings.Append_String (E_Str => Index_Filename,
                                  Str   => Index_Base_Name);
         return Index_Filename;
      end Get_SPARK_Lib_Index_Filename;

   begin -- Look_In_File
      Returned_Filename := LexTokenManager.Null_String;
      Actual_Unit_Type  := ContextManager.InvalidUnit;
      Components        := Component_Lists'(others => LexTokenLists.Null_List);
      Found             := False;
      if CommandLineData.Content.Index then
         --  We never assume that the list of index file has been
         --  initialized.

         --# accept F, 10, File_Spec_Status, "Expect File_Spec_Status Unused";
         FileSystem.Find_Full_File_Name
           (File_Spec      => CommandLineData.Content.Index_File_Name,
            File_Status    => File_Spec_Status,
            Full_File_Name => Index_Filename);
         --# end accept;
         FileSystem.Check_Extension
           (Fn  => Index_Filename,
            Ext => E_Strings.Copy_String (Str => CommandLineData.Default_Index_Extension));
         Index_Table_P.Add_Index_File
           (Filename => FileSystem.Interpret_Relative (File_Name             => Index_Filename,
                                                       Relative_To_Directory => Index_Filename));
         if CommandLineData.Content.SPARK_Lib then
            -- make the SPARK library visible
            LexTokenManager.Insert_Examiner_String (Str     => Index_Filename,
                                                    Lex_Str => Current_Index_Filename);

            -- Add "SPARK auxindex is in <lib directory>/spark.idx" to the user's index file
            SPARK_Library_Unit := LexTokenLists.Null_List;
            LexTokenLists.Append (List => SPARK_Library_Unit,
                                  Item => LexTokenManager.SPARK_Token);
            Index_Table_P.Add_Aux_Index_File
              (Filename    => Get_SPARK_Lib_Index_Filename ("spark.idx"),
               Unit        => SPARK_Library_Unit,
               Position    => File_Position'(Line => 1,
                                             Col  => 1),
               Source_File => Current_Index_Filename);

            -- Add "Interfaces auxindex is in <lib directory>/interfaces.idx" to the user's index file
            Interfaces_Library_Unit := LexTokenLists.Null_List;
            LexTokenLists.Append (List => Interfaces_Library_Unit,
                                  Item => LexTokenManager.Interfaces_Token);
            Index_Table_P.Add_Aux_Index_File
              (Filename    => Get_SPARK_Lib_Index_Filename ("interfaces.idx"),
               Unit        => Interfaces_Library_Unit,
               Position    => File_Position'(Line => 1,
                                             Col  => 1),
               Source_File => Current_Index_Filename);

            -- Add "Ada auxindex is in <lib directory>/ada.idx" to the user's index file
            Ada_Library_Unit := LexTokenLists.Null_List;
            LexTokenLists.Append (List => Ada_Library_Unit,
                                  Item => LexTokenManager.Ada_Token);
            Index_Table_P.Add_Aux_Index_File
              (Filename    => Get_SPARK_Lib_Index_Filename ("ada.idx"),
               Unit        => Ada_Library_Unit,
               Position    => File_Position'(Line => 1,
                                             Col  => 1),
               Source_File => Current_Index_Filename);

         end if;
      elsif CommandLineData.Content.SPARK_Lib then
         -- No index file provided by the user but make SPARK library visible

         -- In this case, we set the (sole) index file as sparklib.idx which is
         -- assumed to contain references or auxiliary indexes for the entire
         -- SPARK Library.
         Index_Table_P.Add_Index_File (Filename => Get_SPARK_Lib_Index_Filename ("sparklib.idx"));
      end if;
      if CommandLineData.Content.Index or else CommandLineData.Content.SPARK_Lib then
         Index_Table_P.Get_Next_Index_File
           (Unit           => Required_Unit,
            Top_Filename   => Top_Filename,
            Filename       => Current_Index_Filename,
            File_Type      => Entry_Type,
            Aux_Index_Unit => Aux_Index_Unit,
            Position       => Source_Position);
         if CommandLineData.Content.Debug.File_Names then
            --  Debug
            SPARK_IO.Put_String (File => SPARK_IO.Standard_Output,
                                 Item => "INDEX MANAGER GET INDEX FILE = ",
                                 Stop => 0);
            Index_Table_P.Debug_Put_E_Str
              (E_Str    => LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename),
               New_Line => True);
         end if;
         In_Aux_Index := Entry_Type = Aux_Index;
         case Entry_Type is
            when Super_Index =>
               Poss_Error_Type := EW_Super;
            when others =>
               Poss_Error_Type := EW_Index;
         end case;
         if LexTokenManager.Lex_String_Case_Insensitive_Compare
           (Lex_Str1 => Current_Index_Filename,
            Lex_Str2 => LexTokenManager.Null_String) /=
           LexTokenManager.Str_Eq then
            Last_Filename := LexTokenManager.Null_String;
            Done          := False;
            loop
               Index_File := SPARK_IO.Null_File;
               E_Strings.Open
                 (File         => Index_File,
                  Mode_Of_File => SPARK_IO.In_File,
                  Name_Of_File => LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename),
                  Form_Of_File => "",
                  Status       => File_Status);

               --# accept F, 41, "Stable expression expected here";
               if CommandLineData.Content.Debug.File_Names then
                  --  Debug
                  SPARK_IO.Put_String (File => SPARK_IO.Standard_Output,
                                       Item => "INDEX MANAGER OPEN INDEX FILE = ",
                                       Stop => 0);
                  Index_Table_P.Debug_Put_E_Str
                    (E_Str    => LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename),
                     New_Line => True);
               end if;
               --# end accept;
               if File_Status = SPARK_IO.Ok then
                  L_Returned_Filename := E_Strings.Empty_String;
                  L_Actual_Unit_Type  := ContextManager.InvalidUnit;
                  L_Components        := Component_Lists'(others => LexTokenLists.Null_List);
                  L_Found             := False;

                  Super_Index_Found := False;
                  First_In_File     := True;
                  Last_Char         := Ada.Characters.Latin_1.NUL;
                  loop
                     exit when SPARK_IO.End_Of_File (Index_File);
                     -- Get Start of Entry
                     Get_Token_Position
                       (Index_File     => Index_File,
                        Index_Filename => Current_Index_Filename,
                        Last_Char      => Last_Char,
                        Position       => Position);
                     Read_Entry
                       (Index_File        => Index_File,
                        Index_Filename    => Current_Index_Filename,
                        Last_Char         => Last_Char,
                        Entry_Unit_Export => Entry_Unit,
                        Entry_Type        => Entry_Type,
                        Entry_Filename    => Entry_Filename,
                        Entry_Components  => Entry_Components,
                        Valid_Entry       => Valid_Entry);

                     if Valid_Entry then

                        if In_Aux_Index
                          and then not LexTokenLists.Prefix_Unit (Poss_Prefix => Aux_Index_Unit,
                                                                  Prefixed    => Entry_Unit) then
                           Index_Table_P.Output_Error
                             (E              => EW_Aux,
                              Source_File    => Current_Index_Filename,
                              Token_Position => Position,
                              Token_String   => LexTokenLists.Token_List_To_String (Token_List => Aux_Index_Unit));
                        end if;

                        case Entry_Type is
                           when Super_Index =>
                              if In_Aux_Index or Super_Index_Found or not First_In_File then
                                 Index_Table_P.Output_Error
                                   (E              => EW_UnexpectedSuper,
                                    Source_File    => Current_Index_Filename,
                                    Token_Position => Position,
                                    Token_String   => E_Strings.Empty_String);
                              else
                                 Super_Index_Found := True;
                                 FileSystem.Check_Extension
                                   (Fn  => Entry_Filename,
                                    Ext => E_Strings.Copy_String (Str => CommandLineData.Default_Index_Extension));
                                 Index_Table_P.Add_Super_Index_File
                                   (Filename    => FileSystem.Interpret_Relative
                                      (File_Name             => Entry_Filename,
                                       Relative_To_Directory =>
                                         LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename)),
                                    Position    => Position,
                                    Source_File => Current_Index_Filename);
                                 --# accept F, 41, "Stable expression expected here";
                                 if CommandLineData.Content.Debug.File_Names then
                                    --  Debug
                                    SPARK_IO.Put_String
                                      (File => SPARK_IO.Standard_Output,
                                       Item => "INDEX MANAGER ADD SUPER INDEX FILE = ",
                                       Stop => 0);
                                    Index_Table_P.Debug_Put_E_Str
                                      (E_Str    => FileSystem.Interpret_Relative
                                         (File_Name             => Entry_Filename,
                                          Relative_To_Directory =>
                                            LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename)),
                                       New_Line => True);
                                 end if;
                                 --# end accept;
                              end if;
                           when Aux_Index =>
                              FileSystem.Check_Extension
                                (Fn  => Entry_Filename,
                                 Ext => E_Strings.Copy_String (Str => CommandLineData.Default_Index_Extension));
                              Index_Table_P.Add_Aux_Index_File
                                (Filename    => FileSystem.Interpret_Relative
                                   (File_Name             => Entry_Filename,
                                    Relative_To_Directory =>
                                      LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename)),
                                 Unit        => Entry_Unit,
                                 Position    => Position,
                                 Source_File => Current_Index_Filename);
                              --# accept F, 41, "Stable expression expected here";
                              if CommandLineData.Content.Debug.File_Names then
                                 --  Debug
                                 SPARK_IO.Put_String
                                   (File => SPARK_IO.Standard_Output,
                                    Item => "INDEX MANAGER ADD AUX INDEX FILE = ",
                                    Stop => 0);
                                 Index_Table_P.Debug_Put_E_Str
                                   (E_Str    => FileSystem.Interpret_Relative
                                      (File_Name             => Entry_Filename,
                                       Relative_To_Directory =>
                                         LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename)),
                                    New_Line => True);
                              end if;
                              --# end accept;
                           when Main_P =>
                              --# accept F, 41, "Stable expression expected here";
                              if not Lookup_Components then
                                 Handle_Main_P
                                   (Entry_Unit          => Entry_Unit,
                                    Required_Unit       => Required_Unit,
                                    Entry_Filename      => Entry_Filename,
                                    Possible_Unit_Types => Possible_Unit_Types,
                                    Found               => L_Found,
                                    Returned_Filename   => L_Returned_Filename,
                                    Actual_Unit_Type    => L_Actual_Unit_Type);
                              end if;
                              --# end accept;
                              FileSystem.Check_Extension (Fn  => Entry_Filename,
                                                          Ext => CommandLineData.Content.Source_Extension);
                              Cache.Add_Unit
                                (Unit            => Entry_Unit,
                                 Unit_Types      => ContextManager.MainProgram,
                                 Source_Filename => FileSystem.Interpret_Relative
                                   (File_Name             => Entry_Filename,
                                    Relative_To_Directory =>
                                      LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename)),
                                 Index_Filename  => Current_Index_Filename,
                                 Index_Position  => Position);
                           when P_Spec =>
                              --# accept F, 41, "Stable expression expected here";
                              if not Lookup_Components then
                                 Handle_P_Spec
                                   (Entry_Unit          => Entry_Unit,
                                    Required_Unit       => Required_Unit,
                                    Entry_Filename      => Entry_Filename,
                                    Possible_Unit_Types => Possible_Unit_Types,
                                    Found               => L_Found,
                                    Returned_Filename   => L_Returned_Filename,
                                    Actual_Unit_Type    => L_Actual_Unit_Type);
                              end if;
                              --# end accept;
                              FileSystem.Check_Extension (Fn  => Entry_Filename,
                                                          Ext => CommandLineData.Content.Source_Extension);
                              Cache.Add_Unit
                                (Unit            => Entry_Unit,
                                 Unit_Types      => ContextManager.PackageSpecification,
                                 Source_Filename => FileSystem.Interpret_Relative
                                   (File_Name             => Entry_Filename,
                                    Relative_To_Directory =>
                                      LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename)),
                                 Index_Filename  => Current_Index_Filename,
                                 Index_Position  => Position);
                              -- GenOption -- when GenericDec => HandleGenericDec;
                           when P_Bodi =>
                              --# accept F, 41, "Stable expression expected here";
                              if not Lookup_Components then
                                 Handle_P_Bodi
                                   (Entry_Unit          => Entry_Unit,
                                    Required_Unit       => Required_Unit,
                                    Entry_Filename      => Entry_Filename,
                                    Possible_Unit_Types => Possible_Unit_Types,
                                    Found               => L_Found,
                                    Returned_Filename   => L_Returned_Filename,
                                    Actual_Unit_Type    => L_Actual_Unit_Type);
                              end if;
                              --# end accept;
                              FileSystem.Check_Extension (Fn  => Entry_Filename,
                                                          Ext => CommandLineData.Content.Source_Extension);
                              Cache.Add_Unit
                                (Unit            => Entry_Unit,
                                 Unit_Types      => ContextManager.PackageBody,
                                 Source_Filename => FileSystem.Interpret_Relative
                                   (File_Name             => Entry_Filename,
                                    Relative_To_Directory =>
                                      LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename)),
                                 Index_Filename  => Current_Index_Filename,
                                 Index_Position  => Position);
                           when Subunit =>
                              --# accept F, 41, "Stable expression expected here";
                              if not Lookup_Components then
                                 Handle_Subunit
                                   (Entry_Unit          => Entry_Unit,
                                    Required_Unit       => Required_Unit,
                                    Entry_Filename      => Entry_Filename,
                                    Possible_Unit_Types => Possible_Unit_Types,
                                    Found               => L_Found,
                                    Returned_Filename   => L_Returned_Filename,
                                    Actual_Unit_Type    => L_Actual_Unit_Type);
                              end if;
                              --# end accept;
                              FileSystem.Check_Extension (Fn  => Entry_Filename,
                                                          Ext => CommandLineData.Content.Source_Extension);
                              Cache.Add_Unit
                                (Unit            => Entry_Unit,
                                 Unit_Types      => ContextManager.SubUnit,
                                 Source_Filename => FileSystem.Interpret_Relative
                                   (File_Name             => Entry_Filename,
                                    Relative_To_Directory =>
                                      LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename)),
                                 Index_Filename  => Current_Index_Filename,
                                 Index_Position  => Position);
                           when Component_List =>
                              --# accept F, 41, "Stable expression expected here";
                              if Lookup_Components then
                                 Handle_Components
                                   (Entry_Unit       => Entry_Unit,
                                    Required_Unit    => Required_Unit,
                                    Entry_Components => Entry_Components,
                                    Components       => L_Components,
                                    Found            => L_Found);
                              end if;
                              --# end accept;
                              Cache.Add_Components
                                (Unit           => Entry_Unit,
                                 Components     => Entry_Components,
                                 Index_Filename => Current_Index_Filename,
                                 Index_Position => Position);
                           when Invalid_Entry_Type =>
                              null;
                        end case;
                     end if;
                     if L_Found then
                        Actual_Unit_Type := L_Actual_Unit_Type;
                        Components       := L_Components;
                        Found            := True;
                        --# accept F, 41, "Stable expression expected here";
                        if not Lookup_Components then
                           FileSystem.Check_Extension (Fn  => L_Returned_Filename,
                                                       Ext => CommandLineData.Content.Source_Extension);
                           LexTokenManager.Insert_Examiner_String
                             (Str     => FileSystem.Interpret_Relative
                                (File_Name             => L_Returned_Filename,
                                 Relative_To_Directory => LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename)),
                              Lex_Str => Returned_Filename);
                        end if;
                        --# end accept;
                        --# accept F, 41, "Stable expression expected here";
                        if CommandLineData.Content.Debug.File_Names then
                           --  Debug
                           if Lookup_Components then
                              SPARK_IO.Put_String (File => SPARK_IO.Standard_Output,
                                                   Item => "INDEXMANAGER FOUND ",
                                                   Stop => 0);
                              for I in Component_Index loop
                                 if Components (I) /= LexTokenLists.Null_List then
                                    LexTokenLists.Print_List (File => SPARK_IO.Standard_Output,
                                                              List => Components (I));
                                 end if;
                              end loop;
                           else
                              SPARK_IO.Put_String (File => SPARK_IO.Standard_Output,
                                                   Item => "INDEXMANAGER FOUND IN ",
                                                   Stop => 0);
                              Index_Table_P.Debug_Put_E_Str
                                (E_Str    => LexTokenManager.Lex_String_To_String (Lex_Str => Returned_Filename),
                                 New_Line => False);
                              SPARK_IO.Put_String (File => SPARK_IO.Standard_Output,
                                                   Item => " FOR TYPE ",
                                                   Stop => 0);
                              Cache.Context_Manager_Unit_Types_Image (Unit_Type => Actual_Unit_Type);
                           end if;
                           SPARK_IO.New_Line (File    => SPARK_IO.Standard_Output,
                                              Spacing => 1);
                        end if;
                        --# end accept;
                     end if;
                     L_Found       := False;
                     First_In_File := False;
                  end loop;

                  Last_Filename := Current_Index_Filename;
                  Index_Table_P.Index_File_Done (Filename => Current_Index_Filename);
                  --# accept F, 10, Index_File, "Expect ineffective assignment" &
                  --#        F, 10, File_Status, "Expect ineffective assignment";
                  SPARK_IO.Close (Index_File, File_Status);
                  --# end accept;
                  --# accept F, 41, "Stable expression expected here";
                  if CommandLineData.Content.Debug.File_Names then
                     --  Debug
                     SPARK_IO.Put_String
                       (File => SPARK_IO.Standard_Output,
                        Item => "INDEX MANAGER CLOSE INDEX FILE = ",
                        Stop => 0);
                     Index_Table_P.Debug_Put_E_Str
                       (E_Str    => LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename),
                        New_Line => True);
                  end if;
                  --# end accept;
                  Index_Table_P.Stop_SPARK;
                  if Found then
                     Done := True;
                  else
                     Index_Table_P.Get_Next_Index_File
                       (Unit           => Required_Unit,
                        Top_Filename   => Top_Filename,
                        Filename       => Current_Index_Filename,
                        File_Type      => Entry_Type,
                        Aux_Index_Unit => Aux_Index_Unit,
                        Position       => Source_Position);
                     --# accept F, 41, "Stable expression expected here";
                     if CommandLineData.Content.Debug.File_Names then
                        --  Debug
                        SPARK_IO.Put_String
                          (File => SPARK_IO.Standard_Output,
                           Item => "INDEX MANAGER GET INDEX FILE = ",
                           Stop => 0);
                        Index_Table_P.Debug_Put_E_Str
                          (E_Str    => LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename),
                           New_Line => True);
                     end if;
                     --# end accept;
                     In_Aux_Index := Entry_Type = Aux_Index;
                     case Entry_Type is
                        when Super_Index =>
                           Poss_Error_Type := EW_Super;
                        when others =>
                           Poss_Error_Type := EW_Index;
                     end case;
                     if LexTokenManager.Lex_String_Case_Insensitive_Compare
                       (Lex_Str1 => Current_Index_Filename,
                        Lex_Str2 => LexTokenManager.Null_String) =
                       LexTokenManager.Str_Eq then
                        Found := False;
                        Done  := True;
                     end if;
                  end if;
               else
                  Found := False;
                  Done  := True;
                  Index_Table_P.Index_File_Done (Filename => Current_Index_Filename);
                  Index_Table_P.Output_Error
                    (E              => Poss_Error_Type,
                     Source_File    => Last_Filename,
                     Token_Position => Source_Position,
                     Token_String   => LexTokenManager.Lex_String_To_String (Lex_Str => Current_Index_Filename));
               end if;
               exit when Done;
            end loop;
         end if;
      end if;
      --# accept F, 33, File_Spec_Status, "Expect File_Spec_Status unused";
   end Look_In_File;

   procedure Look_Up
     (Required_Unit       : in     LexTokenLists.Lists;
      Possible_Unit_Types : in     ContextManager.UnitTypeSets;
      Source_Filename     :    out LexTokenManager.Lex_String;
      Actual_Unit_Type    :    out ContextManager.UnitTypes;
      Found               :    out Boolean)
   --# global in     CommandLineData.Content;
   --#        in out Cache.The_Unit_Hash;
   --#        in out ErrorHandler.Error_Context;
   --#        in out Index_Table_P.Fatal_Error;
   --#        in out Index_Table_P.Index_Table;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Actual_Unit_Type,
   --#         Cache.The_Unit_Hash,
   --#         ErrorHandler.Error_Context,
   --#         Found,
   --#         Index_Table_P.Index_Table,
   --#         LexTokenManager.State,
   --#         Source_Filename,
   --#         SPARK_IO.File_Sys          from Cache.The_Unit_Hash,
   --#                                         CommandLineData.Content,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Index_Table_P.Index_Table,
   --#                                         LexTokenManager.State,
   --#                                         Possible_Unit_Types,
   --#                                         Required_Unit,
   --#                                         SPARK_IO.File_Sys &
   --#         Index_Table_P.Fatal_Error  from *,
   --#                                         Cache.The_Unit_Hash,
   --#                                         CommandLineData.Content,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Index_Table_P.Index_Table,
   --#                                         LexTokenManager.State,
   --#                                         Possible_Unit_Types,
   --#                                         Required_Unit,
   --#                                         SPARK_IO.File_Sys;
   is
      Components : Component_Lists;

      Source_Filename_From_Cache  : LexTokenManager.Lex_String;
      Source_Filename_From_File   : LexTokenManager.Lex_String;
      Actual_Unit_Type_From_Cache : ContextManager.UnitTypes;
      Actual_Unit_Type_From_File  : ContextManager.UnitTypes;
      Found_From_Cache            : Boolean;
      Found_From_File             : Boolean;
      Need_To_Look_In_File        : Boolean;

      Index_Filename_From_Cache : LexTokenManager.Lex_String;
      Index_Filename            : LexTokenManager.Lex_String;
      File_Type                 : Entry_Types;
      Dummy_Aux_Index_Unit      : LexTokenLists.Lists;
      Dummy_Source_Position     : File_Position;

      procedure Trace (S : in LexTokenManager.Lex_String;
                       M : in String)
      --# global in     CommandLineData.Content;
      --#        in     LexTokenManager.State;
      --#        in out SPARK_IO.File_Sys;
      --# derives SPARK_IO.File_Sys from *,
      --#                                CommandLineData.Content,
      --#                                LexTokenManager.State,
      --#                                M,
      --#                                S;
      is
      begin
         if CommandLineData.Content.Debug.File_Names then
            SPARK_IO.Put_String (SPARK_IO.Standard_Output, M, 0);

            if CommandLineData.Content.Plain_Output then
               --# accept F, 22, "Stable expression here OK";
               if FileSystem.Use_Windows_Command_Line then
                  --# end accept;
                  E_Strings.Put_Line
                    (File  => SPARK_IO.Standard_Output,
                     E_Str => E_Strings.Lower_Case
                       (E_Str => FileSystem.Just_File (Fn  => LexTokenManager.Lex_String_To_String (Lex_Str => S),
                                                       Ext => True)));
               else
                  E_Strings.Put_Line
                    (File  => SPARK_IO.Standard_Output,
                     E_Str => FileSystem.Just_File (Fn  => LexTokenManager.Lex_String_To_String (Lex_Str => S),
                                                    Ext => True));
               end if;
            else
               E_Strings.Put_Line (File  => SPARK_IO.Standard_Output,
                                   E_Str => LexTokenManager.Lex_String_To_String (Lex_Str => S));
            end if;
         end if;
      end Trace;

   begin -- Look_Up
      if CommandLineData.Content.Debug.File_Names then
         --  Debug
         SPARK_IO.Put_String (File => SPARK_IO.Standard_Output,
                              Item => "INDEX MANAGER LOOKING FOR ",
                              Stop => 0);
         LexTokenLists.Print_List (File => SPARK_IO.Standard_Output,
                                   List => Required_Unit);
         SPARK_IO.Put_String (File => SPARK_IO.Standard_Output,
                              Item => " IN",
                              Stop => 0);
      end if;
      --  Try to find the required unit in the cache.
      Source_Filename_From_Cache  := LexTokenManager.Null_String;
      Actual_Unit_Type_From_Cache := ContextManager.InvalidUnit;
      Index_Filename_From_Cache   := LexTokenManager.Null_String;
      Found_From_Cache            := False;
      Found_From_File             := False;
      for I in ContextManager.UnitTypes loop
         if Possible_Unit_Types (I) then
            Actual_Unit_Type_From_Cache := I;
            Cache.Get_Unit
              (Required_Unit   => Required_Unit,
               Unit_Types      => Actual_Unit_Type_From_Cache,
               Source_Filename => Source_Filename_From_Cache,
               Index_Filename  => Index_Filename_From_Cache,
               Found           => Found_From_Cache);
            --# accept F, 41, "Stable expression expected here";
            if CommandLineData.Content.Debug.File_Names then
               --  Debug
               SPARK_IO.Put_Char (File => SPARK_IO.Standard_Output,
                                  Item => ' ');
               Cache.Context_Manager_Unit_Types_Image (Unit_Type => Actual_Unit_Type_From_Cache);
            end if;
            --# end accept;
         end if;
         exit when Found_From_Cache;
      end loop;
      if CommandLineData.Content.Debug.File_Names then
         --  Debug
         SPARK_IO.New_Line (File    => SPARK_IO.Standard_Output,
                            Spacing => 1);
      end if;
      if Found_From_Cache then
         --  The required unit has been found in the cache => check if
         --  a more local definition of the required unit may exist in
         --  a not yet parsed auxiliary index file.
         --
         --  The Filename and Aux_Index_Unit values returned from the
         --  call to Index_Table_P.Get_Next_Index_File, rather the
         --  Index_Filename_From_Cache is retained as the most global
         --  index file for Look_In_File.

         --# accept F, 10, Dummy_Aux_Index_Unit, "Ineffective assignment here OK" &
         --#        F, 10, Dummy_Source_Position, "Ineffective assignment here OK";
         Index_Table_P.Get_Next_Index_File
           (Unit           => Required_Unit,
            Top_Filename   => Index_Filename_From_Cache,
            Filename       => Index_Filename,
            File_Type      => File_Type,
            Aux_Index_Unit => Dummy_Aux_Index_Unit,
            Position       => Dummy_Source_Position);
         --# end accept;
         Need_To_Look_In_File := File_Type = Aux_Index;
         if CommandLineData.Content.Debug.File_Names then
            --  Debug

            --  Index_Table_P.Get_Next_Index may return an yet
            --  unparsed auxiliary index or super index.
            SPARK_IO.Put_String (File => SPARK_IO.Standard_Output,
                                 Item => "INDEX FILENAME NOT YET PARSED : ",
                                 Stop => 0);
            Index_Table_P.Debug_Put_E_Str
              (E_Str    => LexTokenManager.Lex_String_To_String (Lex_Str => Index_Filename),
               New_Line => True);
         end if;
      else
         --  The required unit is not in the cache => need to lookup
         --  in the index files.
         Index_Filename_From_Cache := LexTokenManager.Null_String;
         Need_To_Look_In_File      := True;
      end if;
      if Need_To_Look_In_File then
         --  The required unit has not been found in the cache => need
         --  to lookup in the index files
         --
         --  or
         --
         --  a more local definition of the required unit may exist in
         --  a not yet parsed index file => need to lookup in the more
         --  local index files only.

         --# accept F, 10, Components, "Ineffective assignment here OK";
         Look_In_File
           (Lookup_Components   => False,
            Required_Unit       => Required_Unit,
            Possible_Unit_Types => Possible_Unit_Types,
            Top_Filename        => Index_Filename_From_Cache,
            Returned_Filename   => Source_Filename_From_File,
            Actual_Unit_Type    => Actual_Unit_Type_From_File,
            Components          => Components,
            Found               => Found_From_File);
         --# end accept;
         if Found_From_File then
            --  The required unit has been found in the index files or
            --  a more local definition of the required unit has been
            --  found in a previously unparsed auxiliary index file =>
            --  the answer is the value coming from the index file.
            Source_Filename  := Source_Filename_From_File;
            Actual_Unit_Type := Actual_Unit_Type_From_File;
         elsif Found_From_Cache then
            --  A more local definition of the required unit has not
            --  been found in the index files => the answer is the
            --  value stored in the cache.
            Source_Filename  := Source_Filename_From_Cache;
            Actual_Unit_Type := Actual_Unit_Type_From_Cache;
         else
            --  The required unit has not been found either in the
            --  cache or in the index files => the required unit can
            --  not be located.
            Source_Filename  := LexTokenManager.Null_String;
            Actual_Unit_Type := ContextManager.InvalidUnit;
         end if;
      else
         --  The required unit has been found in the cache and no more
         --  local definition of the required unit can exist => the
         --  answer is the value stored in the cache.
         Source_Filename  := Source_Filename_From_Cache;
         Actual_Unit_Type := Actual_Unit_Type_From_Cache;
      end if;
      Found := Found_From_Cache or Found_From_File;
      if Found then
         Trace (S => Source_Filename,
                M => "IndexManager.Lookup Source_Filename is:");
      end if;
      --# accept F, 33, Components, "Expect Components unused" &
      --#        F, 33, Dummy_Aux_Index_Unit, "Expect Dummy_Aux_Index_Unit unused" &
      --#        F, 33, Dummy_Source_Position, "Expect Dummy_Source_Position unused";
   end Look_Up;

   procedure Look_Up_Components (Required_Unit : in     LexTokenLists.Lists;
                                 Components    :    out Component_Lists)
   --# global in     CommandLineData.Content;
   --#        in out Cache.The_Unit_Hash;
   --#        in out ErrorHandler.Error_Context;
   --#        in out Index_Table_P.Fatal_Error;
   --#        in out Index_Table_P.Index_Table;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Cache.The_Unit_Hash,
   --#         Components,
   --#         ErrorHandler.Error_Context,
   --#         Index_Table_P.Index_Table,
   --#         LexTokenManager.State,
   --#         SPARK_IO.File_Sys          from Cache.The_Unit_Hash,
   --#                                         CommandLineData.Content,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Index_Table_P.Index_Table,
   --#                                         LexTokenManager.State,
   --#                                         Required_Unit,
   --#                                         SPARK_IO.File_Sys &
   --#         Index_Table_P.Fatal_Error  from *,
   --#                                         Cache.The_Unit_Hash,
   --#                                         CommandLineData.Content,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Index_Table_P.Index_Table,
   --#                                         LexTokenManager.State,
   --#                                         Required_Unit,
   --#                                         SPARK_IO.File_Sys;
   is
      Possible_Unit_Types : constant ContextManager.UnitTypeSets :=
        ContextManager.UnitTypeSets'(ContextManager.InvalidUnit => True,
                                     others                     => False);
      Source_Filename     : LexTokenManager.Lex_String;
      Actual_Unit_Type    : ContextManager.UnitTypes;

      Components_From_Cache : Component_Lists;
      Components_From_File  : Component_Lists;
      Found_From_Cache      : Boolean;
      Found_From_File       : Boolean;
      Need_To_Look_In_File  : Boolean;

      Index_Filename_From_Cache : LexTokenManager.Lex_String;
      Index_Filename            : LexTokenManager.Lex_String;
      File_Type                 : Entry_Types;
      Dummy_Aux_Index_Unit      : LexTokenLists.Lists;
      Dummy_Source_Position     : File_Position;
   begin
      if CommandLineData.Content.Debug.File_Names then
         --  Debug
         SPARK_IO.Put_String (File => SPARK_IO.Standard_Output,
                              Item => "INDEX MANAGER LOOKING UP COMPONENTS FOR ",
                              Stop => 0);
         LexTokenLists.Print_List (File => SPARK_IO.Standard_Output,
                                   List => Required_Unit);
         SPARK_IO.New_Line (File    => SPARK_IO.Standard_Output,
                            Spacing => 1);
      end if;
      --  Try to find the required unit in the cache.
      Cache.Get_Components
        (Required_Unit  => Required_Unit,
         Components     => Components_From_Cache,
         Index_Filename => Index_Filename_From_Cache,
         Found          => Found_From_Cache);
      if Found_From_Cache then
         --  The required unit has been found in the cache => check if
         --  a more local definition of the required unit may exist in
         --  a not yet parsed auxiliary index file.

         --# accept F, 10, Dummy_Aux_Index_Unit, "Ineffective assignment here OK" &
         --#        F, 10, Dummy_Source_Position, "Ineffective assignment here OK";
         Index_Table_P.Get_Next_Index_File
           (Unit           => Required_Unit,
            Top_Filename   => Index_Filename_From_Cache,
            Filename       => Index_Filename,
            File_Type      => File_Type,
            Aux_Index_Unit => Dummy_Aux_Index_Unit,
            Position       => Dummy_Source_Position);
         --# end accept;
         Need_To_Look_In_File := File_Type = Aux_Index;
         if CommandLineData.Content.Debug.File_Names then
            --  Debug

            --  Index_Table_P.Get_Next_Index may return an yet
            --  unparsed auxiliary index or super index.
            SPARK_IO.Put_String (File => SPARK_IO.Standard_Output,
                                 Item => "INDEX FILENAME NOT YET PARSED : ",
                                 Stop => 0);
            Index_Table_P.Debug_Put_E_Str
              (E_Str    => LexTokenManager.Lex_String_To_String (Lex_Str => Index_Filename),
               New_Line => True);
         end if;
      else
         --  The required unit is not in the cache => need to lookup
         --  in the index files.
         Index_Filename_From_Cache := LexTokenManager.Null_String;
         Need_To_Look_In_File      := True;
      end if;
      if Need_To_Look_In_File then
         --  The required unit has not been found in the cache => need
         --  to lookup in the index files
         --
         --  or
         --
         --  a more local definition of the required unit may exist in
         --  a not yet parsed index file => need to lookup in the more
         --  local index files only.

         --# accept F, 10, Source_Filename, "Ineffective assignment here OK" &
         --#        F, 10, Actual_Unit_Type, "Ineffective assignment here OK";
         Look_In_File
           (Lookup_Components   => True,
            Required_Unit       => Required_Unit,
            Possible_Unit_Types => Possible_Unit_Types,
            Top_Filename        => Index_Filename_From_Cache,
            Returned_Filename   => Source_Filename,
            Actual_Unit_Type    => Actual_Unit_Type,
            Components          => Components_From_File,
            Found               => Found_From_File);
         --# end accept;
         if Found_From_File then
            --  The required unit has been found in the index files or
            --  a more local definition of the required unit has been
            --  found in a previously unparsed auxiliary index file =>
            --  the answer is the value coming from the index file.
            Components := Components_From_File;
         elsif Found_From_Cache then
            --  A more local definition of the required unit has not
            --  been found in the index files => the answer is the
            --  value stored in the cache.
            Components := Components_From_Cache;
         else
            --  The required unit has not been found either in the
            --  cache or in the index files => the required unit can
            --  not be located.
            Components := Component_Lists'(others => LexTokenLists.Null_List);
         end if;
      else
         --  The required unit has been found in the cache and no more
         --  local definition of the required unit can exist => the
         --  answer is the value stored in the cache.
         Components := Components_From_Cache;
      end if;
      --# accept F, 33, Source_Filename, "Expect Actual_Unit_Type unused" &
      --#        F, 33, Actual_Unit_Type, "Expect Actual_Unit_Type unused" &
      --#        F, 33, Dummy_Aux_Index_Unit, "Expect Dummy_Aux_Index_Unit unused" &
      --#        F, 33, Dummy_Source_Position, "Expect Dummy_Source_Position unused";
   end Look_Up_Components;

   procedure Add_Unit
     (Unit            : in LexTokenLists.Lists;
      Unit_Types      : in ContextManager.UnitTypes;
      Source_Filename : in E_Strings.T)
   --# global in     CommandLineData.Content;
   --#        in     Index_Table_P.Index_Table;
   --#        in out Cache.The_Unit_Hash;
   --#        in out ErrorHandler.Error_Context;
   --#        in out Index_Table_P.Fatal_Error;
   --#        in out LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --# derives Cache.The_Unit_Hash,
   --#         ErrorHandler.Error_Context,
   --#         Index_Table_P.Fatal_Error  from *,
   --#                                         Cache.The_Unit_Hash,
   --#                                         Index_Table_P.Index_Table,
   --#                                         LexTokenManager.State,
   --#                                         Source_Filename,
   --#                                         Unit,
   --#                                         Unit_Types &
   --#         LexTokenManager.State      from *,
   --#                                         Source_Filename &
   --#         SPARK_IO.File_Sys          from *,
   --#                                         Cache.The_Unit_Hash,
   --#                                         CommandLineData.Content,
   --#                                         ErrorHandler.Error_Context,
   --#                                         Index_Table_P.Index_Table,
   --#                                         LexTokenManager.State,
   --#                                         Source_Filename,
   --#                                         Unit,
   --#                                         Unit_Types;
   is
   begin
      Cache.Add_Unit
        (Unit            => Unit,
         Unit_Types      => Unit_Types,
         Source_Filename => Source_Filename,
         Index_Filename  => LexTokenManager.Null_String,
         Index_Position  => File_Position'(Line => 1,
                                           Col  => 1));
   end Add_Unit;

   procedure List_Index_File (Report_File : in SPARK_IO.File_Type)
   --# global in     CommandLineData.Content;
   --#        in     Index_Table_P.Index_Table;
   --#        in     LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --#        in out XMLReport.State;
   --# derives SPARK_IO.File_Sys from *,
   --#                                CommandLineData.Content,
   --#                                Index_Table_P.Index_Table,
   --#                                LexTokenManager.State,
   --#                                Report_File,
   --#                                XMLReport.State &
   --#         XMLReport.State   from *,
   --#                                CommandLineData.Content,
   --#                                Index_Table_P.Index_Table;
   is
   begin
      Index_Table_P.List_Index_File (Report_File => Report_File);
   end List_Index_File;

end IndexManager;
