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 Last_Switches
.Increment_Last
;
360 Last_Switches
.Table
(Last_Switches
.Last
) :=
361 new String'("-files=" & Get_Name_String (Temp_File_Name));
363 Unit := Units_Htable.Get_First (Project_Tree.Units_HT);
364 while Unit /= No_Unit_Index loop
366 -- We only need to put the library units, body or spec, but not
369 if Unit.File_Names (Impl) /= null
370 and then not Unit.File_Names (Impl).Locally_Removed
372 -- There is a body, check if it is for this project
375 or else Unit.File_Names (Impl).Project = Project
379 if Unit.File_Names (Spec) = null
380 or else Unit.File_Names (Spec).Locally_Removed
382 -- We have a body with no spec: we need to check if
383 -- this is a subunit, because gnatls will complain
387 Src_Ind : constant Source_File_Index :=
388 Sinput.P.Load_Project_File
390 (Unit.File_Names (Impl).Path.Name));
392 Subunit := Sinput.P.Source_File_Is_Subunit (Src_Ind);
398 (Get_Name_String (Unit.File_Names (Impl).Display_File),
399 Check_File => False);
403 elsif Unit.File_Names (Spec) /= null
404 and then not Unit.File_Names (Spec).Locally_Removed
406 -- We have a spec with no body. Check if it is for this project
409 or else Unit.File_Names (Spec).Project = Project
412 (Get_Name_String (Unit.File_Names (Spec).Display_File),
413 Check_File => False);
417 Unit := Units_Htable.Get_Next (Project_Tree.Units_HT);
420 if FD /= Invalid_FD then
424 Osint.Fail ("disk full");
434 procedure Output_Version is
437 Put_Line (Gnatvsn.Gnat_Version_String);
438 Put_Line ("Copyright 1996-" & Gnatvsn.Current_Year
439 & ", Free Software Foundation, Inc.");
450 Put_Line ("List of available commands");
453 for C in Command_List'Range loop
455 Put (To_Lower (Command_List (C).Cname.all));
457 Put (Program_Name (Command_List (C).Unixcmd.all, "gnat").all);
460 Sws : Argument_List_Access renames Command_List (C).Unixsws;
463 for J in Sws'Range loop
476 procedure Check_Version_And_Help is new Check_Version_And_Help_G (Usage);
478 -- Start of processing for GNATCmd
481 -- All output from GNATCmd is debugging or error output: send to stderr
491 Prj.Tree.Initialize (Root_Environment, Gnatmake_Flags);
493 Project_Node_Tree := new Project_Node_Tree_Data;
494 Prj.Tree.Initialize (Project_Node_Tree);
496 Prj.Initialize (Project_Tree);
499 Last_Switches.Set_Last (0);
502 First_Switches.Set_Last (0);
504 -- Put the command line in environment variable GNAT_DRIVER_COMMAND_LINE,
505 -- so that the spawned tool may know the way the GNAT driver was invoked.
508 Add_Str_To_Name_Buffer (Command_Name);
510 for J in 1 .. Argument_Count loop
511 Add_Char_To_Name_Buffer (' ');
512 Add_Str_To_Name_Buffer (Argument (J));
515 Setenv ("GNAT_DRIVER_COMMAND_LINE", Name_Buffer (1 .. Name_Len));
517 -- Add the directory where the GNAT driver is invoked in front of the path,
518 -- if the GNAT driver is invoked with directory information.
521 Command : constant String := Command_Name;
524 for Index in reverse Command'Range loop
525 if Command (Index) = Directory_Separator then
527 Absolute_Dir : constant String :=
528 Normalize_Pathname (Command (Command'First .. Index));
529 PATH : constant String :=
530 Absolute_Dir & Path_Separator & Getenv ("PATH").all;
532 Setenv ("PATH", PATH);
540 -- Scan the command line
542 -- First, scan to detect --version and/or --help
544 Check_Version_And_Help ("GNAT", "1996");
548 if Command_Arg <= Argument_Count
549 and then Argument (Command_Arg) = "-v"
551 Verbose_Mode := True;
552 Command_Arg := Command_Arg + 1;
554 elsif Command_Arg <= Argument_Count
555 and then Argument (Command_Arg) = "-dn"
557 Keep_Temporary_Files := True;
558 Command_Arg := Command_Arg + 1;
565 -- If there is no command, just output the usage
567 if Command_Arg > Argument_Count then
572 The_Command := Real_Command_Type'Value (Argument (Command_Arg));
575 when Constraint_Error =>
577 -- Check if it is an alternate command
580 Alternate : Alternate_Command;
583 Alternate := Alternate_Command'Value (Argument (Command_Arg));
584 The_Command := Corresponding_To (Alternate);
587 when Constraint_Error =>
589 Fail ("unknown command: " & Argument (Command_Arg));
593 -- Get the arguments from the command line and from the eventual
594 -- argument file(s) specified on the command line.
596 for Arg in Command_Arg + 1 .. Argument_Count loop
598 The_Arg : constant String := Argument (Arg);
601 -- Check if an argument file is specified
603 if The_Arg (The_Arg'First) = '@
' then
605 Arg_File : Ada.Text_IO.File_Type;
606 Line : String (1 .. 256);
610 -- Open the file and fail if the file cannot be found
613 Open (Arg_File, In_File,
614 The_Arg (The_Arg'First + 1 .. The_Arg'Last));
618 Put (Standard_Error, "Cannot open argument file """);
620 The_Arg (The_Arg'First + 1 .. The_Arg'Last));
621 Put_Line (Standard_Error, """");
625 -- Read line by line and put the content of each non-
626 -- empty line in the Last_Switches table.
628 while not End_Of_File (Arg_File) loop
629 Get_Line (Arg_File, Line, Last);
632 Last_Switches.Increment_Last;
633 Last_Switches.Table (Last_Switches.Last) :=
634 new String'(Line
(1 .. Last
));
642 -- It is not an argument file; just put the argument in
643 -- the Last_Switches table.
645 Last_Switches
.Increment_Last
;
646 Last_Switches
.Table
(Last_Switches
.Last
) := new String'(The_Arg);
652 Program : String_Access;
653 Exec_Path : String_Access;
654 Get_Target : Boolean := False;
657 if The_Command = Stack then
659 -- Never call gnatstack with a prefix
661 Program := new String'(Command_List
(The_Command
).Unixcmd
.all);
665 Program_Name
(Command_List
(The_Command
).Unixcmd
.all, "gnat");
667 -- If we want to invoke gnatmake/gnatclean with -P, then check if
668 -- gprbuild/gprclean is available; if it is, use gprbuild/gprclean
669 -- instead of gnatmake/gnatclean.
670 -- Ditto for gnatname -> gprname and gnatls -> gprls.
672 if The_Command
= Make
673 or else The_Command
= Compile
674 or else The_Command
= Bind
675 or else The_Command
= Link
676 or else The_Command
= Clean
677 or else The_Command
= Name
678 or else The_Command
= List
681 Switch
: String_Access
;
682 Dash_V_Switch
: constant String := "-V";
685 for J
in 1 .. Last_Switches
.Last
loop
686 Switch
:= Last_Switches
.Table
(J
);
688 if The_Command
= List
and then Switch
.all = Dash_V_Switch
690 Call_GPR_Tool
:= False;
694 if Switch
'Length >= 2
695 and then Switch
(Switch
'First .. Switch
'First + 1) = "-P"
697 Call_GPR_Tool
:= True;
701 if Call_GPR_Tool
then
703 when Make | Compile | Bind | Link
=>
704 if Locate_Exec_On_Path
(Gprbuild
) /= null then
705 Program
:= new String'(Gprbuild);
708 if The_Command = Bind then
709 First_Switches.Append (new String'("-b"));
710 elsif The_Command
= Link
then
711 First_Switches
.Append
(new String'("-l"));
714 elsif The_Command = Bind then
716 ("'gnat bind
-P
' is no longer supported;" &
717 " use 'gprbuild
-b
' instead.");
719 elsif The_Command = Link then
721 ("'gnat Link
-P
' is no longer supported;" &
722 " use 'gprbuild
-l
' instead.");
726 if Locate_Exec_On_Path (Gprclean) /= null then
727 Program := new String'(Gprclean
);
732 if Locate_Exec_On_Path
(Gprname
) /= null then
733 Program
:= new String'(Gprname);
738 if Locate_Exec_On_Path (Gprls) /= null then
739 Program := new String'(Gprls
);
751 First_Switches
.Append
753 ("--target=" & Name_Buffer (1 .. Name_Len - 5)));
761 -- Locate the executable for the command
763 Exec_Path := Locate_Exec_On_Path (Program.all);
765 if Exec_Path = null then
766 Put_Line (Standard_Error, "could not locate " & Program.all);
770 -- If there are switches for the executable, put them as first switches
772 if Command_List (The_Command).Unixsws /= null then
773 for J in Command_List (The_Command).Unixsws'Range loop
774 First_Switches.Increment_Last;
775 First_Switches.Table (First_Switches.Last) :=
776 Command_List (The_Command).Unixsws (J);
780 -- For FIND and XREF, look for switch -P. If it is specified, then
781 -- report an error indicating that the command is no longer supporting
784 if The_Command = Find or else The_Command = Xref then
786 Argv : String_Access;
788 for Arg_Num in 1 .. Last_Switches.Last loop
789 Argv := Last_Switches.Table (Arg_Num);
791 if Argv'Length >= 2 and then
792 Argv (Argv'First .. Argv'First + 1) = "-P"
794 if The_Command = Find then
795 Fail ("'gnat find
-P
' is no longer supported;");
797 Fail ("'gnat xref
-P
' is no longer supported;");
804 if The_Command = List and then not Call_GPR_Tool then
805 Tool_Package_Name := Name_Gnatls;
806 Packages_To_Check := Packages_To_Check_By_Gnatls;
808 -- Check that the switches are consistent. Detect project file
811 Inspect_Switches : declare
812 Arg_Num : Positive := 1;
813 Argv : String_Access;
815 procedure Remove_Switch (Num : Positive);
816 -- Remove a project related switch from table Last_Switches
822 procedure Remove_Switch (Num : Positive) is
824 Last_Switches.Table (Num .. Last_Switches.Last - 1) :=
825 Last_Switches.Table (Num + 1 .. Last_Switches.Last);
826 Last_Switches.Decrement_Last;
829 -- Start of processing for Inspect_Switches
832 while Arg_Num <= Last_Switches.Last loop
833 Argv := Last_Switches.Table (Arg_Num);
835 if Argv (Argv'First) = '-' then
836 if Argv'Length = 1 then
837 Fail ("switch character cannot be followed by a blank");
840 -- --subdirs=... Specify Subdirs
842 if Argv'Length > Makeutl.Subdirs_Option'Length
846 Argv'First + Makeutl.Subdirs_Option'Length - 1) =
847 Makeutl.Subdirs_Option
851 (Argv
(Argv
'First + Makeutl
.Subdirs_Option
'Length ..
854 Remove_Switch
(Arg_Num
);
856 -- -aPdir Add dir to the project search path
858 elsif Argv
'Length > 3
859 and then Argv
(Argv
'First + 1 .. Argv
'First + 2) = "aP"
861 Prj
.Env
.Add_Directories
862 (Root_Environment
.Project_Path
,
863 Argv
(Argv
'First + 3 .. Argv
'Last));
865 -- Pass -aPdir to gnatls, but not to other tools
867 if The_Command
= List
then
868 Arg_Num
:= Arg_Num
+ 1;
870 Remove_Switch
(Arg_Num
);
873 -- -eL Follow links for files
875 elsif Argv
.all = "-eL" then
876 Follow_Links_For_Files
:= True;
877 Follow_Links_For_Dirs
:= True;
879 Remove_Switch
(Arg_Num
);
881 -- -vPx Specify verbosity while parsing project files
883 elsif Argv
'Length >= 3
884 and then Argv
(Argv
'First + 1 .. Argv
'First + 2) = "vP"
887 and then Argv
(Argv
'Last) in '0' .. '2'
889 case Argv
(Argv
'Last) is
891 Current_Verbosity
:= Prj
.Default
;
893 Current_Verbosity
:= Prj
.Medium
;
895 Current_Verbosity
:= Prj
.High
;
903 Fail
("invalid verbosity level: "
904 & Argv
(Argv
'First + 3 .. Argv
'Last));
907 Remove_Switch
(Arg_Num
);
909 -- -Pproject_file Specify project file to be used
911 elsif Argv
(Argv
'First + 1) = 'P' then
913 -- Only one -P switch can be used
915 if Project_File
/= null then
918 & ": second project file forbidden (first is """
919 & Project_File
.all & """)");
921 elsif Argv
'Length = 2 then
923 -- There is space between -P and the project file
924 -- name. -P cannot be the last option.
926 if Arg_Num
= Last_Switches
.Last
then
927 Fail
("project file name missing after -P");
930 Remove_Switch
(Arg_Num
);
931 Argv
:= Last_Switches
.Table
(Arg_Num
);
933 -- After -P, there must be a project file name,
934 -- not another switch.
936 if Argv
(Argv
'First) = '-' then
937 Fail
("project file name missing after -P");
940 Project_File
:= new String'(Argv.all);
945 -- No space between -P and project file name
948 new String'(Argv
(Argv
'First + 2 .. Argv
'Last));
951 Remove_Switch
(Arg_Num
);
953 -- -Xexternal=value Specify an external reference to be
954 -- used in project files
956 elsif Argv
'Length >= 5
957 and then Argv
(Argv
'First + 1) = 'X'
959 if not Check
(Root_Environment
.External
,
960 Argv
(Argv
'First + 2 .. Argv
'Last))
963 (Argv
.all & " is not a valid external assignment.");
966 Remove_Switch
(Arg_Num
);
968 -- --unchecked-shared-lib-imports
970 elsif Argv
.all = "--unchecked-shared-lib-imports" then
971 Opt
.Unchecked_Shared_Lib_Imports
:= True;
972 Remove_Switch
(Arg_Num
);
978 and then Argv
'Length = 2
979 and then Argv
(2) = 'U'
981 All_Projects
:= True;
982 Remove_Switch
(Arg_Num
);
985 Arg_Num
:= Arg_Num
+ 1;
989 Arg_Num
:= Arg_Num
+ 1;
992 end Inspect_Switches
;
995 -- Add the default project search directories now, after the directories
996 -- that have been specified by switches -aP<dir>.
998 Prj
.Env
.Initialize_Default_Project_Path
999 (Root_Environment
.Project_Path
,
1000 Target_Name
=> Sdefault
.Target_Name
.all);
1002 -- If there is a project file specified, parse it, get the switches
1003 -- for the tool and setup PATH environment variables.
1005 if Project_File
/= null then
1006 Prj
.Pars
.Set_Verbosity
(To
=> Current_Verbosity
);
1009 (Project
=> Project
,
1010 In_Tree
=> Project_Tree
,
1011 In_Node_Tree
=> Project_Node_Tree
,
1012 Project_File_Name
=> Project_File
.all,
1013 Env
=> Root_Environment
,
1014 Packages_To_Check
=> Packages_To_Check
);
1016 -- Prj.Pars.Parse calls Set_Standard_Output, reset to stderr
1020 if Project
= Prj
.No_Project
then
1021 Fail
("""" & Project_File
.all & """ processing failed");
1023 elsif Project
.Qualifier
= Aggregate
then
1024 Fail
("aggregate projects are not supported");
1026 elsif Aggregate_Libraries_In
(Project_Tree
) then
1027 Fail
("aggregate library projects are not supported");
1030 -- Check if a package with the name of the tool is in the project
1031 -- file and if there is one, get the switches, if any, and scan them.
1034 Pkg
: constant Prj
.Package_Id
:=
1036 (Name
=> Tool_Package_Name
,
1037 In_Packages
=> Project
.Decl
.Packages
,
1038 Shared
=> Project_Tree
.Shared
);
1040 Element
: Package_Element
;
1042 Switches_Array
: Array_Element_Id
;
1044 The_Switches
: Prj
.Variable_Value
;
1045 Current
: Prj
.String_List_Id
;
1046 The_String
: String_Element
;
1048 Main
: String_Access
:= null;
1051 if Pkg
/= No_Package
then
1052 Element
:= Project_Tree
.Shared
.Packages
.Table
(Pkg
);
1054 -- Package Gnatls has a single attribute Switches, that is not
1055 -- an associative array.
1057 if The_Command
= List
then
1060 (Variable_Name
=> Snames
.Name_Switches
,
1061 In_Variables
=> Element
.Decl
.Attributes
,
1062 Shared
=> Project_Tree
.Shared
);
1064 -- Packages Binder (for gnatbind), Cross_Reference (for
1065 -- gnatxref), Linker (for gnatlink), Finder (for gnatfind),
1066 -- have an attributed Switches, an associative array, indexed
1067 -- by the name of the file.
1069 -- They also have an attribute Default_Switches, indexed by the
1070 -- name of the programming language.
1073 -- First check if there is a single main
1075 for J
in 1 .. Last_Switches
.Last
loop
1076 if Last_Switches
.Table
(J
) (1) /= '-' then
1078 Main
:= Last_Switches
.Table
(J
);
1086 if Main
/= null then
1089 (Name
=> Name_Switches
,
1090 In_Arrays
=> Element
.Decl
.Arrays
,
1091 Shared
=> Project_Tree
.Shared
);
1094 -- If the single main has been specified as an absolute
1095 -- path, use only the simple file name. If the absolute
1096 -- path is incorrect, an error will be reported by the
1097 -- underlying tool and it does not make a difference
1098 -- what switches are used.
1100 if Is_Absolute_Path
(Main
.all) then
1101 Add_Str_To_Name_Buffer
(File_Name
(Main
.all));
1103 Add_Str_To_Name_Buffer
(Main
.all);
1106 The_Switches
:= Prj
.Util
.Value_Of
1107 (Index
=> Name_Find
,
1109 In_Array
=> Switches_Array
,
1110 Shared
=> Project_Tree
.Shared
);
1113 if The_Switches
.Kind
= Prj
.Undefined
then
1116 (Name
=> Name_Default_Switches
,
1117 In_Arrays
=> Element
.Decl
.Arrays
,
1118 Shared
=> Project_Tree
.Shared
);
1119 The_Switches
:= Prj
.Util
.Value_Of
1122 In_Array
=> Switches_Array
,
1123 Shared
=> Project_Tree
.Shared
);
1127 -- If there are switches specified in the package of the
1128 -- project file corresponding to the tool, scan them.
1130 case The_Switches
.Kind
is
1131 when Prj
.Undefined
=>
1136 Switch
: constant String :=
1137 Get_Name_String
(The_Switches
.Value
);
1139 if Switch
'Length > 0 then
1140 First_Switches
.Increment_Last
;
1141 First_Switches
.Table
(First_Switches
.Last
) :=
1142 new String'(Switch);
1147 Current := The_Switches.Values;
1148 while Current /= Prj.Nil_String loop
1149 The_String := Project_Tree.Shared.String_Elements.
1153 Switch : constant String :=
1154 Get_Name_String (The_String.Value);
1156 if Switch'Length > 0 then
1157 First_Switches.Increment_Last;
1158 First_Switches.Table (First_Switches.Last) :=
1159 new String'(Switch
);
1163 Current
:= The_String
.Next
;
1169 if The_Command
= Bind
or else The_Command
= Link
then
1170 if Project
.Object_Directory
.Name
= No_Path
then
1171 Fail
("project " & Get_Name_String
(Project
.Display_Name
)
1172 & " has no object directory");
1175 Change_Dir
(Get_Name_String
(Project
.Object_Directory
.Name
));
1178 -- Set up the env vars for project path files
1180 Prj
.Env
.Set_Ada_Paths
1181 (Project
, Project_Tree
, Including_Libraries
=> True);
1183 if The_Command
= List
then
1188 -- Gather all the arguments and invoke the executable
1191 The_Args
: Argument_List
1192 (1 .. First_Switches
.Last
+ Last_Switches
.Last
);
1193 Arg_Num
: Natural := 0;
1196 for J
in 1 .. First_Switches
.Last
loop
1197 Arg_Num
:= Arg_Num
+ 1;
1198 The_Args
(Arg_Num
) := First_Switches
.Table
(J
);
1201 for J
in 1 .. Last_Switches
.Last
loop
1202 Arg_Num
:= Arg_Num
+ 1;
1203 The_Args
(Arg_Num
) := Last_Switches
.Table
(J
);
1206 if Verbose_Mode
then
1207 Put
(Exec_Path
.all);
1209 for Arg
in The_Args
'Range loop
1210 Put
(" " & The_Args
(Arg
).all);
1216 My_Exit_Status
:= Exit_Status
(Spawn
(Exec_Path
.all, The_Args
));
1217 Set_Exit_Status
(My_Exit_Status
);
1223 Set_Exit_Status
(Failure
);