OSDN Git Service

PR ada/52494
[pf3gnuchains/gcc-fork.git] / gcc / ada / gnatcmd.adb
index 291d6aa..8798399 100644 (file)
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---          Copyright (C) 1996-2007, Free Software Foundation, Inc.         --
+--          Copyright (C) 1996-2012, 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- --
 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
 
 with Csets;
+with Hostparm; use Hostparm;
+with Makeutl;  use Makeutl;
 with MLib.Tgt; use MLib.Tgt;
 with MLib.Utl;
 with MLib.Fil;
 with Namet;    use Namet;
 with Opt;      use Opt;
 with Osint;    use Osint;
-with Output;
+with Output;   use Output;
 with Prj;      use Prj;
 with Prj.Env;
 with Prj.Ext;  use Prj.Ext;
 with Prj.Pars;
+with Prj.Tree; use Prj.Tree;
 with Prj.Util; use Prj.Util;
+with Sdefault;
 with Sinput.P;
 with Snames;   use Snames;
 with Table;
+with Targparm;
 with Tempdir;
 with Types;    use Types;
-with Hostparm; use Hostparm;
---  Used to determine if we are in VMS or not for error message purposes
+with VMS_Conv; use VMS_Conv;
+with VMS_Cmds; use VMS_Cmds;
 
 with Ada.Characters.Handling; use Ada.Characters.Handling;
 with Ada.Command_Line;        use Ada.Command_Line;
 with Ada.Text_IO;             use Ada.Text_IO;
 
-with GNAT.OS_Lib;             use GNAT.OS_Lib;
-
-with VMS_Conv;                use VMS_Conv;
+with GNAT.OS_Lib; use GNAT.OS_Lib;
 
 procedure GNATCmd is
-   Project_Tree      : constant Project_Tree_Ref := new Project_Tree_Data;
+   Project_Node_Tree : Project_Node_Tree_Ref;
+   Root_Environment  : Prj.Tree.Environment;
    Project_File      : String_Access;
    Project           : Prj.Project_Id;
    Current_Verbosity : Prj.Verbosity := Prj.Default;
@@ -64,17 +68,18 @@ procedure GNATCmd is
    B_Start : String_Ptr    := new String'("b~");
    --  Prefix of binder generated file, changed to b__ for VMS
 
+   Project_Tree : constant Project_Tree_Ref :=
+                    new Project_Tree_Data (Is_Root_Tree => True);
+   --  The project tree
+
    Old_Project_File_Used : Boolean := False;
    --  This flag indicates a switch -p (for gnatxref and gnatfind) for
-   --  an old fashioned project file. -p cannot be used in conjonction
+   --  an old fashioned project file. -p cannot be used in conjunction
    --  with -P.
 
-   Max_Files_On_The_Command_Line : constant := 30; --  Arbitrary
-
-   Temp_File_Name : String_Access := null;
+   Temp_File_Name : Path_Name_Type := No_Path;
    --  The name of the temporary text file to put a list of source/object
-   --  files to pass to a tool, when there are more than
-   --  Max_Files_On_The_Command_Line files.
+   --  files to pass to a tool.
 
    ASIS_Main : String_Access := null;
    --  Main for commands Check, Metric and Pretty, when -U is used
@@ -118,25 +123,33 @@ procedure GNATCmd is
    --  tool. We allocate objects because we cannot declare aliased objects
    --  as we are in a procedure, not a library level package.
 
-   Naming_String    : constant String_Access := new String'("naming");
-   Binder_String    : constant String_Access := new String'("binder");
-   Compiler_String  : constant String_Access := new String'("compiler");
-   Check_String     : constant String_Access := new String'("check");
-   Eliminate_String : constant String_Access := new String'("eliminate");
-   Finder_String    : constant String_Access := new String'("finder");
-   Linker_String    : constant String_Access := new String'("linker");
-   Gnatls_String    : constant String_Access := new String'("gnatls");
-   Pretty_String    : constant String_Access := new String'("pretty_printer");
-   Stack_String     : constant String_Access := new String'("stack");
-   Gnatstub_String  : constant String_Access := new String'("gnatstub");
-   Metric_String    : constant String_Access := new String'("metrics");
-   Xref_String      : constant String_Access := new String'("cross_reference");
+   subtype SA is String_Access;
+
+   Naming_String      : constant SA := new String'("naming");
+   Binder_String      : constant SA := new String'("binder");
+   Builder_String     : constant SA := new String'("builder");
+   Compiler_String    : constant SA := new String'("compiler");
+   Check_String       : constant SA := new String'("check");
+   Synchronize_String : constant SA := new String'("synchronize");
+   Eliminate_String   : constant SA := new String'("eliminate");
+   Finder_String      : constant SA := new String'("finder");
+   Linker_String      : constant SA := new String'("linker");
+   Gnatls_String      : constant SA := new String'("gnatls");
+   Pretty_String      : constant SA := new String'("pretty_printer");
+   Stack_String       : constant SA := new String'("stack");
+   Gnatstub_String    : constant SA := new String'("gnatstub");
+   Metric_String      : constant SA := new String'("metrics");
+   Xref_String        : constant SA := new String'("cross_reference");
 
    Packages_To_Check_By_Binder   : constant String_List_Access :=
      new String_List'((Naming_String, Binder_String));
 
    Packages_To_Check_By_Check : constant String_List_Access :=
-     new String_List'((Naming_String, Check_String, Compiler_String));
+     new String_List'
+          ((Naming_String, Builder_String, Check_String, Compiler_String));
+
+   Packages_To_Check_By_Sync : constant String_List_Access :=
+     new String_List'((Naming_String, Synchronize_String, Compiler_String));
 
    Packages_To_Check_By_Eliminate : constant String_List_Access :=
      new String_List'((Naming_String, Eliminate_String, Compiler_String));
@@ -189,6 +202,9 @@ procedure GNATCmd is
    --  indicate that the underlying tool (gnatcheck, gnatpp or gnatmetric)
    --  should be invoked for all sources of all projects.
 
+   Max_OpenVMS_Logical_Length : constant Integer := 255;
+   --  The maximum length of OpenVMS logicals
+
    -----------------------
    -- Local Subprograms --
    -----------------------
@@ -203,9 +219,9 @@ procedure GNATCmd is
 
    procedure Check_Files;
    --  For GNAT LIST, GNAT PRETTY, GNAT METRIC, and GNAT STACK, check if a
-   --  project file is specified, without any file arguments. If it is the
-   --  case, invoke the GNAT tool with the proper list of files, derived from
-   --  the sources of the project.
+   --  project file is specified, without any file arguments and without a
+   --  switch -files=. If it is the case, invoke the GNAT tool with the proper
+   --  list of files, derived from the sources of the project.
 
    function Check_Project
      (Project      : Project_Id;
@@ -226,16 +242,19 @@ procedure GNATCmd is
    --  STUB), gnatpp (GNAT PRETTY), gnatelim (GNAT ELIM), and gnatmetric (GNAT
    --  METRIC).
 
+   function Mapping_File return Path_Name_Type;
+   --  Create and return the path name of a mapping file. Used for gnatstub
+   --  (GNAT STUB), gnatpp (GNAT PRETTY), gnatelim (GNAT ELIM), and gnatmetric
+   --  (GNAT METRIC).
+
    procedure Delete_Temp_Config_Files;
-   --  Delete all temporary config files
+   --  Delete all temporary config files. The caller is responsible for
+   --  ensuring that Keep_Temporary_Files is False.
 
    procedure Get_Closure;
    --  Get the sources in the closure of the ASIS_Main and add them to the
    --  list of arguments.
 
-   function Index (Char : Character; Str : String) return Natural;
-   --  Returns first occurrence of Char in Str, returns 0 if Char not in Str
-
    procedure Non_VMS_Usage;
    --  Display usage for platforms other than VMS
 
@@ -243,8 +262,9 @@ procedure GNATCmd is
    --  Process GNAT LINK, when there is a project file specified
 
    procedure Set_Library_For
-     (Project             : Project_Id;
-      There_Are_Libraries : in out Boolean);
+     (Project           : Project_Id;
+      Tree              : Project_Tree_Ref;
+      Libraries_Present : in out Boolean);
    --  If Project is a library project, add the correct -L and -l switches to
    --  the linker invocation.
 
@@ -300,127 +320,236 @@ procedure GNATCmd is
 
    procedure Check_Files is
       Add_Sources : Boolean := True;
-      Unit_Data   : Prj.Unit_Data;
+      Unit        : Prj.Unit_Index;
       Subunit     : Boolean := False;
+      FD          : File_Descriptor := Invalid_FD;
+      Status      : Integer;
+      Success     : Boolean;
+
+      procedure Add_To_Response_File
+        (File_Name  : String;
+         Check_File : Boolean := True);
+      --  Include the file name passed as parameter in the response file for
+      --  the tool being called. If the response file can not be written then
+      --  the file name is passed in the parameter list of the tool. If the
+      --  Check_File parameter is True then the procedure verifies the
+      --  existence of the file before adding it to the response file.
+
+      --------------------------
+      -- Add_To_Response_File --
+      --------------------------
+
+      procedure Add_To_Response_File
+        (File_Name  : String;
+         Check_File : Boolean := True)
+      is
+      begin
+         Name_Len := 0;
+
+         Add_Str_To_Name_Buffer (File_Name);
+
+         if not Check_File or else
+           Is_Regular_File (Name_Buffer (1 .. Name_Len))
+         then
+            if FD /= Invalid_FD then
+               Name_Len := Name_Len + 1;
+               Name_Buffer (Name_Len) := ASCII.LF;
+
+               Status := Write (FD, Name_Buffer (1)'Address, Name_Len);
+
+               if Status /= Name_Len then
+                  Osint.Fail ("disk full");
+               end if;
+            else
+               Last_Switches.Increment_Last;
+               Last_Switches.Table (Last_Switches.Last) :=
+                 new String'(File_Name);
+            end if;
+         end if;
+      end Add_To_Response_File;
+
+   --  Start of processing for Check_Files
 
    begin
-      --  Check if there is at least one argument that is not a switch
+      --  Check if there is at least one argument that is not a switch or if
+      --  there is a -files= switch.
 
       for Index in 1 .. Last_Switches.Last loop
-         if Last_Switches.Table (Index) (1) /= '-' then
+         if Last_Switches.Table (Index).all'Length > 7
+           and then Last_Switches.Table (Index) (1 .. 7) = "-files="
+         then
             Add_Sources := False;
             exit;
+
+         elsif Last_Switches.Table (Index) (1) /= '-' then
+            if Index = 1
+              or else
+                (The_Command = Check
+                   and then Last_Switches.Table (Index - 1).all /= "-o")
+              or else
+                (The_Command = Pretty
+                   and then Last_Switches.Table (Index - 1).all /= "-o"
+                   and then Last_Switches.Table (Index - 1).all /= "-of")
+              or else
+                (The_Command = Metric
+                   and then
+                     Last_Switches.Table (Index - 1).all /= "-o"  and then
+                     Last_Switches.Table (Index - 1).all /= "-og" and then
+                     Last_Switches.Table (Index - 1).all /= "-ox" and then
+                     Last_Switches.Table (Index - 1).all /= "-d")
+              or else
+                (The_Command /= Check  and then
+                 The_Command /= Pretty and then
+                 The_Command /= Metric)
+            then
+               Add_Sources := False;
+               exit;
+            end if;
          end if;
       end loop;
 
-      --  If all arguments were switches, add the path names of all the sources
-      --  of the main project.
+      --  If all arguments are switches and there is no switch -files=, add
+      --  the path names of all the sources of the main project.
 
       if Add_Sources then
+
+         --  For gnatcheck, gnatpp, and gnatmetric, create a temporary file
+         --  and put the list of sources in it. For gnatstack create a
+         --  temporary file with the list of .ci files.
+
+         if The_Command = Check  or else
+            The_Command = Pretty or else
+            The_Command = Metric or else
+            The_Command = Stack
+         then
+            Tempdir.Create_Temp_File (FD, Temp_File_Name);
+            Last_Switches.Increment_Last;
+            Last_Switches.Table (Last_Switches.Last) :=
+              new String'("-files=" & Get_Name_String (Temp_File_Name));
+         end if;
+
          declare
-            Current_Last : constant Integer := Last_Switches.Last;
+            Proj : Project_List;
+
          begin
-            --  Gnatstack needs to add the the .ci file for the binder
-            --  generated files corresponding to all of the library projects
-            --  and main units belonging to the application.
+            --  Gnatstack needs to add the .ci file for the binder generated
+            --  files corresponding to all of the library projects and main
+            --  units belonging to the application.
 
             if The_Command = Stack then
-               for Proj in Project_Table.First ..
-                           Project_Table.Last (Project_Tree.Projects)
-               loop
-                  if Check_Project (Proj, Project) then
+               Proj := Project_Tree.Projects;
+               while Proj /= null loop
+                  if Check_Project (Proj.Project, Project) then
                      declare
-                        Data : Project_Data renames
-                                 Project_Tree.Projects.Table (Proj);
-                        Main : String_List_Id := Data.Mains;
-                        File : String_Access;
+                        Main : String_List_Id;
 
                      begin
                         --  Include binder generated files for main programs
 
+                        Main := Proj.Project.Mains;
                         while Main /= Nil_String loop
-                           File :=
-                             new String'
-                               (Get_Name_String (Data.Object_Directory) &
-                                Directory_Separator                     &
-                                B_Start.all                             &
-                                MLib.Fil.Ext_To
-                                  (Get_Name_String
-                                     (Project_Tree.String_Elements.Table
-                                        (Main).Value),
-                                   "ci"));
-
-                           if Is_Regular_File (File.all) then
-                              Last_Switches.Increment_Last;
-                              Last_Switches.Table (Last_Switches.Last) := File;
+                           Add_To_Response_File
+                             (Get_Name_String
+                                (Proj.Project.Object_Directory.Name) &
+                              B_Start.all                            &
+                              MLib.Fil.Ext_To
+                                (Get_Name_String
+                                   (Project_Tree.Shared.String_Elements.Table
+                                      (Main).Value),
+                                 "ci"));
+
+                           --  When looking for the .ci file for a binder
+                           --  generated file, look for both b~xxx and b__xxx
+                           --  as gprbuild always uses b__ as the prefix of
+                           --  such files.
+
+                           if not Is_Regular_File (Name_Buffer (1 .. Name_Len))
+                             and then B_Start.all /= "b__"
+                           then
+                              Add_To_Response_File
+                                (Get_Name_String
+                                   (Proj.Project.Object_Directory.Name) &
+                                 "b__"                                  &
+                                 MLib.Fil.Ext_To
+                                   (Get_Name_String
+                                      (Project_Tree.Shared
+                                       .String_Elements.Table (Main).Value),
+                                    "ci"));
                            end if;
 
-                           Main :=
-                             Project_Tree.String_Elements.Table (Main).Next;
+                           Main := Project_Tree.Shared.String_Elements.Table
+                                     (Main).Next;
                         end loop;
 
-                        if Data.Library then
+                        if Proj.Project.Library then
 
                            --  Include the .ci file for the binder generated
                            --  files that contains the initialization and
                            --  finalization of the library.
 
-                           File :=
-                             new String'
-                               (Get_Name_String (Data.Object_Directory) &
-                                Directory_Separator                     &
-                                B_Start.all                             &
-                                Get_Name_String (Data.Library_Name)     &
-                                ".ci");
-
-                           if Is_Regular_File (File.all) then
-                              Last_Switches.Increment_Last;
-                              Last_Switches.Table (Last_Switches.Last) := File;
+                           Add_To_Response_File
+                             (Get_Name_String
+                                (Proj.Project.Object_Directory.Name)      &
+                              B_Start.all                                 &
+                              Get_Name_String (Proj.Project.Library_Name) &
+                              ".ci");
+
+                           --  When looking for the .ci file for a binder
+                           --  generated file, look for both b~xxx and b__xxx
+                           --  as gprbuild always uses b__ as the prefix of
+                           --  such files.
+
+                           if not Is_Regular_File (Name_Buffer (1 .. Name_Len))
+                               and then B_Start.all /= "b__"
+                           then
+                              Add_To_Response_File
+                                (Get_Name_String
+                                   (Proj.Project.Object_Directory.Name)      &
+                                 "b__"                                       &
+                                 Get_Name_String (Proj.Project.Library_Name) &
+                                 ".ci");
                            end if;
                         end if;
                      end;
                   end if;
+
+                  Proj := Proj.Next;
                end loop;
             end if;
 
-            for Unit in Unit_Table.First ..
-                        Unit_Table.Last (Project_Tree.Units)
-            loop
-               Unit_Data := Project_Tree.Units.Table (Unit);
+            Unit := Units_Htable.Get_First (Project_Tree.Units_HT);
+            while Unit /= No_Unit_Index loop
 
                --  For gnatls, we only need to put the library units, body or
                --  spec, but not the subunits.
 
                if The_Command = List then
-                  if
-                    Unit_Data.File_Names (Body_Part).Name /= No_File
+                  if Unit.File_Names (Impl) /= null
+                    and then not Unit.File_Names (Impl).Locally_Removed
                   then
                      --  There is a body, check if it is for this project
 
-                     if All_Projects or else
-                        Unit_Data.File_Names (Body_Part).Project = Project
+                     if All_Projects
+                       or else Unit.File_Names (Impl).Project = Project
                      then
                         Subunit := False;
 
-                        if
-                          Unit_Data.File_Names (Specification).Name = No_File
+                        if Unit.File_Names (Spec) = null
+                          or else Unit.File_Names (Spec).Locally_Removed
                         then
                            --  We have a body with no spec: we need to check if
                            --  this is a subunit, because gnatls will complain
                            --  about subunits.
 
                            declare
-                              Src_Ind : Source_File_Index;
-
+                              Src_Ind : constant Source_File_Index :=
+                                          Sinput.P.Load_Project_File
+                                            (Get_Name_String
+                                              (Unit.File_Names
+                                                (Impl).Path.Name));
                            begin
-                              Src_Ind := Sinput.P.Load_Project_File
-                                (Get_Name_String
-                                   (Unit_Data.File_Names
-                                      (Body_Part).Path));
-
                               Subunit :=
-                                Sinput.P.Source_File_Is_Subunit
-                                  (Src_Ind);
+                                Sinput.P.Source_File_Is_Subunit (Src_Ind);
                            end;
                         end if;
 
@@ -429,26 +558,24 @@ procedure GNATCmd is
                            Last_Switches.Table (Last_Switches.Last) :=
                              new String'
                                (Get_Name_String
-                                    (Unit_Data.File_Names
-                                         (Body_Part).Display_Name));
+                                    (Unit.File_Names
+                                         (Impl).Display_File));
                         end if;
                      end if;
 
-                  elsif
-                    Unit_Data.File_Names (Specification).Name /= No_File
+                  elsif Unit.File_Names (Spec) /= null
+                    and then not Unit.File_Names (Spec).Locally_Removed
                   then
-                     --  We have a spec with no body; check if it is for this
+                     --  We have a spec with no body. Check if it is for this
                      --  project.
 
                      if All_Projects or else
-                        Unit_Data.File_Names (Specification).Project = Project
+                        Unit.File_Names (Spec).Project = Project
                      then
                         Last_Switches.Increment_Last;
                         Last_Switches.Table (Last_Switches.Last) :=
-                          new String'
-                            (Get_Name_String
-                                 (Unit_Data.File_Names
-                                      (Specification).Display_Name));
+                          new String'(Get_Name_String
+                                       (Unit.File_Names (Spec).Display_File));
                      end if;
                   end if;
 
@@ -458,160 +585,99 @@ procedure GNATCmd is
                --  but not the subunits.
 
                elsif The_Command = Stack then
-                  if
-                    Unit_Data.File_Names (Body_Part).Name /= No_File
+                  if Unit.File_Names (Impl) /= null
+                    and then not Unit.File_Names (Impl).Locally_Removed
                   then
                      --  There is a body. Check if .ci files for this project
                      --  must be added.
 
-                     if
-                       Check_Project
-                         (Unit_Data.File_Names (Body_Part).Project, Project)
+                     if Check_Project
+                          (Unit.File_Names (Impl).Project, Project)
                      then
                         Subunit := False;
 
-                        if
-                          Unit_Data.File_Names (Specification).Name = No_File
+                        if Unit.File_Names (Spec) = null
+                          or else Unit.File_Names (Spec).Locally_Removed
                         then
                            --  We have a body with no spec: we need to check
                            --  if this is a subunit, because .ci files are not
                            --  generated for subunits.
 
                            declare
-                              Src_Ind : Source_File_Index;
-
+                              Src_Ind : constant Source_File_Index :=
+                                          Sinput.P.Load_Project_File
+                                            (Get_Name_String
+                                              (Unit.File_Names
+                                                (Impl).Path.Name));
                            begin
-                              Src_Ind := Sinput.P.Load_Project_File
-                                (Get_Name_String
-                                   (Unit_Data.File_Names (Body_Part).Path));
-
                               Subunit :=
                                 Sinput.P.Source_File_Is_Subunit (Src_Ind);
                            end;
                         end if;
 
                         if not Subunit then
-                           Last_Switches.Increment_Last;
-                           Last_Switches.Table (Last_Switches.Last) :=
-                             new String'
-                               (Get_Name_String
-                                    (Project_Tree.Projects.Table
-                                         (Unit_Data.File_Names
-                                              (Body_Part).Project).
-                                         Object_Directory)           &
-                                Directory_Separator                  &
-                                MLib.Fil.Ext_To
-                                  (Get_Name_String
-                                     (Unit_Data.File_Names
-                                        (Body_Part).Display_Name),
-                                   "ci"));
+                           Add_To_Response_File
+                             (Get_Name_String
+                                (Unit.File_Names
+                                   (Impl).Project. Object_Directory.Name) &
+                              MLib.Fil.Ext_To
+                                (Get_Name_String
+                                   (Unit.File_Names (Impl).Display_File),
+                                 "ci"));
                         end if;
                      end if;
 
-                  elsif
-                    Unit_Data.File_Names (Specification).Name /= No_File
+                  elsif Unit.File_Names (Spec) /= null
+                    and then not Unit.File_Names (Spec).Locally_Removed
                   then
-                     --  We have a spec with no body. Check if it is for this
-                     --  project.
+                     --  Spec with no body, check if it is for this project
 
-                     if
-                       Check_Project
-                         (Unit_Data.File_Names (Specification).Project,
-                          Project)
+                     if Check_Project
+                          (Unit.File_Names (Spec).Project, Project)
                      then
-                        Last_Switches.Increment_Last;
-                        Last_Switches.Table (Last_Switches.Last) :=
-                          new String'
-                            (Get_Name_String
-                                 (Project_Tree.Projects.Table
-                                      (Unit_Data.File_Names
-                                           (Specification).Project).
-                                      Object_Directory)              &
-                             Dir_Separator                           &
-                             MLib.Fil.Ext_To
-                               (Get_Name_String
-                                  (Unit_Data.File_Names
-                                     (Specification).Name),
-                                "ci"));
+                        Add_To_Response_File
+                          (Get_Name_String
+                             (Unit.File_Names
+                                (Spec).Project. Object_Directory.Name) &
+                           Dir_Separator                               &
+                           MLib.Fil.Ext_To
+                             (Get_Name_String (Unit.File_Names (Spec).File),
+                              "ci"));
                      end if;
                   end if;
 
                else
-                  --  For gnatcheck, gnatpp and gnatmetric, put all sources
-                  --  of the project, or of all projects if -U was specified.
+                  --  For gnatcheck, gnatsync, gnatpp and gnatmetric, put all
+                  --  sources of the project, or of all projects if -U was
+                  --  specified.
 
                   for Kind in Spec_Or_Body loop
-
-                     --  Put only sources that belong to the main project
-
-                     if Check_Project
-                          (Unit_Data.File_Names (Kind).Project, Project)
+                     if Unit.File_Names (Kind) /= null
+                       and then Check_Project
+                                  (Unit.File_Names (Kind).Project, Project)
+                       and then not Unit.File_Names (Kind).Locally_Removed
                      then
-                        Last_Switches.Increment_Last;
-                        Last_Switches.Table (Last_Switches.Last) :=
-                          new String'
-                            (Get_Name_String
-                                 (Unit_Data.File_Names
-                                      (Kind).Display_Path));
+                        Add_To_Response_File
+                          (""""                                         &
+                           Get_Name_String
+                             (Unit.File_Names (Kind).Path.Display_Name) &
+                           """",
+                           Check_File => False);
                      end if;
                   end loop;
                end if;
-            end loop;
 
-            --  If the list of files is too long, create a temporary text file
-            --  that lists these files, and pass this temp file to gnatcheck,
-            --  gnatpp or gnatmetric using switch -files=.
-
-            if Last_Switches.Last - Current_Last >
-              Max_Files_On_The_Command_Line
-            then
-               declare
-                  Temp_File_FD : File_Descriptor;
-                  Buffer       : String (1 .. 1_000);
-                  Len          : Natural;
-                  OK           : Boolean := True;
-
-               begin
-                  Create_Temp_File (Temp_File_FD, Temp_File_Name);
-
-                  if Temp_File_Name /= null then
-                     for Index in Current_Last + 1 ..
-                       Last_Switches.Last
-                     loop
-                        Len := Last_Switches.Table (Index)'Length;
-                        Buffer (1 .. Len) := Last_Switches.Table (Index).all;
-                        Len := Len + 1;
-                        Buffer (Len) := ASCII.LF;
-                        Buffer (Len + 1) := ASCII.NUL;
-                        OK :=
-                          Write (Temp_File_FD,
-                                 Buffer (1)'Address,
-                                 Len) = Len;
-                        exit when not OK;
-                     end loop;
-
-                     if OK then
-                        Close (Temp_File_FD, OK);
-                     else
-                        Close (Temp_File_FD, OK);
-                        OK := False;
-                     end if;
-
-                     --  If there were any problem creating the temp file, then
-                     --  pass the list of files.
-
-                     if OK then
+               Unit := Units_Htable.Get_Next (Project_Tree.Units_HT);
+            end loop;
+         end;
 
-                        --  Replace list of files with -files=<temp file name>
+         if FD /= Invalid_FD then
+            Close (FD, Success);
 
-                        Last_Switches.Set_Last (Current_Last + 1);
-                        Last_Switches.Table (Last_Switches.Last) :=
-                          new String'("-files=" & Temp_File_Name.all);
-                     end if;
-                  end if;
-               end;
+            if not Success then
+               Osint.Fail ("disk full");
             end if;
-         end;
+         end if;
       end if;
    end Check_Files;
 
@@ -623,27 +689,24 @@ procedure GNATCmd is
      (Project      : Project_Id;
       Root_Project : Project_Id) return Boolean
    is
+      Proj : Project_Id;
+
    begin
       if Project = No_Project then
          return False;
 
-      elsif All_Projects or Project = Root_Project then
+      elsif All_Projects or else Project = Root_Project then
          return True;
 
       elsif The_Command = Metric then
-         declare
-            Data : Project_Data;
-
-         begin
-            Data := Project_Tree.Projects.Table (Root_Project);
-            while Data.Extends /= No_Project loop
-               if Project = Data.Extends then
-                  return True;
-               end if;
+         Proj := Root_Project;
+         while Proj.Extends /= No_Project loop
+            if Project = Proj.Extends then
+               return True;
+            end if;
 
-               Data := Project_Tree.Projects.Table (Data.Extends);
-            end loop;
-         end;
+            Proj := Proj.Extends;
+         end loop;
       end if;
 
       return False;
@@ -667,8 +730,7 @@ procedure GNATCmd is
             end if;
          end loop;
 
-         Get_Name_String (Project_Tree.Projects.Table
-                            (Project).Exec_Directory);
+         Get_Name_String (Project.Exec_Directory.Name);
 
          if Name_Buffer (Name_Len) /= Directory_Separator then
             Name_Len := Name_Len + 1;
@@ -689,9 +751,8 @@ procedure GNATCmd is
 
    function Configuration_Pragmas_File return Path_Name_Type is
    begin
-      Prj.Env.Create_Config_Pragmas_File
-        (Project, Project, Project_Tree, Include_Config_Files => False);
-      return Project_Tree.Projects.Table (Project).Config_File_Name;
+      Prj.Env.Create_Config_Pragmas_File (Project, Project_Tree);
+      return Project.Config_File_Name;
    end Configuration_Pragmas_File;
 
    ------------------------------
@@ -700,40 +761,31 @@ procedure GNATCmd is
 
    procedure Delete_Temp_Config_Files is
       Success : Boolean;
+      Proj    : Project_List;
+      pragma Warnings (Off, Success);
 
    begin
-      if not Keep_Temporary_Files then
-         if Project /= No_Project then
-            for Prj in Project_Table.First ..
-                       Project_Table.Last (Project_Tree.Projects)
-            loop
-               if
-                 Project_Tree.Projects.Table (Prj).Config_File_Temp
-               then
-                  if Verbose_Mode then
-                     Output.Write_Str ("Deleting temp configuration file """);
-                     Output.Write_Str
-                       (Get_Name_String
-                          (Project_Tree.Projects.Table
-                             (Prj).Config_File_Name));
-                     Output.Write_Line ("""");
-                  end if;
+      --  This should only be called if Keep_Temporary_Files is False
 
-                  Delete_File
-                    (Name    => Get_Name_String
-                       (Project_Tree.Projects.Table
-                          (Prj).Config_File_Name),
-                     Success => Success);
-               end if;
-            end loop;
-         end if;
+      pragma Assert (not Keep_Temporary_Files);
 
-         --  If a temporary text file that contains a list of files for a tool
-         --  has been created, delete this temporary file.
+      if Project /= No_Project then
+         Proj := Project_Tree.Projects;
+         while Proj /= null loop
+            if Proj.Project.Config_File_Temp then
+               Delete_Temporary_File
+                 (Project_Tree.Shared, Proj.Project.Config_File_Name);
+            end if;
 
-         if Temp_File_Name /= null then
-            Delete_File (Temp_File_Name.all, Success);
-         end if;
+            Proj := Proj.Next;
+         end loop;
+      end if;
+
+      --  If a temporary text file that contains a list of files for a tool
+      --  has been created, delete this temporary file.
+
+      if Temp_File_Name /= No_Path then
+         Delete_Temporary_File (Project_Tree.Shared, Temp_File_Name);
       end if;
    end Delete_Temp_Config_Files;
 
@@ -751,7 +803,8 @@ procedure GNATCmd is
                 6 => new String'("-bargs"),
                 7 => new String'("-R"),
                 8 => new String'("-Z"));
-      --  Arguments of the invocation of gnatmake to get the list of
+      --  Arguments for the invocation of gnatmake which are added to the
+      --  Last_Arguments list by this procedure.
 
       FD : File_Descriptor;
       --  File descriptor for the temp file that will get the output of the
@@ -760,7 +813,7 @@ procedure GNATCmd is
       Name : Path_Name_Type;
       --  Path of the file FD
 
-      GN_Name : constant String := Program_Name ("gnatmake").all;
+      GN_Name : constant String := Program_Name ("gnatmake", "gnat").all;
       --  Name for gnatmake
 
       GN_Path : constant String_Access := Locate_Exec_On_Path (GN_Name);
@@ -774,8 +827,10 @@ procedure GNATCmd is
       File : Ada.Text_IO.File_Type;
       Line : String (1 .. 250);
       Last : Natural;
+      --  Used to read file if there is an error, it is good enough to display
+      --  just 250 characters if the first line of the file is very long.
 
-      Udata : Unit_Data;
+      Unit  : Unit_Index;
       Path  : Path_Name_Type;
 
    begin
@@ -803,8 +858,6 @@ procedure GNATCmd is
          Return_Code  => Return_Code,
          Err_To_Out   => True);
 
-      Close (FD);
-
       --  Read the output of the invocation of gnatmake
 
       Open (File, In_File, Get_Name_String (Name));
@@ -815,11 +868,20 @@ procedure GNATCmd is
       if Return_Code /= 0 then
          Get_Line (File, Line, Last);
 
-         if not Keep_Temporary_Files then
-            Delete (File);
-         else
-            Close (File);
-         end if;
+         begin
+            if not Keep_Temporary_Files then
+               Delete (File);
+            else
+               Close (File);
+            end if;
+
+         --  Don't crash if it is not possible to delete or close the file,
+         --  just ignore the situation.
+
+         exception
+            when others =>
+               null;
+         end;
 
          Put_Line (Standard_Error, Line (1 .. Last));
          Put_Line
@@ -827,34 +889,33 @@ procedure GNATCmd is
          raise Error_Exit;
 
       else
-         --  Get each file name in the file, find its path and add it the the
+         --  Get each file name in the file, find its path and add it the
          --  list of arguments.
 
          while not End_Of_File (File) loop
             Get_Line (File, Line, Last);
             Path := No_Path;
 
-            for Unit in Unit_Table.First ..
-                        Unit_Table.Last (Project_Tree.Units)
-            loop
-               Udata := Project_Tree.Units.Table (Unit);
-
-               if Udata.File_Names (Specification).Name /= No_File
+            Unit := Units_Htable.Get_First (Project_Tree.Units_HT);
+            while Unit /= No_Unit_Index loop
+               if Unit.File_Names (Spec) /= null
                  and then
-                   Get_Name_String (Udata.File_Names (Specification).Name) =
+                   Get_Name_String (Unit.File_Names (Spec).File) =
                       Line (1 .. Last)
                then
-                  Path := Udata.File_Names (Specification).Path;
+                  Path := Unit.File_Names (Spec).Path.Name;
                   exit;
 
-               elsif Udata.File_Names (Body_Part).Name /= No_File
+               elsif Unit.File_Names (Impl) /= null
                  and then
-                   Get_Name_String (Udata.File_Names (Body_Part).Name) =
+                   Get_Name_String (Unit.File_Names (Impl).File) =
                      Line (1 .. Last)
                then
-                  Path := Udata.File_Names (Body_Part).Path;
+                  Path := Unit.File_Names (Impl).Path.Name;
                   exit;
                end if;
+
+               Unit := Units_Htable.Get_Next (Project_Tree.Units_HT);
             end loop;
 
             Last_Switches.Increment_Last;
@@ -869,29 +930,37 @@ procedure GNATCmd is
             end if;
          end loop;
 
-         if not Keep_Temporary_Files then
-            Delete (File);
+         begin
+            if not Keep_Temporary_Files then
+               Delete (File);
+            else
+               Close (File);
+            end if;
+
+         --  Don't crash if it is not possible to delete or close the file,
+         --  just ignore the situation.
 
-         else
-            Close (File);
-         end if;
+         exception
+            when others =>
+               null;
+         end;
       end if;
    end Get_Closure;
 
-   -----------
-   -- Index --
-   -----------
+   ------------------
+   -- Mapping_File --
+   ------------------
 
-   function Index (Char : Character; Str : String) return Natural is
+   function Mapping_File return Path_Name_Type is
+      Result : Path_Name_Type;
    begin
-      for Index in Str'Range loop
-         if Str (Index) = Char then
-            return Index;
-         end if;
-      end loop;
-
-      return 0;
-   end Index;
+      Prj.Env.Create_Mapping_File
+        (Project  => Project,
+         Language => Name_Ada,
+         In_Tree  => Project_Tree,
+         Name     => Result);
+      return Result;
+   end Mapping_File;
 
    ------------------
    -- Process_Link --
@@ -899,7 +968,7 @@ procedure GNATCmd is
 
    procedure Process_Link is
       Look_For_Executable : Boolean := True;
-      There_Are_Libraries : Boolean := False;
+      Libraries_Present   : Boolean := False;
       Path_Option         : constant String_Access :=
                               MLib.Linker_Library_Path_Option;
       Prj                 : Project_Id := Project;
@@ -918,12 +987,12 @@ procedure GNATCmd is
       --  Check if there are library project files
 
       if MLib.Tgt.Support_For_Libraries /= None then
-         Set_Libraries (Project, Project_Tree, There_Are_Libraries);
+         Set_Libraries (Project, Project_Tree, Libraries_Present);
       end if;
 
       --  If there are, add the necessary additional switches
 
-      if There_Are_Libraries then
+      if Libraries_Present then
 
          --  Add -L<lib_dir> -lgnarl -lgnat -Wl,-rpath,<lib_dir>
 
@@ -948,54 +1017,80 @@ procedure GNATCmd is
                Current : Natural;
 
             begin
-               --  First, compute the exact length for the switch
+               if MLib.Separate_Run_Path_Options then
 
-               for Index in
-                 Library_Paths.First .. Library_Paths.Last
-               loop
-                  --  Add the length of the library dir plus one for the
-                  --  directory separator.
+                  --  We are going to create one switch of the form
+                  --  "-Wl,-rpath,dir_N" for each directory to consider.
 
-                  Length :=
-                    Length +
-                      Library_Paths.Table (Index)'Length + 1;
-               end loop;
+                  --  One switch for each library directory
 
-               --  Finally, add the length of the standard GNAT library dir
+                  for Index in
+                    Library_Paths.First .. Library_Paths.Last
+                  loop
+                     Last_Switches.Increment_Last;
+                     Last_Switches.Table
+                       (Last_Switches.Last) := new String'
+                       (Path_Option.all &
+                        Last_Switches.Table (Index).all);
+                  end loop;
 
-               Length := Length + MLib.Utl.Lib_Directory'Length;
-               Option := new String (1 .. Length);
-               Option (1 .. Path_Option'Length) := Path_Option.all;
-               Current := Path_Option'Length;
+                  --  One switch for the standard GNAT library dir
 
-               --  Put each library dir followed by a dir separator
+                  Last_Switches.Increment_Last;
+                  Last_Switches.Table
+                    (Last_Switches.Last) := new String'
+                    (Path_Option.all & MLib.Utl.Lib_Directory);
 
-               for Index in
-                 Library_Paths.First .. Library_Paths.Last
-               loop
-                  Option
-                    (Current + 1 ..
+               else
+                  --  First, compute the exact length for the switch
+
+                  for Index in
+                    Library_Paths.First .. Library_Paths.Last
+                  loop
+                     --  Add the length of the library dir plus one for the
+                     --  directory separator.
+
+                     Length :=
+                       Length +
+                         Library_Paths.Table (Index)'Length + 1;
+                  end loop;
+
+                  --  Finally, add the length of the standard GNAT library dir
+
+                  Length := Length + MLib.Utl.Lib_Directory'Length;
+                  Option := new String (1 .. Length);
+                  Option (1 .. Path_Option'Length) := Path_Option.all;
+                  Current := Path_Option'Length;
+
+                  --  Put each library dir followed by a dir separator
+
+                  for Index in
+                    Library_Paths.First .. Library_Paths.Last
+                  loop
+                     Option
+                       (Current + 1 ..
+                          Current +
+                            Library_Paths.Table (Index)'Length) :=
+                       Library_Paths.Table (Index).all;
+                     Current :=
                        Current +
-                         Library_Paths.Table (Index)'Length) :=
-                      Library_Paths.Table (Index).all;
-                  Current :=
-                    Current +
-                      Library_Paths.Table (Index)'Length + 1;
-                  Option (Current) := Path_Separator;
-               end loop;
+                         Library_Paths.Table (Index)'Length + 1;
+                     Option (Current) := Path_Separator;
+                  end loop;
 
-               --  Finally put the standard GNAT library dir
+                  --  Finally put the standard GNAT library dir
 
-               Option
-                 (Current + 1 ..
-                    Current + MLib.Utl.Lib_Directory'Length) :=
-                   MLib.Utl.Lib_Directory;
+                  Option
+                    (Current + 1 ..
+                       Current + MLib.Utl.Lib_Directory'Length) :=
+                      MLib.Utl.Lib_Directory;
 
-               --  And add the switch to the last switches
+                  --  And add the switch to the last switches
 
-               Last_Switches.Increment_Last;
-               Last_Switches.Table (Last_Switches.Last) :=
-                 Option;
+                  Last_Switches.Increment_Last;
+                  Last_Switches.Table (Last_Switches.Last) :=
+                    Option;
+               end if;
             end;
          end if;
       end if;
@@ -1023,11 +1118,10 @@ procedure GNATCmd is
 
          else
             declare
-               Switch         : constant String :=
-                                  Last_Switches.Table (J).all;
-
-               ALI_File       : constant String (1 .. Switch'Length + 4) :=
-                                  Switch & ".ali";
+               Switch    : constant String :=
+                             Last_Switches.Table (J).all;
+               ALI_File  : constant String (1 .. Switch'Length + 4) :=
+                             Switch & ".ali";
 
                Test_Existence : Boolean := False;
 
@@ -1042,8 +1136,7 @@ procedure GNATCmd is
                   --  Append ".ali" if file name does not end with it
 
                   if Switch'Length <= 4
-                    or else Switch (Switch'Last - 3 .. Switch'Last)
-                    /= ".ali"
+                    or else Switch (Switch'Last - 3 .. Switch'Last) /= ".ali"
                   then
                      Last := ALI_File'Last;
                   end if;
@@ -1056,8 +1149,8 @@ procedure GNATCmd is
 
                   else
                      for K in Switch'Range loop
-                        if Switch (K) = '/' or else
-                          Switch (K) = Directory_Separator
+                        if Switch (K) = '/'
+                          or else Switch (K) = Directory_Separator
                         then
                            Test_Existence := True;
                            exit;
@@ -1076,22 +1169,17 @@ procedure GNATCmd is
                      Project_Loop : loop
                         declare
                            Dir : constant String :=
-                                   Get_Name_String
-                                     (Project_Tree.Projects.Table
-                                        (Prj).Object_Directory);
+                                   Get_Name_String (Prj.Object_Directory.Name);
                         begin
                            if Is_Regular_File
                                 (Dir &
-                                 Directory_Separator &
                                  ALI_File (1 .. Last))
                            then
                               --  We have found the correct project, so we
                               --  replace the file with the absolute path.
 
                               Last_Switches.Table (J) :=
-                                new String'
-                                  (Dir & Directory_Separator &
-                                   ALI_File (1 .. Last));
+                                new String'(Dir & ALI_File (1 .. Last));
 
                               --  And we are done
 
@@ -1101,8 +1189,7 @@ procedure GNATCmd is
 
                         --  Go to the project being extended, if any
 
-                        Prj :=
-                          Project_Tree.Projects.Table (Prj).Extends;
+                        Prj := Prj.Extends;
                         exit Project_Loop when Prj = No_Project;
                      end loop Project_Loop;
                   end if;
@@ -1157,13 +1244,10 @@ procedure GNATCmd is
                   Last_Switches.Increment_Last;
                   Last_Switches.Table (Last_Switches.Last) :=
                     new String'("-o");
-                  Get_Name_String
-                    (Project_Tree.Projects.Table
-                       (Project).Exec_Directory);
+                  Get_Name_String (Project.Exec_Directory.Name);
                   Last_Switches.Increment_Last;
                   Last_Switches.Table (Last_Switches.Last) :=
                     new String'(Name_Buffer (1 .. Name_Len) &
-                                Directory_Separator &
                                 Executable_Name
                                   (Base_Name (Arg (Arg'First .. Last))));
                   exit;
@@ -1178,48 +1262,42 @@ procedure GNATCmd is
    ---------------------
 
    procedure Set_Library_For
-     (Project             : Project_Id;
-      There_Are_Libraries : in out Boolean)
+     (Project           : Project_Id;
+      Tree              : Project_Tree_Ref;
+      Libraries_Present : in out Boolean)
    is
+      pragma Unreferenced (Tree);
+
       Path_Option : constant String_Access :=
                       MLib.Linker_Library_Path_Option;
 
    begin
       --  Case of library project
 
-      if Project_Tree.Projects.Table (Project).Library then
-         There_Are_Libraries := True;
+      if Project.Library then
+         Libraries_Present := True;
 
          --  Add the -L switch
 
          Last_Switches.Increment_Last;
          Last_Switches.Table (Last_Switches.Last) :=
-           new String'("-L" &
-                       Get_Name_String
-                         (Project_Tree.Projects.Table
-                            (Project).Library_Dir));
+           new String'("-L" & Get_Name_String (Project.Library_Dir.Name));
 
          --  Add the -l switch
 
          Last_Switches.Increment_Last;
          Last_Switches.Table (Last_Switches.Last) :=
-           new String'("-l" &
-                       Get_Name_String
-                         (Project_Tree.Projects.Table
-                            (Project).Library_Name));
+           new String'("-l" & Get_Name_String (Project.Library_Name));
 
          --  Add the directory to table Library_Paths, to be processed later
          --  if library is not static and if Path_Option is not null.
 
-         if Project_Tree.Projects.Table (Project).Library_Kind /=
-              Static
+         if Project.Library_Kind /= Static
            and then Path_Option /= null
          then
             Library_Paths.Increment_Last;
             Library_Paths.Table (Library_Paths.Last) :=
-              new String'(Get_Name_String
-                            (Project_Tree.Projects.Table
-                               (Project).Library_Dir));
+              new String'(Get_Name_String (Project.Library_Dir.Name));
          end if;
       end if;
    end Set_Library_For;
@@ -1233,61 +1311,11 @@ procedure GNATCmd is
       Parent : String)
    is
    begin
-      if Switch /= null then
-
-         declare
-            Sw : String (1 .. Switch'Length);
-            Start : Positive := 1;
-
-         begin
-            Sw := Switch.all;
-
-            if Sw (1) = '-' then
-               if Sw'Length >= 3
-                 and then (Sw (2) = 'A' or else
-                           Sw (2) = 'I' or else
-                           Sw (2) = 'L')
-               then
-                  Start := 3;
-
-                  if Sw = "-I-" then
-                     return;
-                  end if;
-
-               elsif Sw'Length >= 4
-                 and then (Sw (2 .. 3) = "aL" or else
-                           Sw (2 .. 3) = "aO" or else
-                           Sw (2 .. 3) = "aI")
-               then
-                  Start := 4;
-
-               elsif Sw'Length >= 7
-                 and then Sw (2 .. 6) = "-RTS="
-               then
-                  Start := 7;
-               else
-                  return;
-               end if;
-            end if;
-
-            --  If the path is relative, test if it includes directory
-            --  information. If it does, prepend Parent to the path.
-
-            if not Is_Absolute_Path (Sw (Start .. Sw'Last)) then
-               for J in Start .. Sw'Last loop
-                  if Sw (J) = Directory_Separator then
-                     Switch :=
-                        new String'
-                              (Sw (1 .. Start - 1) &
-                               Parent &
-                               Directory_Separator &
-                               Sw (Start .. Sw'Last));
-                     return;
-                  end if;
-               end loop;
-            end if;
-         end;
-      end if;
+      Makeutl.Test_If_Relative_Path
+        (Switch, Parent,
+         Do_Fail              => Osint.Fail'Access,
+         Including_Non_Switch => False,
+         Including_RTS        => True);
    end Test_If_Relative_Path;
 
    -------------------
@@ -1302,10 +1330,26 @@ procedure GNATCmd is
       New_Line;
 
       for C in Command_List'Range loop
-         if not Command_List (C).VMS_Only then
-            Put ("gnat " & To_Lower (Command_List (C).Cname.all));
+
+         --  No usage for VMS only command or for Sync
+
+         if not Command_List (C).VMS_Only and then C /= Sync then
+            if Targparm.AAMP_On_Target then
+               Put ("gnaampcmd ");
+            else
+               Put ("gnat ");
+            end if;
+
+            Put (To_Lower (Command_List (C).Cname.all));
             Set_Col (25);
-            Put (Command_List (C).Unixcmd.all);
+
+            --  Never call gnatstack with a prefix
+
+            if C = Stack then
+               Put (Command_List (C).Unixcmd.all);
+            else
+               Put (Program_Name (Command_List (C).Unixcmd.all, "gnat").all);
+            end if;
 
             declare
                Sws : Argument_List_Access renames Command_List (C).Unixsws;
@@ -1323,23 +1367,31 @@ procedure GNATCmd is
       end loop;
 
       New_Line;
-      Put_Line ("Commands find, list, metric, pretty, stack, stub and xref " &
+      Put_Line ("All commands except chop, krunch and preprocess " &
                 "accept project file switches -vPx, -Pprj and -Xnam=val");
       New_Line;
    end Non_VMS_Usage;
 
-   -------------------------------------
-   -- Start of processing for GNATCmd --
-   -------------------------------------
+--  Start of processing for GNATCmd
 
 begin
+   --  All output from GNATCmd is debugging or error output: send to stderr
+
+   Set_Standard_Error;
+
    --  Initializations
 
-   Namet.Initialize;
    Csets.Initialize;
-
    Snames.Initialize;
 
+   Prj.Tree.Initialize (Root_Environment, Gnatmake_Flags);
+   Prj.Env.Initialize_Default_Project_Path
+     (Root_Environment.Project_Path,
+      Target_Name => Sdefault.Target_Name.all);
+
+   Project_Node_Tree := new Project_Node_Tree_Data;
+   Prj.Tree.Initialize (Project_Node_Tree);
+
    Prj.Initialize (Project_Tree);
 
    Last_Switches.Init;
@@ -1354,7 +1406,37 @@ begin
 
    VMS_Conv.Initialize;
 
-   Set_Mode (Ada_Only);
+   --  Add the default search directories, to be able to find system.ads in the
+   --  subsequent call to Targparm.Get_Target_Parameters.
+
+   Add_Default_Search_Dirs;
+
+   --  Get target parameters so that AAMP_On_Target will be set, for testing in
+   --  Osint.Program_Name to handle the mapping of GNAAMP tool names.
+
+   Targparm.Get_Target_Parameters;
+
+   --  Put the command line in environment variable GNAT_DRIVER_COMMAND_LINE,
+   --  so that the spawned tool may know the way the GNAT driver was invoked.
+
+   Name_Len := 0;
+   Add_Str_To_Name_Buffer (Command_Name);
+
+   for J in 1 .. Argument_Count loop
+      Add_Char_To_Name_Buffer (' ');
+      Add_Str_To_Name_Buffer (Argument (J));
+   end loop;
+
+   --  On OpenVMS, setenv creates a logical whose length is limited to
+   --  255 bytes.
+
+   if OpenVMS and then Name_Len > Max_OpenVMS_Logical_Length then
+      Name_Buffer (Max_OpenVMS_Logical_Length - 2
+                     .. Max_OpenVMS_Logical_Length) := "...";
+      Name_Len := Max_OpenVMS_Logical_Length;
+   end if;
+
+   Setenv ("GNAT_DRIVER_COMMAND_LINE", Name_Buffer (1 .. Name_Len));
 
    --  Add the directory where the GNAT driver is invoked in front of the path,
    --  if the GNAT driver is invoked with directory information. Do not do this
@@ -1372,10 +1454,8 @@ begin
                                    Normalize_Pathname
                                      (Command (Command'First .. Index));
 
-                  PATH         : constant String :=
-                                   Absolute_Dir &
-                  Path_Separator &
-                  Getenv ("PATH").all;
+                  PATH : constant String :=
+                           Absolute_Dir & Path_Separator & Getenv ("PATH").all;
 
                begin
                   Setenv ("PATH", PATH);
@@ -1428,9 +1508,9 @@ begin
             if Command_List (The_Command).VMS_Only then
                Non_VMS_Usage;
                Fail
-                 ("Command """,
-                  Command_List (The_Command).Cname.all,
-                  """ can only be used on VMS");
+                 ("Command """
+                  & Command_List (The_Command).Cname.all
+                  """ can only be used on VMS");
             end if;
 
          exception
@@ -1449,7 +1529,7 @@ begin
                exception
                   when Constraint_Error =>
                      Non_VMS_Usage;
-                     Fail ("Unknown command: ", Argument (Command_Arg));
+                     Fail ("Unknown command: " & Argument (Command_Arg));
                end;
          end;
 
@@ -1519,18 +1599,36 @@ begin
    end if;
 
    declare
-      Program : constant String :=
-                  Program_Name (Command_List (The_Command).Unixcmd.all).all;
-
+      Program   : String_Access;
       Exec_Path : String_Access;
 
    begin
+      if The_Command = Stack then
+
+         --  Never call gnatstack with a prefix
+
+         Program := new String'(Command_List (The_Command).Unixcmd.all);
+
+      else
+         Program :=
+           Program_Name (Command_List (The_Command).Unixcmd.all, "gnat");
+      end if;
+
+      --  For the tools where the GNAT driver processes the project files,
+      --  allow shared library projects to import projects that are not shared
+      --  library projects, to avoid adding a switch for these tools. For the
+      --  builder (gnatmake), if a shared library project imports a project
+      --  that is not a shared library project and the appropriate switch is
+      --  not specified, the invocation of gnatmake will fail.
+
+      Opt.Unchecked_Shared_Lib_Imports := True;
+
       --  Locate the executable for the command
 
-      Exec_Path := Locate_Exec_On_Path (Program);
+      Exec_Path := Locate_Exec_On_Path (Program.all);
 
       if Exec_Path = null then
-         Put_Line (Standard_Error, "could not locate " & Program);
+         Put_Line (Standard_Error, "could not locate " & Program.all);
          raise Error_Exit;
       end if;
 
@@ -1544,64 +1642,56 @@ begin
          end loop;
       end if;
 
-      --  For BIND, CHECK, ELIM, FIND, LINK, LIST, PRETTY, STACK, STUB,
-      --  METRIC ad  XREF, look for project file related switches.
-
-      if The_Command = Bind
-        or else The_Command = Check
-        or else The_Command = Elim
-        or else The_Command = Find
-        or else The_Command = Link
-        or else The_Command = List
-        or else The_Command = Xref
-        or else The_Command = Pretty
-        or else The_Command = Stack
-        or else The_Command = Stub
-        or else The_Command = Metric
-      then
-         case The_Command is
-            when Bind =>
-               Tool_Package_Name := Name_Binder;
-               Packages_To_Check := Packages_To_Check_By_Binder;
-            when Check =>
-               Tool_Package_Name := Name_Check;
-               Packages_To_Check := Packages_To_Check_By_Check;
-            when Elim =>
-               Tool_Package_Name := Name_Eliminate;
-               Packages_To_Check := Packages_To_Check_By_Eliminate;
-            when Find =>
-               Tool_Package_Name := Name_Finder;
-               Packages_To_Check := Packages_To_Check_By_Finder;
-            when Link =>
-               Tool_Package_Name := Name_Linker;
-               Packages_To_Check := Packages_To_Check_By_Linker;
-            when List =>
-               Tool_Package_Name := Name_Gnatls;
-               Packages_To_Check := Packages_To_Check_By_Gnatls;
-            when Metric =>
-               Tool_Package_Name := Name_Metrics;
-               Packages_To_Check := Packages_To_Check_By_Metric;
-            when Pretty =>
-               Tool_Package_Name := Name_Pretty_Printer;
-               Packages_To_Check := Packages_To_Check_By_Pretty;
-            when Stack =>
-               Tool_Package_Name := Name_Stack;
-               Packages_To_Check := Packages_To_Check_By_Stack;
-            when Stub =>
-               Tool_Package_Name := Name_Gnatstub;
-               Packages_To_Check := Packages_To_Check_By_Gnatstub;
-            when Xref =>
-               Tool_Package_Name := Name_Cross_Reference;
-               Packages_To_Check := Packages_To_Check_By_Xref;
-            when others =>
-               null;
-         end case;
+      --  For BIND, CHECK, ELIM, FIND, LINK, LIST, METRIC, PRETTY, STACK, STUB,
+      --  SYNC and XREF, look for project file related switches.
+
+      case The_Command is
+         when Bind =>
+            Tool_Package_Name := Name_Binder;
+            Packages_To_Check := Packages_To_Check_By_Binder;
+         when Check =>
+            Tool_Package_Name := Name_Check;
+            Packages_To_Check := Packages_To_Check_By_Check;
+         when Elim =>
+            Tool_Package_Name := Name_Eliminate;
+            Packages_To_Check := Packages_To_Check_By_Eliminate;
+         when Find =>
+            Tool_Package_Name := Name_Finder;
+            Packages_To_Check := Packages_To_Check_By_Finder;
+         when Link =>
+            Tool_Package_Name := Name_Linker;
+            Packages_To_Check := Packages_To_Check_By_Linker;
+         when List =>
+            Tool_Package_Name := Name_Gnatls;
+            Packages_To_Check := Packages_To_Check_By_Gnatls;
+         when Metric =>
+            Tool_Package_Name := Name_Metrics;
+            Packages_To_Check := Packages_To_Check_By_Metric;
+         when Pretty =>
+            Tool_Package_Name := Name_Pretty_Printer;
+            Packages_To_Check := Packages_To_Check_By_Pretty;
+         when Stack =>
+            Tool_Package_Name := Name_Stack;
+            Packages_To_Check := Packages_To_Check_By_Stack;
+         when Stub =>
+            Tool_Package_Name := Name_Gnatstub;
+            Packages_To_Check := Packages_To_Check_By_Gnatstub;
+         when Sync =>
+            Tool_Package_Name := Name_Synchronize;
+            Packages_To_Check := Packages_To_Check_By_Sync;
+         when Xref =>
+            Tool_Package_Name := Name_Cross_Reference;
+            Packages_To_Check := Packages_To_Check_By_Xref;
+         when others =>
+            Tool_Package_Name := No_Name;
+      end case;
+
+      if Tool_Package_Name /= No_Name then
 
          --  Check that the switches are consistent. Detect project file
          --  related switches.
 
-         Inspect_Switches :
-         declare
+         Inspect_Switches : declare
             Arg_Num : Positive := 1;
             Argv    : String_Access;
 
@@ -1643,13 +1733,39 @@ begin
                      end if;
                   end if;
 
+                  --  --subdirs=... Specify Subdirs
+
+                  if Argv'Length > Makeutl.Subdirs_Option'Length
+                    and then
+                      Argv
+                       (Argv'First ..
+                        Argv'First + Makeutl.Subdirs_Option'Length - 1) =
+                          Makeutl.Subdirs_Option
+                  then
+                     Subdirs :=
+                       new String'
+                         (Argv
+                           (Argv'First + Makeutl.Subdirs_Option'Length ..
+                            Argv'Last));
+
+                     Remove_Switch (Arg_Num);
+
                   --  -aPdir  Add dir to the project search path
 
-                  if Argv'Length > 3
+                  elsif Argv'Length > 3
                     and then Argv (Argv'First + 1 .. Argv'First + 2) = "aP"
                   then
-                     Add_Search_Project_Directory
-                       (Argv (Argv'First + 3 .. Argv'Last));
+                     Prj.Env.Add_Directories
+                       (Root_Environment.Project_Path,
+                        Argv (Argv'First + 3 .. Argv'Last));
+
+                     Remove_Switch (Arg_Num);
+
+                  --  -eL  Follow links for files
+
+                  elsif Argv.all = "-eL" then
+                     Follow_Links_For_Files := True;
+                     Follow_Links_For_Dirs  := True;
 
                      Remove_Switch (Arg_Num);
 
@@ -1666,7 +1782,7 @@ begin
                         when '2' =>
                            Current_Verbosity := Prj.High;
                         when others =>
-                           Fail ("Invalid switch: ", Argv.all);
+                           Fail ("Invalid switch: " & Argv.all);
                      end case;
 
                      Remove_Switch (Arg_Num);
@@ -1679,9 +1795,10 @@ begin
 
                      if Project_File /= null then
                         Fail
-                          (Argv.all,
-                           ": second project file forbidden (first is """,
-                           Project_File.all & """)");
+                          (Argv.all
+                           & ": second project file forbidden (first is """
+                           & Project_File.all
+                           & """)");
 
                      --  The two style project files (-p and -P) cannot be
                      --  used together.
@@ -1727,28 +1844,18 @@ begin
                   elsif Argv'Length >= 5
                     and then Argv (Argv'First + 1) = 'X'
                   then
-                     declare
-                        Equal_Pos : constant Natural :=
-                                      Index
-                                        ('=',
-                                         Argv (Argv'First + 2 .. Argv'Last));
-                     begin
-                        if Equal_Pos >= Argv'First + 3 and then
-                          Equal_Pos /= Argv'Last then
-                           Add (External_Name =>
-                                  Argv (Argv'First + 2 .. Equal_Pos - 1),
-                                Value => Argv (Equal_Pos + 1 .. Argv'Last));
-                        else
-                           Fail
-                             (Argv.all,
-                              " is not a valid external assignment.");
-                        end if;
-                     end;
+                     if not Check (Root_Environment.External,
+                                    Argv (Argv'First + 2 .. Argv'Last))
+                     then
+                        Fail (Argv.all
+                              & " is not a valid external assignment.");
+                     end if;
 
                      Remove_Switch (Arg_Num);
 
                   elsif
                     (The_Command = Check  or else
+                     The_Command = Sync   or else
                      The_Command = Pretty or else
                      The_Command = Metric or else
                      The_Command = Stack  or else
@@ -1764,6 +1871,7 @@ begin
                   end if;
 
                elsif ((The_Command = Check and then Argv (Argv'First) /= '+')
+                        or else The_Command = Sync
                         or else The_Command = Metric
                         or else The_Command = Pretty)
                  and then Project_File /= null
@@ -1792,37 +1900,42 @@ begin
          Prj.Pars.Parse
            (Project           => Project,
             In_Tree           => Project_Tree,
+            In_Node_Tree      => Project_Node_Tree,
             Project_File_Name => Project_File.all,
+            Env               => Root_Environment,
             Packages_To_Check => Packages_To_Check);
 
+         --  Prj.Pars.Parse calls Set_Standard_Output, reset to stderr
+
+         Set_Standard_Error;
+
          if Project = Prj.No_Project then
-            Fail ("""", Project_File.all, """ processing failed");
+            Fail ("""" & Project_File.all & """ processing failed");
          end if;
 
          --  Check if a package with the name of the tool is in the project
          --  file and if there is one, get the switches, if any, and scan them.
 
          declare
-            Data : constant Prj.Project_Data :=
-                     Project_Tree.Projects.Table (Project);
-
             Pkg : constant Prj.Package_Id :=
                     Prj.Util.Value_Of
                       (Name        => Tool_Package_Name,
-                       In_Packages => Data.Decl.Packages,
-                       In_Tree     => Project_Tree);
+                       In_Packages => Project.Decl.Packages,
+                       Shared      => Project_Tree.Shared);
 
             Element : Package_Element;
 
-            Default_Switches_Array : Array_Element_Id;
+            Switches_Array : Array_Element_Id;
 
             The_Switches : Prj.Variable_Value;
             Current      : Prj.String_List_Id;
             The_String   : String_Element;
 
+            Main : String_Access := null;
+
          begin
             if Pkg /= No_Package then
-               Element := Project_Tree.Packages.Table (Pkg);
+               Element := Project_Tree.Shared.Packages.Table (Pkg);
 
                --  Packages Gnatls and Gnatstack have a single attribute
                --  Switches, that is not an associative array.
@@ -1832,7 +1945,7 @@ begin
                     Prj.Util.Value_Of
                     (Variable_Name => Snames.Name_Switches,
                      In_Variables  => Element.Decl.Attributes,
-                     In_Tree       => Project_Tree);
+                     Shared        => Project_Tree.Shared);
 
                --  Packages Binder (for gnatbind), Cross_Reference (for
                --  gnatxref), Linker (for gnatlink), Finder (for gnatfind),
@@ -1845,17 +1958,46 @@ begin
                --  name of the programming language.
 
                else
+                  --  First check if there is a single main
+
+                  for J in 1 .. Last_Switches.Last loop
+                     if Last_Switches.Table (J) (1) /= '-' then
+                        if Main = null then
+                           Main := Last_Switches.Table (J);
+
+                        else
+                           Main := null;
+                           exit;
+                        end if;
+                     end if;
+                  end loop;
+
+                  if Main /= null then
+                     Switches_Array :=
+                       Prj.Util.Value_Of
+                         (Name      => Name_Switches,
+                          In_Arrays => Element.Decl.Arrays,
+                          Shared    => Project_Tree.Shared);
+                     Name_Len := 0;
+                     Add_Str_To_Name_Buffer (Main.all);
+                     The_Switches := Prj.Util.Value_Of
+                       (Index     => Name_Find,
+                        Src_Index => 0,
+                        In_Array  => Switches_Array,
+                        Shared    => Project_Tree.Shared);
+                  end if;
+
                   if The_Switches.Kind = Prj.Undefined then
-                     Default_Switches_Array :=
+                     Switches_Array :=
                        Prj.Util.Value_Of
                          (Name      => Name_Default_Switches,
                           In_Arrays => Element.Decl.Arrays,
-                          In_Tree   => Project_Tree);
+                          Shared    => Project_Tree.Shared);
                      The_Switches := Prj.Util.Value_Of
                        (Index     => Name_Ada,
                         Src_Index => 0,
-                        In_Array  => Default_Switches_Array,
-                        In_Tree   => Project_Tree);
+                        In_Array  => Switches_Array,
+                        Shared    => Project_Tree.Shared);
                   end if;
                end if;
 
@@ -1882,7 +2024,7 @@ begin
                   when Prj.List =>
                      Current := The_Switches.Values;
                      while Current /= Prj.Nil_String loop
-                        The_String := Project_Tree.String_Elements.
+                        The_String := Project_Tree.Shared.String_Elements.
                                         Table (Current);
 
                         declare
@@ -1903,14 +2045,11 @@ begin
             end if;
          end;
 
-         if The_Command = Bind
+         if        The_Command = Bind
            or else The_Command = Link
            or else The_Command = Elim
          then
-            Change_Dir
-              (Get_Name_String
-                 (Project_Tree.Projects.Table
-                    (Project).Object_Directory));
+            Change_Dir (Get_Name_String (Project.Object_Directory.Name));
          end if;
 
          --  Set up the env vars for project path files
@@ -1921,50 +2060,91 @@ begin
          --  For gnatcheck, gnatstub, gnatmetric, gnatpp and gnatelim, create
          --  a configuration pragmas file, if necessary.
 
-         if The_Command = Pretty
+         if        The_Command = Pretty
            or else The_Command = Metric
            or else The_Command = Stub
            or else The_Command = Elim
            or else The_Command = Check
+           or else The_Command = Sync
          then
             --  If there are switches in package Compiler, put them in the
             --  Carg_Switches table.
 
             declare
-               Data : constant Prj.Project_Data :=
-                        Project_Tree.Projects.Table (Project);
-
                Pkg  : constant Prj.Package_Id :=
                         Prj.Util.Value_Of
                           (Name        => Name_Compiler,
-                           In_Packages => Data.Decl.Packages,
-                           In_Tree     => Project_Tree);
+                           In_Packages => Project.Decl.Packages,
+                           Shared      => Project_Tree.Shared);
 
                Element : Package_Element;
 
-               Default_Switches_Array : Array_Element_Id;
+               Switches_Array : Array_Element_Id;
 
                The_Switches : Prj.Variable_Value;
                Current      : Prj.String_List_Id;
                The_String   : String_Element;
 
+               Main    : String_Access := null;
+               Main_Id : Name_Id;
+
             begin
                if Pkg /= No_Package then
-                  Element := Project_Tree.Packages.Table (Pkg);
 
-                  Default_Switches_Array :=
-                    Prj.Util.Value_Of
-                      (Name      => Name_Default_Switches,
-                       In_Arrays => Element.Decl.Arrays,
-                       In_Tree   => Project_Tree);
-                  The_Switches := Prj.Util.Value_Of
-                    (Index     => Name_Ada,
-                     Src_Index => 0,
-                     In_Array  => Default_Switches_Array,
-                     In_Tree   => Project_Tree);
-
-                  --  If there are switches specified in the package of the
-                  --  project file corresponding to the tool, scan them.
+                  --  First, check if there is a single main specified
+
+                  for J in 1  .. Last_Switches.Last loop
+                     if Last_Switches.Table (J) (1) /= '-' then
+                        if Main = null then
+                           Main := Last_Switches.Table (J);
+
+                        else
+                           Main := null;
+                           exit;
+                        end if;
+                     end if;
+                  end loop;
+
+                  Element := Project_Tree.Shared.Packages.Table (Pkg);
+
+                  --  If there is a single main and there is compilation
+                  --  switches specified in the project file, use them.
+
+                  if Main /= null and then not All_Projects then
+                     Name_Len := Main'Length;
+                     Name_Buffer (1 .. Name_Len) := Main.all;
+                     Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
+                     Main_Id := Name_Find;
+
+                     Switches_Array :=
+                       Prj.Util.Value_Of
+                         (Name      => Name_Switches,
+                          In_Arrays => Element.Decl.Arrays,
+                          Shared    => Project_Tree.Shared);
+                     The_Switches := Prj.Util.Value_Of
+                       (Index     => Main_Id,
+                        Src_Index => 0,
+                        In_Array  => Switches_Array,
+                        Shared    => Project_Tree.Shared);
+                  end if;
+
+                  --  Otherwise, get the Default_Switches ("Ada")
+
+                  if The_Switches.Kind = Undefined then
+                     Switches_Array :=
+                       Prj.Util.Value_Of
+                         (Name      => Name_Default_Switches,
+                          In_Arrays => Element.Decl.Arrays,
+                          Shared    => Project_Tree.Shared);
+                     The_Switches := Prj.Util.Value_Of
+                       (Index     => Name_Ada,
+                        Src_Index => 0,
+                        In_Array  => Switches_Array,
+                        Shared    => Project_Tree.Shared);
+                  end if;
+
+                  --  If there are switches specified, put them in the
+                  --  Carg_Switches table.
 
                   case The_Switches.Kind is
                      when Prj.Undefined =>
@@ -1983,8 +2163,8 @@ begin
                      when Prj.List =>
                         Current := The_Switches.Values;
                         while Current /= Prj.Nil_String loop
-                           The_String :=
-                             Project_Tree.String_Elements.Table (Current);
+                           The_String := Project_Tree.Shared.String_Elements
+                             .Table (Current);
 
                            declare
                               Switch : constant String :=
@@ -2006,26 +2186,87 @@ begin
 
             for J in 1 .. First_Switches.Last loop
                if First_Switches.Table (J).all = "-cargs" then
-                  for K in J + 1 .. First_Switches.Last loop
-                     Add_To_Carg_Switches (First_Switches.Table (K));
-                  end loop;
-                  First_Switches.Set_Last (J - 1);
+                  declare
+                     K    : Positive;
+                     Last : Natural;
+
+                  begin
+                     --  Move the switches that are before -rules when the
+                     --  command is CHECK.
+
+                     K := J + 1;
+                     while K <= First_Switches.Last
+                       and then
+                        (The_Command /= Check
+                          or else First_Switches.Table (K).all /= "-rules")
+                     loop
+                        Add_To_Carg_Switches (First_Switches.Table (K));
+                        K := K + 1;
+                     end loop;
+
+                     if K > First_Switches.Last then
+                        First_Switches.Set_Last (J - 1);
+
+                     else
+                        Last := J - 1;
+                        while K <= First_Switches.Last loop
+                           Last := Last + 1;
+                           First_Switches.Table (Last) :=
+                             First_Switches.Table (K);
+                           K := K + 1;
+                        end loop;
+
+                        First_Switches.Set_Last (Last);
+                     end if;
+                  end;
+
                   exit;
                end if;
             end loop;
 
             for J in 1 .. Last_Switches.Last loop
                if Last_Switches.Table (J).all = "-cargs" then
-                  for K in J + 1 .. Last_Switches.Last loop
-                     Add_To_Carg_Switches (Last_Switches.Table (K));
-                  end loop;
-                  Last_Switches.Set_Last (J - 1);
+                  declare
+                     K    : Positive;
+                     Last : Natural;
+
+                  begin
+                     --  Move the switches that are before -rules when the
+                     --  command is CHECK.
+
+                     K := J + 1;
+                     while K <= Last_Switches.Last
+                       and then
+                        (The_Command /= Check
+                          or else Last_Switches.Table (K).all /= "-rules")
+                     loop
+                        Add_To_Carg_Switches (Last_Switches.Table (K));
+                        K := K + 1;
+                     end loop;
+
+                     if K > Last_Switches.Last then
+                        Last_Switches.Set_Last (J - 1);
+
+                     else
+                        Last := J - 1;
+                        while K <= Last_Switches.Last loop
+                           Last := Last + 1;
+                           Last_Switches.Table (Last) :=
+                             Last_Switches.Table (K);
+                           K := K + 1;
+                        end loop;
+
+                        Last_Switches.Set_Last (Last);
+                     end if;
+                  end;
+
                   exit;
                end if;
             end loop;
 
             declare
                CP_File : constant Path_Name_Type := Configuration_Pragmas_File;
+               M_File  : constant Path_Name_Type := Mapping_File;
 
             begin
                if CP_File /= No_Path then
@@ -2039,6 +2280,96 @@ begin
                        (new String'("-gnatec=" & Get_Name_String (CP_File)));
                   end if;
                end if;
+
+               if M_File /= No_Path then
+                  Add_To_Carg_Switches
+                    (new String'("-gnatem=" & Get_Name_String (M_File)));
+               end if;
+
+               --  For gnatcheck, also indicate a global configuration pragmas
+               --  file and, if -U is not used, a local one.
+
+               if The_Command = Check then
+                  declare
+                     Pkg  : constant Prj.Package_Id :=
+                              Prj.Util.Value_Of
+                                (Name        => Name_Builder,
+                                 In_Packages => Project.Decl.Packages,
+                                 Shared      => Project_Tree.Shared);
+
+                     Variable : Variable_Value :=
+                                  Prj.Util.Value_Of
+                                    (Name                    => No_Name,
+                                     Attribute_Or_Array_Name =>
+                                       Name_Global_Configuration_Pragmas,
+                                     In_Package              => Pkg,
+                                     Shared            => Project_Tree.Shared);
+
+                  begin
+                     if (Variable = Nil_Variable_Value
+                          or else Length_Of_Name (Variable.Value) = 0)
+                       and then Pkg /= No_Package
+                     then
+                        Variable :=
+                          Prj.Util.Value_Of
+                            (Name                    => Name_Ada,
+                             Attribute_Or_Array_Name =>
+                               Name_Global_Config_File,
+                             In_Package              => Pkg,
+                             Shared                  => Project_Tree.Shared);
+                     end if;
+
+                     if Variable /= Nil_Variable_Value
+                       and then Length_Of_Name (Variable.Value) /= 0
+                     then
+                        Add_To_Carg_Switches
+                          (new String'
+                             ("-gnatec=" & Get_Name_String (Variable.Value)));
+                     end if;
+                  end;
+
+                  if not All_Projects then
+                     declare
+                        Pkg : constant Prj.Package_Id :=
+                                Prj.Util.Value_Of
+                                  (Name        => Name_Compiler,
+                                   In_Packages => Project.Decl.Packages,
+                                   Shared      => Project_Tree.Shared);
+
+                        Variable : Variable_Value :=
+                                     Prj.Util.Value_Of
+                                       (Name        => No_Name,
+                                        Attribute_Or_Array_Name =>
+                                          Name_Local_Configuration_Pragmas,
+                                        In_Package  => Pkg,
+                                        Shared      => Project_Tree.Shared);
+
+                     begin
+                        if (Variable = Nil_Variable_Value
+                             or else Length_Of_Name (Variable.Value) = 0)
+                          and then Pkg /= No_Package
+                        then
+                           Variable :=
+                             Prj.Util.Value_Of
+                               (Name                    => Name_Ada,
+                                Attribute_Or_Array_Name =>
+                                  Name_Local_Config_File,
+                                In_Package              => Pkg,
+                                Shared                  =>
+                                  Project_Tree.Shared);
+                        end if;
+
+                        if Variable /= Nil_Variable_Value
+                          and then Length_Of_Name (Variable.Value) /= 0
+                        then
+                           Add_To_Carg_Switches
+                             (new String'
+                                ("-gnatec=" &
+                                 Get_Name_String (Variable.Value)));
+                        end if;
+                     end;
+                  end if;
+               end if;
             end;
          end if;
 
@@ -2046,7 +2377,7 @@ begin
             Process_Link;
          end if;
 
-         if The_Command = Link or The_Command = Bind then
+         if The_Command = Link or else The_Command = Bind then
 
             --  For files that are specified as relative paths with directory
             --  information, we convert them to absolute paths, with parent
@@ -2056,29 +2387,28 @@ begin
             --  arguments.
 
             for J in 1 .. Last_Switches.Last loop
-               Test_If_Relative_Path
+               GNATCmd.Test_If_Relative_Path
                  (Last_Switches.Table (J), Current_Work_Dir);
             end loop;
 
-            Get_Name_String
-              (Project_Tree.Projects.Table (Project).Directory);
+            Get_Name_String (Project.Directory.Name);
 
             declare
                Project_Dir : constant String := Name_Buffer (1 .. Name_Len);
             begin
                for J in 1 .. First_Switches.Last loop
-                  Test_If_Relative_Path
+                  GNATCmd.Test_If_Relative_Path
                     (First_Switches.Table (J), Project_Dir);
                end loop;
             end;
 
          elsif The_Command = Stub then
             declare
-               Data : constant Prj.Project_Data :=
-                        Project_Tree.Projects.Table (Project);
                File_Index : Integer := 0;
                Dir_Index  : Integer := 0;
                Last       : constant Integer := Last_Switches.Last;
+               Lang       : constant Language_Ptr :=
+                              Get_Language_From_Name (Project, "ada");
 
             begin
                for Index in 1 .. Last loop
@@ -2090,33 +2420,28 @@ begin
                   end if;
                end loop;
 
-               --  If the naming scheme of the project file is not standard,
-               --  and if the file name ends with the spec suffix, then
-               --  indicate to gnatstub the name of the body file with
-               --  a -o switch.
+               --  If the project file naming scheme is not standard, and if
+               --  the file name ends with the spec suffix, then indicate to
+               --  gnatstub the name of the body file with a -o switch.
 
-               if Body_Suffix_Id_Of (Project_Tree, "ada", Data.Naming) /=
-                    Prj.Default_Ada_Spec_Suffix
-               then
+               if not Is_Standard_GNAT_Naming (Lang.Config.Naming_Data) then
                   if File_Index /= 0 then
                      declare
                         Spec : constant String :=
-                          Base_Name (Last_Switches.Table (File_Index).all);
+                                 Base_Name
+                                   (Last_Switches.Table (File_Index).all);
                         Last : Natural := Spec'Last;
 
                      begin
-                        Get_Name_String
-                          (Spec_Suffix_Id_Of
-                             (Project_Tree, "ada", Data.Naming));
+                        Get_Name_String (Lang.Config.Naming_Data.Spec_Suffix);
 
                         if Spec'Length > Name_Len
                           and then Spec (Last - Name_Len + 1 .. Last) =
-                          Name_Buffer (1 .. Name_Len)
+                                                  Name_Buffer (1 .. Name_Len)
                         then
                            Last := Last - Name_Len;
                            Get_Name_String
-                             (Body_Suffix_Id_Of
-                                (Project_Tree, "ada", Data.Naming));
+                             (Lang.Config.Naming_Data.Body_Suffix);
                            Last_Switches.Increment_Last;
                            Last_Switches.Table (Last_Switches.Last) :=
                              new String'("-o");
@@ -2136,7 +2461,7 @@ begin
                if File_Index /= 0 then
                   for Index in File_Index + 1 .. Last loop
                      if Last_Switches.Table (Index)
-                       (Last_Switches.Table (Index)'First) /= '-'
+                         (Last_Switches.Table (Index)'First) /= '-'
                      then
                         Dir_Index := Index;
                         exit;
@@ -2155,27 +2480,27 @@ begin
 
          --  For gnatmetric, the generated files should be put in the object
          --  directory. This must be the first switch, because it may be
-         --  overriden by a switch in package Metrics in the project file or by
-         --  a command line option.
+         --  overridden by a switch in package Metrics in the project file or
+         --  by a command line option. Note that we don't add the -d= switch
+         --  if there is no object directory available.
 
-         if The_Command = Metric then
+         if The_Command = Metric
+           and then Project.Object_Directory /= No_Path_Information
+         then
             First_Switches.Increment_Last;
             First_Switches.Table (2 .. First_Switches.Last) :=
               First_Switches.Table (1 .. First_Switches.Last - 1);
             First_Switches.Table (1) :=
               new String'("-d=" &
-                          Get_Name_String
-                            (Project_Tree.Projects.Table
-                               (Project).Object_Directory));
+                          Get_Name_String (Project.Object_Directory.Name));
          end if;
 
          --  For gnat check, -rules and the following switches need to be the
-         --  last options. So, we move all these switches to table
-         --  Rules_Switches.
+         --  last options, so move all these switches to table Rules_Switches.
 
          if The_Command = Check then
             declare
-               New_Last          : Natural;
+               New_Last : Natural;
                --  Set to rank of options preceding "-rules"
 
                In_Rules_Switches : Boolean;
@@ -2218,32 +2543,36 @@ begin
             end;
          end if;
 
-         --  For gnat check, metric or pretty with -U + a main, get the list
-         --  of sources from the closure and add them to the arguments.
+         --  For gnat check, sync, metric or pretty with -U + a main, get the
+         --  list of sources from the closure and add them to the arguments.
 
          if ASIS_Main /= null then
             Get_Closure;
 
-            --  On VMS, set up again the env var for source dirs file. This is
+            --  On VMS, set up the env var again for source dirs file. This is
             --  because the call to gnatmake has set this env var to another
             --  file that has now been deleted.
 
             if Hostparm.OpenVMS then
-               Setenv
-                 (Project_Include_Path_File,
-                  Prj.Env.Ada_Include_Path
-                    (Project, Project_Tree, Recursive => True));
+
+               --  First make sure that the recorded file names are empty
+
+               Prj.Env.Initialize (Project_Tree);
+
+               Prj.Env.Set_Ada_Paths
+                 (Project, Project_Tree, Including_Libraries => False);
             end if;
 
-         --  For gnat check, gnat pretty, gnat metric, gnat list, and gnat
-         --  stack, if no file has been put on the command line, call tool
-         --  with all the sources of the main project.
+         --  For gnat check, gnat sync, gnat pretty, gnat metric, gnat list,
+         --  and gnat stack, if no file has been put on the command line, call
+         --  tool with all the sources of the main project.
 
          elsif The_Command = Check  or else
-            The_Command = Pretty or else
-            The_Command = Metric or else
-            The_Command = List   or else
-            The_Command = Stack
+               The_Command = Sync   or else
+               The_Command = Pretty or else
+               The_Command = Metric or else
+               The_Command = List   or else
+               The_Command = Stack
          then
             Check_Files;
          end if;
@@ -2316,7 +2645,7 @@ begin
 exception
    when Error_Exit =>
       if not Keep_Temporary_Files then
-         Prj.Env.Delete_All_Path_Files (Project_Tree);
+         Prj.Delete_All_Temp_Files (Project_Tree.Shared);
          Delete_Temp_Config_Files;
       end if;
 
@@ -2324,7 +2653,7 @@ exception
 
    when Normal_Exit =>
       if not Keep_Temporary_Files then
-         Prj.Env.Delete_All_Path_Files (Project_Tree);
+         Prj.Delete_All_Temp_Files (Project_Tree.Shared);
          Delete_Temp_Config_Files;
       end if;