1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1996-2016, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
28 with Makeutl
; use Makeutl
;
29 with Namet
; use Namet
;
31 with Osint
; use Osint
;
32 with Output
; use Output
;
35 with Prj
.Ext
; use Prj
.Ext
;
37 with Prj
.Tree
; use Prj
.Tree
;
38 with Prj
.Util
; use Prj
.Util
;
41 with Snames
; use Snames
;
43 with Switch
; use Switch
;
46 with Types
; use Types
;
48 with Ada
.Characters
.Handling
; use Ada
.Characters
.Handling
;
49 with Ada
.Command_Line
; use Ada
.Command_Line
;
50 with Ada
.Text_IO
; use Ada
.Text_IO
;
52 with GNAT
.Directory_Operations
; use GNAT
.Directory_Operations
;
53 with GNAT
.OS_Lib
; use GNAT
.OS_Lib
;
56 Gprbuild
: constant String := "gprbuild";
57 Gprclean
: constant String := "gprclean";
58 Gprname
: constant String := "gprname";
59 Gprls
: constant String := "gprls";
61 Error_Exit
: exception;
62 -- Raise this exception if error detected
86 subtype Real_Command_Type
is Command_Type
range Bind
.. Xref
;
87 -- All real command types (excludes only Undefined).
89 type Alternate_Command
is (Comp
, Ls
, Kr
, Pp
, Prep
);
90 -- Alternate command label
92 Corresponding_To
: constant array (Alternate_Command
) of Command_Type
:=
98 -- Mapping of alternate commands to commands
100 Call_GPR_Tool
: Boolean := False;
101 -- True when a GPR tool should be called, if available
103 Project_Node_Tree
: Project_Node_Tree_Ref
;
104 Project_File
: String_Access
;
105 Project
: Prj
.Project_Id
;
106 Current_Verbosity
: Prj
.Verbosity
:= Prj
.Default
;
107 Tool_Package_Name
: Name_Id
:= No_Name
;
109 Project_Tree
: constant Project_Tree_Ref
:=
110 new Project_Tree_Data
(Is_Root_Tree
=> True);
113 All_Projects
: Boolean := False;
115 Temp_File_Name
: Path_Name_Type
:= No_Path
;
116 -- The name of the temporary text file to put a list of source/object
117 -- files to pass to a tool.
119 package First_Switches
is new Table
.Table
120 (Table_Component_Type
=> String_Access
,
121 Table_Index_Type
=> Integer,
122 Table_Low_Bound
=> 1,
124 Table_Increment
=> 100,
125 Table_Name
=> "Gnatcmd.First_Switches");
126 -- A table to keep the switches from the project file
128 package Last_Switches
is new Table
.Table
129 (Table_Component_Type
=> String_Access
,
130 Table_Index_Type
=> Integer,
131 Table_Low_Bound
=> 1,
133 Table_Increment
=> 100,
134 Table_Name
=> "Gnatcmd.Last_Switches");
136 ----------------------------------
137 -- Declarations for GNATCMD use --
138 ----------------------------------
140 The_Command
: Command_Type
;
141 -- The command specified in the invocation of the GNAT driver
143 Command_Arg
: Positive := 1;
144 -- The index of the command in the arguments of the GNAT driver
146 My_Exit_Status
: Exit_Status
:= Success
;
147 -- The exit status of the spawned tool
149 type Command_Entry
is record
150 Cname
: String_Access
;
151 -- Command name for GNAT xxx command
153 Unixcmd
: String_Access
;
154 -- Corresponding Unix command
156 Unixsws
: Argument_List_Access
;
157 -- List of switches to be used with the Unix command
160 Command_List
: constant array (Real_Command_Type
) of Command_Entry
:=
162 (Cname
=> new String'("BIND"),
163 Unixcmd => new String'("gnatbind"),
167 (Cname
=> new String'("CHOP"),
168 Unixcmd => new String'("gnatchop"),
172 (Cname
=> new String'("CLEAN"),
173 Unixcmd => new String'("gnatclean"),
177 (Cname
=> new String'("COMPILE"),
178 Unixcmd => new String'("gnatmake"),
179 Unixsws
=> new Argument_List
'(1 => new String'("-f"),
180 2 => new String'("-u"),
181 3 => new String'("-c"))),
184 (Cname
=> new String'("CHECK"),
185 Unixcmd => new String'("gnatcheck"),
189 (Cname
=> new String'("ELIM"),
190 Unixcmd => new String'("gnatelim"),
194 (Cname
=> new String'("FIND"),
195 Unixcmd => new String'("gnatfind"),
199 (Cname
=> new String'("KRUNCH"),
200 Unixcmd => new String'("gnatkr"),
204 (Cname
=> new String'("LINK"),
205 Unixcmd => new String'("gnatlink"),
209 (Cname
=> new String'("LIST"),
210 Unixcmd => new String'("gnatls"),
214 (Cname
=> new String'("MAKE"),
215 Unixcmd => new String'("gnatmake"),
219 (Cname
=> new String'("METRIC"),
220 Unixcmd => new String'("gnatmetric"),
224 (Cname
=> new String'("NAME"),
225 Unixcmd => new String'("gnatname"),
229 (Cname
=> new String'("PREPROCESS"),
230 Unixcmd => new String'("gnatprep"),
234 (Cname
=> new String'("PRETTY"),
235 Unixcmd => new String'("gnatpp"),
239 (Cname
=> new String'("STACK"),
240 Unixcmd => new String'("gnatstack"),
244 (Cname
=> new String'("STUB"),
245 Unixcmd => new String'("gnatstub"),
249 (Cname
=> new String'("TEST"),
250 Unixcmd => new String'("gnattest"),
254 (Cname
=> new String'("XREF"),
255 Unixcmd => new String'("gnatxref"),
259 subtype SA
is String_Access
;
261 Naming_String
: constant SA
:= new String'("naming");
262 Gnatls_String : constant SA := new String'("gnatls");
264 Packages_To_Check_By_Gnatls
: constant String_List_Access
:=
265 new String_List
'((Naming_String, Gnatls_String));
267 Packages_To_Check : String_List_Access := Prj.All_Packages;
269 -----------------------
270 -- Local Subprograms --
271 -----------------------
273 procedure Check_Files;
274 -- For GNAT LIST -V, check if a project file is specified, without any file
275 -- arguments and without a switch -files=. If it is the case, invoke the
276 -- GNAT tool with the proper list of files, derived from the sources of
279 procedure Output_Version;
280 -- Output the version of this program
289 procedure Check_Files is
290 Add_Sources : Boolean := True;
291 Unit : Prj.Unit_Index;
292 Subunit : Boolean := False;
293 FD : File_Descriptor := Invalid_FD;
297 procedure Add_To_Response_File
299 Check_File : Boolean := True);
300 -- Include the file name passed as parameter in the response file for
301 -- the tool being called. If the response file can not be written then
302 -- the file name is passed in the parameter list of the tool. If the
303 -- Check_File parameter is True then the procedure verifies the
304 -- existence of the file before adding it to the response file.
306 --------------------------
307 -- Add_To_Response_File --
308 --------------------------
310 procedure Add_To_Response_File
312 Check_File : Boolean := True)
317 Add_Str_To_Name_Buffer (File_Name);
319 if not Check_File or else
320 Is_Regular_File (Name_Buffer (1 .. Name_Len))
322 if FD /= Invalid_FD then
323 Name_Len := Name_Len + 1;
324 Name_Buffer (Name_Len) := ASCII.LF;
326 Status := Write (FD, Name_Buffer (1)'Address, Name_Len);
328 if Status /= Name_Len then
329 Osint.Fail ("disk full");
332 Last_Switches.Increment_Last;
333 Last_Switches.Table (Last_Switches.Last) :=
334 new String'(File_Name
);
337 end Add_To_Response_File
;
339 -- Start of processing for Check_Files
342 -- Check if there is at least one argument that is not a switch
344 for Index
in 1 .. Last_Switches
.Last
loop
345 if Last_Switches
.Table
(Index
) (1) /= '-'
346 or else (Last_Switches
.Table
(Index
).all'Length > 7
347 and then Last_Switches
.Table
(Index
) (1 .. 7) = "-files=")
349 Add_Sources
:= False;
354 -- If all arguments are switches and there is no switch -files=, add the
355 -- path names of all the sources of the main project.
358 Tempdir
.Create_Temp_File
(FD
, Temp_File_Name
);
359 Record_Temp_File
(Project_Tree
.Shared
, Temp_File_Name
);
360 Last_Switches
.Increment_Last
;
361 Last_Switches
.Table
(Last_Switches
.Last
) :=
362 new String'("-files=" & Get_Name_String (Temp_File_Name));
364 Unit := Units_Htable.Get_First (Project_Tree.Units_HT);
365 while Unit /= No_Unit_Index loop
367 -- We only need to put the library units, body or spec, but not
370 if Unit.File_Names (Impl) /= null
371 and then not Unit.File_Names (Impl).Locally_Removed
373 -- There is a body, check if it is for this project
376 or else Unit.File_Names (Impl).Project = Project
380 if Unit.File_Names (Spec) = null
381 or else Unit.File_Names (Spec).Locally_Removed
383 -- We have a body with no spec: we need to check if
384 -- this is a subunit, because gnatls will complain
388 Src_Ind : constant Source_File_Index :=
389 Sinput.P.Load_Project_File
391 (Unit.File_Names (Impl).Path.Name));
393 Subunit := Sinput.P.Source_File_Is_Subunit (Src_Ind);
399 (Get_Name_String (Unit.File_Names (Impl).Display_File),
400 Check_File => False);
404 elsif Unit.File_Names (Spec) /= null
405 and then not Unit.File_Names (Spec).Locally_Removed
407 -- We have a spec with no body. Check if it is for this project
410 or else Unit.File_Names (Spec).Project = Project
413 (Get_Name_String (Unit.File_Names (Spec).Display_File),
414 Check_File => False);
418 Unit := Units_Htable.Get_Next (Project_Tree.Units_HT);
421 if FD /= Invalid_FD then
425 Osint.Fail ("disk full");
435 procedure Output_Version is
438 Put_Line (Gnatvsn.Gnat_Version_String);
439 Put_Line ("Copyright 1996-" & Gnatvsn.Current_Year
440 & ", Free Software Foundation, Inc.");
451 Put_Line ("List of available commands");
454 for C in Command_List'Range loop
456 Put (To_Lower (Command_List (C).Cname.all));
458 Put (Program_Name (Command_List (C).Unixcmd.all, "gnat").all);
461 Sws : Argument_List_Access renames Command_List (C).Unixsws;
464 for J in Sws'Range loop
477 procedure Check_Version_And_Help is new Check_Version_And_Help_G (Usage);
479 -- Start of processing for GNATCmd
482 -- All output from GNATCmd is debugging or error output: send to stderr
492 Prj.Tree.Initialize (Root_Environment, Gnatmake_Flags);
494 Project_Node_Tree := new Project_Node_Tree_Data;
495 Prj.Tree.Initialize (Project_Node_Tree);
497 Prj.Initialize (Project_Tree);
500 Last_Switches.Set_Last (0);
503 First_Switches.Set_Last (0);
505 -- Put the command line in environment variable GNAT_DRIVER_COMMAND_LINE,
506 -- so that the spawned tool may know the way the GNAT driver was invoked.
509 Add_Str_To_Name_Buffer (Command_Name);
511 for J in 1 .. Argument_Count loop
512 Add_Char_To_Name_Buffer (' ');
513 Add_Str_To_Name_Buffer (Argument (J));
516 Setenv ("GNAT_DRIVER_COMMAND_LINE", Name_Buffer (1 .. Name_Len));
518 -- Add the directory where the GNAT driver is invoked in front of the path,
519 -- if the GNAT driver is invoked with directory information.
522 Command : constant String := Command_Name;
525 for Index in reverse Command'Range loop
526 if Command (Index) = Directory_Separator then
528 Absolute_Dir : constant String :=
529 Normalize_Pathname (Command (Command'First .. Index));
530 PATH : constant String :=
531 Absolute_Dir & Path_Separator & Getenv ("PATH").all;
533 Setenv ("PATH", PATH);
541 -- Scan the command line
543 -- First, scan to detect --version and/or --help
545 Check_Version_And_Help ("GNAT", "1996");
549 if Command_Arg <= Argument_Count
550 and then Argument (Command_Arg) = "-v"
552 Verbose_Mode := True;
553 Command_Arg := Command_Arg + 1;
555 elsif Command_Arg <= Argument_Count
556 and then Argument (Command_Arg) = "-dn"
558 Keep_Temporary_Files := True;
559 Command_Arg := Command_Arg + 1;
566 -- If there is no command, just output the usage
568 if Command_Arg > Argument_Count then
573 The_Command := Real_Command_Type'Value (Argument (Command_Arg));
576 when Constraint_Error =>
578 -- Check if it is an alternate command
581 Alternate : Alternate_Command;
584 Alternate := Alternate_Command'Value (Argument (Command_Arg));
585 The_Command := Corresponding_To (Alternate);
588 when Constraint_Error =>
590 Fail ("unknown command: " & Argument (Command_Arg));
594 -- Get the arguments from the command line and from the eventual
595 -- argument file(s) specified on the command line.
597 for Arg in Command_Arg + 1 .. Argument_Count loop
599 The_Arg : constant String := Argument (Arg);
602 -- Check if an argument file is specified
604 if The_Arg (The_Arg'First) = '@
' then
606 Arg_File : Ada.Text_IO.File_Type;
607 Line : String (1 .. 256);
611 -- Open the file and fail if the file cannot be found
614 Open (Arg_File, In_File,
615 The_Arg (The_Arg'First + 1 .. The_Arg'Last));
619 Put (Standard_Error, "Cannot open argument file """);
621 The_Arg (The_Arg'First + 1 .. The_Arg'Last));
622 Put_Line (Standard_Error, """");
626 -- Read line by line and put the content of each non-
627 -- empty line in the Last_Switches table.
629 while not End_Of_File (Arg_File) loop
630 Get_Line (Arg_File, Line, Last);
633 Last_Switches.Increment_Last;
634 Last_Switches.Table (Last_Switches.Last) :=
635 new String'(Line
(1 .. Last
));
643 -- It is not an argument file; just put the argument in
644 -- the Last_Switches table.
646 Last_Switches
.Increment_Last
;
647 Last_Switches
.Table
(Last_Switches
.Last
) := new String'(The_Arg);
653 Program : String_Access;
654 Exec_Path : String_Access;
655 Get_Target : Boolean := False;
658 if The_Command = Stack then
660 -- Never call gnatstack with a prefix
662 Program := new String'(Command_List
(The_Command
).Unixcmd
.all);
666 Program_Name
(Command_List
(The_Command
).Unixcmd
.all, "gnat");
668 -- If we want to invoke gnatmake/gnatclean with -P, then check if
669 -- gprbuild/gprclean is available; if it is, use gprbuild/gprclean
670 -- instead of gnatmake/gnatclean.
671 -- Ditto for gnatname -> gprname and gnatls -> gprls.
673 if The_Command
= Make
674 or else The_Command
= Compile
675 or else The_Command
= Bind
676 or else The_Command
= Link
677 or else The_Command
= Clean
678 or else The_Command
= Name
679 or else The_Command
= List
682 Switch
: String_Access
;
683 Dash_V_Switch
: constant String := "-V";
686 for J
in 1 .. Last_Switches
.Last
loop
687 Switch
:= Last_Switches
.Table
(J
);
689 if The_Command
= List
and then Switch
.all = Dash_V_Switch
691 Call_GPR_Tool
:= False;
695 if Switch
'Length >= 2
696 and then Switch
(Switch
'First .. Switch
'First + 1) = "-P"
698 Call_GPR_Tool
:= True;
702 if Call_GPR_Tool
then
709 if Locate_Exec_On_Path
(Gprbuild
) /= null then
710 Program
:= new String'(Gprbuild);
713 if The_Command = Bind then
714 First_Switches.Append (new String'("-b"));
715 elsif The_Command
= Link
then
716 First_Switches
.Append
(new String'("-l"));
719 elsif The_Command = Bind then
721 ("'gnat bind
-P
' is no longer supported;" &
722 " use 'gprbuild
-b
' instead.");
724 elsif The_Command = Link then
726 ("'gnat Link
-P
' is no longer supported;" &
727 " use 'gprbuild
-l
' instead.");
731 if Locate_Exec_On_Path (Gprclean) /= null then
732 Program := new String'(Gprclean
);
737 if Locate_Exec_On_Path
(Gprname
) /= null then
738 Program
:= new String'(Gprname);
743 if Locate_Exec_On_Path (Gprls) /= null then
744 Program := new String'(Gprls
);
756 First_Switches
.Append
758 ("--target=" & Name_Buffer (1 .. Name_Len - 5)));
766 -- Locate the executable for the command
768 Exec_Path := Locate_Exec_On_Path (Program.all);
770 if Exec_Path = null then
771 Put_Line (Standard_Error, "could not locate " & Program.all);
775 -- If there are switches for the executable, put them as first switches
777 if Command_List (The_Command).Unixsws /= null then
778 for J in Command_List (The_Command).Unixsws'Range loop
779 First_Switches.Increment_Last;
780 First_Switches.Table (First_Switches.Last) :=
781 Command_List (The_Command).Unixsws (J);
785 -- For FIND and XREF, look for switch -P. If it is specified, then
786 -- report an error indicating that the command is no longer supporting
789 if The_Command = Find or else The_Command = Xref then
791 Argv : String_Access;
793 for Arg_Num in 1 .. Last_Switches.Last loop
794 Argv := Last_Switches.Table (Arg_Num);
796 if Argv'Length >= 2 and then
797 Argv (Argv'First .. Argv'First + 1) = "-P"
799 if The_Command = Find then
800 Fail ("'gnat find
-P
' is no longer supported;");
802 Fail ("'gnat xref
-P
' is no longer supported;");
809 if The_Command = List and then not Call_GPR_Tool then
810 Tool_Package_Name := Name_Gnatls;
811 Packages_To_Check := Packages_To_Check_By_Gnatls;
813 -- Check that the switches are consistent. Detect project file
816 Inspect_Switches : declare
817 Arg_Num : Positive := 1;
818 Argv : String_Access;
820 procedure Remove_Switch (Num : Positive);
821 -- Remove a project related switch from table Last_Switches
827 procedure Remove_Switch (Num : Positive) is
829 Last_Switches.Table (Num .. Last_Switches.Last - 1) :=
830 Last_Switches.Table (Num + 1 .. Last_Switches.Last);
831 Last_Switches.Decrement_Last;
834 -- Start of processing for Inspect_Switches
837 while Arg_Num <= Last_Switches.Last loop
838 Argv := Last_Switches.Table (Arg_Num);
840 if Argv (Argv'First) = '-' then
841 if Argv'Length = 1 then
842 Fail ("switch character cannot be followed by a blank");
845 -- --subdirs=... Specify Subdirs
847 if Argv'Length > Makeutl.Subdirs_Option'Length
851 Argv'First + Makeutl.Subdirs_Option'Length - 1) =
852 Makeutl.Subdirs_Option
856 (Argv
(Argv
'First + Makeutl
.Subdirs_Option
'Length ..
859 Remove_Switch
(Arg_Num
);
861 -- -aPdir Add dir to the project search path
863 elsif Argv
'Length > 3
864 and then Argv
(Argv
'First + 1 .. Argv
'First + 2) = "aP"
866 Prj
.Env
.Add_Directories
867 (Root_Environment
.Project_Path
,
868 Argv
(Argv
'First + 3 .. Argv
'Last));
870 -- Pass -aPdir to gnatls, but not to other tools
872 if The_Command
= List
then
873 Arg_Num
:= Arg_Num
+ 1;
875 Remove_Switch
(Arg_Num
);
878 -- -eL Follow links for files
880 elsif Argv
.all = "-eL" then
881 Follow_Links_For_Files
:= True;
882 Follow_Links_For_Dirs
:= True;
884 Remove_Switch
(Arg_Num
);
886 -- -vPx Specify verbosity while parsing project files
888 elsif Argv
'Length >= 3
889 and then Argv
(Argv
'First + 1 .. Argv
'First + 2) = "vP"
892 and then Argv
(Argv
'Last) in '0' .. '2'
894 case Argv
(Argv
'Last) is
896 Current_Verbosity
:= Prj
.Default
;
898 Current_Verbosity
:= Prj
.Medium
;
900 Current_Verbosity
:= Prj
.High
;
908 Fail
("invalid verbosity level: "
909 & Argv
(Argv
'First + 3 .. Argv
'Last));
912 Remove_Switch
(Arg_Num
);
914 -- -Pproject_file Specify project file to be used
916 elsif Argv
(Argv
'First + 1) = 'P' then
918 -- Only one -P switch can be used
920 if Project_File
/= null then
923 & ": second project file forbidden (first is """
924 & Project_File
.all & """)");
926 elsif Argv
'Length = 2 then
928 -- There is space between -P and the project file
929 -- name. -P cannot be the last option.
931 if Arg_Num
= Last_Switches
.Last
then
932 Fail
("project file name missing after -P");
935 Remove_Switch
(Arg_Num
);
936 Argv
:= Last_Switches
.Table
(Arg_Num
);
938 -- After -P, there must be a project file name,
939 -- not another switch.
941 if Argv
(Argv
'First) = '-' then
942 Fail
("project file name missing after -P");
945 Project_File
:= new String'(Argv.all);
950 -- No space between -P and project file name
953 new String'(Argv
(Argv
'First + 2 .. Argv
'Last));
956 Remove_Switch
(Arg_Num
);
958 -- -Xexternal=value Specify an external reference to be
959 -- used in project files
961 elsif Argv
'Length >= 5
962 and then Argv
(Argv
'First + 1) = 'X'
964 if not Check
(Root_Environment
.External
,
965 Argv
(Argv
'First + 2 .. Argv
'Last))
968 (Argv
.all & " is not a valid external assignment.");
971 Remove_Switch
(Arg_Num
);
973 -- --unchecked-shared-lib-imports
975 elsif Argv
.all = "--unchecked-shared-lib-imports" then
976 Opt
.Unchecked_Shared_Lib_Imports
:= True;
977 Remove_Switch
(Arg_Num
);
983 and then Argv
'Length = 2
984 and then Argv
(2) = 'U'
986 All_Projects
:= True;
987 Remove_Switch
(Arg_Num
);
990 Arg_Num
:= Arg_Num
+ 1;
994 Arg_Num
:= Arg_Num
+ 1;
997 end Inspect_Switches
;
1000 -- Add the default project search directories now, after the directories
1001 -- that have been specified by switches -aP<dir>.
1003 Prj
.Env
.Initialize_Default_Project_Path
1004 (Root_Environment
.Project_Path
,
1005 Target_Name
=> Sdefault
.Target_Name
.all);
1007 -- If there is a project file specified, parse it, get the switches
1008 -- for the tool and setup PATH environment variables.
1010 if Project_File
/= null then
1011 Prj
.Pars
.Set_Verbosity
(To
=> Current_Verbosity
);
1014 (Project
=> Project
,
1015 In_Tree
=> Project_Tree
,
1016 In_Node_Tree
=> Project_Node_Tree
,
1017 Project_File_Name
=> Project_File
.all,
1018 Env
=> Root_Environment
,
1019 Packages_To_Check
=> Packages_To_Check
);
1021 -- Prj.Pars.Parse calls Set_Standard_Output, reset to stderr
1025 if Project
= Prj
.No_Project
then
1026 Fail
("""" & Project_File
.all & """ processing failed");
1028 elsif Project
.Qualifier
= Aggregate
then
1029 Fail
("aggregate projects are not supported");
1031 elsif Aggregate_Libraries_In
(Project_Tree
) then
1032 Fail
("aggregate library projects are not supported");
1035 -- Check if a package with the name of the tool is in the project
1036 -- file and if there is one, get the switches, if any, and scan them.
1039 Pkg
: constant Prj
.Package_Id
:=
1041 (Name
=> Tool_Package_Name
,
1042 In_Packages
=> Project
.Decl
.Packages
,
1043 Shared
=> Project_Tree
.Shared
);
1045 Element
: Package_Element
;
1047 Switches_Array
: Array_Element_Id
;
1049 The_Switches
: Prj
.Variable_Value
;
1050 Current
: Prj
.String_List_Id
;
1051 The_String
: String_Element
;
1053 Main
: String_Access
:= null;
1056 if Pkg
/= No_Package
then
1057 Element
:= Project_Tree
.Shared
.Packages
.Table
(Pkg
);
1059 -- Package Gnatls has a single attribute Switches, that is not
1060 -- an associative array.
1062 if The_Command
= List
then
1065 (Variable_Name
=> Snames
.Name_Switches
,
1066 In_Variables
=> Element
.Decl
.Attributes
,
1067 Shared
=> Project_Tree
.Shared
);
1069 -- Packages Binder (for gnatbind), Cross_Reference (for
1070 -- gnatxref), Linker (for gnatlink), Finder (for gnatfind),
1071 -- have an attributed Switches, an associative array, indexed
1072 -- by the name of the file.
1074 -- They also have an attribute Default_Switches, indexed by the
1075 -- name of the programming language.
1078 -- First check if there is a single main
1080 for J
in 1 .. Last_Switches
.Last
loop
1081 if Last_Switches
.Table
(J
) (1) /= '-' then
1083 Main
:= Last_Switches
.Table
(J
);
1091 if Main
/= null then
1094 (Name
=> Name_Switches
,
1095 In_Arrays
=> Element
.Decl
.Arrays
,
1096 Shared
=> Project_Tree
.Shared
);
1099 -- If the single main has been specified as an absolute
1100 -- path, use only the simple file name. If the absolute
1101 -- path is incorrect, an error will be reported by the
1102 -- underlying tool and it does not make a difference
1103 -- what switches are used.
1105 if Is_Absolute_Path
(Main
.all) then
1106 Add_Str_To_Name_Buffer
(File_Name
(Main
.all));
1108 Add_Str_To_Name_Buffer
(Main
.all);
1111 The_Switches
:= Prj
.Util
.Value_Of
1112 (Index
=> Name_Find
,
1114 In_Array
=> Switches_Array
,
1115 Shared
=> Project_Tree
.Shared
);
1118 if The_Switches
.Kind
= Prj
.Undefined
then
1121 (Name
=> Name_Default_Switches
,
1122 In_Arrays
=> Element
.Decl
.Arrays
,
1123 Shared
=> Project_Tree
.Shared
);
1124 The_Switches
:= Prj
.Util
.Value_Of
1127 In_Array
=> Switches_Array
,
1128 Shared
=> Project_Tree
.Shared
);
1132 -- If there are switches specified in the package of the
1133 -- project file corresponding to the tool, scan them.
1135 case The_Switches
.Kind
is
1136 when Prj
.Undefined
=>
1141 Switch
: constant String :=
1142 Get_Name_String
(The_Switches
.Value
);
1144 if Switch
'Length > 0 then
1145 First_Switches
.Increment_Last
;
1146 First_Switches
.Table
(First_Switches
.Last
) :=
1147 new String'(Switch);
1152 Current := The_Switches.Values;
1153 while Current /= Prj.Nil_String loop
1154 The_String := Project_Tree.Shared.String_Elements.
1158 Switch : constant String :=
1159 Get_Name_String (The_String.Value);
1161 if Switch'Length > 0 then
1162 First_Switches.Increment_Last;
1163 First_Switches.Table (First_Switches.Last) :=
1164 new String'(Switch
);
1168 Current
:= The_String
.Next
;
1174 if The_Command
= Bind
or else The_Command
= Link
then
1175 if Project
.Object_Directory
.Name
= No_Path
then
1176 Fail
("project " & Get_Name_String
(Project
.Display_Name
)
1177 & " has no object directory");
1180 Change_Dir
(Get_Name_String
(Project
.Object_Directory
.Name
));
1183 -- Set up the env vars for project path files
1185 Prj
.Env
.Set_Ada_Paths
1186 (Project
, Project_Tree
, Including_Libraries
=> True);
1188 if The_Command
= List
then
1193 -- Gather all the arguments and invoke the executable
1196 The_Args
: Argument_List
1197 (1 .. First_Switches
.Last
+ Last_Switches
.Last
);
1198 Arg_Num
: Natural := 0;
1201 for J
in 1 .. First_Switches
.Last
loop
1202 Arg_Num
:= Arg_Num
+ 1;
1203 The_Args
(Arg_Num
) := First_Switches
.Table
(J
);
1206 for J
in 1 .. Last_Switches
.Last
loop
1207 Arg_Num
:= Arg_Num
+ 1;
1208 The_Args
(Arg_Num
) := Last_Switches
.Table
(J
);
1211 if Verbose_Mode
then
1212 Put
(Exec_Path
.all);
1214 for Arg
in The_Args
'Range loop
1215 Put
(" " & The_Args
(Arg
).all);
1221 My_Exit_Status
:= Exit_Status
(Spawn
(Exec_Path
.all, The_Args
));
1223 if not Keep_Temporary_Files
then
1224 Delete_All_Temp_Files
(Project_Tree
.Shared
);
1227 Set_Exit_Status
(My_Exit_Status
);
1233 Set_Exit_Status
(Failure
);