OSDN Git Service

* config/pa/fptr.c: Update license header.
[pf3gnuchains/gcc-fork.git] / gcc / ada / prj-tree.ads
index 15156e8..470e0a8 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 S p e c                                  --
 --                                                                          --
---             Copyright (C) 2001-2003 Free Software Foundation, Inc.       --
+--          Copyright (C) 2001-2007, 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- --
 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
 -- for  more details.  You should have  received  a copy of the GNU General --
 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
--- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
--- MA 02111-1307, USA.                                                      --
+-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
+-- Boston, MA 02110-1301, USA.                                              --
 --                                                                          --
 -- GNAT was originally developed  by the GNAT team at  New York University. --
 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
 --                                                                          --
 ------------------------------------------------------------------------------
 
---  This package defines the structure of the Project File tree.
+--  This package defines the structure of the Project File tree
 
-with GNAT.HTable;
+with GNAT.Dynamic_HTables;
+with GNAT.Dynamic_Tables;
 
 with Prj.Attr; use Prj.Attr;
-with Prj.Com;  use Prj.Com;
-with Types;    use Types;
-with Table;
 
 package Prj.Tree is
 
+   type Project_Node_Tree_Data;
+   type Project_Node_Tree_Ref is access all Project_Node_Tree_Data;
+   --  Type to designate a project node tree, so that several project node
+   --  trees can coexist in memory.
+
    Project_Nodes_Initial   : constant := 1_000;
    Project_Nodes_Increment : constant := 100;
    --  Allocation parameters for initializing and extending number
@@ -79,319 +82,485 @@ package Prj.Tree is
       N_External_Value,
       N_Attribute_Reference,
       N_Case_Construction,
-      N_Case_Item);
-   --  Each node in the tree is of a Project_Node_Kind
-   --  For the signification of the fields in each node of a
-   --  Project_Node_Kind, look at package Tree_Private_Part.
-
-   procedure Initialize;
+      N_Case_Item,
+      N_Comment_Zones,
+      N_Comment);
+   --  Each node in the tree is of a Project_Node_Kind. For the signification
+   --  of the fields in each node of Project_Node_Kind, look at package
+   --  Tree_Private_Part.
+
+   procedure Initialize (Tree : Project_Node_Tree_Ref);
    --  Initialize the Project File tree: empty the Project_Nodes table
    --  and reset the Projects_Htable.
 
    function Default_Project_Node
-     (Of_Kind       : Project_Node_Kind;
-      And_Expr_Kind : Variable_Kind := Undefined)
-      return          Project_Node_Id;
-   --  Returns a Project_Node_Record with the specified Kind and
-   --  Expr_Kind; all the other components have default nil values.
+     (In_Tree       : Project_Node_Tree_Ref;
+      Of_Kind       : Project_Node_Kind;
+      And_Expr_Kind : Variable_Kind := Undefined) return Project_Node_Id;
+   --  Returns a Project_Node_Record with the specified Kind and Expr_Kind. All
+   --  the other components have default nil values.
 
    function Hash (N : Project_Node_Id) return Header_Num;
    --  Used for hash tables where the key is a Project_Node_Id
 
    function Imported_Or_Extended_Project_Of
      (Project   : Project_Node_Id;
-      With_Name : Name_Id)
-      return      Project_Node_Id;
+      In_Tree   : Project_Node_Tree_Ref;
+      With_Name : Name_Id) return Project_Node_Id;
    --  Return the node of a project imported or extended by project Project and
    --  whose name is With_Name. Return Empty_Node if there is no such project.
 
+   --------------
+   -- Comments --
+   --------------
+
+   type Comment_State is private;
+   --  A type to store the values of several global variables related to
+   --  comments.
+
+   procedure Save (S : out Comment_State);
+   --  Save in variable S the comment state. Called before scanning a new
+   --  project file.
+
+   procedure Restore (S : Comment_State);
+   --  Restore the comment state to a previously saved value. Called after
+   --  scanning a project file.
+
+   procedure Reset_State;
+   --  Set the comment state to its initial value. Called before scanning a
+   --  new project file.
+
+   function There_Are_Unkept_Comments return Boolean;
+   --  Indicates that some of the comments in a project file could not be
+   --  stored in the parse tree.
+
+   procedure Set_Previous_Line_Node (To : Project_Node_Id);
+   --  Indicate the node on the previous line. If there are comments
+   --  immediately following this line, then they should be associated with
+   --  this node.
+
+   procedure Set_Previous_End_Node (To : Project_Node_Id);
+   --  Indicate that on the previous line the "end" belongs to node To.
+   --  If there are comments immediately following this "end" line, they
+   --  should be associated with this node.
+
+   procedure Set_End_Of_Line (To : Project_Node_Id);
+   --  Indicate the node on the current line. If there is an end of line
+   --  comment, then it should be associated with this node.
+
+   procedure Set_Next_End_Node (To : Project_Node_Id);
+   --  Put node To on the top of the end node stack. When an END line is found
+   --  with this node on the top of the end node stack, the comments, if any,
+   --  immediately preceding this "end" line will be associated with this node.
+
+   procedure Remove_Next_End_Node;
+   --  Remove the top of the end node stack
+
+   ------------------------
+   -- Comment Processing --
+   ------------------------
+
+   type Comment_Data is record
+      Value                     : Name_Id := No_Name;
+      Follows_Empty_Line        : Boolean := False;
+      Is_Followed_By_Empty_Line : Boolean := False;
+   end record;
+   --  Component type for Comments Table below
+
+   package Comments is new Table.Table
+     (Table_Component_Type => Comment_Data,
+      Table_Index_Type     => Natural,
+      Table_Low_Bound      => 1,
+      Table_Initial        => 10,
+      Table_Increment      => 100,
+      Table_Name           => "Prj.Tree.Comments");
+   --  A table to store the comments that may be stored is the tree
+
+   procedure Scan (In_Tree : Project_Node_Tree_Ref);
+   --  Scan the tokens and accumulate comments
+
+   type Comment_Location is
+     (Before, After, Before_End, After_End, End_Of_Line);
+   --  Used in call to Add_Comments below
+
+   procedure Add_Comments
+     (To      : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      Where   : Comment_Location);
+   --  Add comments to this node
+
    ----------------------
    -- Access Functions --
    ----------------------
 
    --  The following query functions are part of the abstract interface
-   --  of the Project File tree
+   --  of the Project File tree. They provide access to fields of a project.
+
+   --  In the following, there are "valid if" comments, but no indication
+   --  of what happens if they are called with invalid arguments ???
 
-   function Name_Of (Node : Project_Node_Id) return Name_Id;
+   function Name_Of
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Name_Id;
    pragma Inline (Name_Of);
    --  Valid for all non empty nodes. May return No_Name for nodes that have
    --  no names.
 
-   function Kind_Of (Node : Project_Node_Id) return Project_Node_Kind;
+   function Kind_Of
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Kind;
    pragma Inline (Kind_Of);
    --  Valid for all non empty nodes
 
-   function Location_Of (Node : Project_Node_Id) return Source_Ptr;
+   function Location_Of
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Source_Ptr;
    pragma Inline (Location_Of);
    --  Valid for all non empty nodes
 
-   function Directory_Of (Node : Project_Node_Id) return Name_Id;
+   function First_Comment_After
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
+   --  Valid only for N_Comment_Zones nodes
+
+   function First_Comment_After_End
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
+   --  Valid only for N_Comment_Zones nodes
+
+   function First_Comment_Before
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
+   --  Valid only for N_Comment_Zones nodes
+
+   function First_Comment_Before_End
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
+   --  Valid only for N_Comment_Zones nodes
+
+   function Next_Comment
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
+   --  Valid only for N_Comment nodes
+
+   function End_Of_Line_Comment
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Name_Id;
+   --  Valid only for non empty nodes
+
+   function Follows_Empty_Line
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Boolean;
+   --  Valid only for N_Comment nodes
+
+   function Is_Followed_By_Empty_Line
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Boolean;
+   --  Valid only for N_Comment nodes
+
+   function Project_File_Includes_Unkept_Comments
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref)
+      return Boolean;
+   --  Valid only for N_Project nodes
+
+   function Directory_Of
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Path_Name_Type;
    pragma Inline (Directory_Of);
-   --  Only valid for N_Project nodes.
+   --  Only valid for N_Project nodes
 
-   function Expression_Kind_Of (Node : Project_Node_Id) return Variable_Kind;
+   function Expression_Kind_Of
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Variable_Kind;
    pragma Inline (Expression_Kind_Of);
    --  Only valid for N_Literal_String, N_Attribute_Declaration,
    --  N_Variable_Declaration, N_Typed_Variable_Declaration, N_Expression,
    --  N_Term, N_Variable_Reference or N_Attribute_Reference nodes.
 
-   function Is_Extending_All (Node  : Project_Node_Id) return Boolean;
+   function Is_Extending_All
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Boolean;
    pragma Inline (Is_Extending_All);
-   --  Only valid for N_Project
+   --  Only valid for N_Project and N_With_Clause
+
+   function Is_Not_Last_In_List
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Boolean;
+   pragma Inline (Is_Not_Last_In_List);
+   --  Only valid for N_With_Clause
 
    function First_Variable_Of
-     (Node  : Project_Node_Id)
-      return  Variable_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Variable_Node_Id;
    pragma Inline (First_Variable_Of);
    --  Only valid for N_Project or N_Package_Declaration nodes
 
    function First_Package_Of
-     (Node  : Project_Node_Id)
-      return  Package_Declaration_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Package_Declaration_Id;
    pragma Inline (First_Package_Of);
    --  Only valid for N_Project nodes
 
-   function Package_Id_Of (Node  : Project_Node_Id) return Package_Node_Id;
+   function Package_Id_Of
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Package_Node_Id;
    pragma Inline (Package_Id_Of);
    --  Only valid for N_Package_Declaration nodes
 
-   function Path_Name_Of (Node  : Project_Node_Id) return Name_Id;
+   function Path_Name_Of
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Path_Name_Type;
    pragma Inline (Path_Name_Of);
-   --  Only valid for N_Project and N_With_Clause nodes.
+   --  Only valid for N_Project and N_With_Clause nodes
 
-   function String_Value_Of (Node  : Project_Node_Id) return Name_Id;
+   function String_Value_Of
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Name_Id;
    pragma Inline (String_Value_Of);
-   --  Only valid for N_With_Clause or N_Literal_String nodes.
+   --  Only valid for N_With_Clause, N_Literal_String nodes or N_Comment.
+   --  For a N_With_Clause created automatically for a virtual extending
+   --  project, No_Name is returned.
+
+   function Source_Index_Of
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Int;
+   pragma Inline (Source_Index_Of);
+   --  Only valid for N_Literal_String and N_Attribute_Declaration nodes
 
    function First_With_Clause_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (First_With_Clause_Of);
    --  Only valid for N_Project nodes
 
    function Project_Declaration_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Project_Declaration_Of);
    --  Only valid for N_Project nodes
 
    function Extending_Project_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Extending_Project_Of);
    --  Only valid for N_Project_Declaration nodes
 
    function First_String_Type_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (First_String_Type_Of);
    --  Only valid for N_Project nodes
 
    function Extended_Project_Path_Of
-     (Node  : Project_Node_Id)
-      return  Name_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Path_Name_Type;
    pragma Inline (Extended_Project_Path_Of);
    --  Only valid for N_With_Clause nodes
 
    function Project_Node_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Project_Node_Of);
    --  Only valid for N_With_Clause, N_Variable_Reference and
    --  N_Attribute_Reference nodes.
 
    function Non_Limited_Project_Node_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Non_Limited_Project_Node_Of);
    --  Only valid for N_With_Clause nodes. Returns Empty_Node for limited
    --  imported project files, otherwise returns the same result as
    --  Project_Node_Of.
 
    function Next_With_Clause_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Next_With_Clause_Of);
    --  Only valid for N_With_Clause nodes
 
    function First_Declarative_Item_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (First_Declarative_Item_Of);
    --  Only valid for N_With_Clause nodes
 
    function Extended_Project_Of
-     (Node  : Project_Node_Id)
-      return Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Extended_Project_Of);
    --  Only valid for N_Project_Declaration nodes
 
    function Current_Item_Node
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Current_Item_Node);
    --  Only valid for N_Declarative_Item nodes
 
    function Next_Declarative_Item
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Next_Declarative_Item);
    --  Only valid for N_Declarative_Item node
 
    function Project_Of_Renamed_Package_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Project_Of_Renamed_Package_Of);
    --  Only valid for N_Package_Declaration nodes.
    --  May return Empty_Node.
 
    function Next_Package_In_Project
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Next_Package_In_Project);
    --  Only valid for N_Package_Declaration nodes
 
    function First_Literal_String
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (First_Literal_String);
    --  Only valid for N_String_Type_Declaration nodes
 
    function Next_String_Type
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Next_String_Type);
    --  Only valid for N_String_Type_Declaration nodes
 
    function Next_Literal_String
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Next_Literal_String);
    --  Only valid for N_Literal_String nodes
 
    function Expression_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Expression_Of);
    --  Only valid for N_Attribute_Declaration, N_Typed_Variable_Declaration
    --  or N_Variable_Declaration nodes
 
    function Associative_Project_Of
-     (Node  : Project_Node_Id)
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref)
       return  Project_Node_Id;
    pragma Inline (Associative_Project_Of);
    --  Only valid for N_Attribute_Declaration nodes
 
    function Associative_Package_Of
-     (Node  : Project_Node_Id)
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref)
       return  Project_Node_Id;
    pragma Inline (Associative_Package_Of);
    --  Only valid for N_Attribute_Declaration nodes
 
    function Value_Is_Valid
      (For_Typed_Variable : Project_Node_Id;
-      Value              : Name_Id)
-      return               Boolean;
+      In_Tree            : Project_Node_Tree_Ref;
+      Value              : Name_Id) return Boolean;
    pragma Inline (Value_Is_Valid);
    --  Only valid for N_Typed_Variable_Declaration. Returns True if Value is
    --  in the list of allowed strings for For_Typed_Variable. False otherwise.
 
    function Associative_Array_Index_Of
-     (Node  : Project_Node_Id)
-      return  Name_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Name_Id;
    pragma Inline (Associative_Array_Index_Of);
    --  Only valid for N_Attribute_Declaration and N_Attribute_Reference.
    --  Returns No_String for non associative array attributes.
 
    function Next_Variable
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Next_Variable);
    --  Only valid for N_Typed_Variable_Declaration or N_Variable_Declaration
    --  nodes.
 
    function First_Term
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (First_Term);
    --  Only valid for N_Expression nodes
 
    function Next_Expression_In_List
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Next_Expression_In_List);
    --  Only valid for N_Expression nodes
 
    function Current_Term
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Current_Term);
    --  Only valid for N_Term nodes
 
    function Next_Term
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Next_Term);
    --  Only valid for N_Term nodes
 
    function First_Expression_In_List
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (First_Expression_In_List);
    --  Only valid for N_Literal_String_List nodes
 
    function Package_Node_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Package_Node_Of);
    --  Only valid for N_Variable_Reference or N_Attribute_Reference nodes.
    --  May return Empty_Node.
 
    function String_Type_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (String_Type_Of);
    --  Only valid for N_Variable_Reference or N_Typed_Variable_Declaration
    --  nodes.
 
    function External_Reference_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (External_Reference_Of);
    --  Only valid for N_External_Value nodes
 
    function External_Default_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (External_Default_Of);
    --  Only valid for N_External_Value nodes
 
    function Case_Variable_Reference_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Case_Variable_Reference_Of);
    --  Only valid for N_Case_Construction nodes
 
    function First_Case_Item_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (First_Case_Item_Of);
    --  Only valid for N_Case_Construction nodes
 
    function First_Choice_Of
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (First_Choice_Of);
    --  Return the first choice in a N_Case_Item, or Empty_Node if
    --  this is when others.
 
    function Next_Case_Item
-     (Node  : Project_Node_Id)
-      return  Project_Node_Id;
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Project_Node_Id;
    pragma Inline (Next_Case_Item);
    --  Only valid for N_Case_Item nodes
 
-   function Case_Insensitive (Node : Project_Node_Id) return Boolean;
+   function Case_Insensitive
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref) return Boolean;
    --  Only valid for N_Attribute_Declaration and N_Attribute_Reference nodes
 
    --------------------
@@ -405,232 +574,325 @@ package Prj.Tree is
    --  nodes as the corresponding query function above.
 
    procedure Set_Name_Of
-     (Node : Project_Node_Id;
-      To   : Name_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Name_Id);
    pragma Inline (Set_Name_Of);
 
    procedure Set_Kind_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Kind);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Kind);
    pragma Inline (Set_Kind_Of);
 
    procedure Set_Location_Of
-     (Node : Project_Node_Id;
-      To   : Source_Ptr);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Source_Ptr);
    pragma Inline (Set_Location_Of);
 
+   procedure Set_First_Comment_After
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
+   pragma Inline (Set_First_Comment_After);
+
+   procedure Set_First_Comment_After_End
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
+   pragma Inline (Set_First_Comment_After_End);
+
+   procedure Set_First_Comment_Before
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
+   pragma Inline (Set_First_Comment_Before);
+
+   procedure Set_First_Comment_Before_End
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
+   pragma Inline (Set_First_Comment_Before_End);
+
+   procedure Set_Next_Comment
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
+   pragma Inline (Set_Next_Comment);
+
+   procedure Set_Project_File_Includes_Unkept_Comments
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Boolean);
+
    procedure Set_Directory_Of
-     (Node : Project_Node_Id;
-      To   : Name_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Path_Name_Type);
    pragma Inline (Set_Directory_Of);
 
    procedure Set_Expression_Kind_Of
-     (Node : Project_Node_Id;
-      To   : Variable_Kind);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Variable_Kind);
    pragma Inline (Set_Expression_Kind_Of);
 
-   procedure Set_Is_Extending_All (Node  : Project_Node_Id);
+   procedure Set_Is_Extending_All
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref);
    pragma Inline (Set_Is_Extending_All);
 
+   procedure Set_Is_Not_Last_In_List
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref);
+   pragma Inline (Set_Is_Not_Last_In_List);
+
    procedure Set_First_Variable_Of
-     (Node : Project_Node_Id;
-      To   : Variable_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Variable_Node_Id);
    pragma Inline (Set_First_Variable_Of);
 
    procedure Set_First_Package_Of
-     (Node : Project_Node_Id;
-      To   : Package_Declaration_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Package_Declaration_Id);
    pragma Inline (Set_First_Package_Of);
 
    procedure Set_Package_Id_Of
-     (Node : Project_Node_Id;
-      To   : Package_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Package_Node_Id);
    pragma Inline (Set_Package_Id_Of);
 
    procedure Set_Path_Name_Of
-     (Node : Project_Node_Id;
-      To   : Name_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Path_Name_Type);
    pragma Inline (Set_Path_Name_Of);
 
    procedure Set_String_Value_Of
-     (Node : Project_Node_Id;
-      To   : Name_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Name_Id);
    pragma Inline (Set_String_Value_Of);
 
    procedure Set_First_With_Clause_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_First_With_Clause_Of);
 
    procedure Set_Project_Declaration_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Project_Declaration_Of);
 
    procedure Set_Extending_Project_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Extending_Project_Of);
 
    procedure Set_First_String_Type_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_First_String_Type_Of);
 
    procedure Set_Extended_Project_Path_Of
-     (Node : Project_Node_Id;
-      To   : Name_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Path_Name_Type);
    pragma Inline (Set_Extended_Project_Path_Of);
 
    procedure Set_Project_Node_Of
      (Node         : Project_Node_Id;
+      In_Tree      : Project_Node_Tree_Ref;
       To           : Project_Node_Id;
       Limited_With : Boolean := False);
    pragma Inline (Set_Project_Node_Of);
 
    procedure Set_Next_With_Clause_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Next_With_Clause_Of);
 
    procedure Set_First_Declarative_Item_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_First_Declarative_Item_Of);
 
    procedure Set_Extended_Project_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Extended_Project_Of);
 
    procedure Set_Current_Item_Node
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Current_Item_Node);
 
    procedure Set_Next_Declarative_Item
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Next_Declarative_Item);
 
    procedure Set_Project_Of_Renamed_Package_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Project_Of_Renamed_Package_Of);
 
    procedure Set_Next_Package_In_Project
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Next_Package_In_Project);
 
    procedure Set_First_Literal_String
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_First_Literal_String);
 
    procedure Set_Next_String_Type
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Next_String_Type);
 
    procedure Set_Next_Literal_String
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Next_Literal_String);
 
    procedure Set_Expression_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Expression_Of);
 
    procedure Set_Associative_Project_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Associative_Project_Of);
 
    procedure Set_Associative_Package_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Associative_Package_Of);
 
    procedure Set_Associative_Array_Index_Of
-     (Node : Project_Node_Id;
-      To   : Name_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Name_Id);
    pragma Inline (Set_Associative_Array_Index_Of);
 
    procedure Set_Next_Variable
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Next_Variable);
 
    procedure Set_First_Term
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_First_Term);
 
    procedure Set_Next_Expression_In_List
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Next_Expression_In_List);
 
    procedure Set_Current_Term
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Current_Term);
 
    procedure Set_Next_Term
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Next_Term);
 
    procedure Set_First_Expression_In_List
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_First_Expression_In_List);
 
    procedure Set_Package_Node_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Package_Node_Of);
 
+   procedure Set_Source_Index_Of
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Int);
+   pragma Inline (Set_Source_Index_Of);
+
    procedure Set_String_Type_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_String_Type_Of);
 
    procedure Set_External_Reference_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_External_Reference_Of);
 
    procedure Set_External_Default_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_External_Default_Of);
 
    procedure Set_Case_Variable_Reference_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Case_Variable_Reference_Of);
 
    procedure Set_First_Case_Item_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_First_Case_Item_Of);
 
    procedure Set_First_Choice_Of
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_First_Choice_Of);
 
    procedure Set_Next_Case_Item
-     (Node : Project_Node_Id;
-      To   : Project_Node_Id);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Project_Node_Id);
    pragma Inline (Set_Next_Case_Item);
 
    procedure Set_Case_Insensitive
-     (Node : Project_Node_Id;
-      To   : Boolean);
+     (Node    : Project_Node_Id;
+      In_Tree : Project_Node_Tree_Ref;
+      To      : Boolean);
 
    -------------------------------
    -- Restricted Access Section --
@@ -638,8 +900,9 @@ package Prj.Tree is
 
    package Tree_Private_Part is
 
-      --  This is conceptually in the private part.
-      --  However, for efficiency, some packages are accessing it directly.
+      --  This is conceptually in the private part
+
+      --  However, for efficiency, some packages are accessing it directly
 
       type Project_Node_Record is record
 
@@ -647,7 +910,7 @@ package Prj.Tree is
 
          Location : Source_Ptr := No_Location;
 
-         Directory : Name_Id       := No_Name;
+         Directory : Path_Name_Type := No_Path;
          --  Only for N_Project
 
          Expr_Kind : Variable_Kind := Undefined;
@@ -672,7 +935,11 @@ package Prj.Tree is
          Name : Name_Id := No_Name;
          --  See below for what Project_Node_Kind it is used
 
-         Path_Name : Name_Id := No_Name;
+         Src_Index : Int := 0;
+         --  Index of a unit in a multi-unit source.
+         --  Onli for some N_Attribute_Declaration and N_Literal_String.
+
+         Path_Name : Path_Name_Type := No_Path;
          --  See below for what Project_Node_Kind it is used
 
          Value : Name_Id := No_Name;
@@ -687,14 +954,41 @@ package Prj.Tree is
          Field3 : Project_Node_Id := Empty_Node;
          --  See below the meaning for each Project_Node_Kind
 
-         Case_Insensitive : Boolean := False;
-         --  This flag is significant only for N_Attribute_Declaration and
-         --  N_Atribute_Reference. It indicates for an associative array
-         --  attribute, that the index is case insensitive.
-
-         Extending_All : Boolean := False;
-         --  This flag is significant only for N_Project. It indicates that
-         --  the project "extends all" another project.
+         Flag1 : Boolean := False;
+         --  This flag is significant only for:
+         --    N_Attribute_Declaration and N_Atribute_Reference
+         --      It indicates for an associative array attribute, that the
+         --      index is case insensitive.
+         --    N_Comment - it indicates that the comment is preceded by an
+         --                empty line.
+         --    N_Project - it indicates that there are comments in the project
+         --                source that cannot be kept in the tree.
+         --    N_Project_Declaration
+         --              - it indicates that there are unkept comments in the
+         --                project.
+         --    N_With_Clause
+         --              - it indicates that this is not the last with in a
+         --                with clause. It is set for "A", but not for "B" in
+         --                    with "B";
+         --                  and
+         --                    with "A", "B";
+
+         Flag2 : Boolean := False;
+         --  This flag is significant only for:
+         --    N_Project - it indicates that the project "extends all" another
+         --                project.
+         --    N_Comment - it indicates that the comment is followed by an
+         --                empty line.
+         --    N_With_Clause
+         --              - it indicates that the originally imported project
+         --                is an extending all project.
+
+         Comments : Project_Node_Id := Empty_Node;
+         --  For nodes other that N_Comment_Zones or N_Comment, designates the
+         --  comment zones associated with the node.
+         --  for N_Comment_Zones, designates the comment after the "end" of
+         --  the construct.
+         --  For N_Comment, designates the next comment, if any.
 
       end record;
 
@@ -862,7 +1156,7 @@ package Prj.Tree is
       --    --  Field3:    not used
       --    --  Value:     not used
 
-      --    N_Case_Item);
+      --    N_Case_Item
       --    --  Name:      not used
       --    --  Path_Name: not used
       --    --  Expr_Kind: not used
@@ -872,13 +1166,35 @@ package Prj.Tree is
       --    --  Field3:    next case item
       --    --  Value:     not used
 
-      package Project_Nodes is
-         new Table.Table (Table_Component_Type => Project_Node_Record,
-                          Table_Index_Type     => Project_Node_Id,
-                          Table_Low_Bound      => First_Node_Id,
-                          Table_Initial        => Project_Nodes_Initial,
-                          Table_Increment      => Project_Nodes_Increment,
-                          Table_Name           => "Project_Nodes");
+      --    N_Comment_zones
+      --    --  Name:      not used
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: not used
+      --    --  Field1:    comment before the construct
+      --    --  Field2:    comment after the construct
+      --    --  Field3:    comment before the "end" of the construct
+      --    --  Value:     end of line comment
+      --    --  Comments:  comment after the "end" of the construct
+
+      --    N_Comment
+      --    --  Name:      not used
+      --    --  Path_Name: not used
+      --    --  Expr_Kind: not used
+      --    --  Field1:    not used
+      --    --  Field2:    not used
+      --    --  Field3:    not used
+      --    --  Value:     comment
+      --    --  Flag1:     comment is preceded by an empty line
+      --    --  Flag2:     comment is followed by an empty line
+      --    --  Comments:  next comment
+
+      package Project_Node_Table is
+        new GNAT.Dynamic_Tables
+          (Table_Component_Type => Project_Node_Record,
+           Table_Index_Type     => Project_Node_Id,
+           Table_Low_Bound      => First_Node_Id,
+           Table_Initial        => Project_Nodes_Initial,
+           Table_Increment      => Project_Nodes_Increment);
       --  This table contains the syntactic tree of project data
       --  from project files.
 
@@ -889,14 +1205,20 @@ package Prj.Tree is
          Node : Project_Node_Id;
          --  Node of the project in table Project_Nodes
 
+         Canonical_Path : Path_Name_Type;
+         --  Resolved and canonical path of the project file
+
          Extended : Boolean;
          --  True when the project is being extended by another project
       end record;
 
       No_Project_Name_And_Node : constant Project_Name_And_Node :=
-        (Name => No_Name, Node => Empty_Node, Extended => True);
+        (Name           => No_Name,
+         Node           => Empty_Node,
+         Canonical_Path => No_Path,
+         Extended       => True);
 
-      package Projects_Htable is new GNAT.HTable.Simple_HTable
+      package Projects_Htable is new GNAT.Dynamic_HTables.Simple_HTable
         (Header_Num => Header_Num,
          Element    => Project_Name_And_Node,
          No_Element => No_Project_Name_And_Node,
@@ -905,10 +1227,31 @@ package Prj.Tree is
          Equal      => "=");
       --  This hash table contains a mapping of project names to project nodes.
       --  Note that this hash table contains only the nodes whose Kind is
-      --  N_Project. It is used to find the node of a project from its
-      --  name, and to verify if a project has already been parsed, knowing
-      --  its name.
+      --  N_Project. It is used to find the node of a project from its name,
+      --  and to verify if a project has already been parsed, knowing its name.
 
    end Tree_Private_Part;
 
+   type Project_Node_Tree_Data is record
+      Project_Nodes : Tree_Private_Part.Project_Node_Table.Instance;
+      Projects_HT   : Tree_Private_Part.Projects_Htable.Instance;
+   end record;
+   --  The data for a project node tree
+
+private
+   type Comment_Array is array (Positive range <>) of Comment_Data;
+   type Comments_Ptr is access Comment_Array;
+
+   type Comment_State is record
+      End_Of_Line_Node   : Project_Node_Id := Empty_Node;
+
+      Previous_Line_Node : Project_Node_Id := Empty_Node;
+
+      Previous_End_Node  : Project_Node_Id := Empty_Node;
+
+      Unkept_Comments    : Boolean := False;
+
+      Comments           : Comments_Ptr := null;
+   end record;
+
 end Prj.Tree;