with GNAT.Case_Util; use GNAT.Case_Util;
with GNAT.Directory_Operations; use GNAT.Directory_Operations;
with GNAT.Dynamic_HTables;
+with GNAT.Table;
with Err_Vars; use Err_Vars;
with Opt; use Opt;
with Osint; use Osint;
with Output; use Output;
+with Prj.Com;
with Prj.Err; use Prj.Err;
with Prj.Util; use Prj.Util;
with Sinput.P;
Name : File_Name_Type; -- ??? duplicates the key
Location : Source_Ptr;
Source : Source_Id := No_Source;
+ Listed : Boolean := False;
Found : Boolean := False;
end record;
+
No_Name_Location : constant Name_Location :=
- (No_File, No_Location, No_Source, False);
+ (Name => No_File,
+ Location => No_Location,
+ Source => No_Source,
+ Listed => False,
+ Found => False);
+
package Source_Names_Htable is new GNAT.Dynamic_HTables.Simple_HTable
(Header_Num => Header_Num,
Element => Name_Location,
Key => File_Name_Type,
Hash => Hash,
Equal => "=");
- -- Information about file names found in string list attribute
- -- (Source_Files or Source_List_File).
- -- Except is set to True if source is a naming exception in the project.
- -- This is used to check that all referenced files were indeed found on the
- -- disk.
+ -- File name information found in string list attribute (Source_Files or
+ -- Source_List_File). Except is set to True if source is a naming exception
+ -- in the project. Used to check that all referenced files were indeed
+ -- found on the disk.
type Unit_Exception is record
Name : Name_Id; -- ??? duplicates the key
type Tree_Processing_Data is record
Tree : Project_Tree_Ref;
+ Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
File_To_Source : Files_Htable.Instance;
Flags : Prj.Processing_Flags;
end record;
-- This data must be initialized before processing any project, and the
-- same data is used for processing all projects in the tree.
+ type Lib_Data is record
+ Name : Name_Id;
+ Proj : Project_Id;
+ end record;
+
+ package Lib_Data_Table is new GNAT.Table
+ (Table_Component_Type => Lib_Data,
+ Table_Index_Type => Natural,
+ Table_Low_Bound => 1,
+ Table_Initial => 10,
+ Table_Increment => 100);
+ -- A table to record library names in order to check that two library
+ -- projects do not have the same library names.
+
procedure Initialize
- (Data : out Tree_Processing_Data;
- Tree : Project_Tree_Ref;
- Flags : Prj.Processing_Flags);
+ (Data : out Tree_Processing_Data;
+ Tree : Project_Tree_Ref;
+ Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
+ Flags : Prj.Processing_Flags);
-- Initialize Data
procedure Free (Data : in out Tree_Processing_Data);
-- exceptions, and copied into the Source_Names and Unit_Exceptions tables
-- as appropriate.
+ type Search_Type is (Search_Files, Search_Directories);
+ pragma Unreferenced (Search_Files);
+
+ generic
+ with procedure Callback
+ (Path_Id : Path_Name_Type;
+ Display_Path_Id : Path_Name_Type;
+ Pattern_Index : Natural);
+ procedure Expand_Subdirectory_Pattern
+ (Project : Project_Id;
+ Data : in out Tree_Processing_Data;
+ Patterns : String_List_Id;
+ Search_For : Search_Type;
+ Resolve_Links : Boolean);
+ -- Search the subdirectories of Project's directory for files or
+ -- directories that match the globbing patterns found in Patterns (for
+ -- instance "**/*.adb"). Typically, Patterns will be the value of the
+ -- Source_Dirs or Excluded_Source_Dirs attributes.
+ -- Every time such a file or directory is found, the callback is called.
+ -- Resolve_Links indicates whether we should resolve links while
+ -- normalizing names.
+ -- In the callback, Pattern_Index is the index within Patterns where the
+ -- expanded pattern was found (1 for the first element of Patterns and
+ -- all its matching directories, then 2,...).
+ -- We use a generic and not an access-to-subprogram because in some cases
+ -- this code is compiled with the restriction No_Implicit_Dynamic_Code
+
procedure Add_Source
(Id : out Source_Id;
Data : in out Tree_Processing_Data;
procedure Check_Package_Naming
(Project : Project_Id;
- Data : in out Tree_Processing_Data;
- Bodies : out Array_Element_Id;
- Specs : out Array_Element_Id);
+ Data : in out Tree_Processing_Data);
-- Check the naming scheme part of Data, and initialize the naming scheme
- -- data in the config of the various languages. This also returns the
- -- naming scheme exceptions for unit-based languages (Bodies and Specs are
- -- associative arrays mapping individual unit names to source file names).
+ -- data in the config of the various languages.
procedure Check_Configuration
(Project : Project_Id;
-- Check the library attributes of project Project in project tree
-- and modify its data Data accordingly.
+ procedure Check_Aggregate_Project
+ (Project : Project_Id;
+ Data : in out Tree_Processing_Data);
+ -- Check aggregate projects attributes
+
+ procedure Check_Abstract_Project
+ (Project : Project_Id;
+ Data : in out Tree_Processing_Data);
+ -- Check abstract projects attributes
+
procedure Check_Programming_Languages
(Project : Project_Id;
Data : in out Tree_Processing_Data);
Data : in out Tree_Processing_Data;
Source_Dir_Rank : Natural;
Path : Path_Name_Type;
+ Display_Path : Path_Name_Type;
File_Name : File_Name_Type;
Display_File_Name : File_Name_Type;
Locally_Removed : Boolean;
-- schemes, it is added to various htables through Add_Source and to
-- Source_Paths_Htable.
--
- -- Name is the name of the candidate file. It hasn't been normalized yet
- -- and is the direct result of readdir().
+ -- File_Name is the same as Display_File_Name, but has been normalized.
+ -- They do not include the directory information.
--
- -- File_Name is the same as Name, but has been normalized.
- -- Display_File_Name, however, has not been normalized.
+ -- Path and Display_Path on the other hand are the full path to the file.
+ -- Path must have been normalized (canonical casing and possibly links
+ -- resolved).
--
-- Source_Directory is the directory in which the file was found. It is
-- neither normalized nor has had links resolved, and must not end with a
(Project : in out Project_Processing_Data;
Data : in out Tree_Processing_Data);
-- Find all the sources of project Project in project tree Data.Tree and
- -- update its Data accordingly. This assumes that Data.First_Source has
- -- been initialized with the list of excluded sources and special naming
- -- exceptions.
+ -- update its Data accordingly. This assumes that the special naming
+ -- exceptions have already been processed.
function Path_Name_Of
(File_Name : File_Name_Type;
-- Debug print a value for a specific property. Does nothing when not in
-- debug mode
+ procedure Error_Or_Warning
+ (Flags : Processing_Flags;
+ Kind : Error_Warning;
+ Msg : String;
+ Location : Source_Ptr;
+ Project : Project_Id);
+ -- Emits either an error or warning message (or nothing), depending on Kind
+
+ ----------------------
+ -- Error_Or_Warning --
+ ----------------------
+
+ procedure Error_Or_Warning
+ (Flags : Processing_Flags;
+ Kind : Error_Warning;
+ Msg : String;
+ Location : Source_Ptr;
+ Project : Project_Id) is
+ begin
+ case Kind is
+ when Error => Error_Msg (Flags, Msg, Location, Project);
+ when Warning => Error_Msg (Flags, "?" & Msg, Location, Project);
+ when Silent => null;
+ end case;
+ end Error_Or_Warning;
+
------------------------------
-- Replace_Into_Name_Buffer --
------------------------------
end if;
elsif Prev_Unit /= No_Unit_Index
+ and then Prev_Unit.File_Names (Kind) /= null
and then not Source.Locally_Removed
then
-- Path is set if this is a source we found on the disk, in which
elsif not Source.Locally_Removed
and then not Data.Flags.Allow_Duplicate_Basenames
and then Lang_Id.Config.Kind = Unit_Based
+ and then Source.Language.Config.Kind = Unit_Based
then
Error_Msg_File_1 := File_Name;
Error_Msg_File_2 := File_Name_Type (Source.Project.Name);
if Current_Verbosity = High then
Write_Str ("Adding source File: ");
- Write_Str (Get_Name_String (File_Name));
+ Write_Str (Get_Name_String (Display_File));
if Index /= 0 then
Write_Str (" at" & Index'Img);
end if;
Id.Project := Project;
+ Id.Location := Location;
Id.Source_Dir_Rank := Source_Dir_Rank;
Id.Language := Lang_Id;
Id.Kind := Kind;
end if;
end Canonical_Case_File_Name;
+ -----------------------------
+ -- Check_Aggregate_Project --
+ -----------------------------
+
+ procedure Check_Aggregate_Project
+ (Project : Project_Id;
+ Data : in out Tree_Processing_Data)
+ is
+ Project_Files : constant Prj.Variable_Value :=
+ Prj.Util.Value_Of
+ (Snames.Name_Project_Files,
+ Project.Decl.Attributes,
+ Data.Tree);
+ begin
+ if Project_Files.Default then
+ Error_Msg_Name_1 := Snames.Name_Project_Files;
+ Error_Msg
+ (Data.Flags,
+ "Attribute %% must be specified in aggregate project",
+ Project.Location, Project);
+ end if;
+ end Check_Aggregate_Project;
+
+ ----------------------------
+ -- Check_Abstract_Project --
+ ----------------------------
+
+ procedure Check_Abstract_Project
+ (Project : Project_Id;
+ Data : in out Tree_Processing_Data)
+ is
+ Source_Dirs : constant Variable_Value :=
+ Util.Value_Of
+ (Name_Source_Dirs,
+ Project.Decl.Attributes, Data.Tree);
+ Source_Files : constant Variable_Value :=
+ Util.Value_Of
+ (Name_Source_Files,
+ Project.Decl.Attributes, Data.Tree);
+ Source_List_File : constant Variable_Value :=
+ Util.Value_Of
+ (Name_Source_List_File,
+ Project.Decl.Attributes, Data.Tree);
+ Languages : constant Variable_Value :=
+ Util.Value_Of
+ (Name_Languages,
+ Project.Decl.Attributes, Data.Tree);
+
+ begin
+ if Project.Source_Dirs /= Nil_String then
+ if Source_Dirs.Values = Nil_String
+ and then Source_Files.Values = Nil_String
+ and then Languages.Values = Nil_String
+ and then Source_List_File.Default
+ then
+ Project.Source_Dirs := Nil_String;
+
+ else
+ Error_Msg
+ (Data.Flags,
+ "at least one of Source_Files, Source_Dirs or Languages "
+ & "must be declared empty for an abstract project",
+ Project.Location, Project);
+ end if;
+ end if;
+ end Check_Abstract_Project;
+
-----------
-- Check --
-----------
procedure Check
- (Project : Project_Id;
- Data : in out Tree_Processing_Data)
+ (Project : Project_Id;
+ Data : in out Tree_Processing_Data)
is
- Specs : Array_Element_Id;
- Bodies : Array_Element_Id;
- Extending : Boolean := False;
Prj_Data : Project_Processing_Data;
begin
Initialize (Prj_Data, Project);
- Check_If_Externally_Built (Project, Data);
-
- -- Object, exec and source directories
-
- Get_Directories (Project, Data);
-
- -- Get the programming languages
-
+ Check_If_Externally_Built (Project, Data);
+ Get_Directories (Project, Data);
Check_Programming_Languages (Project, Data);
- if Project.Qualifier = Dry
- and then Project.Source_Dirs /= Nil_String
- then
- declare
- Source_Dirs : constant Variable_Value :=
- Util.Value_Of
- (Name_Source_Dirs,
- Project.Decl.Attributes, Data.Tree);
- Source_Files : constant Variable_Value :=
- Util.Value_Of
- (Name_Source_Files,
- Project.Decl.Attributes, Data.Tree);
- Source_List_File : constant Variable_Value :=
- Util.Value_Of
- (Name_Source_List_File,
- Project.Decl.Attributes, Data.Tree);
- Languages : constant Variable_Value :=
- Util.Value_Of
- (Name_Languages,
- Project.Decl.Attributes, Data.Tree);
-
- begin
- if Source_Dirs.Values = Nil_String
- and then Source_Files.Values = Nil_String
- and then Languages.Values = Nil_String
- and then Source_List_File.Default
- then
- Project.Source_Dirs := Nil_String;
-
- else
- Error_Msg
- (Data.Flags,
- "at least one of Source_Files, Source_Dirs or Languages "
- & "must be declared empty for an abstract project",
- Project.Location, Project);
- end if;
- end;
- end if;
+ case Project.Qualifier is
+ when Aggregate => Check_Aggregate_Project (Project, Data);
+ when Dry => Check_Abstract_Project (Project, Data);
+ when others => null;
+ end case;
-- Check configuration. This must be done even for gnatmake (even though
-- no user configuration file was provided) since the default config we
Check_Configuration (Project, Data);
- -- Library attributes
-
Check_Library_Attributes (Project, Data);
if Current_Verbosity = High then
Show_Source_Dirs (Project, Data.Tree);
end if;
- Extending := Project.Extends /= No_Project;
+ Check_Package_Naming (Project, Data);
- Check_Package_Naming (Project, Data, Bodies => Bodies, Specs => Specs);
-
- -- Find the sources
-
- if Project.Source_Dirs /= Nil_String then
+ if Project.Qualifier /= Aggregate then
Look_For_Sources (Prj_Data, Data);
-
- if not Project.Externally_Built
- and then not Extending
- then
- declare
- Language : Language_Ptr;
- Source : Source_Id;
- Alt_Lang : Language_List;
- Continuation : Boolean := False;
- Iter : Source_Iterator;
-
- begin
- Language := Project.Languages;
- while Language /= No_Language_Index loop
-
- -- If there are no sources for this language, check if there
- -- are sources for which this is an alternate language.
-
- if Language.First_Source = No_Source
- and then (Data.Flags.Require_Sources_Other_Lang
- or else Language.Name = Name_Ada)
- then
- Iter := For_Each_Source (In_Tree => Data.Tree,
- Project => Project);
- Source_Loop : loop
- Source := Element (Iter);
- exit Source_Loop when Source = No_Source
- or else Source.Language = Language;
-
- Alt_Lang := Source.Alternate_Languages;
- while Alt_Lang /= null loop
- exit Source_Loop when Alt_Lang.Language = Language;
- Alt_Lang := Alt_Lang.Next;
- end loop;
-
- Next (Iter);
- end loop Source_Loop;
-
- if Source = No_Source then
-
- Report_No_Sources
- (Project,
- Get_Name_String (Language.Display_Name),
- Data,
- Prj_Data.Source_List_File_Location,
- Continuation);
- Continuation := True;
- end if;
- end if;
-
- Language := Language.Next;
- end loop;
- end;
- end if;
end if;
- -- If a list of sources is specified in attribute Interfaces, set
- -- In_Interfaces only for the sources specified in the list.
-
Check_Interfaces (Project, Data);
- -- If it is a library project file, check if it is a standalone library
-
if Project.Library then
Check_Stand_Alone_Library (Project, Data);
end if;
- -- Put the list of Mains, if any, in the project data
-
Get_Mains (Project, Data);
Free (Prj_Data);
elsif Attribute.Name = Name_Required_Switches then
- -- Attribute Required_Switches: the minimum
+ -- Attribute Required_Switches: the minimum trailing
-- options to use when invoking the linker
- Put (Into_List => Project.Config.Minimum_Linker_Options,
+ Put (Into_List =>
+ Project.Config.Trailing_Linker_Required_Switches,
From_List => Attribute.Value.Values,
In_Tree => Data.Tree);
elsif Name = Name_Option_List then
Project.Config.Resp_File_Format := Option_List;
+ elsif Name_Buffer (1 .. Name_Len) = "gcc" then
+ Project.Config.Resp_File_Format := GCC;
+
+ elsif Name_Buffer (1 .. Name_Len) = "gcc_gnu" then
+ Project.Config.Resp_File_Format := GCC_GNU;
+
+ elsif
+ Name_Buffer (1 .. Name_Len) = "gcc_option_list"
+ then
+ Project.Config.Resp_File_Format := GCC_Option_List;
+
+ elsif
+ Name_Buffer (1 .. Name_Len) = "gcc_object_list"
+ then
+ Project.Config.Resp_File_Format := GCC_Object_List;
+
else
Error_Msg
(Data.Flags,
procedure Check_Package_Naming
(Project : Project_Id;
- Data : in out Tree_Processing_Data;
- Bodies : out Array_Element_Id;
- Specs : out Array_Element_Id)
+ Data : in out Tree_Processing_Data)
is
Naming_Id : constant Package_Id :=
Util.Value_Of
Kind => Kind,
File_Name => File_Name,
Display_File => File_Name_Type (Element.Value),
- Naming_Exception => True);
+ Naming_Exception => True,
+ Location => Element.Location);
else
-- Check if the file name is already recorded for another
-- Get the naming exceptions for all languages
- for Kind in Spec .. Impl loop
+ for Kind in Spec_Or_Body loop
Lang_Id := Project.Languages;
while Lang_Id /= No_Language_Index loop
case Lang_Id.Config.Kind is
-- Start of processing for Check_Naming_Schemes
begin
- Specs := No_Array_Element;
- Bodies := No_Array_Element;
-
-- No Naming package or parsing a configuration file? nothing to do
if Naming_Id /= No_Package
end;
end if;
- if Project.Extends /= No_Project then
+ if Project.Extends /= No_Project and then Project.Extends.Library then
+
+ -- Remove the library name from Lib_Data_Table
+
+ for J in 1 .. Lib_Data_Table.Last loop
+ if Lib_Data_Table.Table (J).Proj = Project.Extends then
+ Lib_Data_Table.Table (J) :=
+ Lib_Data_Table.Table (Lib_Data_Table.Last);
+ Lib_Data_Table.Set_Last (Lib_Data_Table.Last - 1);
+ exit;
+ end if;
+ end loop;
+
Project.Extends.Library := False;
end if;
+
+ if Project.Library and then not Lib_Name.Default then
+
+ -- Check if the same library name is used in an other library project
+
+ for J in 1 .. Lib_Data_Table.Last loop
+ if Lib_Data_Table.Table (J).Name = Project.Library_Name then
+ Error_Msg_Name_1 := Lib_Data_Table.Table (J).Proj.Name;
+ Error_Msg
+ (Data.Flags,
+ "Library name cannot be the same as in project %%",
+ Lib_Name.Location, Project);
+ Project.Library := False;
+ exit;
+ end if;
+ end loop;
+ end if;
+
+ if Project.Library then
+
+ -- Record the library name
+
+ Lib_Data_Table.Append
+ ((Name => Project.Library_Name, Proj => Project));
+ end if;
end Check_Library_Attributes;
---------------------------------
---------------------
procedure Get_Directories
- (Project : Project_Id;
- Data : in out Tree_Processing_Data)
+ (Project : Project_Id;
+ Data : in out Tree_Processing_Data)
is
- package Recursive_Dirs is new GNAT.Dynamic_HTables.Simple_HTable
- (Header_Num => Header_Num,
- Element => Boolean,
- No_Element => False,
- Key => Path_Name_Type,
- Hash => Hash,
- Equal => "=");
- -- Hash table stores recursive source directories, to avoid looking
- -- several times, and to avoid cycles that may be introduced by symbolic
- -- links.
-
- Visited : Recursive_Dirs.Instance;
-
Object_Dir : constant Variable_Value :=
Util.Value_Of
(Name_Object_Dir, Project.Decl.Attributes, Data.Tree);
Languages : constant Variable_Value :=
Prj.Util.Value_Of
- (Name_Languages, Project.Decl.Attributes, Data.Tree);
+ (Name_Languages, Project.Decl.Attributes, Data.Tree);
- procedure Find_Source_Dirs
- (From : File_Name_Type;
- Location : Source_Ptr;
- Rank : Natural;
- Removed : Boolean := False);
- -- Find one or several source directories, and add (or remove, if
- -- Removed is True) them to list of source directories of the project.
+ Remove_Source_Dirs : Boolean := False;
procedure Add_To_Or_Remove_From_Source_Dirs
(Path_Id : Path_Name_Type;
Display_Path_Id : Path_Name_Type;
- Rank : Natural;
- Removed : Boolean);
+ Rank : Natural);
-- When Removed = False, the directory Path_Id to the list of
-- source_dirs if not already in the list. When Removed = True,
-- removed directory Path_Id if in the list.
+ procedure Find_Source_Dirs is new Expand_Subdirectory_Pattern
+ (Add_To_Or_Remove_From_Source_Dirs);
+
---------------------------------------
-- Add_To_Or_Remove_From_Source_Dirs --
---------------------------------------
procedure Add_To_Or_Remove_From_Source_Dirs
(Path_Id : Path_Name_Type;
Display_Path_Id : Path_Name_Type;
- Rank : Natural;
- Removed : Boolean)
+ Rank : Natural)
is
List : String_List_Id;
Prev : String_List_Id;
-- The directory is in the list if List is not Nil_String
- if not Removed and then List = Nil_String then
+ if not Remove_Source_Dirs and then List = Nil_String then
if Current_Verbosity = High then
Write_Str (" Adding Source Dir=");
- Write_Line (Get_Name_String (Path_Id));
+ Write_Line (Get_Name_String (Display_Path_Id));
end if;
String_Element_Table.Increment_Last (Data.Tree.String_Elements);
Data.Tree.Number_Lists.Table (Last_Src_Dir_Rank) :=
(Number => Rank, Next => No_Number_List);
- elsif Removed and then List /= Nil_String then
+ elsif Remove_Source_Dirs and then List /= Nil_String then
-- Remove source dir, if present
end if;
end Add_To_Or_Remove_From_Source_Dirs;
- ----------------------
- -- Find_Source_Dirs --
- ----------------------
-
- procedure Find_Source_Dirs
- (From : File_Name_Type;
- Location : Source_Ptr;
- Rank : Natural;
- Removed : Boolean := False)
- is
- Directory : constant String := Get_Name_String (From);
-
- procedure Recursive_Find_Dirs (Path : Name_Id);
- -- Find all the subdirectories (recursively) of Path and add them
- -- to the list of source directories of the project.
+ -- Local declarations
- -------------------------
- -- Recursive_Find_Dirs --
- -------------------------
-
- procedure Recursive_Find_Dirs (Path : Name_Id) is
- Dir : Dir_Type;
- Name : String (1 .. 250);
- Last : Natural;
-
- Non_Canonical_Path : Path_Name_Type := No_Path;
- Canonical_Path : Path_Name_Type := No_Path;
-
- The_Path : constant String :=
- Normalize_Pathname
- (Get_Name_String (Path),
- Directory =>
- Get_Name_String (Project.Directory.Display_Name),
- Resolve_Links => Opt.Follow_Links_For_Dirs) &
- Directory_Separator;
-
- The_Path_Last : constant Natural :=
- Compute_Directory_Last (The_Path);
-
- begin
- Name_Len := The_Path_Last - The_Path'First + 1;
- Name_Buffer (1 .. Name_Len) :=
- The_Path (The_Path'First .. The_Path_Last);
- Non_Canonical_Path := Name_Find;
- Canonical_Path :=
- Path_Name_Type
- (Canonical_Case_File_Name (Name_Id (Non_Canonical_Path)));
-
- -- To avoid processing the same directory several times, check
- -- if the directory is already in Recursive_Dirs. If it is, then
- -- there is nothing to do, just return. If it is not, put it there
- -- and continue recursive processing.
-
- if not Removed then
- if Recursive_Dirs.Get (Visited, Canonical_Path) then
- return;
- else
- Recursive_Dirs.Set (Visited, Canonical_Path, True);
- end if;
- end if;
-
- Add_To_Or_Remove_From_Source_Dirs
- (Path_Id => Canonical_Path,
- Display_Path_Id => Non_Canonical_Path,
- Rank => Rank,
- Removed => Removed);
-
- -- Now look for subdirectories. Do that even when this directory
- -- is already in the list, because some of its subdirectories may
- -- not be in the list yet.
-
- Open (Dir, The_Path (The_Path'First .. The_Path_Last));
-
- loop
- Read (Dir, Name, Last);
- exit when Last = 0;
-
- if Name (1 .. Last) /= "."
- and then Name (1 .. Last) /= ".."
- then
- -- Avoid . and .. directories
-
- if Current_Verbosity = High then
- Write_Str (" Checking ");
- Write_Line (Name (1 .. Last));
- end if;
-
- declare
- Path_Name : constant String :=
- Normalize_Pathname
- (Name => Name (1 .. Last),
- Directory =>
- The_Path
- (The_Path'First .. The_Path_Last),
- Resolve_Links =>
- Opt.Follow_Links_For_Dirs,
- Case_Sensitive => True);
-
- begin
- if Is_Directory (Path_Name) then
-
- -- We have found a new subdirectory, call self
-
- Name_Len := Path_Name'Length;
- Name_Buffer (1 .. Name_Len) := Path_Name;
- Recursive_Find_Dirs (Name_Find);
- end if;
- end;
- end if;
- end loop;
-
- Close (Dir);
-
- exception
- when Directory_Error =>
- null;
- end Recursive_Find_Dirs;
-
- -- Start of processing for Find_Source_Dirs
-
- begin
- if Current_Verbosity = High and then not Removed then
- Write_Str ("Find_Source_Dirs (""");
- Write_Str (Directory);
- Write_Str (",");
- Write_Str (Rank'Img);
- Write_Line (""")");
- end if;
-
- -- First, check if we are looking for a directory tree, indicated
- -- by "/**" at the end.
+ Dir_Exists : Boolean;
- if Directory'Length >= 3
- and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
- and then (Directory (Directory'Last - 2) = '/'
+ No_Sources : constant Boolean :=
+ ((not Source_Files.Default
+ and then Source_Files.Values = Nil_String)
or else
- Directory (Directory'Last - 2) = Directory_Separator)
- then
- Name_Len := Directory'Length - 3;
-
- if Name_Len = 0 then
-
- -- Case of "/**": all directories in file system
-
- Name_Len := 1;
- Name_Buffer (1) := Directory (Directory'First);
-
- else
- Name_Buffer (1 .. Name_Len) :=
- Directory (Directory'First .. Directory'Last - 3);
- end if;
-
- if Current_Verbosity = High then
- Write_Str ("Looking for all subdirectories of """);
- Write_Str (Name_Buffer (1 .. Name_Len));
- Write_Line ("""");
- end if;
-
- declare
- Base_Dir : constant File_Name_Type := Name_Find;
- Root_Dir : constant String :=
- Normalize_Pathname
- (Name => Name_Buffer (1 .. Name_Len),
- Directory =>
- Get_Name_String
- (Project.Directory.Display_Name),
- Resolve_Links =>
- Opt.Follow_Links_For_Dirs,
- Case_Sensitive => True);
-
- begin
- if Root_Dir'Length = 0 then
- Err_Vars.Error_Msg_File_1 := Base_Dir;
- Error_Msg
- (Data.Flags,
- "{ is not a valid directory.", Location, Project);
-
- else
- -- We have an existing directory, we register it and all of
- -- its subdirectories.
-
- if Current_Verbosity = High then
- Write_Line ("Looking for source directories:");
- end if;
-
- Name_Len := Root_Dir'Length;
- Name_Buffer (1 .. Name_Len) := Root_Dir;
- Recursive_Find_Dirs (Name_Find);
-
- if Current_Verbosity = High then
- Write_Line ("End of looking for source directories.");
- end if;
- end if;
- end;
-
- -- We have a single directory
-
- else
- declare
- Path_Name : Path_Information;
- Dir_Exists : Boolean;
-
- begin
- Locate_Directory
- (Project => Project,
- Name => From,
- Path => Path_Name,
- Dir_Exists => Dir_Exists,
- Data => Data,
- Must_Exist => False);
-
- if not Dir_Exists then
- Err_Vars.Error_Msg_File_1 := From;
- Error_Msg
- (Data.Flags,
- "{ is not a valid directory", Location, Project);
-
- else
- -- links have been resolved if necessary, and Path_Name
- -- always ends with a directory separator
- Add_To_Or_Remove_From_Source_Dirs
- (Path_Id => Path_Name.Name,
- Display_Path_Id => Path_Name.Display_Name,
- Rank => Rank,
- Removed => Removed);
- end if;
- end;
- end if;
-
- Recursive_Dirs.Reset (Visited);
- end Find_Source_Dirs;
+ (not Source_Dirs.Default
+ and then Source_Dirs.Values = Nil_String)
+ or else
+ (not Languages.Default
+ and then Languages.Values = Nil_String))
+ and then Project.Extends = No_Project;
-- Start of processing for Get_Directories
- Dir_Exists : Boolean;
-
begin
if Current_Verbosity = High then
Write_Line ("Starting to look for directories");
-- Set the object directory to its default which may be nil, if there
-- is no sources in the project.
- if (((not Source_Files.Default)
- and then Source_Files.Values = Nil_String)
- or else
- ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
- or else
- ((not Languages.Default) and then Languages.Values = Nil_String))
- and then Project.Extends = No_Project
- then
+ if No_Sources then
Project.Object_Directory := No_Path_Information;
else
Project.Object_Directory := Project.Directory;
"Object_Dir cannot be empty",
Object_Dir.Location, Project);
- else
+ elsif not No_Sources then
+
-- We check that the specified object directory does exist.
-- However, even when it doesn't exist, we set it to a default
-- value. This is for the benefit of tools that recover from
if not Dir_Exists
and then not Project.Externally_Built
then
- -- The object directory does not exist, report an error if
- -- the project is not externally built.
+ -- The object directory does not exist, report an error if the
+ -- project is not externally built.
Err_Vars.Error_Msg_File_1 :=
File_Name_Type (Object_Dir.Value);
-
- case Data.Flags.Require_Obj_Dirs is
- when Error =>
- Error_Msg
- (Data.Flags,
- "object directory { not found",
- Project.Location, Project);
- when Warning =>
- Error_Msg
- (Data.Flags,
- "?object directory { not found",
- Project.Location, Project);
- when Silent =>
- null;
- end case;
+ Error_Or_Warning
+ (Data.Flags, Data.Flags.Require_Obj_Dirs,
+ "object directory { not found", Project.Location, Project);
end if;
end if;
- elsif Project.Object_Directory /= No_Path_Information
- and then Subdirs /= null
- then
+ elsif not No_Sources and then Subdirs /= null then
Name_Len := 1;
Name_Buffer (1) := '.';
Locate_Directory
"Exec_Dir cannot be empty",
Exec_Dir.Location, Project);
- else
+ elsif not No_Sources then
+
-- We check that the specified exec directory does exist
Locate_Directory
if not Dir_Exists then
Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
- Error_Msg
- (Data.Flags,
- "exec directory { not found",
- Project.Location, Project);
+ Error_Or_Warning
+ (Data.Flags, Data.Flags.Missing_Source_Files,
+ "exec directory { not found", Project.Location, Project);
end if;
end if;
end if;
-- No Source_Dirs specified: the single source directory is the one
-- containing the project file.
+ Remove_Source_Dirs := False;
Add_To_Or_Remove_From_Source_Dirs
(Path_Id => Project.Directory.Name,
Display_Path_Id => Project.Directory.Display_Name,
- Rank => 1,
- Removed => False);
+ Rank => 1);
else
- declare
- Source_Dir : String_List_Id;
- Element : String_Element;
- Rank : Natural;
- begin
- -- Process the source directories for each element of the list
-
- Source_Dir := Source_Dirs.Values;
- Rank := 0;
- while Source_Dir /= Nil_String loop
- Element := Data.Tree.String_Elements.Table (Source_Dir);
- Rank := Rank + 1;
- Find_Source_Dirs
- (File_Name_Type (Element.Value), Element.Location, Rank);
- Source_Dir := Element.Next;
- end loop;
-
- if Project.Source_Dirs = Nil_String
- and then Project.Qualifier = Standard
- then
- Error_Msg
- (Data.Flags,
- "a standard project cannot have no source directories",
- Source_Dirs.Location, Project);
- end if;
- end;
+ Remove_Source_Dirs := False;
+ Find_Source_Dirs
+ (Project => Project,
+ Data => Data,
+ Patterns => Source_Dirs.Values,
+ Search_For => Search_Directories,
+ Resolve_Links => Opt.Follow_Links_For_Dirs);
+
+ if Project.Source_Dirs = Nil_String
+ and then Project.Qualifier = Standard
+ then
+ Error_Msg
+ (Data.Flags,
+ "a standard project cannot have no source directories",
+ Source_Dirs.Location, Project);
+ end if;
end if;
if not Excluded_Source_Dirs.Default
and then Excluded_Source_Dirs.Values /= Nil_String
then
- declare
- Source_Dir : String_List_Id;
- Element : String_Element;
-
- begin
- -- Process the source directories for each element of the list
-
- Source_Dir := Excluded_Source_Dirs.Values;
- while Source_Dir /= Nil_String loop
- Element := Data.Tree.String_Elements.Table (Source_Dir);
- Find_Source_Dirs
- (File_Name_Type (Element.Value),
- Element.Location,
- 0,
- Removed => True);
- Source_Dir := Element.Next;
- end loop;
- end;
+ Remove_Source_Dirs := True;
+ Find_Source_Dirs
+ (Project => Project,
+ Data => Data,
+ Patterns => Excluded_Source_Dirs.Values,
+ Search_For => Search_Directories,
+ Resolve_Links => Opt.Follow_Links_For_Dirs);
end if;
if Current_Verbosity = High then
Element := Data.Tree.String_Elements.Table (Current);
if Element.Value /= No_Name then
Element.Value :=
- Name_Id (Canonical_Case_File_Name (Name_Id (Element.Value)));
+ Name_Id (Canonical_Case_File_Name (Element.Value));
Data.Tree.String_Elements.Table (Current) := Element;
end if;
(Name => Source_Name,
Location => Location,
Source => No_Source,
+ Listed => True,
Found => False);
+
+ else
+ Name_Loc.Listed := True;
end if;
Source_Names_Htable.Set
------------------
procedure Find_Sources
- (Project : in out Project_Processing_Data;
- Data : in out Tree_Processing_Data)
+ (Project : in out Project_Processing_Data;
+ Data : in out Tree_Processing_Data)
is
Sources : constant Variable_Value :=
Util.Value_Of
(Name_Source_Files,
- Project.Project.Decl.Attributes,
- Data.Tree);
+ Project.Project.Decl.Attributes,
+ Data.Tree);
Source_List_File : constant Variable_Value :=
Util.Value_Of
(Name => Name,
Location => Location,
Source => No_Source,
+ Listed => True,
Found => False);
- Source_Names_Htable.Set
- (Project.Source_Names, Name, Name_Loc);
+
+ else
+ Name_Loc.Listed := True;
end if;
+ Source_Names_Htable.Set
+ (Project.Source_Names, Name, Name_Loc);
+
Current := Element.Next;
end loop;
Has_Explicit_Sources := False;
end if;
+ -- Remove any exception that is not in the specified list of sources
+
+ if Has_Explicit_Sources then
+ declare
+ Source : Source_Id;
+ Iter : Source_Iterator;
+ NL : Name_Location;
+ Again : Boolean;
+ begin
+ Iter_Loop :
+ loop
+ Again := False;
+ Iter := For_Each_Source (Data.Tree, Project.Project);
+
+ Source_Loop :
+ loop
+ Source := Prj.Element (Iter);
+ exit Source_Loop when Source = No_Source;
+
+ if Source.Naming_Exception then
+ NL := Source_Names_Htable.Get
+ (Project.Source_Names, Source.File);
+
+ if NL /= No_Name_Location and then not NL.Listed then
+ -- Remove the exception
+ Source_Names_Htable.Set
+ (Project.Source_Names,
+ Source.File,
+ No_Name_Location);
+ Remove_Source (Source, No_Source);
+
+ Error_Msg_Name_1 := Name_Id (Source.File);
+ Error_Msg
+ (Data.Flags,
+ "? unknown source file %%",
+ NL.Location,
+ Project.Project);
+
+ Again := True;
+ exit Source_Loop;
+ end if;
+ end if;
+
+ Next (Iter);
+ end loop Source_Loop;
+
+ exit Iter_Loop when not Again;
+ end loop Iter_Loop;
+ end;
+ end if;
+
Search_Directories
(Project,
Data => Data,
declare
Source : Source_Id;
Iter : Source_Iterator;
+ Found : Boolean := False;
+ Path : Path_Information;
begin
Iter := For_Each_Source (Data.Tree, Project.Project);
and then Source.Path = No_Path_Information
then
if Source.Unit /= No_Unit_Index then
+ Found := False;
-- For multi-unit source files, source_id gets duplicated
-- once for every unit. Only the first source_id got its
- -- full path set. So if it isn't set for that first one,
- -- the file wasn't found. Otherwise we need to update for
- -- units after the first one.
+ -- full path set.
- if Source.Index = 0
- or else Source.Index = 1
- then
+ if Source.Index /= 0 then
+ Path := Files_Htable.Get
+ (Data.File_To_Source, Source.File).Path;
+
+ if Path /= No_Path_Information then
+ Found := True;
+ end if;
+ end if;
+
+ if not Found then
Error_Msg_Name_1 := Name_Id (Source.Display_File);
- Error_Msg_Name_2 := Name_Id (Source.Unit.Name);
- Error_Msg
- (Data.Flags,
+ Error_Msg_Name_2 := Source.Unit.Name;
+ Error_Or_Warning
+ (Data.Flags, Data.Flags.Missing_Source_Files,
"source file %% for unit %% not found",
No_Location, Project.Project);
else
- Source.Path := Files_Htable.Get
- (Data.File_To_Source, Source.File).Path;
+ Source.Path := Path;
if Current_Verbosity = High then
if Source.Path /= No_Path_Information then
& Get_Name_String (Source.File)
& " at" & Source.Index'Img
& " to "
- & Get_Name_String (Source.Path.Name));
+ & Get_Name_String (Path.Name));
end if;
end if;
end if;
while NL /= No_Name_Location loop
if not NL.Found then
Err_Vars.Error_Msg_File_1 := NL.Name;
-
if First_Error then
- Error_Msg
- (Data.Flags,
+ Error_Or_Warning
+ (Data.Flags, Data.Flags.Missing_Source_Files,
"source file { not found",
NL.Location, Project.Project);
First_Error := False;
-
else
- Error_Msg
- (Data.Flags,
+ Error_Or_Warning
+ (Data.Flags, Data.Flags.Missing_Source_Files,
"\source file { not found",
NL.Location, Project.Project);
end if;
----------------
procedure Initialize
- (Data : out Tree_Processing_Data;
- Tree : Project_Tree_Ref;
- Flags : Prj.Processing_Flags)
+ (Data : out Tree_Processing_Data;
+ Tree : Project_Tree_Ref;
+ Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
+ Flags : Prj.Processing_Flags)
is
begin
Files_Htable.Reset (Data.File_To_Source);
- Data.Tree := Tree;
- Data.Flags := Flags;
+ Data.Tree := Tree;
+ Data.Node_Tree := Node_Tree;
+ Data.Flags := Flags;
end Initialize;
----------
Data : in out Tree_Processing_Data;
Source_Dir_Rank : Natural;
Path : Path_Name_Type;
+ Display_Path : Path_Name_Type;
File_Name : File_Name_Type;
Display_File_Name : File_Name_Type;
Locally_Removed : Boolean;
For_All_Sources : Boolean)
is
- Canonical_Path : constant Path_Name_Type :=
- Path_Name_Type
- (Canonical_Case_File_Name (Name_Id (Path)));
-
Name_Loc : Name_Location :=
Source_Names_Htable.Get
(Project.Source_Names, File_Name);
Check_Name := True;
else
- Name_Loc.Source.Path := (Canonical_Path, Path);
+ Name_Loc.Source.Path := (Path, Display_Path);
Source_Paths_Htable.Set
(Data.Tree.Source_Paths_HT,
- Canonical_Path,
+ Path,
Name_Loc.Source);
-- Check if this is a subunit
and then Name_Loc.Source.Kind = Impl
then
Src_Ind := Sinput.P.Load_Project_File
- (Get_Name_String (Canonical_Path));
+ (Get_Name_String (Display_Path));
if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
Override_Kind (Name_Loc.Source, Sep);
Display_File => Display_File_Name,
Unit => Unit,
Locally_Removed => Locally_Removed,
- Path => (Canonical_Path, Path));
+ Path => (Path, Display_Path));
-- If it is a source specified in a list, update the entry in
-- the Source_Names table.
end if;
end Check_File;
+ ---------------------------------
+ -- Expand_Subdirectory_Pattern --
+ ---------------------------------
+
+ procedure Expand_Subdirectory_Pattern
+ (Project : Project_Id;
+ Data : in out Tree_Processing_Data;
+ Patterns : String_List_Id;
+ Search_For : Search_Type;
+ Resolve_Links : Boolean)
+ is
+ pragma Unreferenced (Search_For);
+ package Recursive_Dirs is new GNAT.Dynamic_HTables.Simple_HTable
+ (Header_Num => Header_Num,
+ Element => Boolean,
+ No_Element => False,
+ Key => Path_Name_Type,
+ Hash => Hash,
+ Equal => "=");
+ -- Hash table stores recursive source directories, to avoid looking
+ -- several times, and to avoid cycles that may be introduced by symbolic
+ -- links.
+
+ Visited : Recursive_Dirs.Instance;
+
+ procedure Find_Pattern
+ (Pattern : String; Rank : Natural; Location : Source_Ptr);
+ -- Find a specific pattern
+
+ procedure Recursive_Find_Dirs (Normalized_Path : String; Rank : Natural);
+ -- Search all the subdirectories (recursively) of Path
+
+ procedure Check_Directory_And_Subdirs
+ (Directory : String;
+ Include_Subdirs : Boolean;
+ Rank : Natural;
+ Location : Source_Ptr);
+ -- Make sur that Directory exists (and if not report an error/warning
+ -- message depending on the flags.
+ -- Calls Callback for Directory itself and all its subdirectories if
+ -- Include_Subdirs is True).
+
+ -------------------------
+ -- Recursive_Find_Dirs --
+ -------------------------
+
+ procedure Recursive_Find_Dirs
+ (Normalized_Path : String; Rank : Natural)
+ is
+ Dir : Dir_Type;
+ Name : String (1 .. 250);
+ Last : Natural;
+
+ Non_Canonical_Path : Path_Name_Type := No_Path;
+ Canonical_Path : Path_Name_Type := No_Path;
+
+ The_Path_Last : constant Natural :=
+ Compute_Directory_Last (Normalized_Path);
+
+ begin
+ Name_Len := 0;
+ Add_Str_To_Name_Buffer
+ (Normalized_Path (Normalized_Path'First .. The_Path_Last));
+ Non_Canonical_Path := Name_Find;
+
+ Canonical_Path :=
+ Path_Name_Type
+ (Canonical_Case_File_Name (Name_Id (Non_Canonical_Path)));
+
+ if Recursive_Dirs.Get (Visited, Canonical_Path) then
+ return;
+ end if;
+
+ Recursive_Dirs.Set (Visited, Canonical_Path, True);
+
+ Callback (Canonical_Path, Non_Canonical_Path, Rank);
+
+ Open (Dir, Normalized_Path (Normalized_Path'First .. The_Path_Last));
+
+ loop
+ Read (Dir, Name, Last);
+ exit when Last = 0;
+
+ if Name (1 .. Last) /= "."
+ and then Name (1 .. Last) /= ".."
+ then
+ if Current_Verbosity = High then
+ Write_Str (" Checking ");
+ Write_Line (Name (1 .. Last));
+ end if;
+
+ declare
+ Path_Name : constant String :=
+ Normalize_Pathname
+ (Name => Name (1 .. Last),
+ Directory =>
+ Normalized_Path
+ (Normalized_Path'First .. The_Path_Last),
+ Resolve_Links => Resolve_Links)
+ & Directory_Separator;
+ begin
+ if Is_Directory (Path_Name) then
+ Recursive_Find_Dirs (Path_Name, Rank);
+ end if;
+ end;
+ end if;
+ end loop;
+
+ Close (Dir);
+
+ exception
+ when Directory_Error =>
+ null;
+ end Recursive_Find_Dirs;
+
+ ---------------------------------
+ -- Check_Directory_And_Subdirs --
+ ---------------------------------
+
+ procedure Check_Directory_And_Subdirs
+ (Directory : String;
+ Include_Subdirs : Boolean;
+ Rank : Natural;
+ Location : Source_Ptr)
+ is
+ Dir : File_Name_Type;
+ Path_Name : Path_Information;
+ Dir_Exists : Boolean;
+ Has_Error : Boolean := False;
+ begin
+ Name_Len := Directory'Length;
+ Name_Buffer (1 .. Name_Len) := Directory;
+ Dir := Name_Find;
+
+ Locate_Directory
+ (Project => Project,
+ Name => Dir,
+ Path => Path_Name,
+ Dir_Exists => Dir_Exists,
+ Data => Data,
+ Must_Exist => False);
+
+ if not Dir_Exists then
+ Err_Vars.Error_Msg_File_1 := Dir;
+ Error_Or_Warning
+ (Data.Flags, Data.Flags.Missing_Source_Files,
+ "{ is not a valid directory", Location, Project);
+ Has_Error := Data.Flags.Missing_Source_Files = Error;
+ end if;
+
+ if not Has_Error then
+ -- Links have been resolved if necessary, and Path_Name
+ -- always ends with a directory separator.
+
+ if Include_Subdirs then
+ if Current_Verbosity = High then
+ Write_Str ("Looking for all subdirectories of """);
+ Write_Str (Directory);
+ Write_Line ("""");
+ end if;
+
+ Recursive_Find_Dirs (Get_Name_String (Path_Name.Name), Rank);
+
+ if Current_Verbosity = High then
+ Write_Line ("End of looking for source directories.");
+ end if;
+
+ else
+ Callback (Path_Name.Name, Path_Name.Display_Name, Rank);
+ end if;
+ end if;
+ end Check_Directory_And_Subdirs;
+
+ ------------------
+ -- Find_Pattern --
+ ------------------
+
+ procedure Find_Pattern
+ (Pattern : String; Rank : Natural; Location : Source_Ptr) is
+ begin
+ if Current_Verbosity = High then
+ Write_Str ("Expand_Subdirectory_Pattern (""");
+ Write_Str (Pattern);
+ Write_Line (""")");
+ end if;
+
+ -- First, check if we are looking for a directory tree, indicated
+ -- by "/**" at the end.
+
+ if Pattern'Length >= 3
+ and then Pattern (Pattern'Last - 1 .. Pattern'Last) = "**"
+ and then (Pattern (Pattern'Last - 2) = '/'
+ or else Pattern (Pattern'Last - 2) = Directory_Separator)
+ then
+ if Pattern'Length = 3 then
+ -- Case of "/**": all directories in file system
+ Check_Directory_And_Subdirs
+ (Pattern (Pattern'First .. Pattern'First),
+ True, Rank, Location);
+ else
+ Check_Directory_And_Subdirs
+ (Pattern (Pattern'First .. Pattern'Last - 3),
+ True, Rank, Location);
+ end if;
+ else
+ Check_Directory_And_Subdirs (Pattern, False, Rank, Location);
+ end if;
+ end Find_Pattern;
+
+ -- Start of processing for Expand_Subdirectory_Pattern
+
+ Pattern_Id : String_List_Id := Patterns;
+ Element : String_Element;
+ Rank : Natural := 1;
+ begin
+ while Pattern_Id /= Nil_String loop
+ Element := Data.Tree.String_Elements.Table (Pattern_Id);
+ Find_Pattern
+ (Get_Name_String (Element.Value), Rank, Element.Location);
+ Rank := Rank + 1;
+ Pattern_Id := Element.Next;
+ end loop;
+
+ Recursive_Dirs.Reset (Visited);
+ end Expand_Subdirectory_Pattern;
+
------------------------
-- Search_Directories --
------------------------
Num_Nod := Data.Tree.Number_Lists.Table (Src_Dir_Rank);
Element := Data.Tree.String_Elements.Table (Source_Dir);
+ -- Use Element.Value in this test, not Display_Value, because we
+ -- want the symbolic links to be resolved when appropriate.
+
if Element.Value /= No_Name then
declare
- -- We use Element.Value, not Display_Value, because we want
- -- the symbolic links to be resolved when appropriate.
Source_Directory : constant String :=
Get_Name_String (Element.Value)
& Directory_Separator;
+
Dir_Last : constant Natural :=
- Compute_Directory_Last
- (Source_Directory);
+ Compute_Directory_Last (Source_Directory);
+
+ Display_Source_Directory : constant String :=
+ Get_Name_String
+ (Element.Display_Value)
+ & Directory_Separator;
+ -- Display_Source_Directory is to allow us to open a UTF-8
+ -- encoded directory on Windows.
begin
if Current_Verbosity = High then
- Write_Attr ("Source_Dir", Source_Directory);
+ Write_Attr
+ ("Source_Dir",
+ Source_Directory (Source_Directory'First .. Dir_Last));
Write_Line (Num_Nod.Number'Img);
end if;
-- We look to every entry in the source directory
- Open (Dir, Source_Directory);
+ Open (Dir, Display_Source_Directory);
loop
Read (Dir, Name, Last);
if not Opt.Follow_Links_For_Files
or else Is_Regular_File
- (Source_Directory & Name (1 .. Last))
+ (Display_Source_Directory & Name (1 .. Last))
then
if Current_Verbosity = High then
Write_Str (" Checking ");
Opt.Follow_Links_For_Files,
Case_Sensitive => True);
- Path : Path_Name_Type;
- FF : File_Found := Excluded_Sources_Htable.Get
- (Project.Excluded, File_Name);
+ Path : Path_Name_Type;
+ FF : File_Found :=
+ Excluded_Sources_Htable.Get
+ (Project.Excluded, File_Name);
To_Remove : Boolean := False;
begin
Name_Len := Path_Name'Length;
Name_Buffer (1 .. Name_Len) := Path_Name;
- Path := Name_Find;
+
+ if Osint.File_Names_Case_Sensitive then
+ Path := Name_Find;
+ else
+ Canonical_Case_File_Name
+ (Name_Buffer (1 .. Name_Len));
+ Path := Name_Find;
+ end if;
if FF /= No_File_Found then
if not FF.Found then
if Current_Verbosity = High then
Write_Str (" excluded source """);
- Write_Str (Get_Name_String (File_Name));
+ Write_Str
+ (Get_Name_String (Display_File_Name));
Write_Line ("""");
end if;
end if;
end if;
+ -- Preserve the user's original casing and use of
+ -- links. The display_value (a directory) already
+ -- ends with a directory separator by construction,
+ -- so no need to add one.
+
+ Get_Name_String (Element.Display_Value);
+ Get_Name_String_And_Append (Display_File_Name);
+
Check_File
(Project => Project,
Source_Dir_Rank => Num_Nod.Number,
Data => Data,
Path => Path,
+ Display_Path => Name_Find,
File_Name => File_Name,
Locally_Removed => To_Remove,
Display_File_Name => Display_File_Name,
K => Source.File,
E => Name_Location'
(Name => Source.File,
- Location => No_Location,
+ Location => Source.Location,
Source => Source,
+ Listed => False,
Found => False));
-- If this is an Ada exception, record in table Unit_Exceptions
Data : in out Tree_Processing_Data)
is
Object_Files : Object_File_Names_Htable.Instance;
- Iter : Source_Iterator;
- Src : Source_Id;
+ Iter : Source_Iterator;
+ Src : Source_Id;
procedure Check_Object (Src : Source_Id);
-- Check if object file name of Src is already used in the project tree,
procedure Mark_Excluded_Sources;
-- Mark as such the sources that are declared as excluded
+ procedure Check_Missing_Sources;
+ -- Check whether one of the languages has no sources, and report an
+ -- error when appropriate
+
+ procedure Get_Sources_From_Source_Info;
+ -- Get the source information from the tabes that were created when a
+ -- source info fie was read.
+
+ ---------------------------
+ -- Check_Missing_Sources --
+ ---------------------------
+
+ procedure Check_Missing_Sources is
+ Extending : constant Boolean :=
+ Project.Project.Extends /= No_Project;
+ Language : Language_Ptr;
+ Source : Source_Id;
+ Alt_Lang : Language_List;
+ Continuation : Boolean := False;
+ Iter : Source_Iterator;
+ begin
+ if not Project.Project.Externally_Built
+ and then not Extending
+ then
+ Language := Project.Project.Languages;
+ while Language /= No_Language_Index loop
+
+ -- If there are no sources for this language, check if there
+ -- are sources for which this is an alternate language.
+
+ if Language.First_Source = No_Source
+ and then (Data.Flags.Require_Sources_Other_Lang
+ or else Language.Name = Name_Ada)
+ then
+ Iter := For_Each_Source (In_Tree => Data.Tree,
+ Project => Project.Project);
+ Source_Loop : loop
+ Source := Element (Iter);
+ exit Source_Loop when Source = No_Source
+ or else Source.Language = Language;
+
+ Alt_Lang := Source.Alternate_Languages;
+ while Alt_Lang /= null loop
+ exit Source_Loop when Alt_Lang.Language = Language;
+ Alt_Lang := Alt_Lang.Next;
+ end loop;
+
+ Next (Iter);
+ end loop Source_Loop;
+
+ if Source = No_Source then
+ Report_No_Sources
+ (Project.Project,
+ Get_Name_String (Language.Display_Name),
+ Data,
+ Project.Source_List_File_Location,
+ Continuation);
+ Continuation := True;
+ end if;
+ end if;
+
+ Language := Language.Next;
+ end loop;
+ end if;
+ end Check_Missing_Sources;
+
------------------
-- Check_Object --
------------------
Src_Ind :=
Sinput.P.Load_Project_File
- (Get_Name_String (Src_Id.Path.Name));
+ (Get_Name_String (Src_Id.Path.Display_Name));
if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
Override_Kind (Src_Id, Sep);
end loop;
end Check_Object_Files;
+ ----------------------------------
+ -- Get_Sources_From_Source_Info --
+ ----------------------------------
+
+ procedure Get_Sources_From_Source_Info is
+ Iter : Source_Info_Iterator;
+ Src : Source_Info;
+ Id : Source_Id;
+ Lang_Id : Language_Ptr;
+ begin
+ Initialize (Iter, Project.Project.Name);
+
+ loop
+ Src := Source_Info_Of (Iter);
+
+ exit when Src = No_Source_Info;
+
+ Id := new Source_Data;
+
+ Id.Project := Project.Project;
+
+ Lang_Id := Project.Project.Languages;
+ while Lang_Id /= No_Language_Index and then
+ Lang_Id.Name /= Src.Language
+ loop
+ Lang_Id := Lang_Id.Next;
+ end loop;
+
+ if Lang_Id = No_Language_Index then
+ Prj.Com.Fail
+ ("unknown language " &
+ Get_Name_String (Src.Language) &
+ " for project " &
+ Get_Name_String (Src.Project) &
+ " in source info file");
+ end if;
+
+ Id.Language := Lang_Id;
+ Id.Kind := Src.Kind;
+
+ Id.Index := Src.Index;
+
+ Id.Path :=
+ (Path_Name_Type (Src.Display_Path_Name),
+ Path_Name_Type (Src.Path_Name));
+
+ Name_Len := 0;
+ Add_Str_To_Name_Buffer
+ (Ada.Directories.Simple_Name
+ (Get_Name_String (Src.Path_Name)));
+ Id.File := Name_Find;
+
+ Name_Len := 0;
+ Add_Str_To_Name_Buffer
+ (Ada.Directories.Simple_Name
+ (Get_Name_String (Src.Display_Path_Name)));
+ Id.Display_File := Name_Find;
+
+ Id.Dep_Name := Dependency_Name
+ (Id.File, Id.Language.Config.Dependency_Kind);
+ Id.Naming_Exception := Src.Naming_Exception;
+ Id.Object := Object_Name
+ (Id.File, Id.Language.Config.Object_File_Suffix);
+ Id.Switches := Switches_Name (Id.File);
+
+ -- Add the source id to the Unit_Sources_HT hash table, if the
+ -- unit name is not null.
+
+ if Src.Kind /= Sep and then Src.Unit_Name /= No_Name then
+
+ declare
+ UData : Unit_Index :=
+ Units_Htable.Get (Data.Tree.Units_HT, Src.Unit_Name);
+ begin
+ if UData = No_Unit_Index then
+ UData := new Unit_Data;
+ UData.Name := Src.Unit_Name;
+ Units_Htable.Set
+ (Data.Tree.Units_HT, Src.Unit_Name, UData);
+ end if;
+
+ Id.Unit := UData;
+ end;
+
+ -- Note that this updates Unit information as well
+
+ Override_Kind (Id, Id.Kind);
+ end if;
+
+ if Src.Index /= 0 then
+ Project.Project.Has_Multi_Unit_Sources := True;
+ end if;
+
+ -- Add the source to the language list
+
+ Id.Next_In_Lang := Id.Language.First_Source;
+ Id.Language.First_Source := Id;
+
+ Files_Htable.Set (Data.File_To_Source, Id.File, Id);
+
+ Next (Iter);
+ end loop;
+ end Get_Sources_From_Source_Info;
+
-- Start of processing for Look_For_Sources
begin
- Find_Excluded_Sources (Project, Data);
+ if Data.Tree.Source_Info_File_Exists then
+ Get_Sources_From_Source_Info;
- if Project.Project.Languages /= No_Language_Index then
- Load_Naming_Exceptions (Project, Data);
- Find_Sources (Project, Data);
- Mark_Excluded_Sources;
- Check_Object_Files;
- end if;
+ else
+ if Project.Project.Source_Dirs /= Nil_String then
+ Find_Excluded_Sources (Project, Data);
+
+ if Project.Project.Languages /= No_Language_Index then
+ Load_Naming_Exceptions (Project, Data);
+ Find_Sources (Project, Data);
+ Mark_Excluded_Sources;
+ Check_Object_Files;
+ Check_Missing_Sources;
+ end if;
+ end if;
- Object_File_Names_Htable.Reset (Object_Files);
+ Object_File_Names_Htable.Reset (Object_Files);
+ end if;
end Look_For_Sources;
------------------
while Current /= Nil_String loop
Element := In_Tree.String_Elements.Table (Current);
Write_Str (" ");
- Write_Line (Get_Name_String (Element.Value));
+ Write_Line (Get_Name_String (Element.Display_Value));
Current := Element.Next;
end loop;
procedure Process_Naming_Scheme
(Tree : Project_Tree_Ref;
Root_Project : Project_Id;
+ Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
Flags : Processing_Flags)
is
procedure Recursive_Check
-- Start of processing for Process_Naming_Scheme
begin
- Initialize (Data, Tree => Tree, Flags => Flags);
+ Lib_Data_Table.Init;
+ Initialize (Data, Tree => Tree, Node_Tree => Node_Tree, Flags => Flags);
Check_All_Projects (Root_Project, Data, Imported_First => True);
Free (Data);