diff options
Diffstat (limited to 'gcc-4.4.0/gcc/ada/prj-part.adb')
-rw-r--r-- | gcc-4.4.0/gcc/ada/prj-part.adb | 2052 |
1 files changed, 0 insertions, 2052 deletions
diff --git a/gcc-4.4.0/gcc/ada/prj-part.adb b/gcc-4.4.0/gcc/ada/prj-part.adb deleted file mode 100644 index 5e0b14f01..000000000 --- a/gcc-4.4.0/gcc/ada/prj-part.adb +++ /dev/null @@ -1,2052 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT COMPILER COMPONENTS -- --- -- --- P R J . P A R T -- --- -- --- B o d y -- --- -- --- Copyright (C) 2001-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 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- --- for more details. You should have received a copy of the GNU General -- --- Public License distributed with GNAT; see file COPYING3. If not, go to -- --- http://www.gnu.org/licenses for a complete copy of the license. -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with Err_Vars; use Err_Vars; -with Opt; use Opt; -with Osint; use Osint; -with Output; use Output; -with Prj.Com; use Prj.Com; -with Prj.Dect; -with Prj.Err; use Prj.Err; -with Prj.Ext; use Prj.Ext; -with Sinput; use Sinput; -with Sinput.P; use Sinput.P; -with Snames; -with Table; - -with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Exceptions; use Ada.Exceptions; - -with GNAT.Directory_Operations; use GNAT.Directory_Operations; - -with System.HTable; use System.HTable; - -package body Prj.Part is - - Buffer : String_Access; - Buffer_Last : Natural := 0; - - Dir_Sep : Character renames GNAT.OS_Lib.Directory_Separator; - - ------------------------------------ - -- Local Packages and Subprograms -- - ------------------------------------ - - type With_Id is new Nat; - No_With : constant With_Id := 0; - - type With_Record is record - Path : Path_Name_Type; - Location : Source_Ptr; - Limited_With : Boolean; - Node : Project_Node_Id; - Next : With_Id; - end record; - -- Information about an imported project, to be put in table Withs below - - package Withs is new Table.Table - (Table_Component_Type => With_Record, - Table_Index_Type => With_Id, - Table_Low_Bound => 1, - Table_Initial => 10, - Table_Increment => 100, - Table_Name => "Prj.Part.Withs"); - -- Table used to store temporarily paths and locations of imported - -- projects. These imported projects will be effectively parsed later: just - -- before parsing the current project for the non limited withed projects, - -- after getting its name; after complete parsing of the current project - -- for the limited withed projects. - - type Names_And_Id is record - Path_Name : Path_Name_Type; - Canonical_Path_Name : Path_Name_Type; - Id : Project_Node_Id; - Limited_With : Boolean; - end record; - - package Project_Stack is new Table.Table - (Table_Component_Type => Names_And_Id, - Table_Index_Type => Nat, - Table_Low_Bound => 1, - Table_Initial => 10, - Table_Increment => 100, - Table_Name => "Prj.Part.Project_Stack"); - -- This table is used to detect circular dependencies - -- for imported and extended projects and to get the project ids of - -- limited imported projects when there is a circularity with at least - -- one limited imported project file. - - package Virtual_Hash is new System.HTable.Simple_HTable - (Header_Num => Header_Num, - Element => Project_Node_Id, - No_Element => Empty_Node, - Key => Project_Node_Id, - Hash => Prj.Tree.Hash, - Equal => "="); - -- Hash table to store the node id of the project for which a virtual - -- extending project need to be created. - - package Processed_Hash is new System.HTable.Simple_HTable - (Header_Num => Header_Num, - Element => Boolean, - No_Element => False, - Key => Project_Node_Id, - Hash => Prj.Tree.Hash, - Equal => "="); - -- Hash table to store the project process when looking for project that - -- need to have a virtual extending project, to avoid processing the same - -- project twice. - - package Projects_Paths is new System.HTable.Simple_HTable - (Header_Num => Header_Num, - Element => Path_Name_Type, - No_Element => No_Path, - Key => Name_Id, - Hash => Hash, - Equal => "="); - -- Hash table to cache project path to avoid looking for them on the path - - procedure Create_Virtual_Extending_Project - (For_Project : Project_Node_Id; - Main_Project : Project_Node_Id; - In_Tree : Project_Node_Tree_Ref); - -- Create a virtual extending project of For_Project. Main_Project is - -- the extending all project. - -- - -- The String_Value_Of is not set for the automatically added with - -- clause and keeps the default value of No_Name. This enables Prj.PP - -- to skip these automatically added with clauses to be processed. - - procedure Look_For_Virtual_Projects_For - (Proj : Project_Node_Id; - In_Tree : Project_Node_Tree_Ref; - Potentially_Virtual : Boolean); - -- Look for projects that need to have a virtual extending project. - -- This procedure is recursive. If called with Potentially_Virtual set to - -- True, then Proj may need an virtual extending project; otherwise it - -- does not (because it is already extended), but other projects that it - -- imports may need to be virtually extended. - - type Extension_Origin is (None, Extending_Simple, Extending_All); - -- Type of parameter From_Extended for procedures Parse_Single_Project and - -- Post_Parse_Context_Clause. Extending_All means that we are parsing the - -- tree rooted at an extending all project. - - procedure Parse_Single_Project - (In_Tree : Project_Node_Tree_Ref; - Project : out Project_Node_Id; - Extends_All : out Boolean; - Path_Name : String; - Extended : Boolean; - From_Extended : Extension_Origin; - In_Limited : Boolean; - Packages_To_Check : String_List_Access; - Depth : Natural; - Current_Dir : String); - -- Parse a project file. This is a recursive procedure: it calls itself for - -- imported and extended projects. When From_Extended is not None, if the - -- project has already been parsed and is an extended project A, return the - -- ultimate (not extended) project that extends A. When In_Limited is True, - -- the importing path includes at least one "limited with". When parsing - -- configuration projects, do not allow a depth > 1. - - procedure Pre_Parse_Context_Clause - (In_Tree : Project_Node_Tree_Ref; - Context_Clause : out With_Id); - -- Parse the context clause of a project. Store the paths and locations of - -- the imported projects in table Withs. Does nothing if there is no - -- context clause (if the current token is not "with" or "limited" followed - -- by "with"). - - procedure Post_Parse_Context_Clause - (Context_Clause : With_Id; - In_Tree : Project_Node_Tree_Ref; - Limited_Withs : Boolean; - Imported_Projects : in out Project_Node_Id; - Project_Directory : Path_Name_Type; - From_Extended : Extension_Origin; - In_Limited : Boolean; - Packages_To_Check : String_List_Access; - Depth : Natural; - Current_Dir : String); - -- Parse the imported projects that have been stored in table Withs, if - -- any. From_Extended is used for the call to Parse_Single_Project below. - -- When In_Limited is True, the importing path includes at least one - -- "limited with". When Limited_Withs is False, only non limited withed - -- projects are parsed. When Limited_Withs is True, only limited withed - -- projects are parsed. - - function Project_Path_Name_Of - (Project_File_Name : String; - Directory : String) return String; - -- Returns the path name of a project file. Returns an empty string - -- if project file cannot be found. - - function Immediate_Directory_Of - (Path_Name : Path_Name_Type) return Path_Name_Type; - -- Get the directory of the file with the specified path name. - -- This includes the directory separator as the last character. - -- Returns "./" if Path_Name contains no directory separator. - - function Project_Name_From (Path_Name : String) return Name_Id; - -- Returns the name of the project that corresponds to its path name. - -- Returns No_Name if the path name is invalid, because the corresponding - -- project name does not have the syntax of an ada identifier. - - -------------------------------------- - -- Create_Virtual_Extending_Project -- - -------------------------------------- - - procedure Create_Virtual_Extending_Project - (For_Project : Project_Node_Id; - Main_Project : Project_Node_Id; - In_Tree : Project_Node_Tree_Ref) - is - - Virtual_Name : constant String := - Virtual_Prefix & - Get_Name_String (Name_Of (For_Project, In_Tree)); - -- The name of the virtual extending project - - Virtual_Name_Id : Name_Id; - -- Virtual extending project name id - - Virtual_Path_Id : Path_Name_Type; - -- Fake path name of the virtual extending project. The directory is - -- the same directory as the extending all project. - - Virtual_Dir_Id : constant Path_Name_Type := - Immediate_Directory_Of (Path_Name_Of (Main_Project, In_Tree)); - -- The directory of the extending all project - - -- The source of the virtual extending project is something like: - - -- project V$<project name> extends <project path> is - - -- for Source_Dirs use (); - - -- end V$<project name>; - - -- The project directory cannot be specified during parsing; it will be - -- put directly in the virtual extending project data during processing. - - -- Nodes that made up the virtual extending project - - Virtual_Project : constant Project_Node_Id := - Default_Project_Node - (In_Tree, N_Project); - With_Clause : constant Project_Node_Id := - Default_Project_Node - (In_Tree, N_With_Clause); - Project_Declaration : constant Project_Node_Id := - Default_Project_Node - (In_Tree, N_Project_Declaration); - Source_Dirs_Declaration : constant Project_Node_Id := - Default_Project_Node - (In_Tree, N_Declarative_Item); - Source_Dirs_Attribute : constant Project_Node_Id := - Default_Project_Node - (In_Tree, N_Attribute_Declaration, List); - Source_Dirs_Expression : constant Project_Node_Id := - Default_Project_Node - (In_Tree, N_Expression, List); - Source_Dirs_Term : constant Project_Node_Id := - Default_Project_Node - (In_Tree, N_Term, List); - Source_Dirs_List : constant Project_Node_Id := - Default_Project_Node - (In_Tree, N_Literal_String_List, List); - - begin - -- Get the virtual name id - - Name_Len := Virtual_Name'Length; - Name_Buffer (1 .. Name_Len) := Virtual_Name; - Virtual_Name_Id := Name_Find; - - -- Get the virtual path name - - Get_Name_String (Path_Name_Of (Main_Project, In_Tree)); - - while Name_Len > 0 - and then Name_Buffer (Name_Len) /= Directory_Separator - and then Name_Buffer (Name_Len) /= '/' - loop - Name_Len := Name_Len - 1; - end loop; - - Name_Buffer (Name_Len + 1 .. Name_Len + Virtual_Name'Length) := - Virtual_Name; - Name_Len := Name_Len + Virtual_Name'Length; - Virtual_Path_Id := Name_Find; - - -- With clause - - Set_Name_Of (With_Clause, In_Tree, Virtual_Name_Id); - Set_Path_Name_Of (With_Clause, In_Tree, Virtual_Path_Id); - Set_Project_Node_Of (With_Clause, In_Tree, Virtual_Project); - Set_Next_With_Clause_Of - (With_Clause, In_Tree, First_With_Clause_Of (Main_Project, In_Tree)); - Set_First_With_Clause_Of (Main_Project, In_Tree, With_Clause); - - -- Virtual project node - - Set_Name_Of (Virtual_Project, In_Tree, Virtual_Name_Id); - Set_Path_Name_Of (Virtual_Project, In_Tree, Virtual_Path_Id); - Set_Location_Of - (Virtual_Project, In_Tree, Location_Of (Main_Project, In_Tree)); - Set_Directory_Of (Virtual_Project, In_Tree, Virtual_Dir_Id); - Set_Project_Declaration_Of - (Virtual_Project, In_Tree, Project_Declaration); - Set_Extended_Project_Path_Of - (Virtual_Project, In_Tree, Path_Name_Of (For_Project, In_Tree)); - - -- Project declaration - - Set_First_Declarative_Item_Of - (Project_Declaration, In_Tree, Source_Dirs_Declaration); - Set_Extended_Project_Of (Project_Declaration, In_Tree, For_Project); - - -- Source_Dirs declaration - - Set_Current_Item_Node - (Source_Dirs_Declaration, In_Tree, Source_Dirs_Attribute); - - -- Source_Dirs attribute - - Set_Name_Of (Source_Dirs_Attribute, In_Tree, Snames.Name_Source_Dirs); - Set_Expression_Of - (Source_Dirs_Attribute, In_Tree, Source_Dirs_Expression); - - -- Source_Dirs expression - - Set_First_Term (Source_Dirs_Expression, In_Tree, Source_Dirs_Term); - - -- Source_Dirs term - - Set_Current_Term (Source_Dirs_Term, In_Tree, Source_Dirs_List); - - -- Source_Dirs empty list: nothing to do - - -- Put virtual project into Projects_Htable - - Prj.Tree.Tree_Private_Part.Projects_Htable.Set - (T => In_Tree.Projects_HT, - K => Virtual_Name_Id, - E => (Name => Virtual_Name_Id, - Node => Virtual_Project, - Canonical_Path => No_Path, - Extended => False, - Proj_Qualifier => Unspecified)); - end Create_Virtual_Extending_Project; - - ---------------------------- - -- Immediate_Directory_Of -- - ---------------------------- - - function Immediate_Directory_Of - (Path_Name : Path_Name_Type) return Path_Name_Type - is - begin - Get_Name_String (Path_Name); - - for Index in reverse 1 .. Name_Len loop - if Name_Buffer (Index) = '/' - or else Name_Buffer (Index) = Dir_Sep - then - -- Remove all chars after last directory separator from name - - if Index > 1 then - Name_Len := Index - 1; - - else - Name_Len := Index; - end if; - - return Name_Find; - end if; - end loop; - - -- There is no directory separator in name. Return "./" or ".\" - - Name_Len := 2; - Name_Buffer (1) := '.'; - Name_Buffer (2) := Dir_Sep; - return Name_Find; - end Immediate_Directory_Of; - - ----------------------------------- - -- Look_For_Virtual_Projects_For -- - ----------------------------------- - - procedure Look_For_Virtual_Projects_For - (Proj : Project_Node_Id; - In_Tree : Project_Node_Tree_Ref; - Potentially_Virtual : Boolean) - is - Declaration : Project_Node_Id := Empty_Node; - -- Node for the project declaration of Proj - - With_Clause : Project_Node_Id := Empty_Node; - -- Node for a with clause of Proj - - Imported : Project_Node_Id := Empty_Node; - -- Node for a project imported by Proj - - Extended : Project_Node_Id := Empty_Node; - -- Node for the eventual project extended by Proj - - begin - -- Nothing to do if Proj is not defined or if it has already been - -- processed. - - if Present (Proj) and then not Processed_Hash.Get (Proj) then - -- Make sure the project will not be processed again - - Processed_Hash.Set (Proj, True); - - Declaration := Project_Declaration_Of (Proj, In_Tree); - - if Present (Declaration) then - Extended := Extended_Project_Of (Declaration, In_Tree); - end if; - - -- If this is a project that may need a virtual extending project - -- and it is not itself an extending project, put it in the list. - - if Potentially_Virtual and then No (Extended) then - Virtual_Hash.Set (Proj, Proj); - end if; - - -- Now check the projects it imports - - With_Clause := First_With_Clause_Of (Proj, In_Tree); - - while Present (With_Clause) loop - Imported := Project_Node_Of (With_Clause, In_Tree); - - if Present (Imported) then - Look_For_Virtual_Projects_For - (Imported, In_Tree, Potentially_Virtual => True); - end if; - - With_Clause := Next_With_Clause_Of (With_Clause, In_Tree); - end loop; - - -- Check also the eventual project extended by Proj. As this project - -- is already extended, call recursively with Potentially_Virtual - -- being False. - - Look_For_Virtual_Projects_For - (Extended, In_Tree, Potentially_Virtual => False); - end if; - end Look_For_Virtual_Projects_For; - - ----------- - -- Parse -- - ----------- - - procedure Parse - (In_Tree : Project_Node_Tree_Ref; - Project : out Project_Node_Id; - Project_File_Name : String; - Always_Errout_Finalize : Boolean; - Packages_To_Check : String_List_Access := All_Packages; - Store_Comments : Boolean := False; - Current_Directory : String := "") - is - Dummy : Boolean; - pragma Warnings (Off, Dummy); - - Real_Project_File_Name : String_Access := - Osint.To_Canonical_File_Spec - (Project_File_Name); - - begin - if Real_Project_File_Name = null then - Real_Project_File_Name := new String'(Project_File_Name); - end if; - - Project := Empty_Node; - - Projects_Paths.Reset; - - if Current_Verbosity >= Medium then - Write_Str ("GPR_PROJECT_PATH="""); - Write_Str (Project_Path); - Write_Line (""""); - end if; - - declare - Path_Name : constant String := - Project_Path_Name_Of (Real_Project_File_Name.all, - Directory => Current_Directory); - - begin - Free (Real_Project_File_Name); - - Prj.Err.Initialize; - Prj.Err.Scanner.Set_Comment_As_Token (Store_Comments); - Prj.Err.Scanner.Set_End_Of_Line_As_Token (Store_Comments); - - -- Parse the main project file - - if Path_Name = "" then - Prj.Com.Fail - ("project file """, - Project_File_Name, - """ not found in " & Project_Path); - Project := Empty_Node; - return; - end if; - - Parse_Single_Project - (In_Tree => In_Tree, - Project => Project, - Extends_All => Dummy, - Path_Name => Path_Name, - Extended => False, - From_Extended => None, - In_Limited => False, - Packages_To_Check => Packages_To_Check, - Depth => 0, - Current_Dir => Current_Directory); - - -- If Project is an extending-all project, create the eventual - -- virtual extending projects and check that there are no illegally - -- imported projects. - - if Present (Project) - and then Is_Extending_All (Project, In_Tree) - then - -- First look for projects that potentially need a virtual - -- extending project. - - Virtual_Hash.Reset; - Processed_Hash.Reset; - - -- Mark the extending all project as processed, to avoid checking - -- the imported projects in case of a "limited with" on this - -- extending all project. - - Processed_Hash.Set (Project, True); - - declare - Declaration : constant Project_Node_Id := - Project_Declaration_Of (Project, In_Tree); - begin - Look_For_Virtual_Projects_For - (Extended_Project_Of (Declaration, In_Tree), In_Tree, - Potentially_Virtual => False); - end; - - -- Now, check the projects directly imported by the main project. - -- Remove from the potentially virtual any project extended by one - -- of these imported projects. For non extending imported - -- projects, check that they do not belong to the project tree of - -- the project being "extended-all" by the main project. - - declare - With_Clause : Project_Node_Id; - Imported : Project_Node_Id := Empty_Node; - Declaration : Project_Node_Id := Empty_Node; - - begin - With_Clause := First_With_Clause_Of (Project, In_Tree); - while Present (With_Clause) loop - Imported := Project_Node_Of (With_Clause, In_Tree); - - if Present (Imported) then - Declaration := Project_Declaration_Of (Imported, In_Tree); - - if Extended_Project_Of (Declaration, In_Tree) /= - Empty_Node - then - loop - Imported := - Extended_Project_Of (Declaration, In_Tree); - exit when No (Imported); - Virtual_Hash.Remove (Imported); - Declaration := - Project_Declaration_Of (Imported, In_Tree); - end loop; - end if; - end if; - - With_Clause := Next_With_Clause_Of (With_Clause, In_Tree); - end loop; - end; - - -- Now create all the virtual extending projects - - declare - Proj : Project_Node_Id := Virtual_Hash.Get_First; - begin - while Present (Proj) loop - Create_Virtual_Extending_Project (Proj, Project, In_Tree); - Proj := Virtual_Hash.Get_Next; - end loop; - end; - end if; - - -- If there were any kind of error during the parsing, serious - -- or not, then the parsing fails. - - if Err_Vars.Total_Errors_Detected > 0 then - Project := Empty_Node; - end if; - - if No (Project) or else Always_Errout_Finalize then - Prj.Err.Finalize; - end if; - end; - - exception - when X : others => - - -- Internal error - - Write_Line (Exception_Information (X)); - Write_Str ("Exception "); - Write_Str (Exception_Name (X)); - Write_Line (" raised, while processing project file"); - Project := Empty_Node; - end Parse; - - ------------------------------ - -- Pre_Parse_Context_Clause -- - ------------------------------ - - procedure Pre_Parse_Context_Clause - (In_Tree : Project_Node_Tree_Ref; - Context_Clause : out With_Id) - is - Current_With_Clause : With_Id := No_With; - Limited_With : Boolean := False; - Current_With : With_Record; - Current_With_Node : Project_Node_Id := Empty_Node; - - begin - -- Assume no context clause - - Context_Clause := No_With; - With_Loop : - - -- If Token is not WITH or LIMITED, there is no context clause, or we - -- have exhausted the with clauses. - - while Token = Tok_With or else Token = Tok_Limited loop - Current_With_Node := - Default_Project_Node (Of_Kind => N_With_Clause, In_Tree => In_Tree); - Limited_With := Token = Tok_Limited; - - if In_Configuration then - Error_Msg - ("configuration project cannot import " & - "other configuration projects", - Token_Ptr); - end if; - - if Limited_With then - Scan (In_Tree); -- scan past LIMITED - Expect (Tok_With, "WITH"); - exit With_Loop when Token /= Tok_With; - end if; - - Comma_Loop : - loop - Scan (In_Tree); -- past WITH or "," - - Expect (Tok_String_Literal, "literal string"); - - if Token /= Tok_String_Literal then - return; - end if; - - -- Store path and location in table Withs - - Current_With := - (Path => Path_Name_Type (Token_Name), - Location => Token_Ptr, - Limited_With => Limited_With, - Node => Current_With_Node, - Next => No_With); - - Withs.Increment_Last; - Withs.Table (Withs.Last) := Current_With; - - if Current_With_Clause = No_With then - Context_Clause := Withs.Last; - - else - Withs.Table (Current_With_Clause).Next := Withs.Last; - end if; - - Current_With_Clause := Withs.Last; - - Scan (In_Tree); - - if Token = Tok_Semicolon then - Set_End_Of_Line (Current_With_Node); - Set_Previous_Line_Node (Current_With_Node); - - -- End of (possibly multiple) with clause; - - Scan (In_Tree); -- past the semicolon - exit Comma_Loop; - - elsif Token = Tok_Comma then - Set_Is_Not_Last_In_List (Current_With_Node, In_Tree); - - else - Error_Msg ("expected comma or semi colon", Token_Ptr); - exit Comma_Loop; - end if; - - Current_With_Node := - Default_Project_Node - (Of_Kind => N_With_Clause, In_Tree => In_Tree); - end loop Comma_Loop; - end loop With_Loop; - end Pre_Parse_Context_Clause; - - ------------------------------- - -- Post_Parse_Context_Clause -- - ------------------------------- - - procedure Post_Parse_Context_Clause - (Context_Clause : With_Id; - In_Tree : Project_Node_Tree_Ref; - Limited_Withs : Boolean; - Imported_Projects : in out Project_Node_Id; - Project_Directory : Path_Name_Type; - From_Extended : Extension_Origin; - In_Limited : Boolean; - Packages_To_Check : String_List_Access; - Depth : Natural; - Current_Dir : String) - is - Current_With_Clause : With_Id := Context_Clause; - - Current_Project : Project_Node_Id := Imported_Projects; - Previous_Project : Project_Node_Id := Empty_Node; - Next_Project : Project_Node_Id := Empty_Node; - - Project_Directory_Path : constant String := - Get_Name_String (Project_Directory); - - Current_With : With_Record; - Extends_All : Boolean := False; - - begin - -- Set Current_Project to the last project in the current list, if the - -- list is not empty. - - if Present (Current_Project) then - while - Present (Next_With_Clause_Of (Current_Project, In_Tree)) - loop - Current_Project := Next_With_Clause_Of (Current_Project, In_Tree); - end loop; - end if; - - while Current_With_Clause /= No_With loop - Current_With := Withs.Table (Current_With_Clause); - Current_With_Clause := Current_With.Next; - - if Limited_Withs = Current_With.Limited_With then - declare - Original_Path : constant String := - Get_Name_String (Current_With.Path); - - Imported_Path_Name : constant String := - Project_Path_Name_Of - (Original_Path, - Project_Directory_Path); - - Resolved_Path : constant String := - Normalize_Pathname - (Imported_Path_Name, - Directory => Current_Dir, - Resolve_Links => - Opt.Follow_Links_For_Files, - Case_Sensitive => True); - - Withed_Project : Project_Node_Id := Empty_Node; - - begin - if Imported_Path_Name = "" then - - -- The project file cannot be found - - Error_Msg_File_1 := File_Name_Type (Current_With.Path); - Error_Msg - ("unknown project file: {", Current_With.Location); - - -- If this is not imported by the main project file, display - -- the import path. - - if Project_Stack.Last > 1 then - for Index in reverse 1 .. Project_Stack.Last loop - Error_Msg_File_1 := - File_Name_Type - (Project_Stack.Table (Index).Path_Name); - Error_Msg - ("\imported by {", Current_With.Location); - end loop; - end if; - - else - -- New with clause - - Previous_Project := Current_Project; - - if No (Current_Project) then - - -- First with clause of the context clause - - Current_Project := Current_With.Node; - Imported_Projects := Current_Project; - - else - Next_Project := Current_With.Node; - Set_Next_With_Clause_Of - (Current_Project, In_Tree, Next_Project); - Current_Project := Next_Project; - end if; - - Set_String_Value_Of - (Current_Project, - In_Tree, - Name_Id (Current_With.Path)); - Set_Location_Of - (Current_Project, In_Tree, Current_With.Location); - - -- If it is a limited with, check if we have a circularity. - -- If we have one, get the project id of the limited - -- imported project file, and do not parse it. - - if Limited_Withs and then Project_Stack.Last > 1 then - declare - Canonical_Path_Name : Path_Name_Type; - - begin - Name_Len := Resolved_Path'Length; - Name_Buffer (1 .. Name_Len) := Resolved_Path; - Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len)); - Canonical_Path_Name := Name_Find; - - for Index in 1 .. Project_Stack.Last loop - if Project_Stack.Table (Index).Canonical_Path_Name = - Canonical_Path_Name - then - -- We have found the limited imported project, - -- get its project id, and do not parse it. - - Withed_Project := Project_Stack.Table (Index).Id; - exit; - end if; - end loop; - end; - end if; - - -- Parse the imported project, if its project id is unknown - - if No (Withed_Project) then - Parse_Single_Project - (In_Tree => In_Tree, - Project => Withed_Project, - Extends_All => Extends_All, - Path_Name => Imported_Path_Name, - Extended => False, - From_Extended => From_Extended, - In_Limited => Limited_Withs, - Packages_To_Check => Packages_To_Check, - Depth => Depth, - Current_Dir => Current_Dir); - - else - Extends_All := Is_Extending_All (Withed_Project, In_Tree); - end if; - - if No (Withed_Project) then - - -- If parsing unsuccessful, remove the context clause - - Current_Project := Previous_Project; - - if No (Current_Project) then - Imported_Projects := Empty_Node; - - else - Set_Next_With_Clause_Of - (Current_Project, In_Tree, Empty_Node); - end if; - else - -- If parsing was successful, record project name and - -- path name in with clause - - Set_Project_Node_Of - (Node => Current_Project, - In_Tree => In_Tree, - To => Withed_Project, - Limited_With => Current_With.Limited_With); - Set_Name_Of - (Current_Project, - In_Tree, - Name_Of (Withed_Project, In_Tree)); - - Name_Len := Resolved_Path'Length; - Name_Buffer (1 .. Name_Len) := Resolved_Path; - Set_Path_Name_Of (Current_Project, In_Tree, Name_Find); - - if Extends_All then - Set_Is_Extending_All (Current_Project, In_Tree); - end if; - end if; - end if; - end; - end if; - end loop; - end Post_Parse_Context_Clause; - - -------------------------- - -- Parse_Single_Project -- - -------------------------- - - procedure Parse_Single_Project - (In_Tree : Project_Node_Tree_Ref; - Project : out Project_Node_Id; - Extends_All : out Boolean; - Path_Name : String; - Extended : Boolean; - From_Extended : Extension_Origin; - In_Limited : Boolean; - Packages_To_Check : String_List_Access; - Depth : Natural; - Current_Dir : String) - is - Normed_Path_Name : Path_Name_Type; - Canonical_Path_Name : Path_Name_Type; - Project_Directory : Path_Name_Type; - Project_Scan_State : Saved_Project_Scan_State; - Source_Index : Source_File_Index; - - Extending : Boolean := False; - - Extended_Project : Project_Node_Id := Empty_Node; - - A_Project_Name_And_Node : Tree_Private_Part.Project_Name_And_Node := - Tree_Private_Part.Projects_Htable.Get_First - (In_Tree.Projects_HT); - - Name_From_Path : constant Name_Id := Project_Name_From (Path_Name); - Name_Of_Project : Name_Id := No_Name; - - Duplicated : Boolean := False; - - First_With : With_Id; - Imported_Projects : Project_Node_Id := Empty_Node; - - use Tree_Private_Part; - - Project_Comment_State : Tree.Comment_State; - - Proj_Qualifier : Project_Qualifier := Unspecified; - Qualifier_Location : Source_Ptr; - - begin - Extends_All := False; - - declare - Normed_Path : constant String := Normalize_Pathname - (Path_Name, - Directory => Current_Dir, - Resolve_Links => False, - Case_Sensitive => True); - Canonical_Path : constant String := Normalize_Pathname - (Normed_Path, - Directory => Current_Dir, - Resolve_Links => Opt.Follow_Links_For_Files, - Case_Sensitive => False); - begin - Name_Len := Normed_Path'Length; - Name_Buffer (1 .. Name_Len) := Normed_Path; - Normed_Path_Name := Name_Find; - Name_Len := Canonical_Path'Length; - Name_Buffer (1 .. Name_Len) := Canonical_Path; - Canonical_Path_Name := Name_Find; - end; - - -- Check for a circular dependency - - for Index in reverse 1 .. Project_Stack.Last loop - exit when Project_Stack.Table (Index).Limited_With; - - if Canonical_Path_Name = - Project_Stack.Table (Index).Canonical_Path_Name - then - Error_Msg ("circular dependency detected", Token_Ptr); - Error_Msg_Name_1 := Name_Id (Normed_Path_Name); - Error_Msg ("\ %% is imported by", Token_Ptr); - - for Current in reverse 1 .. Project_Stack.Last loop - Error_Msg_Name_1 := - Name_Id (Project_Stack.Table (Current).Path_Name); - - if Project_Stack.Table (Current).Canonical_Path_Name /= - Canonical_Path_Name - then - Error_Msg - ("\ %% which itself is imported by", Token_Ptr); - - else - Error_Msg ("\ %%", Token_Ptr); - exit; - end if; - end loop; - - Project := Empty_Node; - return; - end if; - end loop; - - -- Put the new path name on the stack - - Project_Stack.Append - ((Path_Name => Normed_Path_Name, - Canonical_Path_Name => Canonical_Path_Name, - Id => Empty_Node, - Limited_With => In_Limited)); - - -- Check if the project file has already been parsed - - while - A_Project_Name_And_Node /= Tree_Private_Part.No_Project_Name_And_Node - loop - if A_Project_Name_And_Node.Canonical_Path = Canonical_Path_Name then - if Extended then - - if A_Project_Name_And_Node.Extended then - if A_Project_Name_And_Node.Proj_Qualifier /= Dry then - Error_Msg - ("cannot extend the same project file several times", - Token_Ptr); - end if; - else - Error_Msg - ("cannot extend an already imported project file", - Token_Ptr); - end if; - - elsif A_Project_Name_And_Node.Extended then - Extends_All := - Is_Extending_All (A_Project_Name_And_Node.Node, In_Tree); - - -- If the imported project is an extended project A, and we are - -- in an extended project, replace A with the ultimate project - -- extending A. - - if From_Extended /= None then - declare - Decl : Project_Node_Id := - Project_Declaration_Of - (A_Project_Name_And_Node.Node, In_Tree); - - Prj : Project_Node_Id := - Extending_Project_Of (Decl, In_Tree); - - begin - loop - Decl := Project_Declaration_Of (Prj, In_Tree); - exit when Extending_Project_Of (Decl, In_Tree) = - Empty_Node; - Prj := Extending_Project_Of (Decl, In_Tree); - end loop; - - A_Project_Name_And_Node.Node := Prj; - end; - else - Error_Msg - ("cannot import an already extended project file", - Token_Ptr); - end if; - end if; - - Project := A_Project_Name_And_Node.Node; - Project_Stack.Decrement_Last; - return; - end if; - - A_Project_Name_And_Node := - Tree_Private_Part.Projects_Htable.Get_Next (In_Tree.Projects_HT); - end loop; - - -- We never encountered this project file. Save the scan state, load the - -- project file and start to scan it. - - Save_Project_Scan_State (Project_Scan_State); - Source_Index := Load_Project_File (Path_Name); - Tree.Save (Project_Comment_State); - - -- If we cannot find it, we stop - - if Source_Index = No_Source_File then - Project := Empty_Node; - Project_Stack.Decrement_Last; - return; - end if; - - Prj.Err.Scanner.Initialize_Scanner (Source_Index); - Tree.Reset_State; - Scan (In_Tree); - - if not In_Configuration and then Name_From_Path = No_Name then - - -- The project file name is not correct (no or bad extension, or not - -- following Ada identifier's syntax). - - Error_Msg_File_1 := File_Name_Type (Canonical_Path_Name); - Error_Msg ("?{ is not a valid path name for a project file", - Token_Ptr); - end if; - - if Current_Verbosity >= Medium then - Write_Str ("Parsing """); - Write_Str (Path_Name); - Write_Char ('"'); - Write_Eol; - end if; - - Project_Directory := Immediate_Directory_Of (Normed_Path_Name); - - -- Is there any imported project? - - Pre_Parse_Context_Clause - (In_Tree => In_Tree, - Context_Clause => First_With); - - Project := Default_Project_Node - (Of_Kind => N_Project, In_Tree => In_Tree); - Project_Stack.Table (Project_Stack.Last).Id := Project; - Set_Directory_Of (Project, In_Tree, Project_Directory); - Set_Path_Name_Of (Project, In_Tree, Normed_Path_Name); - - -- Check if there is a qualifier before the reserved word "project" - - Qualifier_Location := Token_Ptr; - - if Token = Tok_Abstract then - Proj_Qualifier := Dry; - Scan (In_Tree); - - elsif Token = Tok_Identifier then - case Token_Name is - when Snames.Name_Standard => - Proj_Qualifier := Standard; - Scan (In_Tree); - - when Snames.Name_Aggregate => - Proj_Qualifier := Aggregate; - Scan (In_Tree); - - if Token = Tok_Identifier and then - Token_Name = Snames.Name_Library - then - Proj_Qualifier := Aggregate_Library; - Scan (In_Tree); - end if; - - when Snames.Name_Library => - Proj_Qualifier := Library; - Scan (In_Tree); - - when Snames.Name_Configuration => - if not In_Configuration then - Error_Msg ("configuration projects cannot belong to a user" & - " project tree", - Token_Ptr); - end if; - - Scan (In_Tree); - - when others => - null; - end case; - end if; - - if Proj_Qualifier /= Unspecified then - if In_Configuration then - Error_Msg ("a configuration project cannot be qualified except " & - "as configuration project", - Qualifier_Location); - end if; - - Set_Project_Qualifier_Of (Project, In_Tree, Proj_Qualifier); - end if; - - Set_Location_Of (Project, In_Tree, Token_Ptr); - - Expect (Tok_Project, "PROJECT"); - - -- Mark location of PROJECT token if present - - if Token = Tok_Project then - Scan (In_Tree); -- past PROJECT - Set_Location_Of (Project, In_Tree, Token_Ptr); - end if; - - -- Clear the Buffer - - Buffer_Last := 0; - loop - Expect (Tok_Identifier, "identifier"); - - -- If the token is not an identifier, clear the buffer before - -- exiting to indicate that the name of the project is ill-formed. - - if Token /= Tok_Identifier then - Buffer_Last := 0; - exit; - end if; - - -- Add the identifier name to the buffer - - Get_Name_String (Token_Name); - Add_To_Buffer (Name_Buffer (1 .. Name_Len), Buffer, Buffer_Last); - - -- Scan past the identifier - - Scan (In_Tree); - - -- If we have a dot, add a dot to the Buffer and look for the next - -- identifier. - - exit when Token /= Tok_Dot; - Add_To_Buffer (".", Buffer, Buffer_Last); - - -- Scan past the dot - - Scan (In_Tree); - end loop; - - -- See if this is an extending project - - if Token = Tok_Extends then - - if In_Configuration then - Error_Msg - ("extending configuration project not allowed", Token_Ptr); - end if; - - -- Make sure that gnatmake will use mapping files - - Create_Mapping_File := True; - - -- We are extending another project - - Extending := True; - - Scan (In_Tree); -- past EXTENDS - - if Token = Tok_All then - Extends_All := True; - Set_Is_Extending_All (Project, In_Tree); - Scan (In_Tree); -- scan past ALL - end if; - end if; - - -- If the name is well formed, Buffer_Last is > 0 - - if Buffer_Last > 0 then - - -- The Buffer contains the name of the project - - Name_Len := Buffer_Last; - Name_Buffer (1 .. Name_Len) := Buffer (1 .. Buffer_Last); - Name_Of_Project := Name_Find; - Set_Name_Of (Project, In_Tree, Name_Of_Project); - - -- To get expected name of the project file, replace dots by dashes - - Name_Len := Buffer_Last; - Name_Buffer (1 .. Name_Len) := Buffer (1 .. Buffer_Last); - - for Index in 1 .. Name_Len loop - if Name_Buffer (Index) = '.' then - Name_Buffer (Index) := '-'; - end if; - end loop; - - Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len)); - - declare - Expected_Name : constant Name_Id := Name_Find; - Extension : String_Access; - - begin - -- Output a warning if the actual name is not the expected name - - if not In_Configuration - and then (Name_From_Path /= No_Name) - and then Expected_Name /= Name_From_Path - then - Error_Msg_Name_1 := Expected_Name; - - if In_Configuration then - Extension := new String'(Config_Project_File_Extension); - - else - Extension := new String'(Project_File_Extension); - end if; - - Error_Msg ("?file name does not match project name, " & - "should be `%%" & Extension.all & "`", - Token_Ptr); - end if; - end; - - declare - From_Ext : Extension_Origin := None; - - begin - -- Extending_All is always propagated - - if From_Extended = Extending_All or else Extends_All then - From_Ext := Extending_All; - - -- Otherwise, From_Extended is set to Extending_Single if the - -- current project is an extending project. - - elsif Extended then - From_Ext := Extending_Simple; - end if; - - Post_Parse_Context_Clause - (In_Tree => In_Tree, - Context_Clause => First_With, - Limited_Withs => False, - Imported_Projects => Imported_Projects, - Project_Directory => Project_Directory, - From_Extended => From_Ext, - In_Limited => In_Limited, - Packages_To_Check => Packages_To_Check, - Depth => Depth + 1, - Current_Dir => Current_Dir); - Set_First_With_Clause_Of (Project, In_Tree, Imported_Projects); - end; - - if not In_Configuration then - declare - Name_And_Node : Tree_Private_Part.Project_Name_And_Node := - Tree_Private_Part.Projects_Htable.Get_First - (In_Tree.Projects_HT); - Project_Name : Name_Id := Name_And_Node.Name; - - begin - -- Check if we already have a project with this name - - while Project_Name /= No_Name - and then Project_Name /= Name_Of_Project - loop - Name_And_Node := - Tree_Private_Part.Projects_Htable.Get_Next - (In_Tree.Projects_HT); - Project_Name := Name_And_Node.Name; - end loop; - - -- Report an error if we already have a project with this name - - if Project_Name /= No_Name then - Duplicated := True; - Error_Msg_Name_1 := Project_Name; - Error_Msg - ("duplicate project name %%", - Location_Of (Project, In_Tree)); - Error_Msg_Name_1 := - Name_Id (Path_Name_Of (Name_And_Node.Node, In_Tree)); - Error_Msg - ("\already in %%", Location_Of (Project, In_Tree)); - end if; - end; - end if; - - end if; - - if Extending then - Expect (Tok_String_Literal, "literal string"); - - if Token = Tok_String_Literal then - Set_Extended_Project_Path_Of - (Project, - In_Tree, - Path_Name_Type (Token_Name)); - - declare - Original_Path_Name : constant String := - Get_Name_String (Token_Name); - - Extended_Project_Path_Name : constant String := - Project_Path_Name_Of - (Original_Path_Name, - Get_Name_String - (Project_Directory)); - - begin - if Extended_Project_Path_Name = "" then - - -- We could not find the project file to extend - - Error_Msg_Name_1 := Token_Name; - - Error_Msg ("unknown project file: %%", Token_Ptr); - - -- If we are not in the main project file, display the - -- import path. - - if Project_Stack.Last > 1 then - Error_Msg_Name_1 := - Name_Id - (Project_Stack.Table (Project_Stack.Last).Path_Name); - Error_Msg ("\extended by %%", Token_Ptr); - - for Index in reverse 1 .. Project_Stack.Last - 1 loop - Error_Msg_Name_1 := - Name_Id - (Project_Stack.Table (Index).Path_Name); - Error_Msg ("\imported by %%", Token_Ptr); - end loop; - end if; - - else - declare - From_Ext : Extension_Origin := None; - - begin - if From_Extended = Extending_All or else Extends_All then - From_Ext := Extending_All; - end if; - - Parse_Single_Project - (In_Tree => In_Tree, - Project => Extended_Project, - Extends_All => Extends_All, - Path_Name => Extended_Project_Path_Name, - Extended => True, - From_Extended => From_Ext, - In_Limited => In_Limited, - Packages_To_Check => Packages_To_Check, - Depth => Depth + 1, - Current_Dir => Current_Dir); - end; - - if Present (Extended_Project) then - - -- A project that extends an extending-all project is - -- also an extending-all project. - - if Is_Extending_All (Extended_Project, In_Tree) then - Set_Is_Extending_All (Project, In_Tree); - end if; - - -- An abstract project can only extend an abstract - -- project, otherwise we may have an abstract project - -- with sources, if it inherits sources from the project - -- it extends. - - if Proj_Qualifier = Dry and then - Project_Qualifier_Of (Extended_Project, In_Tree) /= Dry - then - Error_Msg - ("an abstract project can only extend " & - "another abstract project", - Qualifier_Location); - end if; - end if; - end if; - end; - - Scan (In_Tree); -- past the extended project path - end if; - end if; - - -- Check that a non extending-all project does not import an - -- extending-all project. - - if not Is_Extending_All (Project, In_Tree) then - declare - With_Clause : Project_Node_Id := - First_With_Clause_Of (Project, In_Tree); - Imported : Project_Node_Id := Empty_Node; - - begin - With_Clause_Loop : - while Present (With_Clause) loop - Imported := Project_Node_Of (With_Clause, In_Tree); - - if Is_Extending_All (With_Clause, In_Tree) then - Error_Msg_Name_1 := Name_Of (Imported, In_Tree); - Error_Msg ("cannot import extending-all project %%", - Token_Ptr); - exit With_Clause_Loop; - end if; - - With_Clause := Next_With_Clause_Of (With_Clause, In_Tree); - end loop With_Clause_Loop; - end; - end if; - - -- Check that a project with a name including a dot either imports - -- or extends the project whose name precedes the last dot. - - if Name_Of_Project /= No_Name then - Get_Name_String (Name_Of_Project); - - else - Name_Len := 0; - end if; - - -- Look for the last dot - - while Name_Len > 0 and then Name_Buffer (Name_Len) /= '.' loop - Name_Len := Name_Len - 1; - end loop; - - -- If a dot was find, check if the parent project is imported - -- or extended. - - if Name_Len > 0 then - Name_Len := Name_Len - 1; - - declare - Parent_Name : constant Name_Id := Name_Find; - Parent_Found : Boolean := False; - Parent_Node : Project_Node_Id := Empty_Node; - With_Clause : Project_Node_Id := - First_With_Clause_Of (Project, In_Tree); - - begin - -- If there is an extended project, check its name - - if Present (Extended_Project) then - Parent_Node := Extended_Project; - Parent_Found := - Name_Of (Extended_Project, In_Tree) = Parent_Name; - end if; - - -- If the parent project is not the extended project, - -- check each imported project until we find the parent project. - - while not Parent_Found and then Present (With_Clause) loop - Parent_Node := Project_Node_Of (With_Clause, In_Tree); - Parent_Found := Name_Of (Parent_Node, In_Tree) = Parent_Name; - With_Clause := Next_With_Clause_Of (With_Clause, In_Tree); - end loop; - - if Parent_Found then - Set_Parent_Project_Of (Project, In_Tree, To => Parent_Node); - - else - -- If the parent project was not found, report an error - - Error_Msg_Name_1 := Name_Of_Project; - Error_Msg_Name_2 := Parent_Name; - Error_Msg ("project %% does not import or extend project %%", - Location_Of (Project, In_Tree)); - end if; - end; - end if; - - Expect (Tok_Is, "IS"); - Set_End_Of_Line (Project); - Set_Previous_Line_Node (Project); - Set_Next_End_Node (Project); - - declare - Project_Declaration : Project_Node_Id := Empty_Node; - - begin - -- No need to Scan past "is", Prj.Dect.Parse will do it - - Prj.Dect.Parse - (In_Tree => In_Tree, - Declarations => Project_Declaration, - Current_Project => Project, - Extends => Extended_Project, - Packages_To_Check => Packages_To_Check); - Set_Project_Declaration_Of (Project, In_Tree, Project_Declaration); - - if Present (Extended_Project) - and then Project_Qualifier_Of (Extended_Project, In_Tree) /= Dry - then - Set_Extending_Project_Of - (Project_Declaration_Of (Extended_Project, In_Tree), In_Tree, - To => Project); - end if; - end; - - Expect (Tok_End, "END"); - Remove_Next_End_Node; - - -- Skip "end" if present - - if Token = Tok_End then - Scan (In_Tree); - end if; - - -- Clear the Buffer - - Buffer_Last := 0; - - -- Store the name following "end" in the Buffer. The name may be made of - -- several simple names. - - loop - Expect (Tok_Identifier, "identifier"); - - -- If we don't have an identifier, clear the buffer before exiting to - -- avoid checking the name. - - if Token /= Tok_Identifier then - Buffer_Last := 0; - exit; - end if; - - -- Add the identifier to the Buffer - Get_Name_String (Token_Name); - Add_To_Buffer (Name_Buffer (1 .. Name_Len), Buffer, Buffer_Last); - - -- Scan past the identifier - - Scan (In_Tree); - exit when Token /= Tok_Dot; - Add_To_Buffer (".", Buffer, Buffer_Last); - Scan (In_Tree); - end loop; - - -- If we have a valid name, check if it is the name of the project - - if Name_Of_Project /= No_Name and then Buffer_Last > 0 then - if To_Lower (Buffer (1 .. Buffer_Last)) /= - Get_Name_String (Name_Of (Project, In_Tree)) - then - -- Invalid name: report an error - - Error_Msg ("expected """ & - Get_Name_String (Name_Of (Project, In_Tree)) & """", - Token_Ptr); - end if; - end if; - - Expect (Tok_Semicolon, "`;`"); - - -- Check that there is no more text following the end of the project - -- source. - - if Token = Tok_Semicolon then - Set_Previous_End_Node (Project); - Scan (In_Tree); - - if Token /= Tok_EOF then - Error_Msg - ("unexpected text following end of project", Token_Ptr); - end if; - end if; - - if not Duplicated and then Name_Of_Project /= No_Name then - - -- Add the name of the project to the hash table, so that we can - -- check that no other subsequent project will have the same name. - - Tree_Private_Part.Projects_Htable.Set - (T => In_Tree.Projects_HT, - K => Name_Of_Project, - E => (Name => Name_Of_Project, - Node => Project, - Canonical_Path => Canonical_Path_Name, - Extended => Extended, - Proj_Qualifier => Proj_Qualifier)); - end if; - - declare - From_Ext : Extension_Origin := None; - - begin - -- Extending_All is always propagated - - if From_Extended = Extending_All or else Extends_All then - From_Ext := Extending_All; - - -- Otherwise, From_Extended is set to Extending_Single if the - -- current project is an extending project. - - elsif Extended then - From_Ext := Extending_Simple; - end if; - - Post_Parse_Context_Clause - (In_Tree => In_Tree, - Context_Clause => First_With, - Limited_Withs => True, - Imported_Projects => Imported_Projects, - Project_Directory => Project_Directory, - From_Extended => From_Ext, - In_Limited => In_Limited, - Packages_To_Check => Packages_To_Check, - Depth => Depth + 1, - Current_Dir => Current_Dir); - Set_First_With_Clause_Of (Project, In_Tree, Imported_Projects); - end; - - -- Restore the scan state, in case we are not the main project - - Restore_Project_Scan_State (Project_Scan_State); - - -- And remove the project from the project stack - - Project_Stack.Decrement_Last; - - -- Indicate if there are unkept comments - - Tree.Set_Project_File_Includes_Unkept_Comments - (Node => Project, - In_Tree => In_Tree, - To => Tree.There_Are_Unkept_Comments); - - -- And restore the comment state that was saved - - Tree.Restore (Project_Comment_State); - end Parse_Single_Project; - - ----------------------- - -- Project_Name_From -- - ----------------------- - - function Project_Name_From (Path_Name : String) return Name_Id is - Canonical : String (1 .. Path_Name'Length) := Path_Name; - First : Natural := Canonical'Last; - Last : Natural := First; - Index : Positive; - - begin - if Current_Verbosity = High then - Write_Str ("Project_Name_From ("""); - Write_Str (Canonical); - Write_Line (""")"); - end if; - - -- If the path name is empty, return No_Name to indicate failure - - if First = 0 then - return No_Name; - end if; - - Canonical_Case_File_Name (Canonical); - - -- Look for the last dot in the path name - - while First > 0 - and then - Canonical (First) /= '.' - loop - First := First - 1; - end loop; - - -- If we have a dot, check that it is followed by the correct extension - - if First > 0 and then Canonical (First) = '.' then - if (not In_Configuration - and then Canonical (First .. Last) = Project_File_Extension - and then First /= 1) - or else - (In_Configuration - and then - Canonical (First .. Last) = Config_Project_File_Extension - and then First /= 1) - then - -- Look for the last directory separator, if any - - First := First - 1; - Last := First; - while First > 0 - and then Canonical (First) /= '/' - and then Canonical (First) /= Dir_Sep - loop - First := First - 1; - end loop; - - else - -- Not the correct extension, return No_Name to indicate failure - - return No_Name; - end if; - - -- If no dot in the path name, return No_Name to indicate failure - - else - return No_Name; - end if; - - First := First + 1; - - -- If the extension is the file name, return No_Name to indicate failure - - if First > Last then - return No_Name; - end if; - - -- Put the name in lower case into Name_Buffer - - Name_Len := Last - First + 1; - Name_Buffer (1 .. Name_Len) := To_Lower (Canonical (First .. Last)); - - Index := 1; - - -- Check if it is a well formed project name. Return No_Name if it is - -- ill formed. - - loop - if not Is_Letter (Name_Buffer (Index)) then - return No_Name; - - else - loop - Index := Index + 1; - - exit when Index >= Name_Len; - - if Name_Buffer (Index) = '_' then - if Name_Buffer (Index + 1) = '_' then - return No_Name; - end if; - end if; - - exit when Name_Buffer (Index) = '-'; - - if Name_Buffer (Index) /= '_' - and then not Is_Alphanumeric (Name_Buffer (Index)) - then - return No_Name; - end if; - - end loop; - end if; - - if Index >= Name_Len then - if Is_Alphanumeric (Name_Buffer (Name_Len)) then - - -- All checks have succeeded. Return name in Name_Buffer - - return Name_Find; - - else - return No_Name; - end if; - - elsif Name_Buffer (Index) = '-' then - Index := Index + 1; - end if; - end loop; - end Project_Name_From; - - -------------------------- - -- Project_Path_Name_Of -- - -------------------------- - - function Project_Path_Name_Of - (Project_File_Name : String; - Directory : String) return String - is - - function Try_Path_Name (Path : String) return String_Access; - pragma Inline (Try_Path_Name); - -- Try the specified Path - - ------------------- - -- Try_Path_Name -- - ------------------- - - function Try_Path_Name (Path : String) return String_Access is - Prj_Path : constant String := Project_Path; - First : Natural; - Last : Natural; - Result : String_Access := null; - - begin - if Current_Verbosity = High then - Write_Str (" Trying "); - Write_Line (Path); - end if; - - if Is_Absolute_Path (Path) then - if Is_Regular_File (Path) then - Result := new String'(Path); - end if; - - else - -- Because we don't want to resolve symbolic links, we cannot use - -- Locate_Regular_File. So, we try each possible path - -- successively. - - First := Prj_Path'First; - while First <= Prj_Path'Last loop - while First <= Prj_Path'Last - and then Prj_Path (First) = Path_Separator - loop - First := First + 1; - end loop; - - exit when First > Prj_Path'Last; - - Last := First; - while Last < Prj_Path'Last - and then Prj_Path (Last + 1) /= Path_Separator - loop - Last := Last + 1; - end loop; - - Name_Len := 0; - - if not Is_Absolute_Path (Prj_Path (First .. Last)) then - Add_Str_To_Name_Buffer (Get_Current_Dir); - Add_Char_To_Name_Buffer (Directory_Separator); - end if; - - Add_Str_To_Name_Buffer (Prj_Path (First .. Last)); - Add_Char_To_Name_Buffer (Directory_Separator); - Add_Str_To_Name_Buffer (Path); - - if Is_Regular_File (Name_Buffer (1 .. Name_Len)) then - Result := new String'(Name_Buffer (1 .. Name_Len)); - exit; - end if; - - First := Last + 1; - end loop; - end if; - - return Result; - end Try_Path_Name; - - -- Local Declarations - - Result : String_Access; - Result_Id : Path_Name_Type; - Has_Dot : Boolean := False; - Key : Name_Id; - - -- Start of processing for Project_Path_Name_Of - - begin - if Current_Verbosity = High then - Write_Str ("Project_Path_Name_Of ("""); - Write_Str (Project_File_Name); - Write_Str (""", """); - Write_Str (Directory); - Write_Line (""");"); - end if; - - -- Check the project cache - - Name_Len := Project_File_Name'Length; - Name_Buffer (1 .. Name_Len) := Project_File_Name; - Key := Name_Find; - Result_Id := Projects_Paths.Get (Key); - - if Result_Id /= No_Path then - return Get_Name_String (Result_Id); - end if; - - -- Check if Project_File_Name contains an extension (a dot before a - -- directory separator). If it is the case we do not try project file - -- with an added extension as it is not possible to have multiple dots - -- on a project file name. - - Check_Dot : for K in reverse Project_File_Name'Range loop - if Project_File_Name (K) = '.' then - Has_Dot := True; - exit Check_Dot; - end if; - - exit Check_Dot when Project_File_Name (K) = Directory_Separator - or else Project_File_Name (K) = '/'; - end loop Check_Dot; - - if not Is_Absolute_Path (Project_File_Name) then - - -- First we try <directory>/<file_name>.<extension> - - if not Has_Dot then - Result := Try_Path_Name - (Directory & Directory_Separator & - Project_File_Name & Project_File_Extension); - end if; - - -- Then we try <directory>/<file_name> - - if Result = null then - Result := Try_Path_Name - (Directory & Directory_Separator & Project_File_Name); - end if; - end if; - - -- Then we try <file_name>.<extension> - - if Result = null and then not Has_Dot then - Result := Try_Path_Name (Project_File_Name & Project_File_Extension); - end if; - - -- Then we try <file_name> - - if Result = null then - Result := Try_Path_Name (Project_File_Name); - end if; - - -- If we cannot find the project file, we return an empty string - - if Result = null then - return ""; - - else - declare - Final_Result : constant String := - GNAT.OS_Lib.Normalize_Pathname - (Result.all, - Directory => Directory, - Resolve_Links => False, - Case_Sensitive => True); - begin - Free (Result); - Name_Len := Final_Result'Length; - Name_Buffer (1 .. Name_Len) := Final_Result; - Result_Id := Name_Find; - - Projects_Paths.Set (Key, Result_Id); - return Final_Result; - end; - end if; - end Project_Path_Name_Of; - -end Prj.Part; |