OSDN Git Service

2008-05-27 Vincent Celier <celier@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / ali.adb
index 8f340e8..e00bc46 100644 (file)
@@ -6,37 +6,56 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1992-2004 Free Software Foundation, Inc.          --
+--          Copyright (C) 1992-2008, Free Software Foundation, Inc.         --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
--- ware  Foundation;  either version 2,  or (at your option) any later ver- --
+-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
 -- for  more details.  You should have  received  a copy of the GNU General --
--- Public License  distributed with GNAT;  see file COPYING.  If not, write --
--- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
--- MA 02111-1307, USA.                                                      --
+-- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
+-- http://www.gnu.org/licenses for a complete copy of the license.          --
 --                                                                          --
 -- GNAT was originally developed  by the GNAT team at  New York University. --
 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
 --                                                                          --
 ------------------------------------------------------------------------------
 
-with Butil;    use Butil;
-with Debug;    use Debug;
-with Fname;    use Fname;
-with Namet;    use Namet;
-with Opt;      use Opt;
-with Osint;    use Osint;
-with Output;   use Output;
+with Butil;  use Butil;
+with Debug;  use Debug;
+with Fname;  use Fname;
+with Opt;    use Opt;
+with Osint;  use Osint;
+with Output; use Output;
 
 package body ALI is
 
    use ASCII;
    --  Make control characters visible
 
+   --  The following variable records which characters currently are
+   --  used as line type markers in the ALI file. This is used in
+   --  Scan_ALI to detect (or skip) invalid lines.
+
+   Known_ALI_Lines : constant array (Character range 'A' .. 'Z') of Boolean :=
+     ('V'    => True,   -- version
+      'M'    => True,   -- main program
+      'A'    => True,   -- argument
+      'P'    => True,   -- program
+      'R'    => True,   -- restriction
+      'I'    => True,   -- interrupt
+      'U'    => True,   -- unit
+      'W'    => True,   -- with
+      'L'    => True,   -- linker option
+      'E'    => True,   -- external
+      'D'    => True,   -- dependency
+      'X'    => True,   -- xref
+      'S'    => True,   -- specific dispatching
+      'Y'    => True,   -- limited_with
+      others => False);
+
    --------------------
    -- Initialize_ALI --
    --------------------
@@ -65,6 +84,7 @@ package body ALI is
       --  Initialize all tables
 
       ALIs.Init;
+      No_Deps.Init;
       Units.Init;
       Withs.Init;
       Sdep.Init;
@@ -99,14 +119,14 @@ package body ALI is
    --------------
 
    function Scan_ALI
-     (F            : File_Name_Type;
-      T            : Text_Buffer_Ptr;
-      Ignore_ED    : Boolean;
-      Err          : Boolean;
-      Read_Xref    : Boolean := False;
-      Read_Lines   : String := "";
-      Ignore_Lines : String := "X")
-      return         ALI_Id
+     (F             : File_Name_Type;
+      T             : Text_Buffer_Ptr;
+      Ignore_ED     : Boolean;
+      Err           : Boolean;
+      Read_Xref     : Boolean := False;
+      Read_Lines    : String  := "";
+      Ignore_Lines  : String  := "X";
+      Ignore_Errors : Boolean := False) return ALI_Id
    is
       P         : Text_Ptr := T'First;
       Line      : Logical_Line_Number := 1;
@@ -120,13 +140,6 @@ package body ALI is
       --  be ignored by Scan_ALI and skipped, and False if the lines
       --  are to be read and processed.
 
-      Restrictions_Initial : Rident.Restrictions_Info;
-      pragma Warnings (Off, Restrictions_Initial);
-      --  This variable, which should really be a constant (but that's not
-      --  allowed by the language) is used only for initialization, and the
-      --  reason we are declaring it is to get the default initialization
-      --  set for the object.
-
       Bad_ALI_Format : exception;
       --  Exception raised by Fatal_Error if Err is True
 
@@ -142,42 +155,92 @@ package body ALI is
       procedure Checkc (C : Character);
       --  Check next character is C. If so bump past it, if not fatal error
 
+      procedure Check_Unknown_Line;
+      --  If Ignore_Errors mode, then checks C to make sure that it is not
+      --  an unknown ALI line type characters, and if so, skips lines
+      --  until the first character of the line is one of these characters,
+      --  at which point it does a Getc to put that character in C. The
+      --  call has no effect if C is already an appropriate character.
+      --  If not in Ignore_Errors mode, a fatal error is signalled if the
+      --  line is unknown. Note that if C is an EOL on entry, the line is
+      --  skipped (it is assumed that blank lines are never significant).
+      --  If C is EOF on entry, the call has no effect (it is assumed that
+      --  the caller will properly handle this case).
+
       procedure Fatal_Error;
       --  Generate fatal error message for badly formatted ALI file if
       --  Err is false, or raise Bad_ALI_Format if Err is True.
 
+      procedure Fatal_Error_Ignore;
+      pragma Inline (Fatal_Error_Ignore);
+      --  In Ignore_Errors mode, has no effect, otherwise same as Fatal_Error
+
       function Getc return Character;
       --  Get next character, bumping P past the character obtained
 
+      function Get_File_Name (Lower : Boolean := False) return File_Name_Type;
+      --  Skip blanks, then scan out a file name (name is left in Name_Buffer
+      --  with length in Name_Len, as well as returning a File_Name_Type value.
+      --  If lower is false, the case is unchanged, if Lower is True then the
+      --  result is forced to all lower case for systems where file names are
+      --  not case sensitive. This ensures that gnatbind works correctly
+      --  regardless of the case of the file name on all systems. The scan
+      --  is terminated by a end of line, space or horizontal tab. Any other
+      --  special characters are included in the returned name.
+
       function Get_Name
-        (Lower         : Boolean := False;
-         Ignore_Spaces : Boolean := False) return Name_Id;
+        (Ignore_Spaces  : Boolean := False;
+         Ignore_Special : Boolean := False)return Name_Id;
       --  Skip blanks, then scan out a name (name is left in Name_Buffer with
       --  length in Name_Len, as well as being returned in Name_Id form).
       --  If Lower is set to True then the Name_Buffer will be converted to
       --  all lower case, for systems where file names are not case sensitive.
       --  This ensures that gnatbind works correctly regardless of the case
-      --  of the file name on all systems. The name is terminated by a either
-      --  white space (when Ignore_Spaces is False) or a typeref bracket or
-      --  an equal sign except for the special case of an operator name
-      --  starting with a double quite which is terminated by another double
-      --  quote.
+      --  of the file name on all systems. The termination condition depends
+      --  on the settings of Ignore_Spaces and Ignore_Special:
+      --
+      --    If Ignore_Spaces is False (normal case), then scan is terminated
+      --    by the normal end of field condition (EOL, space, horizontal tab)
+      --
+      --    If Ignore_Special is False (normal case), the scan is terminated by
+      --    a typeref bracket or an equal sign except for the special case of
+      --    an operator name starting with a double quite which is terminated
+      --    by another double quote.
+      --
+      --  It is an error to set both Ignore_Spaces and Ignore_Special to True.
+      --  This function handles wide characters properly.
 
       function Get_Nat return Nat;
-      --  Skip blanks, then scan out an unsigned integer value in Nat range.
+      --  Skip blanks, then scan out an unsigned integer value in Nat range
+      --  raises ALI_Reading_Error if the encoutered type is not natural.
 
       function Get_Stamp return Time_Stamp_Type;
       --  Skip blanks, then scan out a time stamp
 
+      function Get_Unit_Name return Unit_Name_Type;
+      --  Skip blanks, then scan out a file name (name is left in Name_Buffer
+      --  with length in Name_Len, as well as returning a Unit_Name_Type value.
+      --  The case is unchanged and terminated by a normal end of field.
+
       function Nextc return Character;
       --  Return current character without modifying pointer P
 
+      procedure Get_Typeref
+        (Current_File_Num : Sdep_Id;
+         Ref             : out Tref_Kind;
+         File_Num        : out Sdep_Id;
+         Line            : out Nat;
+         Ref_Type        : out Character;
+         Col             : out Nat;
+         Standard_Entity : out Name_Id);
+      --  Parse the definition of a typeref (<...>, {...} or (...))
+
       procedure Skip_Eol;
       --  Skip past spaces, then skip past end of line (fatal error if not
       --  at end of line). Also skips past any following blank lines.
 
       procedure Skip_Line;
-      --  Skip rest of current line and any following blank lines.
+      --  Skip rest of current line and any following blank lines
 
       procedure Skip_Space;
       --  Skip past white space (blanks or horizontal tab)
@@ -211,10 +274,42 @@ package body ALI is
       procedure Check_At_End_Of_Field is
       begin
          if not At_End_Of_Field then
-            Fatal_Error;
+            if Ignore_Errors then
+               while Nextc > ' ' loop
+                  P := P + 1;
+               end loop;
+            else
+               Fatal_Error;
+            end if;
          end if;
       end Check_At_End_Of_Field;
 
+      ------------------------
+      -- Check_Unknown_Line --
+      ------------------------
+
+      procedure Check_Unknown_Line is
+      begin
+         while C not in 'A' .. 'Z'
+           or else not Known_ALI_Lines (C)
+         loop
+            if C = CR or else C = LF then
+               Skip_Line;
+               C := Nextc;
+
+            elsif C = EOF then
+               return;
+
+            elsif Ignore_Errors then
+               Skip_Line;
+               C := Getc;
+
+            else
+               Fatal_Error;
+            end if;
+         end loop;
+      end Check_Unknown_Line;
+
       ------------
       -- Checkc --
       ------------
@@ -223,6 +318,8 @@ package body ALI is
       begin
          if Nextc = C then
             P := P + 1;
+         elsif Ignore_Errors then
+            P := P + 1;
          else
             Fatal_Error;
          end if;
@@ -266,14 +363,19 @@ package body ALI is
          Write_Name (F);
          Write_Str (" is incorrectly formatted");
          Write_Eol;
-         Write_Str
-           ("make sure you are using consistent versions of gcc/gnatbind");
+
+         Write_Str ("make sure you are using consistent versions " &
+
+         --  Split the following line so that it can easily be transformed for
+         --  e.g. JVM/.NET back-ends where the compiler has a different name.
+
+                    "of gcc/gnatbind");
+
          Write_Eol;
 
          --  Find start of line
 
          Ptr1 := P;
-
          while Ptr1 > T'First
            and then T (Ptr1 - 1) /= CR
            and then T (Ptr1 - 1) /= LF
@@ -324,18 +426,59 @@ package body ALI is
          Exit_Program (E_Fatal);
       end Fatal_Error;
 
+      ------------------------
+      -- Fatal_Error_Ignore --
+      ------------------------
+
+      procedure Fatal_Error_Ignore is
+      begin
+         if not Ignore_Errors then
+            Fatal_Error;
+         end if;
+      end Fatal_Error_Ignore;
+
+      -------------------
+      -- Get_File_Name --
+      -------------------
+
+      function Get_File_Name
+        (Lower : Boolean := False) return File_Name_Type
+      is
+         F : Name_Id;
+
+      begin
+         F := Get_Name (Ignore_Special => True);
+
+         --  Convert file name to all lower case if file names are not case
+         --  sensitive. This ensures that we handle names in the canonical
+         --  lower case format, regardless of the actual case.
+
+         if Lower and not File_Names_Case_Sensitive then
+            Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+            return Name_Find;
+         else
+            return File_Name_Type (F);
+         end if;
+      end Get_File_Name;
+
       --------------
       -- Get_Name --
       --------------
 
-      function Get_Name (Lower : Boolean := False;
-                         Ignore_Spaces : Boolean := False) return Name_Id is
+      function Get_Name
+        (Ignore_Spaces  : Boolean := False;
+         Ignore_Special : Boolean := False) return Name_Id
+      is
       begin
          Name_Len := 0;
          Skip_Space;
 
          if At_Eol then
-            Fatal_Error;
+            if Ignore_Errors then
+               return Error_Name;
+            else
+               Fatal_Error;
+            end if;
          end if;
 
          loop
@@ -344,29 +487,42 @@ package body ALI is
 
             exit when At_End_Of_Field and not Ignore_Spaces;
 
-            if Name_Buffer (1) = '"' then
-               exit when Name_Len > 1 and then Name_Buffer (Name_Len) = '"';
+            if not Ignore_Special then
+               if Name_Buffer (1) = '"' then
+                  exit when Name_Len > 1 and then Name_Buffer (Name_Len) = '"';
 
-            else
-               exit when (At_End_Of_Field and not Ignore_Spaces)
-                 or else Nextc = '(' or else Nextc = ')'
-                 or else Nextc = '{' or else Nextc = '}'
-                 or else Nextc = '<' or else Nextc = '>'
-                 or else Nextc = '=';
-            end if;
-         end loop;
+               else
+                  --  Terminate on parens or angle brackets or equal sign
 
-         --  Convert file name to all lower case if file names are not case
-         --  sensitive. This ensures that we handle names in the canonical
-         --  lower case format, regardless of the actual case.
+                  exit when Nextc = '(' or else Nextc = ')'
+                    or else Nextc = '{' or else Nextc = '}'
+                    or else Nextc = '<' or else Nextc = '>'
+                    or else Nextc = '=';
 
-         if Lower and not File_Names_Case_Sensitive then
-            Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
-         end if;
+                  --  Terminate if left bracket not part of wide char sequence
+                  --  Note that we only recognize brackets notation so far ???
+
+                  exit when Nextc = '[' and then T (P + 1) /= '"';
+
+                  --  Terminate if right bracket not part of wide char sequence
+
+                  exit when Nextc = ']' and then T (P - 1) /= '"';
+               end if;
+            end if;
+         end loop;
 
          return Name_Find;
       end Get_Name;
 
+      -------------------
+      -- Get_Unit_Name --
+      -------------------
+
+      function Get_Unit_Name return Unit_Name_Type is
+      begin
+         return Unit_Name_Type (Get_Name);
+      end Get_Unit_Name;
+
       -------------
       -- Get_Nat --
       -------------
@@ -377,9 +533,17 @@ package body ALI is
       begin
          Skip_Space;
 
+         --  Check if we are on a number. In the case of bas ALI files, this
+         --  may not be true.
+
+         if not (Nextc in '0' .. '9') then
+            Fatal_Error;
+         end if;
+
          V := 0;
          loop
             V := V * 10 + (Character'Pos (Getc) - Character'Pos ('0'));
+
             exit when At_End_Of_Field;
             exit when Nextc < '0' or Nextc > '9';
          end loop;
@@ -399,7 +563,11 @@ package body ALI is
          Skip_Space;
 
          if At_Eol then
-            Fatal_Error;
+            if Ignore_Errors then
+               return Dummy_Time_Stamp;
+            else
+               Fatal_Error;
+            end if;
          end if;
 
          --  Following reads old style time stamp missing first two digits
@@ -422,6 +590,94 @@ package body ALI is
          return T;
       end Get_Stamp;
 
+      -----------------
+      -- Get_Typeref --
+      -----------------
+
+      procedure Get_Typeref
+        (Current_File_Num : Sdep_Id;
+         Ref              : out Tref_Kind;
+         File_Num         : out Sdep_Id;
+         Line             : out Nat;
+         Ref_Type         : out Character;
+         Col              : out Nat;
+         Standard_Entity  : out Name_Id)
+      is
+         N : Nat;
+      begin
+         case Nextc is
+            when '<'    => Ref := Tref_Derived;
+            when '('    => Ref := Tref_Access;
+            when '{'    => Ref := Tref_Type;
+            when others => Ref := Tref_None;
+         end case;
+
+         --  Case of typeref field present
+
+         if Ref /= Tref_None then
+            P := P + 1; -- skip opening bracket
+
+            if Nextc in 'a' .. 'z' then
+               File_Num        := No_Sdep_Id;
+               Line            := 0;
+               Ref_Type        := ' ';
+               Col             := 0;
+               Standard_Entity := Get_Name (Ignore_Spaces => True);
+            else
+               N := Get_Nat;
+
+               if Nextc = '|' then
+                  File_Num := Sdep_Id (N + Nat (First_Sdep_Entry) - 1);
+                  P := P + 1;
+                  N := Get_Nat;
+               else
+                  File_Num := Current_File_Num;
+               end if;
+
+               Line            := N;
+               Ref_Type        := Getc;
+               Col             := Get_Nat;
+               Standard_Entity := No_Name;
+            end if;
+
+            --  ??? Temporary workaround for nested generics case:
+            --     4i4 Directories{1|4I9[4|6[3|3]]}
+            --  See C918-002
+
+            declare
+               Nested_Brackets : Natural := 0;
+
+            begin
+               loop
+                  case Nextc is
+                     when '['   =>
+                        Nested_Brackets := Nested_Brackets + 1;
+                     when ']' =>
+                        Nested_Brackets := Nested_Brackets - 1;
+                     when others =>
+                        if Nested_Brackets = 0 then
+                           exit;
+                        end if;
+                  end case;
+
+                  Skipc;
+               end loop;
+            end;
+
+            P := P + 1; -- skip closing bracket
+            Skip_Space;
+
+         --  No typeref entry present
+
+         else
+            File_Num        := No_Sdep_Id;
+            Line            := 0;
+            Ref_Type        := ' ';
+            Col             := 0;
+            Standard_Entity := No_Name;
+         end if;
+      end Get_Typeref;
+
       ----------
       -- Getc --
       ----------
@@ -453,7 +709,15 @@ package body ALI is
       begin
          Skip_Space;
 
-         if not At_Eol then Fatal_Error; end if;
+         if not At_Eol then
+            if Ignore_Errors then
+               while not At_Eol loop
+                  P := P + 1;
+               end loop;
+            else
+               Fatal_Error;
+            end if;
+         end if;
 
          --  Loop to skip past blank lines (first time through skips this EOL)
 
@@ -504,10 +768,12 @@ package body ALI is
    --  Start of processing for Scan_ALI
 
    begin
+      First_Sdep_Entry := Sdep.Last + 1;
+
       --  Acquire lines to be ignored
 
       if Read_Xref then
-         Ignore := ('U' | 'W' | 'D' | 'X' => False, others => True);
+         Ignore := ('U' | 'W' | 'Y' | 'D' | 'X' => False, others => True);
 
       --  Read_Lines parameter given
 
@@ -540,10 +806,12 @@ package body ALI is
         Compile_Errors             => False,
         First_Interrupt_State      => Interrupt_States.Last + 1,
         First_Sdep                 => No_Sdep_Id,
+        First_Specific_Dispatching => Specific_Dispatching.Last + 1,
         First_Unit                 => No_Unit_Id,
         Float_Format               => 'I',
         Last_Interrupt_State       => Interrupt_States.Last,
         Last_Sdep                  => No_Sdep_Id,
+        Last_Specific_Dispatching  => Specific_Dispatching.Last,
         Last_Unit                  => No_Unit_Id,
         Locking_Policy             => ' ',
         Main_Priority              => -1,
@@ -552,15 +820,15 @@ package body ALI is
         Normalize_Scalars          => False,
         Ofile_Full_Name            => Full_Object_File_Name,
         Queuing_Policy             => ' ',
-        Restrictions               => Restrictions_Initial,
-        Sfile                      => No_Name,
+        Restrictions               => No_Restrictions,
+        SAL_Interface              => False,
+        Sfile                      => No_File,
         Task_Dispatching_Policy    => ' ',
         Time_Slice_Value           => -1,
-        WC_Encoding                => '8',
+        WC_Encoding                => 'b',
         Unit_Exception_Table       => False,
         Ver                        => (others => ' '),
         Ver_Len                    => 0,
-        Interface                  => False,
         Zero_Cost_Exceptions       => False);
 
       --  Now we acquire the input lines from the ALI file. Note that the
@@ -568,10 +836,16 @@ package body ALI is
       --  C is set to contain the first character of the following line.
 
       C := Getc;
+      Check_Unknown_Line;
 
       --  Acquire library version
 
       if C /= 'V' then
+
+         --  The V line missing really indicates trouble, most likely it
+         --  means we don't have an ALI file at all, so here we give a
+         --  fatal error even if we are in Ignore_Errors mode.
+
          Fatal_Error;
 
       elsif Ignore ('V') then
@@ -593,6 +867,7 @@ package body ALI is
       end if;
 
       C := Getc;
+      Check_Unknown_Line;
 
       --  Acquire main program line if present
 
@@ -647,19 +922,32 @@ package body ALI is
 
       First_Arg := Args.Last + 1;
 
-      Arg_Loop : while C = 'A' loop
+      A_Loop : loop
+         Check_Unknown_Line;
+         exit A_Loop when C /= 'A';
+
          if Ignore ('A') then
             Skip_Line;
 
          else
             Checkc (' ');
-            Name_Len := 0;
 
+            --  Scan out argument
+
+            Name_Len := 0;
             while not At_Eol loop
                Name_Len := Name_Len + 1;
                Name_Buffer (Name_Len) := Getc;
             end loop;
 
+            --  If -fstack-check, record that it occurred
+
+            if Name_Buffer (1 .. Name_Len) = "-fstack-check" then
+               Stack_Check_Switch_Set := True;
+            end if;
+
+            --  Store the argument
+
             Args.Increment_Last;
             Args.Table (Args.Last) := new String'(Name_Buffer (1 .. Name_Len));
 
@@ -667,16 +955,30 @@ package body ALI is
          end if;
 
          C := Getc;
-      end loop Arg_Loop;
+      end loop A_Loop;
 
       --  Acquire P line
 
-      if C /= 'P' then
-         Fatal_Error;
+      Check_Unknown_Line;
+
+      while C /= 'P' loop
+         if Ignore_Errors then
+            if C = EOF then
+               Fatal_Error;
+            else
+               Skip_Line;
+               C := Nextc;
+            end if;
+         else
+            Fatal_Error;
+         end if;
+      end loop;
 
-      elsif Ignore ('P') then
+      if Ignore ('P') then
          Skip_Line;
 
+      --  Process P line
+
       else
          NS_Found := False;
 
@@ -691,6 +993,12 @@ package body ALI is
                Checkc ('E');
                ALIs.Table (Id).Compile_Errors := True;
 
+            --  Processing for DB
+
+            elsif C = 'D' then
+               Checkc ('B');
+               Detect_Blocking := True;
+
             --  Processing for FD/FG/FI
 
             elsif C = 'F' then
@@ -730,7 +1038,7 @@ package body ALI is
                --  Invalid switch starting with N
 
                else
-                  Fatal_Error;
+                  Fatal_Error_Ignore;
                end if;
 
             --  Processing for Qx
@@ -747,7 +1055,7 @@ package body ALI is
                --  Processing for SL
 
                if C = 'L' then
-                  ALIs.Table (Id).Interface := True;
+                  ALIs.Table (Id).SAL_Interface := True;
 
                --  Processing for SS
 
@@ -757,7 +1065,7 @@ package body ALI is
                --  Invalid switch starting with S
 
                else
-                  Fatal_Error;
+                  Fatal_Error_Ignore;
                end if;
 
             --  Processing for Tx
@@ -785,18 +1093,26 @@ package body ALI is
                --  Invalid switches starting with U
 
                else
-                  Fatal_Error;
+                  Fatal_Error_Ignore;
                end if;
 
             --  Processing for ZX
 
             elsif C = 'Z' then
-               Checkc ('X');
+               C := Getc;
+
+               if C = 'X' then
                   ALIs.Table (Id).Zero_Cost_Exceptions := True;
                   Zero_Cost_Exceptions_Specified := True;
+               else
+                  Fatal_Error_Ignore;
+               end if;
+
+            --  Invalid parameter
 
             else
-               Fatal_Error;
+               C := Getc;
+               Fatal_Error_Ignore;
             end if;
          end loop;
 
@@ -808,149 +1124,185 @@ package body ALI is
       end if;
 
       C := Getc;
+      Check_Unknown_Line;
 
       --  Acquire first restrictions line
 
-      if C /= 'R' then
-         Fatal_Error;
+      while C /= 'R' loop
+         if Ignore_Errors then
+            if C = EOF then
+               Fatal_Error;
+            else
+               Skip_Line;
+               C := Nextc;
+            end if;
+         else
+            Fatal_Error;
+         end if;
+      end loop;
 
-      elsif Ignore ('R') then
+      if Ignore ('R') then
          Skip_Line;
 
+      --  Process restrictions line
+
       else
-         Checkc (' ');
-         Skip_Space;
+         Scan_Restrictions : declare
+            Save_R : constant Restrictions_Info := Cumulative_Restrictions;
+            --  Save cumulative restrictions in case we have a fatal error
 
-         for R in All_Boolean_Restrictions loop
-            C := Getc;
+            Bad_R_Line : exception;
+            --  Signal bad restrictions line (raised on unexpected character)
 
-            case C is
-               when 'v' =>
-                  ALIs.Table (Id).Restrictions.Violated (R) := True;
-                  Cumulative_Restrictions.Violated (R) := True;
+         begin
+            Checkc (' ');
+            Skip_Space;
 
-               when 'r' =>
-                  ALIs.Table (Id).Restrictions.Set (R) := True;
-                  Cumulative_Restrictions.Set (R) := True;
+            --  Acquire information for boolean restrictions
 
-               when 'n' =>
-                  null;
+            for R in All_Boolean_Restrictions loop
+               C := Getc;
 
-               when others =>
-                  Fatal_Error;
-            end case;
-         end loop;
+               case C is
+                  when 'v' =>
+                     ALIs.Table (Id).Restrictions.Violated (R) := True;
+                     Cumulative_Restrictions.Violated (R) := True;
 
-         Skip_Eol;
-      end if;
+                  when 'r' =>
+                     ALIs.Table (Id).Restrictions.Set (R) := True;
+                     Cumulative_Restrictions.Set (R) := True;
 
-      C := Getc;
+                  when 'n' =>
+                     null;
 
-      --  See if we have a second R line
+                  when others =>
+                     raise Bad_R_Line;
+               end case;
+            end loop;
 
-      if C /= 'R' then
+            --  Acquire information for parameter restrictions
 
-         --  If not, just ignore, and leave the restrictions variables
-         --  unchanged. This is useful for dealing with old format ALI
-         --  files with only one R line (this can be removed later on,
-         --  but is useful for transitional purposes).
+            for RP in All_Parameter_Restrictions loop
 
-         null;
+               --  Acquire restrictions pragma information
 
-         --  Here we have a second R line, ignore it if ignore flag set
+               case Getc is
+                  when 'n' =>
+                     null;
 
-      elsif Ignore ('R') then
-         Skip_Line;
-         C := Getc;
+                  when 'r' =>
+                     ALIs.Table (Id).Restrictions.Set (RP) := True;
 
-      --  Otherwise acquire second R line
+                     declare
+                        N : constant Integer := Integer (Get_Nat);
+                     begin
+                        ALIs.Table (Id).Restrictions.Value (RP) := N;
 
-      else
-         Checkc (' ');
-         Skip_Space;
+                        if Cumulative_Restrictions.Set (RP) then
+                           Cumulative_Restrictions.Value (RP) :=
+                             Integer'Min
+                               (Cumulative_Restrictions.Value (RP), N);
+                        else
+                           Cumulative_Restrictions.Set (RP) := True;
+                           Cumulative_Restrictions.Value (RP) := N;
+                        end if;
+                     end;
 
-         for RP in All_Parameter_Restrictions loop
+                  when others =>
+                     raise Bad_R_Line;
+               end case;
 
-            --  Acquire restrictions pragma information
+               --  Acquire restrictions violations information
 
-            case Getc is
-               when 'n' =>
-                  null;
+               case Getc is
+                  when 'n' =>
+                     null;
 
-               when 'r' =>
-                  ALIs.Table (Id).Restrictions.Set (RP) := True;
+                  when 'v' =>
+                     ALIs.Table (Id).Restrictions.Violated (RP) := True;
+                     Cumulative_Restrictions.Violated (RP) := True;
 
-                  declare
-                     N : constant Integer := Integer (Get_Nat);
-                  begin
-                     ALIs.Table (Id).Restrictions.Value (RP) := N;
+                     declare
+                        N : constant Integer := Integer (Get_Nat);
+                        pragma Unsuppress (Overflow_Check);
 
-                     if Cumulative_Restrictions.Set (RP) then
-                        Cumulative_Restrictions.Value (RP) :=
-                          Integer'Min (Cumulative_Restrictions.Value (RP), N);
-                     else
-                        Cumulative_Restrictions.Set (RP) := True;
-                        Cumulative_Restrictions.Value (RP) := N;
-                     end if;
-                  end;
+                     begin
+                        ALIs.Table (Id).Restrictions.Count (RP) := N;
 
-               when others =>
-                  Fatal_Error;
-            end case;
+                        if RP in Checked_Max_Parameter_Restrictions then
+                           Cumulative_Restrictions.Count (RP) :=
+                             Integer'Max
+                               (Cumulative_Restrictions.Count (RP), N);
+                        else
+                           Cumulative_Restrictions.Count (RP) :=
+                             Cumulative_Restrictions.Count (RP) + N;
+                        end if;
 
-            --  Acquire restrictions violations information
+                     exception
+                        when Constraint_Error =>
 
-            case Getc is
-               when 'n' =>
-                  null;
+                           --  A constraint error comes from the addition in
+                           --  the else branch. We reset to the maximum and
+                           --  indicate that the real value is now unknown.
 
-               when 'v' =>
-                  ALIs.Table (Id).Restrictions.Violated (RP) := True;
-                  Cumulative_Restrictions.Violated (RP) := True;
+                           Cumulative_Restrictions.Value (RP) := Integer'Last;
+                           Cumulative_Restrictions.Unknown (RP) := True;
+                     end;
 
-                  declare
-                     N : constant Integer := Integer (Get_Nat);
-                     pragma Unsuppress (Overflow_Check);
+                     if Nextc = '+' then
+                        Skipc;
+                        ALIs.Table (Id).Restrictions.Unknown (RP) := True;
+                        Cumulative_Restrictions.Unknown (RP) := True;
+                     end if;
 
-                  begin
-                     ALIs.Table (Id).Restrictions.Count (RP) := N;
+                  when others =>
+                     raise Bad_R_Line;
+               end case;
+            end loop;
 
-                     if RP in Checked_Max_Parameter_Restrictions then
-                        Cumulative_Restrictions.Count (RP) :=
-                          Integer'Max (Cumulative_Restrictions.Count (RP), N);
-                     else
-                        Cumulative_Restrictions.Count (RP) :=
-                          Cumulative_Restrictions.Count (RP) + N;
-                     end if;
+            Skip_Eol;
 
-                  exception
-                     when Constraint_Error =>
+         --  Here if error during scanning of restrictions line
 
-                        --  A constraint error comes from the addition in
-                        --  the else branch. We reset to the maximum and
-                        --  indicate that the real value is now unknown.
+         exception
+            when Bad_R_Line =>
 
-                        Cumulative_Restrictions.Value (RP) := Integer'Last;
-                        Cumulative_Restrictions.Unknown (RP) := True;
-                  end;
+               --  In Ignore_Errors mode, undo any changes to restrictions
+               --  from this unit, and continue on.
 
-                  if Nextc = '+' then
-                     Skipc;
-                     ALIs.Table (Id).Restrictions.Unknown (RP) := True;
-                     Cumulative_Restrictions.Unknown (RP) := True;
-                  end if;
+               if Ignore_Errors then
+                  Cumulative_Restrictions := Save_R;
+                  ALIs.Table (Id).Restrictions := No_Restrictions;
+                  Skip_Eol;
+
+               --  In normal mode, this is a fatal error
 
-               when others =>
+               else
                   Fatal_Error;
-            end case;
-         end loop;
+               end if;
+
+         end Scan_Restrictions;
+      end if;
+
+      --  Acquire additional restrictions (No_Dependence) lines if present
+
+      C := Getc;
+      while C = 'R' loop
+         if Ignore ('R') then
+            Skip_Line;
+         else
+            Skip_Space;
+            No_Deps.Append ((Id, Get_Name));
+         end if;
 
          Skip_Eol;
          C := Getc;
-      end if;
+      end loop;
 
       --  Acquire 'I' lines if present
 
+      Check_Unknown_Line;
+
       while C = 'I' loop
          if Ignore ('I') then
             Skip_Line;
@@ -980,9 +1332,52 @@ package body ALI is
          C := Getc;
       end loop;
 
+      --  Acquire 'S' lines if present
+
+      Check_Unknown_Line;
+
+      while C = 'S' loop
+         if Ignore ('S') then
+            Skip_Line;
+
+         else
+            declare
+               Policy     : Character;
+               First_Prio : Nat;
+               Last_Prio  : Nat;
+               Line_No    : Nat;
+
+            begin
+               Checkc (' ');
+               Skip_Space;
+
+               Policy := Getc;
+               Skip_Space;
+               First_Prio := Get_Nat;
+               Last_Prio := Get_Nat;
+               Line_No := Get_Nat;
+
+               Specific_Dispatching.Append (
+                 (Dispatching_Policy => Policy,
+                  First_Priority     => First_Prio,
+                  Last_Priority      => Last_Prio,
+                  PSD_Pragma_Line    => Line_No));
+
+               ALIs.Table (Id).Last_Specific_Dispatching :=
+                 Specific_Dispatching.Last;
+
+               Skip_Eol;
+            end;
+         end if;
+
+         C := Getc;
+      end loop;
+
       --  Loop to acquire unit entries
 
-      Unit_Loop : while C = 'U' loop
+      U_Loop : loop
+         Check_Unknown_Line;
+         exit U_Loop when C /= 'U';
 
          --  Note: as per spec, we never ignore U lines
 
@@ -994,40 +1389,48 @@ package body ALI is
             ALIs.Table (Id).First_Unit := Units.Last;
          end if;
 
-         Units.Table (Units.Last).Uname           := Get_Name;
-         Units.Table (Units.Last).Predefined      := Is_Predefined_Unit;
-         Units.Table (Units.Last).Internal        := Is_Internal_Unit;
-         Units.Table (Units.Last).My_ALI          := Id;
-         Units.Table (Units.Last).Sfile           := Get_Name (Lower => True);
-         Units.Table (Units.Last).Pure            := False;
-         Units.Table (Units.Last).Preelab         := False;
-         Units.Table (Units.Last).No_Elab         := False;
-         Units.Table (Units.Last).Shared_Passive  := False;
-         Units.Table (Units.Last).RCI             := False;
-         Units.Table (Units.Last).Remote_Types    := False;
-         Units.Table (Units.Last).Has_RACW        := False;
-         Units.Table (Units.Last).Init_Scalars    := False;
-         Units.Table (Units.Last).Is_Generic      := False;
-         Units.Table (Units.Last).Icasing         := Mixed_Case;
-         Units.Table (Units.Last).Kcasing         := All_Lower_Case;
-         Units.Table (Units.Last).Dynamic_Elab    := False;
-         Units.Table (Units.Last).Elaborate_Body  := False;
-         Units.Table (Units.Last).Set_Elab_Entity := False;
-         Units.Table (Units.Last).Version         := "00000000";
-         Units.Table (Units.Last).First_With      := Withs.Last + 1;
-         Units.Table (Units.Last).First_Arg       := First_Arg;
-         Units.Table (Units.Last).Elab_Position   := 0;
-         Units.Table (Units.Last).Interface       := ALIs.Table (Id).Interface;
-
-         if Debug_Flag_U then
-            Write_Str (" ----> reading unit ");
-            Write_Int (Int (Units.Last));
-            Write_Str ("  ");
-            Write_Unit_Name (Units.Table (Units.Last).Uname);
-            Write_Str (" from file ");
-            Write_Name (Units.Table (Units.Last).Sfile);
-            Write_Eol;
-         end if;
+         declare
+            UL : Unit_Record renames Units.Table (Units.Last);
+
+         begin
+            UL.Uname                    := Get_Unit_Name;
+            UL.Predefined               := Is_Predefined_Unit;
+            UL.Internal                 := Is_Internal_Unit;
+            UL.My_ALI                   := Id;
+            UL.Sfile                    := Get_File_Name (Lower => True);
+            UL.Pure                     := False;
+            UL.Preelab                  := False;
+            UL.No_Elab                  := False;
+            UL.Shared_Passive           := False;
+            UL.RCI                      := False;
+            UL.Remote_Types             := False;
+            UL.Has_RACW                 := False;
+            UL.Init_Scalars             := False;
+            UL.Is_Generic               := False;
+            UL.Icasing                  := Mixed_Case;
+            UL.Kcasing                  := All_Lower_Case;
+            UL.Dynamic_Elab             := False;
+            UL.Elaborate_Body           := False;
+            UL.Set_Elab_Entity          := False;
+            UL.Version                  := "00000000";
+            UL.First_With               := Withs.Last + 1;
+            UL.First_Arg                := First_Arg;
+            UL.Elab_Position            := 0;
+            UL.SAL_Interface            := ALIs.Table (Id).SAL_Interface;
+            UL.Body_Needed_For_SAL      := False;
+            UL.Elaborate_Body_Desirable := False;
+            UL.Optimize_Alignment       := 'O';
+
+            if Debug_Flag_U then
+               Write_Str (" ----> reading unit ");
+               Write_Int (Int (Units.Last));
+               Write_Str ("  ");
+               Write_Unit_Name (UL.Uname);
+               Write_Str (" from file ");
+               Write_Name (UL.Sfile);
+               Write_Eol;
+            end if;
+         end;
 
          --  Check for duplicated unit in different files
 
@@ -1100,20 +1503,35 @@ package body ALI is
                   Units.Table (Units.Last).Version (J) := C;
                end loop;
 
-            --  BN parameter (Body needed)
+            --  BD/BN parameters
 
             elsif C = 'B' then
-               Checkc ('N');
-               Check_At_End_Of_Field;
-               Units.Table (Units.Last).Body_Needed_For_SAL := True;
+               C := Getc;
+
+               if C = 'D' then
+                  Check_At_End_Of_Field;
+                  Units.Table (Units.Last).Elaborate_Body_Desirable := True;
 
-            --  DE parameter (Dynamic elaboration checks
+               elsif C = 'N' then
+                  Check_At_End_Of_Field;
+                  Units.Table (Units.Last).Body_Needed_For_SAL := True;
+
+               else
+                  Fatal_Error_Ignore;
+               end if;
+
+            --  DE parameter (Dynamic elaboration checks)
 
             elsif C = 'D' then
-               Checkc ('E');
-               Check_At_End_Of_Field;
-               Units.Table (Units.Last).Dynamic_Elab := True;
-               Dynamic_Elaboration_Checks_Specified := True;
+               C := Getc;
+
+               if C = 'E' then
+                  Check_At_End_Of_Field;
+                  Units.Table (Units.Last).Dynamic_Elab := True;
+                  Dynamic_Elaboration_Checks_Specified := True;
+               else
+                  Fatal_Error_Ignore;
+               end if;
 
             --  EB/EE parameters
 
@@ -1122,12 +1540,10 @@ package body ALI is
 
                if C = 'B' then
                   Units.Table (Units.Last).Elaborate_Body := True;
-
                elsif C = 'E' then
                   Units.Table (Units.Last).Set_Elab_Entity := True;
-
                else
-                  Fatal_Error;
+                  Fatal_Error_Ignore;
                end if;
 
                Check_At_End_Of_Field;
@@ -1135,9 +1551,14 @@ package body ALI is
             --  GE parameter (generic)
 
             elsif C = 'G' then
-               Checkc ('E');
-               Check_At_End_Of_Field;
-               Units.Table (Units.Last).Is_Generic := True;
+               C := Getc;
+
+               if C = 'E' then
+                  Check_At_End_Of_Field;
+                  Units.Table (Units.Last).Is_Generic := True;
+               else
+                  Fatal_Error_Ignore;
+               end if;
 
             --  IL/IS/IU parameters
 
@@ -1146,16 +1567,13 @@ package body ALI is
 
                if C = 'L' then
                   Units.Table (Units.Last).Icasing := All_Lower_Case;
-
                elsif C = 'S' then
                   Units.Table (Units.Last).Init_Scalars := True;
                   Initialize_Scalars_Used := True;
-
                elsif C = 'U' then
                   Units.Table (Units.Last).Icasing := All_Upper_Case;
-
                else
-                  Fatal_Error;
+                  Fatal_Error_Ignore;
                end if;
 
                Check_At_End_Of_Field;
@@ -1167,12 +1585,10 @@ package body ALI is
 
                if C = 'M' then
                   Units.Table (Units.Last).Kcasing := Mixed_Case;
-
                elsif C = 'U' then
                   Units.Table (Units.Last).Kcasing := All_Upper_Case;
-
                else
-                  Fatal_Error;
+                  Fatal_Error_Ignore;
                end if;
 
                Check_At_End_Of_Field;
@@ -1180,32 +1596,41 @@ package body ALI is
             --  NE parameter
 
             elsif C = 'N' then
-               Checkc ('E');
-               Units.Table (Units.Last).No_Elab := True;
-               Check_At_End_Of_Field;
+               C := Getc;
+
+               if C = 'E' then
+                  Units.Table (Units.Last).No_Elab := True;
+                  Check_At_End_Of_Field;
+               else
+                  Fatal_Error_Ignore;
+               end if;
 
             --  PR/PU/PK parameters
 
             elsif C = 'P' then
                C := Getc;
 
-               --  PR parameter (preelaborate)
-
                if C = 'R' then
                   Units.Table (Units.Last).Preelab := True;
-
-               --  PU parameter (pure)
-
                elsif C = 'U' then
                   Units.Table (Units.Last).Pure := True;
-
-               --  PK indicates unit is package
-
                elsif C = 'K' then
                   Units.Table (Units.Last).Unit_Kind := 'p';
+               else
+                  Fatal_Error_Ignore;
+               end if;
 
+               Check_At_End_Of_Field;
+
+            --  OL/OO/OS/OT parameters
+
+            elsif C = 'O' then
+               C := Getc;
+
+               if C = 'L' or else C = 'O' or else C = 'S' or else C = 'T' then
+                  Units.Table (Units.Last).Optimize_Alignment := C;
                else
-                  Fatal_Error;
+                  Fatal_Error_Ignore;
                end if;
 
                Check_At_End_Of_Field;
@@ -1215,23 +1640,14 @@ package body ALI is
             elsif C = 'R' then
                C := Getc;
 
-               --  RC parameter (remote call interface)
-
                if C = 'C' then
                   Units.Table (Units.Last).RCI := True;
-
-               --  RT parameter (remote types)
-
                elsif C = 'T' then
                   Units.Table (Units.Last).Remote_Types := True;
-
-               --  RA parameter (remote access to class wide type)
-
                elsif C = 'A' then
                   Units.Table (Units.Last).Has_RACW := True;
-
                else
-                  Fatal_Error;
+                  Fatal_Error_Ignore;
                end if;
 
                Check_At_End_Of_Field;
@@ -1239,24 +1655,19 @@ package body ALI is
             elsif C = 'S' then
                C := Getc;
 
-               --  SP parameter (shared passive)
-
                if C = 'P' then
                   Units.Table (Units.Last).Shared_Passive := True;
-
-               --  SU parameter indicates unit is subprogram
-
                elsif C = 'U' then
                   Units.Table (Units.Last).Unit_Kind := 's';
-
                else
-                  Fatal_Error;
+                  Fatal_Error_Ignore;
                end if;
 
                Check_At_End_Of_Field;
 
             else
-               Fatal_Error;
+               C := Getc;
+               Fatal_Error_Ignore;
             end if;
          end loop;
 
@@ -1274,7 +1685,10 @@ package body ALI is
 
          --  Scan out With lines for this unit
 
-         With_Loop : while C = 'W' loop
+         With_Loop : loop
+            Check_Unknown_Line;
+            exit With_Loop when C /= 'W' and then C /= 'Y';
+
             if Ignore ('W') then
                Skip_Line;
 
@@ -1282,11 +1696,13 @@ package body ALI is
                Checkc (' ');
                Skip_Space;
                Withs.Increment_Last;
-               Withs.Table (Withs.Last).Uname              := Get_Name;
+               Withs.Table (Withs.Last).Uname              := Get_Unit_Name;
                Withs.Table (Withs.Last).Elaborate          := False;
                Withs.Table (Withs.Last).Elaborate_All      := False;
+               Withs.Table (Withs.Last).Elab_Desirable     := False;
                Withs.Table (Withs.Last).Elab_All_Desirable := False;
-               Withs.Table (Withs.Last).Interface          := False;
+               Withs.Table (Withs.Last).SAL_Interface      := False;
+               Withs.Table (Withs.Last).Limited_With       := (C = 'Y');
 
                --  Generic case with no object file available
 
@@ -1297,15 +1713,29 @@ package body ALI is
                --  Normal case
 
                else
-                  Withs.Table (Withs.Last).Sfile := Get_Name (Lower => True);
-                  Withs.Table (Withs.Last).Afile := Get_Name;
+                  Withs.Table (Withs.Last).Sfile := Get_File_Name
+                                                      (Lower => True);
+                  Withs.Table (Withs.Last).Afile := Get_File_Name
+                                                      (Lower => True);
 
-                  --  Scan out possible E, EA, and NE parameters
+                  --  Scan out possible E, EA, ED, and AD parameters
 
                   while not At_Eol loop
                      Skip_Space;
 
-                     if Nextc = 'E' then
+                     if Nextc = 'A' then
+                        P := P + 1;
+                        Checkc ('D');
+                        Check_At_End_Of_Field;
+
+                        --  Store AD indication unless ignore required
+
+                        if not Ignore_ED then
+                           Withs.Table (Withs.Last).Elab_All_Desirable :=
+                             True;
+                        end if;
+
+                     elsif Nextc = 'E' then
                         P := P + 1;
 
                         if At_End_Of_Field then
@@ -1323,10 +1753,13 @@ package body ALI is
                            --  Store ED indication unless ignore required
 
                            if not Ignore_ED then
-                              Withs.Table (Withs.Last).Elab_All_Desirable :=
+                              Withs.Table (Withs.Last).Elab_Desirable :=
                                 True;
                            end if;
                         end if;
+
+                     else
+                        Fatal_Error;
                      end if;
                   end loop;
                end if;
@@ -1344,7 +1777,9 @@ package body ALI is
 
          Name_Len := 0;
 
-         Linker_Options_Loop : while C = 'L' loop
+         Linker_Options_Loop : loop
+            Check_Unknown_Line;
+            exit Linker_Options_Loop when C /= 'L';
 
             if Ignore ('L') then
                Skip_Line;
@@ -1360,7 +1795,7 @@ package body ALI is
                   if C < Character'Val (16#20#)
                     or else C > Character'Val (16#7E#)
                   then
-                     Fatal_Error;
+                     Fatal_Error_Ignore;
 
                   elsif C = '{' then
                      C := Character'Val (0);
@@ -1385,7 +1820,7 @@ package body ALI is
                                          10;
 
                            else
-                              Fatal_Error;
+                              Fatal_Error_Ignore;
                            end if;
                         end loop;
 
@@ -1403,7 +1838,7 @@ package body ALI is
                   end if;
                end loop;
 
-               Add_Char_To_Name_Buffer (nul);
+               Add_Char_To_Name_Buffer (NUL);
                Skip_Eol;
             end if;
 
@@ -1427,7 +1862,7 @@ package body ALI is
             Linker_Options.Table (Linker_Options.Last).Original_Pos :=
               Linker_Options.Last;
          end if;
-      end loop Unit_Loop;
+      end loop U_Loop;
 
       --  End loop through units for one ALI file
 
@@ -1456,7 +1891,10 @@ package body ALI is
 
       --  Scan out external version references and put in hash table
 
-      while C = 'E' loop
+      E_Loop : loop
+         Check_Unknown_Line;
+         exit E_Loop when C /= 'E';
+
          if Ignore ('E') then
             Skip_Line;
 
@@ -1482,13 +1920,16 @@ package body ALI is
          end if;
 
          C := Getc;
-      end loop;
+      end loop E_Loop;
 
       --  Scan out source dependency lines for this ALI file
 
       ALIs.Table (Id).First_Sdep := Sdep.Last + 1;
 
-      while C = 'D' loop
+      D_Loop : loop
+         Check_Unknown_Line;
+         exit D_Loop when C /= 'D';
+
          if Ignore ('D') then
             Skip_Line;
 
@@ -1496,7 +1937,12 @@ package body ALI is
             Checkc (' ');
             Skip_Space;
             Sdep.Increment_Last;
-            Sdep.Table (Sdep.Last).Sfile := Get_Name (Lower => True);
+
+            --  In the following call, Lower is not set to True, this is either
+            --  a bug, or it deserves a special comment as to why this is so???
+
+            Sdep.Table (Sdep.Last).Sfile := Get_File_Name;
+
             Sdep.Table (Sdep.Last).Stamp := Get_Stamp;
             Sdep.Table (Sdep.Last).Dummy_Entry :=
               (Sdep.Table (Sdep.Last).Stamp = Dummy_Time_Stamp);
@@ -1584,13 +2030,19 @@ package body ALI is
          end if;
 
          C := Getc;
-      end loop;
+      end loop D_Loop;
 
       ALIs.Table (Id).Last_Sdep := Sdep.Last;
 
       --  We must at this stage be at an Xref line or the end of file
 
-      if C /= EOF and then C /= 'X' then
+      if C = EOF then
+         return Id;
+      end if;
+
+      Check_Unknown_Line;
+
+      if C /= 'X' then
          Fatal_Error;
       end if;
 
@@ -1603,7 +2055,9 @@ package body ALI is
 
       --  Loop through Xref sections
 
-      while C = 'X' loop
+      X_Loop : loop
+         Check_Unknown_Line;
+         exit X_Loop when C /= 'X';
 
          --  Make new entry in section table
 
@@ -1618,7 +2072,7 @@ package body ALI is
 
          begin
             XS.File_Num     := Sdep_Id (Get_Nat + Nat (First_Sdep_Entry) - 1);
-            XS.File_Name    := Get_Name;
+            XS.File_Name    := Get_File_Name;
             XS.First_Entity := Xref_Entity.Last + 1;
 
             Current_File_Num := XS.File_Num;
@@ -1648,6 +2102,8 @@ package body ALI is
                   ----------------------------------
 
                   procedure Read_Instantiation_Reference is
+                     Local_File_Num : Sdep_Id := Current_File_Num;
+
                   begin
                      Xref.Increment_Last;
 
@@ -1661,12 +2117,12 @@ package body ALI is
                         if Nextc = '|' then
                            XR.File_Num :=
                              Sdep_Id (N + Nat (First_Sdep_Entry) - 1);
-                           Current_File_Num := XR.File_Num;
+                           Local_File_Num := XR.File_Num;
                            P := P + 1;
                            N := Get_Nat;
 
                         else
-                           XR.File_Num := Current_File_Num;
+                           XR.File_Num := Local_File_Num;
                         end if;
 
                         XR.Line  := N;
@@ -1696,6 +2152,31 @@ package body ALI is
                   XE.Lib    := (Getc = '*');
                   XE.Entity := Get_Name;
 
+                  --  Handle the information about generic instantiations
+
+                  if Nextc = '[' then
+                     Skipc; --  Opening '['
+                     N := Get_Nat;
+
+                     if Nextc /= '|' then
+                        XE.Iref_File_Num := Current_File_Num;
+                        XE.Iref_Line     := N;
+                     else
+                        XE.Iref_File_Num :=
+                          Sdep_Id (N + Nat (First_Sdep_Entry) - 1);
+                        Skipc;
+                        XE.Iref_Line := Get_Nat;
+                     end if;
+
+                     if Getc /= ']' then
+                        Fatal_Error;
+                     end if;
+
+                  else
+                     XE.Iref_File_Num := No_Sdep_Id;
+                     XE.Iref_Line     := 0;
+                  end if;
+
                   Current_File_Num := XS.File_Num;
 
                   --  Renaming reference is present
@@ -1719,85 +2200,82 @@ package body ALI is
 
                   Skip_Space;
 
-                  --  See if type reference present
-
-                  case Nextc is
-                     when '<'    => XE.Tref := Tref_Derived;
-                     when '('    => XE.Tref := Tref_Access;
-                     when '{'    => XE.Tref := Tref_Type;
-                     when others => XE.Tref := Tref_None;
-                  end case;
-
-                  --  Case of typeref field present
-
-                  if XE.Tref /= Tref_None then
-                     P := P + 1; -- skip opening bracket
+                  XE.Oref_File_Num := No_Sdep_Id;
+                  XE.Tref_File_Num := No_Sdep_Id;
+                  XE.Tref          := Tref_None;
+                  XE.First_Xref    := Xref.Last + 1;
 
-                     if Nextc in 'a' .. 'z' then
-                        XE.Tref_File_Num        := No_Sdep_Id;
-                        XE.Tref_Line            := 0;
-                        XE.Tref_Type            := ' ';
-                        XE.Tref_Col             := 0;
-                        XE.Tref_Standard_Entity :=
-                          Get_Name (Ignore_Spaces => True);
+                  --  Loop to check for additional info present
 
-                     else
-                        N := Get_Nat;
+                  loop
+                     declare
+                        Ref  : Tref_Kind;
+                        File : Sdep_Id;
+                        Line : Nat;
+                        Typ  : Character;
+                        Col  : Nat;
+                        Std  : Name_Id;
 
-                        if Nextc = '|' then
-                           XE.Tref_File_Num :=
-                             Sdep_Id (N + Nat (First_Sdep_Entry) - 1);
-                           P := P + 1;
-                           N := Get_Nat;
+                     begin
+                        Get_Typeref
+                          (Current_File_Num, Ref, File, Line, Typ, Col, Std);
+                        exit when Ref = Tref_None;
+
+                        --  Do we have an overriding procedure?
+
+                        if Ref = Tref_Derived and then Typ = 'p' then
+                           XE.Oref_File_Num := File;
+                           XE.Oref_Line     := Line;
+                           XE.Oref_Col      := Col;
+
+                        --  Arrays never override anything, and <> points to
+                        --  the index types instead
+
+                        elsif Ref = Tref_Derived and then XE.Etype = 'A' then
+
+                           --  Index types are stored in the list of references
+
+                           Xref.Increment_Last;
+
+                           declare
+                              XR : Xref_Record renames Xref.Table (Xref.Last);
+                           begin
+                              XR.File_Num := File;
+                              XR.Line     := Line;
+                              XR.Rtype    := Array_Index_Reference;
+                              XR.Col      := Col;
+                              XR.Name     := Std;
+                           end;
+
+                        --  Interfaces are stored in the list of references,
+                        --  although the parent type itself is stored in XE
+
+                        elsif Ref = Tref_Derived
+                          and then Typ = 'R'
+                          and then XE.Tref_File_Num /= No_Sdep_Id
+                        then
+                           Xref.Increment_Last;
+
+                           declare
+                              XR : Xref_Record renames Xref.Table (Xref.Last);
+                           begin
+                              XR.File_Num := File;
+                              XR.Line     := Line;
+                              XR.Rtype    := Interface_Reference;
+                              XR.Col      := Col;
+                              XR.Name     := Std;
+                           end;
 
                         else
-                           XE.Tref_File_Num := Current_File_Num;
+                           XE.Tref                 := Ref;
+                           XE.Tref_File_Num        := File;
+                           XE.Tref_Line            := Line;
+                           XE.Tref_Type            := Typ;
+                           XE.Tref_Col             := Col;
+                           XE.Tref_Standard_Entity := Std;
                         end if;
-
-                        XE.Tref_Line            := N;
-                        XE.Tref_Type            := Getc;
-                        XE.Tref_Col             := Get_Nat;
-                        XE.Tref_Standard_Entity := No_Name;
-                     end if;
-
-                     --  ??? Temporary workaround for nested generics case:
-                     --     4i4 Directories{1|4I9[4|6[3|3]]}
-                     --  See C918-002
-
-                     declare
-                        Nested_Brackets : Natural := 0;
-
-                     begin
-                        loop
-                           case Nextc is
-                              when '['   =>
-                                 Nested_Brackets := Nested_Brackets + 1;
-                              when ']' =>
-                                 Nested_Brackets := Nested_Brackets - 1;
-                              when others =>
-                                 if Nested_Brackets = 0 then
-                                    exit;
-                                 end if;
-                           end case;
-
-                           Skipc;
-                        end loop;
                      end;
-
-                     P := P + 1; -- skip closing bracket
-                     Skip_Space;
-
-                  --  No typeref entry present
-
-                  else
-                     XE.Tref_File_Num        := No_Sdep_Id;
-                     XE.Tref_Line            := 0;
-                     XE.Tref_Type            := ' ';
-                     XE.Tref_Col             := 0;
-                     XE.Tref_Standard_Entity := No_Name;
-                  end if;
-
-                  XE.First_Xref := Xref.Last + 1;
+                  end loop;
 
                   --  Loop through cross-references for this entity
 
@@ -1853,6 +2331,24 @@ package body ALI is
 
                   XE.Last_Xref := Xref.Last;
                   C := Nextc;
+
+               exception
+                  when Bad_ALI_Format =>
+
+                     --  If ignoring errors, then we skip a line with an
+                     --  unexpected error, and try to continue subsequent
+                     --  xref lines.
+
+                     if Ignore_Errors then
+                        Xref_Entity.Decrement_Last;
+                        Skip_Line;
+                        C := Nextc;
+
+                     --  Otherwise, we reraise the fatal exception
+
+                     else
+                        raise;
+                     end if;
                end Read_Refs_For_One_Entity;
             end loop;
 
@@ -1863,7 +2359,7 @@ package body ALI is
          end Read_Refs_For_One_File;
 
          C := Getc;
-      end loop;
+      end loop X_Loop;
 
       --  Here after dealing with xref sections
 
@@ -1876,7 +2372,6 @@ package body ALI is
    exception
       when Bad_ALI_Format =>
          return No_ALI_Id;
-
    end Scan_ALI;
 
    ---------