-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2006, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2009, 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, 51 Franklin Street, Fifth Floor, --
--- Boston, MA 02110-1301, 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;
'D' => True, -- dependency
'X' => True, -- xref
'S' => True, -- specific dispatching
+ 'Y' => True, -- limited_with
others => False);
--------------------
--------------
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";
- Ignore_Errors : Boolean := False) 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;
+ Directly_Scanned : Boolean := False) return ALI_Id
is
P : Text_Ptr := T'First;
Line : Logical_Line_Number := 1;
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. This function handles wide characters properly.
+ -- 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 quote 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
+ -- 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
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
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
+ (Ignore_Spaces : Boolean := False;
+ Ignore_Special : Boolean := False) return Name_Id
is
begin
Name_Len := 0;
end if;
loop
- Name_Len := Name_Len + 1;
- Name_Buffer (Name_Len) := Getc;
+ Add_Char_To_Name_Buffer (Getc);
- exit when At_End_Of_Field and not Ignore_Spaces;
+ exit when At_End_Of_Field and then 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
- -- Terminate on parens or angle brackets or equal sign
+ else
+ -- Terminate on parens or angle brackets or equal sign
- exit when Nextc = '(' or else Nextc = ')'
- or else Nextc = '{' or else Nextc = '}'
- or else Nextc = '<' or else Nextc = '>'
- or else Nextc = '=';
+ exit when Nextc = '(' or else Nextc = ')'
+ or else Nextc = '{' or else Nextc = '}'
+ or else Nextc = '<' or else Nextc = '>'
+ or else Nextc = '=';
- -- Terminate if left bracket not part of wide char sequence
- -- Note that we only recognize brackets notation so far ???
+ -- 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) /= '"';
+ exit when Nextc = '[' and then T (P + 1) /= '"';
- -- Terminate if right bracket not part of wide char sequence
+ -- Terminate if right bracket not part of wide char sequence
- exit when Nextc = ']' and then T (P - 1) /= '"';
+ exit when Nextc = ']' and then T (P - 1) /= '"';
+ end if;
end if;
end loop;
- -- 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));
- end if;
-
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 --
-------------
begin
Skip_Space;
+ -- Check if we are on a number. In the case of bad 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';
+ exit when Nextc < '0' or else Nextc > '9';
end loop;
return V;
-- 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
Queuing_Policy => ' ',
Restrictions => No_Restrictions,
SAL_Interface => False,
- Sfile => No_Name,
+ 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,
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;
+ Add_Char_To_Name_Buffer (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));
UL : Unit_Record renames Units.Table (Units.Last);
begin
- UL.Uname := Get_Name;
+ UL.Uname := Get_Unit_Name;
UL.Predefined := Is_Predefined_Unit;
UL.Internal := Is_Internal_Unit;
UL.My_ALI := Id;
- UL.Sfile := Get_Name (Lower => True);
+ UL.Sfile := Get_File_Name (Lower => True);
UL.Pure := False;
UL.Preelab := False;
UL.No_Elab := False;
UL.First_Arg := First_Arg;
UL.Elab_Position := 0;
UL.SAL_Interface := ALIs.Table (Id).SAL_Interface;
+ UL.Directly_Scanned := Directly_Scanned;
UL.Body_Needed_For_SAL := False;
UL.Elaborate_Body_Desirable := False;
+ UL.Optimize_Alignment := 'O';
if Debug_Flag_U then
Write_Str (" ----> reading unit ");
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_Ignore;
+ end if;
+
+ Check_At_End_Of_Field;
+
-- RC/RT parameters
elsif C = 'R' then
With_Loop : loop
Check_Unknown_Line;
- exit With_Loop when C /= 'W';
+ exit With_Loop when C /= 'W' and then C /= 'Y';
if Ignore ('W') then
Skip_Line;
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).SAL_Interface := False;
+ Withs.Table (Withs.Last).Limited_With := (C = 'Y');
-- Generic case with no object file available
-- 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, ED, and AD parameters
True;
end if;
end if;
+
+ else
+ Fatal_Error;
end if;
end loop;
end if;
end if;
end loop;
- Add_Char_To_Name_Buffer (nul);
+ Add_Char_To_Name_Buffer (NUL);
Skip_Eol;
end if;
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);
if Nextc not in '0' .. '9' then
Name_Len := 0;
-
while not At_End_Of_Field loop
- Name_Len := Name_Len + 1;
- Name_Buffer (Name_Len) := Getc;
+ Add_Char_To_Name_Buffer (Getc);
end loop;
- Sdep.Table (Sdep.Last).Subunit_Name := Name_Enter;
+ -- Set the subunit name. Note that we use Name_Find rather
+ -- than Name_Enter here as the subunit name may already
+ -- have been put in the name table by the Project Manager.
+
+ Sdep.Table (Sdep.Last).Subunit_Name := Name_Find;
+
Skip_Space;
end if;
Name_Len := 0;
while not At_End_Of_Field loop
- Name_Len := Name_Len + 1;
- Name_Buffer (Name_Len) := Getc;
+ Add_Char_To_Name_Buffer (Getc);
end loop;
Sdep.Table (Sdep.Last).Rfile := Name_Enter;
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;
Skip_Space;
- -- See if type reference present
+ XE.Oref_File_Num := No_Sdep_Id;
+ XE.Tref_File_Num := No_Sdep_Id;
+ XE.Tref := Tref_None;
+ XE.First_Xref := Xref.Last + 1;
- Get_Typeref
- (Current_File_Num, XE.Tref, XE.Tref_File_Num, XE.Tref_Line,
- XE.Tref_Type, XE.Tref_Col, XE.Tref_Standard_Entity);
+ -- Loop to check for additional info present
- -- Do we have an overriding procedure, instead ?
- if XE.Tref_Type = 'p' then
- XE.Oref_File_Num := XE.Tref_File_Num;
- XE.Oref_Line := XE.Tref_Line;
- XE.Oref_Col := XE.Tref_Col;
- XE.Tref_File_Num := No_Sdep_Id;
- XE.Tref := Tref_None;
- else
- -- We might have additional information about the
- -- overloaded subprograms
+ loop
declare
- Ref : Tref_Kind;
- Typ : Character;
- Standard_Entity : Name_Id;
+ Ref : Tref_Kind;
+ File : Sdep_Id;
+ Line : Nat;
+ Typ : Character;
+ Col : Nat;
+ Std : Name_Id;
+
begin
Get_Typeref
- (Current_File_Num,
- Ref, XE.Oref_File_Num,
- XE.Oref_Line, Typ, XE.Oref_Col, Standard_Entity);
- end;
- end if;
+ (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.
+ -- The first interface (when there are only
+ -- interfaces) is stored in XE.Tref*)
+
+ 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;
- XE.First_Xref := Xref.Last + 1;
+ else
+ 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;
+ end;
+ end loop;
-- Loop through cross-references for this entity
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;
exception
when Bad_ALI_Format =>
return No_ALI_Id;
-
end Scan_ALI;
---------