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
704 when Make | Compile | Bind | Link
=>
705 if Locate_Exec_On_Path
(Gprbuild
) /= null then
706 Program
:= new String'(Gprbuild);
709 if The_Command = Bind then
710 First_Switches.Append (new String'("-b"));
711 elsif The_Command
= Link
then
712 First_Switches
.Append
(new String'("-l"));
715 elsif The_Command = Bind then
717 ("'gnat bind
-P
' is no longer supported;" &
718 " use 'gprbuild
-b
' instead.");
720 elsif The_Command = Link then
722 ("'gnat Link
-P
' is no longer supported;" &
723 " use 'gprbuild
-l
' instead.");
727 if Locate_Exec_On_Path (Gprclean) /= null then
728 Program := new String'(Gprclean
);
733 if Locate_Exec_On_Path
(Gprname
) /= null then
734 Program
:= new String'(Gprname);
739 if Locate_Exec_On_Path (Gprls) /= null then
740 Program := new String'(Gprls
);
752 First_Switches
.Append
754 ("--target=" & Name_Buffer (1 .. Name_Len - 5)));
762 -- Locate the executable for the command
764 Exec_Path := Locate_Exec_On_Path (Program.all);
766 if Exec_Path = null then
767 Put_Line (Standard_Error, "could not locate " & Program.all);
771 -- If there are switches for the executable, put them as first switches
773 if Command_List (The_Command).Unixsws /= null then
774 for J in Command_List (The_Command).Unixsws'Range loop
775 First_Switches.Increment_Last;
776 First_Switches.Table (First_Switches.Last) :=
777 Command_List (The_Command).Unixsws (J);
781 -- For FIND and XREF, look for switch -P. If it is specified, then
782 -- report an error indicating that the command is no longer supporting
785 if The_Command = Find or else The_Command = Xref then
787 Argv : String_Access;
789 for Arg_Num in 1 .. Last_Switches.Last loop
790 Argv := Last_Switches.Table (Arg_Num);
792 if Argv'Length >= 2 and then
793 Argv (Argv'First .. Argv'First + 1) = "-P"
795 if The_Command = Find then
796 Fail ("'gnat find
-P
' is no longer supported;");
798 Fail ("'gnat xref
-P
' is no longer supported;");
805 if The_Command = List and then not Call_GPR_Tool then
806 Tool_Package_Name := Name_Gnatls;
807 Packages_To_Check := Packages_To_Check_By_Gnatls;
809 -- Check that the switches are consistent. Detect project file
812 Inspect_Switches : declare
813 Arg_Num : Positive := 1;
814 Argv : String_Access;
816 procedure Remove_Switch (Num : Positive);
817 -- Remove a project related switch from table Last_Switches
823 procedure Remove_Switch (Num : Positive) is
825 Last_Switches.Table (Num .. Last_Switches.Last - 1) :=
826 Last_Switches.Table (Num + 1 .. Last_Switches.Last);
827 Last_Switches.Decrement_Last;
830 -- Start of processing for Inspect_Switches
833 while Arg_Num <= Last_Switches.Last loop
834 Argv := Last_Switches.Table (Arg_Num);
836 if Argv (Argv'First) = '-' then
837 if Argv'Length = 1 then
838 Fail ("switch character cannot be followed by a blank");
841 -- --subdirs=... Specify Subdirs
843 if Argv'Length > Makeutl.Subdirs_Option'Length
847 Argv'First + Makeutl.Subdirs_Option'Length - 1) =
848 Makeutl.Subdirs_Option
852 (Argv
(Argv
'First + Makeutl
.Subdirs_Option
'Length ..
855 Remove_Switch
(Arg_Num
);
857 -- -aPdir Add dir to the project search path
859 elsif Argv
'Length > 3
860 and then Argv
(Argv
'First + 1 .. Argv
'First + 2) = "aP"
862 Prj
.Env
.Add_Directories
863 (Root_Environment
.Project_Path
,
864 Argv
(Argv
'First + 3 .. Argv
'Last));
866 -- Pass -aPdir to gnatls, but not to other tools
868 if The_Command
= List
then
869 Arg_Num
:= Arg_Num
+ 1;
871 Remove_Switch
(Arg_Num
);
874 -- -eL Follow links for files
876 elsif Argv
.all = "-eL" then
877 Follow_Links_For_Files
:= True;
878 Follow_Links_For_Dirs
:= True;
880 Remove_Switch
(Arg_Num
);
882 -- -vPx Specify verbosity while parsing project files
884 elsif Argv
'Length >= 3
885 and then Argv
(Argv
'First + 1 .. Argv
'First + 2) = "vP"
888 and then Argv
(Argv
'Last) in '0' .. '2'
890 case Argv
(Argv
'Last) is
892 Current_Verbosity
:= Prj
.Default
;
894 Current_Verbosity
:= Prj
.Medium
;
896 Current_Verbosity
:= Prj
.High
;
904 Fail
("invalid verbosity level: "
905 & Argv
(Argv
'First + 3 .. Argv
'Last));
908 Remove_Switch
(Arg_Num
);
910 -- -Pproject_file Specify project file to be used
912 elsif Argv
(Argv
'First + 1) = 'P' then
914 -- Only one -P switch can be used
916 if Project_File
/= null then
919 & ": second project file forbidden (first is """
920 & Project_File
.all & """)");
922 elsif Argv
'Length = 2 then
924 -- There is space between -P and the project file
925 -- name. -P cannot be the last option.
927 if Arg_Num
= Last_Switches
.Last
then
928 Fail
("project file name missing after -P");
931 Remove_Switch
(Arg_Num
);
932 Argv
:= Last_Switches
.Table
(Arg_Num
);
934 -- After -P, there must be a project file name,
935 -- not another switch.
937 if Argv
(Argv
'First) = '-' then
938 Fail
("project file name missing after -P");
941 Project_File
:= new String'(Argv.all);
946 -- No space between -P and project file name
949 new String'(Argv
(Argv
'First + 2 .. Argv
'Last));
952 Remove_Switch
(Arg_Num
);
954 -- -Xexternal=value Specify an external reference to be
955 -- used in project files
957 elsif Argv
'Length >= 5
958 and then Argv
(Argv
'First + 1) = 'X'
960 if not Check
(Root_Environment
.External
,
961 Argv
(Argv
'First + 2 .. Argv
'Last))
964 (Argv
.all & " is not a valid external assignment.");
967 Remove_Switch
(Arg_Num
);
969 -- --unchecked-shared-lib-imports
971 elsif Argv
.all = "--unchecked-shared-lib-imports" then
972 Opt
.Unchecked_Shared_Lib_Imports
:= True;
973 Remove_Switch
(Arg_Num
);
979 and then Argv
'Length = 2
980 and then Argv
(2) = 'U'
982 All_Projects
:= True;
983 Remove_Switch
(Arg_Num
);
986 Arg_Num
:= Arg_Num
+ 1;
990 Arg_Num
:= Arg_Num
+ 1;
993 end Inspect_Switches
;
996 -- Add the default project search directories now, after the directories
997 -- that have been specified by switches -aP<dir>.
999 Prj
.Env
.Initialize_Default_Project_Path
1000 (Root_Environment
.Project_Path
,
1001 Target_Name
=> Sdefault
.Target_Name
.all);
1003 -- If there is a project file specified, parse it, get the switches
1004 -- for the tool and setup PATH environment variables.
1006 if Project_File
/= null then
1007 Prj
.Pars
.Set_Verbosity
(To
=> Current_Verbosity
);
1010 (Project
=> Project
,
1011 In_Tree
=> Project_Tree
,
1012 In_Node_Tree
=> Project_Node_Tree
,
1013 Project_File_Name
=> Project_File
.all,
1014 Env
=> Root_Environment
,
1015 Packages_To_Check
=> Packages_To_Check
);
1017 -- Prj.Pars.Parse calls Set_Standard_Output, reset to stderr
1021 if Project
= Prj
.No_Project
then
1022 Fail
("""" & Project_File
.all & """ processing failed");
1024 elsif Project
.Qualifier
= Aggregate
then
1025 Fail
("aggregate projects are not supported");
1027 elsif Aggregate_Libraries_In
(Project_Tree
) then
1028 Fail
("aggregate library projects are not supported");
1031 -- Check if a package with the name of the tool is in the project
1032 -- file and if there is one, get the switches, if any, and scan them.
1035 Pkg
: constant Prj
.Package_Id
:=
1037 (Name
=> Tool_Package_Name
,
1038 In_Packages
=> Project
.Decl
.Packages
,
1039 Shared
=> Project_Tree
.Shared
);
1041 Element
: Package_Element
;
1043 Switches_Array
: Array_Element_Id
;
1045 The_Switches
: Prj
.Variable_Value
;
1046 Current
: Prj
.String_List_Id
;
1047 The_String
: String_Element
;
1049 Main
: String_Access
:= null;
1052 if Pkg
/= No_Package
then
1053 Element
:= Project_Tree
.Shared
.Packages
.Table
(Pkg
);
1055 -- Package Gnatls has a single attribute Switches, that is not
1056 -- an associative array.
1058 if The_Command
= List
then
1061 (Variable_Name
=> Snames
.Name_Switches
,
1062 In_Variables
=> Element
.Decl
.Attributes
,
1063 Shared
=> Project_Tree
.Shared
);
1065 -- Packages Binder (for gnatbind), Cross_Reference (for
1066 -- gnatxref), Linker (for gnatlink), Finder (for gnatfind),
1067 -- have an attributed Switches, an associative array, indexed
1068 -- by the name of the file.
1070 -- They also have an attribute Default_Switches, indexed by the
1071 -- name of the programming language.
1074 -- First check if there is a single main
1076 for J
in 1 .. Last_Switches
.Last
loop
1077 if Last_Switches
.Table
(J
) (1) /= '-' then
1079 Main
:= Last_Switches
.Table
(J
);
1087 if Main
/= null then
1090 (Name
=> Name_Switches
,
1091 In_Arrays
=> Element
.Decl
.Arrays
,
1092 Shared
=> Project_Tree
.Shared
);
1095 -- If the single main has been specified as an absolute
1096 -- path, use only the simple file name. If the absolute
1097 -- path is incorrect, an error will be reported by the
1098 -- underlying tool and it does not make a difference
1099 -- what switches are used.
1101 if Is_Absolute_Path
(Main
.all) then
1102 Add_Str_To_Name_Buffer
(File_Name
(Main
.all));
1104 Add_Str_To_Name_Buffer
(Main
.all);
1107 The_Switches
:= Prj
.Util
.Value_Of
1108 (Index
=> Name_Find
,
1110 In_Array
=> Switches_Array
,
1111 Shared
=> Project_Tree
.Shared
);
1114 if The_Switches
.Kind
= Prj
.Undefined
then
1117 (Name
=> Name_Default_Switches
,
1118 In_Arrays
=> Element
.Decl
.Arrays
,
1119 Shared
=> Project_Tree
.Shared
);
1120 The_Switches
:= Prj
.Util
.Value_Of
1123 In_Array
=> Switches_Array
,
1124 Shared
=> Project_Tree
.Shared
);
1128 -- If there are switches specified in the package of the
1129 -- project file corresponding to the tool, scan them.
1131 case The_Switches
.Kind
is
1132 when Prj
.Undefined
=>
1137 Switch
: constant String :=
1138 Get_Name_String
(The_Switches
.Value
);
1140 if Switch
'Length > 0 then
1141 First_Switches
.Increment_Last
;
1142 First_Switches
.Table
(First_Switches
.Last
) :=
1143 new String'(Switch);
1148 Current := The_Switches.Values;
1149 while Current /= Prj.Nil_String loop
1150 The_String := Project_Tree.Shared.String_Elements.
1154 Switch : constant String :=
1155 Get_Name_String (The_String.Value);
1157 if Switch'Length > 0 then
1158 First_Switches.Increment_Last;
1159 First_Switches.Table (First_Switches.Last) :=
1160 new String'(Switch
);
1164 Current
:= The_String
.Next
;
1170 if The_Command
= Bind
or else The_Command
= Link
then
1171 if Project
.Object_Directory
.Name
= No_Path
then
1172 Fail
("project " & Get_Name_String
(Project
.Display_Name
)
1173 & " has no object directory");
1176 Change_Dir
(Get_Name_String
(Project
.Object_Directory
.Name
));
1179 -- Set up the env vars for project path files
1181 Prj
.Env
.Set_Ada_Paths
1182 (Project
, Project_Tree
, Including_Libraries
=> True);
1184 if The_Command
= List
then
1189 -- Gather all the arguments and invoke the executable
1192 The_Args
: Argument_List
1193 (1 .. First_Switches
.Last
+ Last_Switches
.Last
);
1194 Arg_Num
: Natural := 0;
1197 for J
in 1 .. First_Switches
.Last
loop
1198 Arg_Num
:= Arg_Num
+ 1;
1199 The_Args
(Arg_Num
) := First_Switches
.Table
(J
);
1202 for J
in 1 .. Last_Switches
.Last
loop
1203 Arg_Num
:= Arg_Num
+ 1;
1204 The_Args
(Arg_Num
) := Last_Switches
.Table
(J
);
1207 if Verbose_Mode
then
1208 Put
(Exec_Path
.all);
1210 for Arg
in The_Args
'Range loop
1211 Put
(" " & The_Args
(Arg
).all);
1217 My_Exit_Status
:= Exit_Status
(Spawn
(Exec_Path
.all, The_Args
));
1219 if not Keep_Temporary_Files
then
1220 Delete_All_Temp_Files
(Project_Tree
.Shared
);
1223 Set_Exit_Status
(My_Exit_Status
);
1229 Set_Exit_Status
(Failure
);