[multiple changes]
[platform/upstream/gcc.git] / gcc / ada / make.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                                 M A K E                                  --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2003 Free Software Foundation, Inc.          --
10 --                                                                          --
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 2,  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 COPYING.  If not, write --
19 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
20 -- MA 02111-1307, USA.                                                      --
21 --                                                                          --
22 -- GNAT was originally developed  by the GNAT team at  New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
24 --                                                                          --
25 ------------------------------------------------------------------------------
26
27 with ALI;      use ALI;
28 with ALI.Util; use ALI.Util;
29 with Csets;
30 with Debug;
31 with Fmap;
32 with Fname;    use Fname;
33 with Fname.SF; use Fname.SF;
34 with Fname.UF; use Fname.UF;
35 with Gnatvsn;  use Gnatvsn;
36 with Hostparm; use Hostparm;
37 with Makeusg;
38 with MLib.Prj;
39 with MLib.Tgt; use MLib.Tgt;
40 with MLib.Utl;
41 with Namet;    use Namet;
42 with Opt;      use Opt;
43 with Osint.M;  use Osint.M;
44 with Osint;    use Osint;
45 with Gnatvsn;
46 with Output;   use Output;
47 with Prj;      use Prj;
48 with Prj.Com;
49 with Prj.Env;
50 with Prj.Ext;
51 with Prj.Pars;
52 with Prj.Util;
53 with SFN_Scan;
54 with Sinput.P;
55 with Snames;   use Snames;
56 with Switch;   use Switch;
57 with Switch.M; use Switch.M;
58 with System.HTable;
59 with Targparm;
60 with Tempdir;
61
62 with Ada.Exceptions;   use Ada.Exceptions;
63 with Ada.Command_Line; use Ada.Command_Line;
64
65 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
66 with GNAT.Case_Util;            use GNAT.Case_Util;
67
68 package body Make is
69
70    use ASCII;
71    --  Make control characters visible
72
73    Standard_Library_Package_Body_Name : constant String := "s-stalib.adb";
74    --  Every program depends on this package, that must then be checked,
75    --  especially when -f and -a are used.
76
77    type Sigint_Handler is access procedure;
78
79    procedure Install_Int_Handler (Handler : Sigint_Handler);
80    pragma Import (C, Install_Int_Handler, "__gnat_install_int_handler");
81    --  Called by Gnatmake to install the SIGINT handler below
82
83    procedure Sigint_Intercepted;
84    --  Called when the program is interrupted by Ctrl-C to delete the
85    --  temporary mapping files and configuration pragmas files.
86
87    -------------------------
88    -- Note on terminology --
89    -------------------------
90
91    --  In this program, we use the phrase "termination" of a file name to
92    --  refer to the suffix that appears after the unit name portion. Very
93    --  often this is simply the extension, but in some cases, the sequence
94    --  may be more complex, for example in main.1.ada, the termination in
95    --  this name is ".1.ada" and in main_.ada the termination is "_.ada".
96
97    -------------------------------------
98    -- Queue (Q) Manipulation Routines --
99    -------------------------------------
100
101    --  The Q is used in Compile_Sources below. Its implementation uses the
102    --  GNAT generic package Table (basically an extensible array). Q_Front
103    --  points to the first valid element in the Q, whereas Q.First is the first
104    --  element ever enqueued, while Q.Last - 1 is the last element in the Q.
105    --
106    --        +---+--------------+---+---+---+-----------+---+--------
107    --    Q   |   |  ........    |   |   |   | .......   |   |
108    --        +---+--------------+---+---+---+-----------+---+--------
109    --          ^                  ^                       ^
110    --       Q.First             Q_Front               Q.Last - 1
111    --
112    --  The elements comprised between Q.First and Q_Front - 1 are the
113    --  elements that have been enqueued and then dequeued, while the
114    --  elements between Q_Front and Q.Last - 1 are the elements currently
115    --  in the Q. When the Q is initialized Q_Front = Q.First = Q.Last.
116    --  After Compile_Sources has terminated its execution, Q_Front = Q.Last
117    --  and the elements contained between Q.Front and Q.Last-1 are those that
118    --  were explored and thus marked by Compile_Sources. Whenever the Q is
119    --  reinitialized, the elements between Q.First and Q.Last - 1 are unmarked.
120
121    procedure Init_Q;
122    --  Must be called to (re)initialize the Q.
123
124    procedure Insert_Q
125      (Source_File : File_Name_Type;
126       Source_Unit : Unit_Name_Type := No_Name);
127    --  Inserts Source_File at the end of Q. Provide Source_Unit when
128    --  possible for external use (gnatdist).
129
130    function Empty_Q return Boolean;
131    --  Returns True if Q is empty.
132
133    procedure Extract_From_Q
134      (Source_File : out File_Name_Type;
135       Source_Unit : out Unit_Name_Type);
136    --  Extracts the first element from the Q.
137
138    procedure Insert_Project_Sources
139      (The_Project  : Project_Id;
140       All_Projects : Boolean;
141       Into_Q       : Boolean);
142    --  If Into_Q is True, insert all sources of the project file(s) that are
143    --  not already marked into the Q. If Into_Q is False, call Osint.Add_File
144    --  for the first source, then insert all other sources that are not already
145    --  marked into the Q. If All_Projects is True, all sources of all projects
146    --  are concerned; otherwise, only sources of The_Project are concerned,
147    --  including, if The_Project is an extending project, sources inherited
148    --  from projects being extended.
149
150    First_Q_Initialization : Boolean := True;
151    --  Will be set to false after Init_Q has been called once.
152
153    Q_Front : Natural;
154    --  Points to the first valid element in the Q.
155
156    Unique_Compile : Boolean := False;
157    --  Set to True if -u or -U or a project file with no main is used
158
159    Unique_Compile_All_Projects : Boolean := False;
160    --  Set to True if -U is used
161
162    RTS_Specified : String_Access := null;
163    --  Used to detect multiple --RTS= switches
164
165    type Q_Record is record
166       File : File_Name_Type;
167       Unit : Unit_Name_Type;
168    end record;
169    --  File is the name of the file to compile. Unit is for gnatdist
170    --  use in order to easily get the unit name of a file to compile
171    --  when its name is krunched or declared in gnat.adc.
172
173    package Q is new Table.Table (
174      Table_Component_Type => Q_Record,
175      Table_Index_Type     => Natural,
176      Table_Low_Bound      => 0,
177      Table_Initial        => 4000,
178      Table_Increment      => 100,
179      Table_Name           => "Make.Q");
180    --  This is the actual Q.
181
182
183    --  Package Mains is used to store the mains specified on the command line
184    --  and to retrieve them when a project file is used, to verify that the
185    --  files exist and that they belong to a project file.
186
187    package Mains is
188
189       --  Mains are stored in a table. An index is used to retrieve the mains
190       --  from the table.
191
192       procedure Add_Main (Name : String);
193       --  Add one main to the table
194
195       procedure Delete;
196       --  Empty the table
197
198       procedure Reset;
199       --  Reset the index to the beginning of the table
200
201       function Next_Main return String;
202       --  Increase the index and return the next main.
203       --  If table is exhausted, return an empty string.
204
205    end Mains;
206
207    --  The following instantiations and variables are necessary to save what
208    --  is found on the command line, in case there is a project file specified.
209
210    package Saved_Gcc_Switches is new Table.Table (
211      Table_Component_Type => String_Access,
212      Table_Index_Type     => Integer,
213      Table_Low_Bound      => 1,
214      Table_Initial        => 20,
215      Table_Increment      => 100,
216      Table_Name           => "Make.Saved_Gcc_Switches");
217
218    package Saved_Binder_Switches is new Table.Table (
219      Table_Component_Type => String_Access,
220      Table_Index_Type     => Integer,
221      Table_Low_Bound      => 1,
222      Table_Initial        => 20,
223      Table_Increment      => 100,
224      Table_Name           => "Make.Saved_Binder_Switches");
225
226    package Saved_Linker_Switches is new Table.Table
227      (Table_Component_Type => String_Access,
228       Table_Index_Type     => Integer,
229       Table_Low_Bound      => 1,
230       Table_Initial        => 20,
231       Table_Increment      => 100,
232       Table_Name           => "Make.Saved_Linker_Switches");
233
234    package Switches_To_Check is new Table.Table (
235      Table_Component_Type => String_Access,
236      Table_Index_Type     => Integer,
237      Table_Low_Bound      => 1,
238      Table_Initial        => 20,
239      Table_Increment      => 100,
240      Table_Name           => "Make.Switches_To_Check");
241
242    package Library_Paths is new Table.Table (
243      Table_Component_Type => String_Access,
244      Table_Index_Type     => Integer,
245      Table_Low_Bound      => 1,
246      Table_Initial        => 20,
247      Table_Increment      => 100,
248      Table_Name           => "Make.Library_Paths");
249
250    package Failed_Links is new Table.Table (
251      Table_Component_Type => File_Name_Type,
252      Table_Index_Type     => Integer,
253      Table_Low_Bound      => 1,
254      Table_Initial        => 10,
255      Table_Increment      => 100,
256      Table_Name           => "Make.Failed_Links");
257
258    package Successful_Links is new Table.Table (
259      Table_Component_Type => File_Name_Type,
260      Table_Index_Type     => Integer,
261      Table_Low_Bound      => 1,
262      Table_Initial        => 10,
263      Table_Increment      => 100,
264      Table_Name           => "Make.Successful_Links");
265
266    package Library_Projs is new Table.Table (
267      Table_Component_Type => Project_Id,
268      Table_Index_Type     => Integer,
269      Table_Low_Bound      => 1,
270      Table_Initial        => 10,
271      Table_Increment      => 100,
272      Table_Name           => "Make.Library_Projs");
273
274    type Linker_Options_Data is record
275       Project : Project_Id;
276       Options : String_List_Id;
277    end record;
278
279    package Linker_Opts is new Table.Table (
280      Table_Component_Type => Linker_Options_Data,
281      Table_Index_Type     => Integer,
282      Table_Low_Bound      => 1,
283      Table_Initial        => 10,
284      Table_Increment      => 100,
285      Table_Name           => "Make.Linker_Opts");
286
287    --  Two variables to keep the last binder and linker switch index
288    --  in tables Binder_Switches and Linker_Switches, before adding
289    --  switches from the project file (if any) and switches from the
290    --  command line (if any).
291
292    Last_Binder_Switch : Integer := 0;
293    Last_Linker_Switch : Integer := 0;
294
295    Normalized_Switches : Argument_List_Access := new Argument_List (1 .. 10);
296    Last_Norm_Switch    : Natural := 0;
297
298    Saved_Maximum_Processes : Natural := 0;
299
300    type Arg_List_Ref is access Argument_List;
301    The_Saved_Gcc_Switches : Arg_List_Ref;
302
303    Project_File_Name : String_Access  := null;
304    --  The path name of the main project file, if any
305
306    Project_File_Name_Present : Boolean := False;
307    --  True when -P is used with a space between -P and the project file name
308
309    Current_Verbosity : Prj.Verbosity  := Prj.Default;
310    --  Verbosity to parse the project files
311
312    Main_Project : Prj.Project_Id := No_Project;
313    --  The project id of the main project file, if any
314
315    Project_Object_Directory : Project_Id := No_Project;
316    --  The object directory of the project for the last compilation.
317    --  Avoid calling Change_Dir if the current working directory is already
318    --  this directory
319
320    --  Packages of project files where unknown attributes are errors.
321
322    Naming_String   : aliased String := "naming";
323    Builder_String  : aliased String := "builder";
324    Compiler_String : aliased String := "compiler";
325    Binder_String   : aliased String := "binder";
326    Linker_String   : aliased String := "linker";
327
328    Gnatmake_Packages : aliased String_List :=
329      (Naming_String   'Access,
330       Builder_String  'Access,
331       Compiler_String 'Access,
332       Binder_String   'Access,
333       Linker_String   'Access);
334
335    Packages_To_Check_By_Gnatmake : constant String_List_Access :=
336      Gnatmake_Packages'Access;
337
338    procedure Add_Source_Dir (N : String);
339    --  Call Add_Src_Search_Dir.
340    --  Output one line when in verbose mode.
341
342    procedure Add_Source_Directories is
343      new Prj.Env.For_All_Source_Dirs (Action => Add_Source_Dir);
344
345    procedure Add_Object_Dir (N : String);
346    --  Call Add_Lib_Search_Dir.
347    --  Output one line when in verbose mode.
348
349    procedure Add_Object_Directories is
350      new Prj.Env.For_All_Object_Dirs (Action => Add_Object_Dir);
351
352    procedure Change_To_Object_Directory (Project : Project_Id);
353    --  Change to the object directory of project Project, if this is not
354    --  already the current working directory.
355
356    type Bad_Compilation_Info is record
357       File  : File_Name_Type;
358       Unit  : Unit_Name_Type;
359       Found : Boolean;
360    end record;
361    --  File is the name of the file for which a compilation failed.
362    --  Unit is for gnatdist use in order to easily get the unit name
363    --  of a file when its name is krunched or declared in gnat.adc.
364    --  Found is False if the compilation failed because the file could
365    --  not be found.
366
367    package Bad_Compilation is new Table.Table (
368      Table_Component_Type => Bad_Compilation_Info,
369      Table_Index_Type     => Natural,
370      Table_Low_Bound      => 1,
371      Table_Initial        => 20,
372      Table_Increment      => 100,
373      Table_Name           => "Make.Bad_Compilation");
374    --  Full name of all the source files for which compilation fails.
375
376    Do_Compile_Step : Boolean := True;
377    Do_Bind_Step    : Boolean := True;
378    Do_Link_Step    : Boolean := True;
379    --  Flags to indicate what step should be executed.
380    --  Can be set to False with the switches -c, -b and -l.
381    --  These flags are reset to True for each invokation of procedure Gnatmake.
382
383    Shared_String : aliased String := "-shared";
384
385    No_Shared_Switch  : aliased Argument_List := (1 .. 0 => null);
386    Shared_Switch     : aliased Argument_List := (1 => Shared_String'Access);
387    Bind_Shared       : Argument_List_Access := No_Shared_Switch'Access;
388    --  Switch to added in front of gnatbind switches. By default no switch is
389    --  added. Switch "-shared" is added if there is a non-static Library
390    --  Project File.
391
392    Bind_Shared_Known : Boolean := False;
393    --  Set to True after the first time Bind_Shared is computed
394
395    procedure Make_Failed (S1 : String; S2 : String := ""; S3 : String := "");
396    --  Delete all temp files created by Gnatmake and call Osint.Fail,
397    --  with the parameter S1, S2 and S3 (see osint.ads).
398    --  This is called from the Prj hierarchy and the MLib hierarchy.
399
400    --------------------------
401    -- Obsolete Executables --
402    --------------------------
403
404    Executable_Obsolete : Boolean := False;
405    --  Executable_Obsolete is initially set to False for each executable,
406    --  and is set to True whenever one of the source of the executable is
407    --  compiled, or has already been compiled for another executable.
408
409    Max_Header : constant := 200; --  Arbitrary
410
411    type Header_Num is range 1 .. Max_Header;
412    --  Header_Num for the hash table Obsoleted below
413
414    function Hash (F : Name_Id) return Header_Num;
415    --  Hash function for the hash table Obsoleted below
416
417    package Obsoleted is new System.HTable.Simple_HTable
418      (Header_Num => Header_Num,
419       Element    => Boolean,
420       No_Element => False,
421       Key        => Name_Id,
422       Hash       => Hash,
423       Equal      => "=");
424    --  A hash table to keep all files that have been compiled, to detect
425    --  if an executable is up to date or not.
426
427    procedure Enter_Into_Obsoleted (F : Name_Id);
428    --  Enter a file name, without directory information, into the has table
429    --  Obsoleted.
430
431    function Is_In_Obsoleted (F : Name_Id) return Boolean;
432    --  Check if a file name, without directory information, has already been
433    --  entered into the hash table Obsoleted.
434
435    type Dependency is record
436       This       : Name_Id;
437       Depends_On : Name_Id;
438    end record;
439    --  Components of table Dependencies below.
440
441    package Dependencies is new Table.Table (
442      Table_Component_Type => Dependency,
443      Table_Index_Type     => Integer,
444      Table_Low_Bound      => 1,
445      Table_Initial        => 20,
446      Table_Increment      => 100,
447      Table_Name           => "Make.Dependencies");
448    --  A table to keep dependencies, to be able to decide if an executable
449    --  is obsolete.
450
451    procedure Add_Dependency (S : Name_Id; On : Name_Id);
452    --  Add one entry in table Dependencies
453
454    ----------------------------
455    -- Arguments and Switches --
456    ----------------------------
457
458    Arguments : Argument_List_Access;
459    --  Used to gather the arguments for invocation of the compiler
460
461    Last_Argument : Natural := 0;
462    --  Last index of arguments in Arguments above
463
464    Arguments_Collected : Boolean := False;
465    --  Set to True when the arguments for the next invocation of the compiler
466    --  have been collected.
467
468    Arguments_Project : Project_Id;
469    --  Project id, if any, of the source to be compiled
470
471    Arguments_Path_Name : File_Name_Type;
472    --  Full path of the source to be compiled, when Arguments_Project is not
473    --  No_Project.
474
475    Dummy_Switch : constant String_Access := new String'("- ");
476    --  Used to initialized Prev_Switch in procedure Check
477
478    procedure Add_Arguments (Args : Argument_List);
479    --  Add arguments to global variable Arguments, increasing its size
480    --  if necessary and adjusting Last_Argument.
481
482    function Configuration_Pragmas_Switch
483      (For_Project : Project_Id) return Argument_List;
484    --  Return an argument list of one element, if there is a configuration
485    --  pragmas file to be specified for For_Project,
486    --  otherwise return an empty argument list.
487
488    ----------------------
489    -- Marking Routines --
490    ----------------------
491
492    Marking_Label : Byte := 1;
493    --  Value to mark the source files
494
495    procedure Mark (Source_File : File_Name_Type);
496    --  Mark Source_File. Marking is used to signal that Source_File has
497    --  already been inserted in the Q.
498
499    function Is_Marked (Source_File : File_Name_Type) return Boolean;
500    --  Returns True if Source_File was previously marked.
501
502    -------------------
503    -- Misc Routines --
504    -------------------
505
506    procedure List_Depend;
507    --  Prints to standard output the list of object dependencies. This list
508    --  can be used directly in a Makefile. A call to Compile_Sources must
509    --  precede the call to List_Depend. Also because this routine uses the
510    --  ALI files that were originally loaded and scanned by Compile_Sources,
511    --  no additional ALI files should be scanned between the two calls (i.e.
512    --  between the call to Compile_Sources and List_Depend.)
513
514    procedure Inform (N : Name_Id := No_Name; Msg : String);
515    --  Prints out the program name followed by a colon, N and S.
516
517    procedure List_Bad_Compilations;
518    --  Prints out the list of all files for which the compilation failed.
519
520    procedure Verbose_Msg
521      (N1     : Name_Id;
522       S1     : String;
523       N2     : Name_Id := No_Name;
524       S2     : String  := "";
525       Prefix : String  := "  -> ");
526    --  If the verbose flag (Verbose_Mode) is set then print Prefix to standard
527    --  output followed by N1 and S1. If N2 /= No_Name then N2 is then printed
528    --  after S1. S2 is printed last. Both N1 and N2 are printed in quotation
529    --  marks.
530
531    Usage_Needed : Boolean := True;
532    --  Flag used to make sure Makeusg is call at most once
533
534    procedure Usage;
535    --  Call Makeusg, if Usage_Needed is True.
536    --  Set Usage_Needed to False.
537
538    procedure Debug_Msg (S : String; N : Name_Id);
539    --  If Debug.Debug_Flag_W is set outputs string S followed by name N.
540
541    type Project_Array is array (Positive range <>) of Project_Id;
542    No_Projects : constant Project_Array := (1 .. 0 => No_Project);
543
544    procedure Recursive_Compute_Depth
545      (Project : Project_Id;
546       Visited : Project_Array;
547       Depth   : Natural);
548    --  Compute depth of Project and of the projects it depends on
549
550    -----------------------
551    -- Gnatmake Routines --
552    -----------------------
553
554    Gnatmake_Called : Boolean := False;
555    --  Set to True when procedure Gnatmake is called.
556    --  Attempt to delete temporary files is made only when Gnatmake_Called
557    --  is True.
558
559    subtype Lib_Mark_Type is Byte;
560    --  Used in Mark_Directory
561
562    Ada_Lib_Dir : constant Lib_Mark_Type := 1;
563    --  Used to mark a directory as a GNAT lib dir
564
565    --  Note that the notion of GNAT lib dir is no longer used. The code
566    --  related to it has not been removed to give an idea on how to use
567    --  the directory prefix marking mechanism.
568
569    --  An Ada library directory is a directory containing ali and object
570    --  files but no source files for the bodies (the specs can be in the
571    --  same or some other directory). These directories are specified
572    --  in the Gnatmake command line with the switch "-Adir" (to specify the
573    --  spec location -Idir cab be used).  Gnatmake skips the missing sources
574    --  whose ali are in Ada library directories. For an explanation of why
575    --  Gnatmake behaves that way, see the spec of Make.Compile_Sources.
576    --  The directory lookup penalty is incurred every single time this
577    --  routine is called.
578
579    procedure Check_Steps;
580    --  Check what steps (Compile, Bind, Link) must be executed.
581    --  Set the step flags accordingly.
582
583    function Is_External_Assignment (Argv : String) return Boolean;
584    --  Verify that an external assignment switch is syntactically correct.
585    --  Correct forms are
586    --      -Xname=value
587    --      -X"name=other value"
588    --  Assumptions: 'First = 1, Argv (1 .. 2) = "-X"
589    --  When this function returns True, the external assignment has
590    --  been entered by a call to Prj.Ext.Add, so that in a project
591    --  file, External ("name") will return "value".
592
593    function In_Ada_Lib_Dir  (File : File_Name_Type) return Boolean;
594    --  Get directory prefix of this file and get lib mark stored in name
595    --  table for this directory. Then check if an Ada lib mark has been set.
596
597    procedure Mark_Directory
598      (Dir  : String;
599       Mark : Lib_Mark_Type);
600    --  Store Dir in name table and set lib mark as name info to identify
601    --  Ada libraries.
602
603    Output_Is_Object : Boolean := True;
604    --  Set to False when using a switch -S for the compiler
605
606    procedure Check_For_S_Switch;
607    --  Set Output_Is_Object to False when the -S switch is used for the
608    --  compiler.
609
610    function Switches_Of
611      (Source_File      : Name_Id;
612       Source_File_Name : String;
613       Naming           : Naming_Data;
614       In_Package       : Package_Id;
615       Allow_ALI        : Boolean) return Variable_Value;
616    --  Return the switches for the source file in the specified package
617    --  of a project file. If the Source_File ends with a standard GNAT
618    --  extension (".ads" or ".adb"), try first the full name, then the
619    --  name without the extension, then, if Allow_ALI is True, the name with
620    --  the extension ".ali". If there is no switches for either names, try the
621    --  default switches for Ada. If all failed, return No_Variable_Value.
622
623    procedure Test_If_Relative_Path
624      (Switch             : in out String_Access;
625       Parent             : String_Access;
626       Including_L_Switch : Boolean := True);
627    --  Test if Switch is a relative search path switch.
628    --  If it is, fail if Parent is null, otherwise prepend the path with
629    --  Parent. This subprogram is only called when using project files.
630    --  For gnatbind switches, Including_L_Switch is False, because the
631    --  argument of the -L switch is not a path.
632
633    function Is_In_Object_Directory
634      (Source_File   : File_Name_Type;
635       Full_Lib_File : File_Name_Type) return Boolean;
636    --  Check if, when using a project file, the ALI file is in the project
637    --  directory of the ultimate extending project. If it is not, we ignore
638    --  the fact that this ALI file is read-only.
639
640    ----------------------------------------------------
641    -- Compiler, Binder & Linker Data and Subprograms --
642    ----------------------------------------------------
643
644    Gcc             : String_Access := Program_Name ("gcc");
645    Gnatbind        : String_Access := Program_Name ("gnatbind");
646    Gnatlink        : String_Access := Program_Name ("gnatlink");
647    --  Default compiler, binder, linker programs
648
649    Saved_Gcc       : String_Access := null;
650    Saved_Gnatbind  : String_Access := null;
651    Saved_Gnatlink  : String_Access := null;
652    --  Given by the command line. Will be used, if non null.
653
654    Gcc_Path        : String_Access :=
655                        GNAT.OS_Lib.Locate_Exec_On_Path (Gcc.all);
656    Gnatbind_Path   : String_Access :=
657                        GNAT.OS_Lib.Locate_Exec_On_Path (Gnatbind.all);
658    Gnatlink_Path   : String_Access :=
659                        GNAT.OS_Lib.Locate_Exec_On_Path (Gnatlink.all);
660    --  Path for compiler, binder, linker programs, defaulted now for gnatdist.
661    --  Changed later if overridden on command line.
662
663    Comp_Flag         : constant String_Access := new String'("-c");
664    Output_Flag       : constant String_Access := new String'("-o");
665    Ada_Flag_1        : constant String_Access := new String'("-x");
666    Ada_Flag_2        : constant String_Access := new String'("ada");
667    No_gnat_adc       : constant String_Access := new String'("-gnatA");
668    GNAT_Flag         : constant String_Access := new String'("-gnatpg");
669    Do_Not_Check_Flag : constant String_Access := new String'("-x");
670
671    Object_Suffix     : constant String := Get_Object_Suffix.all;
672    Executable_Suffix : constant String := Get_Executable_Suffix.all;
673
674    Syntax_Only : Boolean := False;
675    --  Set to True when compiling with -gnats
676
677    Display_Executed_Programs : Boolean := True;
678    --  Set to True if name of commands should be output on stderr.
679
680    Output_File_Name_Seen : Boolean := False;
681    --  Set to True after having scanned the file_name for
682    --  switch "-o file_name"
683
684    Object_Directory_Seen : Boolean := False;
685    --  Set to True after having scanned the object directory for
686    --  switch "-D obj_dir".
687
688    Object_Directory_Path : String_Access := null;
689    --  The path name of the object directory, set with switch -D.
690
691    type Make_Program_Type is (None, Compiler, Binder, Linker);
692
693    Program_Args : Make_Program_Type := None;
694    --  Used to indicate if we are scanning gnatmake, gcc, gnatbind, or gnatbind
695    --  options within the gnatmake command line.
696    --  Used in Scan_Make_Arg only, but must be a global variable.
697
698    Temporary_Config_File : Boolean := False;
699    --  Set to True when there is a temporary config file used for a project
700    --  file, to avoid displaying the -gnatec switch for a temporary file.
701
702    procedure Add_Switches
703      (The_Package : Package_Id;
704       File_Name   : String;
705       Program     : Make_Program_Type);
706    procedure Add_Switch
707      (S             : String_Access;
708       Program       : Make_Program_Type;
709       Append_Switch : Boolean := True;
710       And_Save      : Boolean := True);
711    procedure Add_Switch
712      (S             : String;
713       Program       : Make_Program_Type;
714       Append_Switch : Boolean := True;
715       And_Save      : Boolean := True);
716    --  Make invokes one of three programs (the compiler, the binder or the
717    --  linker). For the sake of convenience, some program specific switches
718    --  can be passed directly on the gnatmake commande line. This procedure
719    --  records these switches so that gnamake can pass them to the right
720    --  program.  S is the switch to be added at the end of the command line
721    --  for Program if Append_Switch is True. If Append_Switch is False S is
722    --  added at the beginning of the command line.
723
724    procedure Check
725      (Source_File : File_Name_Type;
726       The_Args    : Argument_List;
727       Lib_File    : File_Name_Type;
728       Read_Only   : Boolean;
729       ALI         : out ALI_Id;
730       O_File      : out File_Name_Type;
731       O_Stamp     : out Time_Stamp_Type);
732    --  Determines whether the library file Lib_File is up-to-date or not. The
733    --  full name (with path information) of the object file corresponding to
734    --  Lib_File is returned in O_File. Its time stamp is saved in O_Stamp.
735    --  ALI is the ALI_Id corresponding to Lib_File. If Lib_File in not
736    --  up-to-date, then the corresponding source file needs to be recompiled.
737    --  In this case ALI = No_ALI_Id.
738
739    procedure Check_Linker_Options
740      (E_Stamp : Time_Stamp_Type;
741       O_File  : out File_Name_Type;
742       O_Stamp : out Time_Stamp_Type);
743    --  Checks all linker options for linker files that are newer
744    --  than E_Stamp. If such objects are found, the youngest object
745    --  is returned in O_File and its stamp in O_Stamp.
746    --
747    --  If no obsolete linker files were found, the first missing
748    --  linker file is returned in O_File and O_Stamp is empty.
749    --  Otherwise O_File is No_File.
750
751    procedure Collect_Arguments
752      (Source_File : File_Name_Type;
753       Args        : Argument_List);
754    --  Collect all arguments for a source to be compiled, including those
755    --  that come from a project file.
756
757    procedure Display (Program : String; Args : Argument_List);
758    --  Displays Program followed by the arguments in Args if variable
759    --  Display_Executed_Programs is set. The lower bound of Args must be 1.
760
761    -----------------
762    --  Mapping files
763    -----------------
764
765    type Temp_File_Names is
766      array (Project_Id range <>, Positive range <>) of Name_Id;
767
768    type Temp_Files_Ptr is access Temp_File_Names;
769
770    type Indices is array (Project_Id range <>) of Natural;
771
772    type Indices_Ptr is access Indices;
773
774    type Free_File_Indices is array
775      (Project_Id range <>, Positive range <>) of Positive;
776
777    type Free_Indices_Ptr is access Free_File_Indices;
778
779    The_Mapping_File_Names : Temp_Files_Ptr;
780    --  For each project, the name ids of the temporary mapping files used
781
782    Last_Mapping_File_Names : Indices_Ptr;
783    --  For each project, the index of the last mapping file created
784
785    The_Free_Mapping_File_Indices : Free_Indices_Ptr;
786    --  For each project, the indices in The_Mapping_File_Names of the mapping
787    --  file names that can be reused for subsequent compilations.
788
789    Last_Free_Indices : Indices_Ptr;
790    --  For each project, the number of mapping files that can be reused
791
792    Gnatmake_Mapping_File : String_Access := null;
793    --  The path name of a mapping file specified by switch -C=
794
795    procedure Delete_Mapping_Files;
796    --  Delete all temporary mapping files
797
798    procedure Init_Mapping_File
799      (Project : Project_Id;
800       File_Index : in out Natural);
801    --  Create a new temporary mapping file, and fill it with the project file
802    --  mappings, when using project file(s). The out parameter File_Index is
803    --  the index to the name of the file in the array The_Mapping_File_Names.
804
805    procedure Delete_Temp_Config_Files;
806    --  Delete all temporary config files
807
808    procedure Delete_All_Temp_Files;
809    --  Delete all temp files (config files, mapping files, path files)
810
811    -------------------
812    -- Add_Arguments --
813    -------------------
814
815    procedure Add_Arguments (Args : Argument_List) is
816    begin
817       if Arguments = null then
818          Arguments := new Argument_List (1 .. Args'Length + 10);
819
820       else
821          while Last_Argument + Args'Length > Arguments'Last loop
822             declare
823                New_Arguments : Argument_List_Access :=
824                  new Argument_List (1 .. Arguments'Last * 2);
825
826             begin
827                New_Arguments (1 .. Last_Argument) :=
828                  Arguments (1 .. Last_Argument);
829                Arguments := New_Arguments;
830             end;
831          end loop;
832       end if;
833
834       Arguments (Last_Argument + 1 .. Last_Argument + Args'Length) := Args;
835       Last_Argument := Last_Argument + Args'Length;
836    end Add_Arguments;
837
838    --------------------
839    -- Add_Dependency --
840    --------------------
841
842    procedure Add_Dependency (S : Name_Id; On : Name_Id) is
843    begin
844       Dependencies.Increment_Last;
845       Dependencies.Table (Dependencies.Last) := (S, On);
846    end Add_Dependency;
847
848    --------------------
849    -- Add_Object_Dir --
850    --------------------
851
852    procedure Add_Object_Dir (N : String) is
853    begin
854       Add_Lib_Search_Dir (N);
855
856       if Opt.Verbose_Mode then
857          Write_Str ("Adding object directory """);
858          Write_Str (N);
859          Write_Str (""".");
860          Write_Eol;
861       end if;
862    end Add_Object_Dir;
863
864    --------------------
865    -- Add_Source_Dir --
866    --------------------
867
868    procedure Add_Source_Dir (N : String) is
869    begin
870       Add_Src_Search_Dir (N);
871
872       if Opt.Verbose_Mode then
873          Write_Str ("Adding source directory """);
874          Write_Str (N);
875          Write_Str (""".");
876          Write_Eol;
877       end if;
878    end Add_Source_Dir;
879
880    ----------------
881    -- Add_Switch --
882    ----------------
883
884    procedure Add_Switch
885      (S             : String_Access;
886       Program       : Make_Program_Type;
887       Append_Switch : Boolean := True;
888       And_Save      : Boolean := True)
889    is
890       generic
891          with package T is new Table.Table (<>);
892       procedure Generic_Position (New_Position : out Integer);
893       --  Generic procedure that chooses a position for S in T at the
894       --  beginning or the end, depending on the boolean Append_Switch.
895       --  Calling this procedure may expand the table.
896
897       ----------------------
898       -- Generic_Position --
899       ----------------------
900
901       procedure  Generic_Position (New_Position : out Integer) is
902       begin
903          T.Increment_Last;
904
905          if Append_Switch then
906             New_Position := Integer (T.Last);
907          else
908             for J in reverse T.Table_Index_Type'Succ (T.First) .. T.Last loop
909                T.Table (J) := T.Table (T.Table_Index_Type'Pred (J));
910             end loop;
911
912             New_Position := Integer (T.First);
913          end if;
914       end Generic_Position;
915
916       procedure Gcc_Switches_Pos    is new Generic_Position (Gcc_Switches);
917       procedure Binder_Switches_Pos is new Generic_Position (Binder_Switches);
918       procedure Linker_Switches_Pos is new Generic_Position (Linker_Switches);
919
920       procedure Saved_Gcc_Switches_Pos is new
921         Generic_Position (Saved_Gcc_Switches);
922
923       procedure Saved_Binder_Switches_Pos is new
924         Generic_Position (Saved_Binder_Switches);
925
926       procedure Saved_Linker_Switches_Pos is new
927         Generic_Position (Saved_Linker_Switches);
928
929       New_Position : Integer;
930
931    --  Start of processing for Add_Switch
932
933    begin
934       if And_Save then
935          case Program is
936             when Compiler =>
937                Saved_Gcc_Switches_Pos (New_Position);
938                Saved_Gcc_Switches.Table (New_Position) := S;
939
940             when Binder   =>
941                Saved_Binder_Switches_Pos (New_Position);
942                Saved_Binder_Switches.Table (New_Position) := S;
943
944             when Linker   =>
945                Saved_Linker_Switches_Pos (New_Position);
946                Saved_Linker_Switches.Table (New_Position) := S;
947
948             when None =>
949                raise Program_Error;
950          end case;
951
952       else
953          case Program is
954             when Compiler =>
955                Gcc_Switches_Pos (New_Position);
956                Gcc_Switches.Table (New_Position) := S;
957
958             when Binder   =>
959                Binder_Switches_Pos (New_Position);
960                Binder_Switches.Table (New_Position) := S;
961
962             when Linker   =>
963                Linker_Switches_Pos (New_Position);
964                Linker_Switches.Table (New_Position) := S;
965
966             when None =>
967                raise Program_Error;
968          end case;
969       end if;
970    end Add_Switch;
971
972    procedure Add_Switch
973      (S             : String;
974       Program       : Make_Program_Type;
975       Append_Switch : Boolean := True;
976       And_Save      : Boolean := True)
977    is
978    begin
979       Add_Switch (S             => new String'(S),
980                   Program       => Program,
981                   Append_Switch => Append_Switch,
982                   And_Save      => And_Save);
983    end Add_Switch;
984
985    ------------------
986    -- Add_Switches --
987    ------------------
988
989    procedure Add_Switches
990      (The_Package : Package_Id;
991       File_Name   : String;
992       Program     : Make_Program_Type)
993    is
994       Switches      : Variable_Value;
995       Switch_List   : String_List_Id;
996       Element       : String_Element;
997
998    begin
999       if File_Name'Length > 0 then
1000          Name_Len := File_Name'Length;
1001          Name_Buffer (1 .. Name_Len) := File_Name;
1002          Switches :=
1003            Switches_Of
1004            (Source_File      => Name_Find,
1005             Source_File_Name => File_Name,
1006             Naming           => Projects.Table (Main_Project).Naming,
1007             In_Package       => The_Package,
1008             Allow_ALI        =>
1009               Program = Binder or else Program = Linker);
1010
1011          case Switches.Kind is
1012             when Undefined =>
1013                null;
1014
1015             when List =>
1016                Program_Args := Program;
1017
1018                Switch_List := Switches.Values;
1019
1020                while Switch_List /= Nil_String loop
1021                   Element := String_Elements.Table (Switch_List);
1022                   Get_Name_String (Element.Value);
1023
1024                   if Name_Len > 0 then
1025                      declare
1026                         Argv : constant String := Name_Buffer (1 .. Name_Len);
1027                         --  We need a copy, because Name_Buffer may be
1028                         --  modified.
1029
1030                      begin
1031                         if Opt.Verbose_Mode then
1032                            Write_Str ("   Adding ");
1033                            Write_Line (Argv);
1034                         end if;
1035
1036                         Scan_Make_Arg (Argv, And_Save => False);
1037                      end;
1038                   end if;
1039
1040                   Switch_List := Element.Next;
1041                end loop;
1042
1043             when Single =>
1044                Program_Args := Program;
1045                Get_Name_String (Switches.Value);
1046
1047                if Name_Len > 0 then
1048                   declare
1049                      Argv : constant String := Name_Buffer (1 .. Name_Len);
1050                      --  We need a copy, because Name_Buffer may be modified
1051
1052                   begin
1053                      if Opt.Verbose_Mode then
1054                         Write_Str ("   Adding ");
1055                         Write_Line (Argv);
1056                      end if;
1057
1058                      Scan_Make_Arg (Argv, And_Save => False);
1059                   end;
1060                end if;
1061          end case;
1062       end if;
1063    end Add_Switches;
1064
1065    ----------
1066    -- Bind --
1067    ----------
1068
1069    procedure Bind (ALI_File : File_Name_Type; Args : Argument_List) is
1070       Bind_Args : Argument_List (1 .. Args'Last + 2);
1071       Bind_Last : Integer;
1072       Success   : Boolean;
1073
1074    begin
1075       pragma Assert (Args'First = 1);
1076
1077       --  Optimize the simple case where the gnatbind command line looks like
1078       --     gnatbind -aO. -I- file.ali   --into->   gnatbind file.adb
1079
1080       if Args'Length = 2
1081         and then Args (Args'First).all = "-aO" & Normalized_CWD
1082         and then Args (Args'Last).all = "-I-"
1083         and then ALI_File = Strip_Directory (ALI_File)
1084       then
1085          Bind_Last := Args'First - 1;
1086
1087       else
1088          Bind_Last := Args'Last;
1089          Bind_Args (Args'Range) := Args;
1090       end if;
1091
1092       --  It is completely pointless to re-check source file time stamps.
1093       --  This has been done already by gnatmake
1094
1095       Bind_Last := Bind_Last + 1;
1096       Bind_Args (Bind_Last) := Do_Not_Check_Flag;
1097
1098       Get_Name_String (ALI_File);
1099
1100       Bind_Last := Bind_Last + 1;
1101       Bind_Args (Bind_Last) := new String'(Name_Buffer (1 .. Name_Len));
1102
1103       GNAT.OS_Lib.Normalize_Arguments (Bind_Args (Args'First .. Bind_Last));
1104
1105       Display (Gnatbind.all, Bind_Args (Args'First .. Bind_Last));
1106
1107       if Gnatbind_Path = null then
1108          Make_Failed ("error, unable to locate ", Gnatbind.all);
1109       end if;
1110
1111       GNAT.OS_Lib.Spawn
1112         (Gnatbind_Path.all, Bind_Args (Args'First .. Bind_Last), Success);
1113
1114       if not Success then
1115          raise Bind_Failed;
1116       end if;
1117    end Bind;
1118
1119    --------------------------------
1120    -- Change_To_Object_Directory --
1121    --------------------------------
1122
1123    procedure Change_To_Object_Directory (Project : Project_Id) is
1124    begin
1125       --  Nothing to do if the current working directory is alresdy the one
1126       --  we want.
1127
1128       if Project_Object_Directory /= Project then
1129          Project_Object_Directory := Project;
1130
1131          --  If in a real project, set the working directory to the object
1132          --  directory of the project.
1133
1134          if Project /= No_Project then
1135             Change_Dir
1136               (Get_Name_String (Projects.Table (Project).Object_Directory));
1137
1138          --  Otherwise, for sources outside of any project, set the working
1139          --  directory to the object directory of the main project.
1140
1141          elsif Main_Project /= No_Project then
1142             Change_Dir
1143               (Get_Name_String
1144                  (Projects.Table (Main_Project).Object_Directory));
1145          end if;
1146       end if;
1147    end Change_To_Object_Directory;
1148
1149    -----------
1150    -- Check --
1151    -----------
1152
1153    procedure Check
1154      (Source_File : File_Name_Type;
1155       The_Args    : Argument_List;
1156       Lib_File    : File_Name_Type;
1157       Read_Only   : Boolean;
1158       ALI         : out ALI_Id;
1159       O_File      : out File_Name_Type;
1160       O_Stamp     : out Time_Stamp_Type)
1161    is
1162       function First_New_Spec (A : ALI_Id) return File_Name_Type;
1163       --  Looks in the with table entries of A and returns the spec file name
1164       --  of the first withed unit (subprogram) for which no spec existed when
1165       --  A was generated but for which there exists one now, implying that A
1166       --  is now obsolete. If no such unit is found No_File is returned.
1167       --  Otherwise the spec file name of the unit is returned.
1168       --
1169       --  **WARNING** in the event of Uname format modifications, one *MUST*
1170       --  make sure this function is also updated.
1171       --
1172       --  Note: This function should really be in ali.adb and use Uname
1173       --  services, but this causes the whole compiler to be dragged along
1174       --  for gnatbind and gnatmake.
1175
1176       --------------------
1177       -- First_New_Spec --
1178       --------------------
1179
1180       function First_New_Spec (A : ALI_Id) return File_Name_Type is
1181          Spec_File_Name : File_Name_Type := No_File;
1182
1183          function New_Spec (Uname : Unit_Name_Type) return Boolean;
1184          --  Uname is the name of the spec or body of some ada unit.
1185          --  This function returns True if the Uname is the name of a body
1186          --  which has a spec not mentioned inali file A. If True is returned
1187          --  Spec_File_Name above is set to the name of this spec file.
1188
1189          --------------
1190          -- New_Spec --
1191          --------------
1192
1193          function New_Spec (Uname : Unit_Name_Type) return Boolean is
1194             Spec_Name : Unit_Name_Type;
1195             File_Name : File_Name_Type;
1196
1197          begin
1198             --  Test whether Uname is the name of a body unit (ie ends with %b)
1199
1200             Get_Name_String (Uname);
1201             pragma
1202               Assert (Name_Len > 2 and then Name_Buffer (Name_Len - 1) = '%');
1203
1204             if Name_Buffer (Name_Len) /= 'b' then
1205                return False;
1206             end if;
1207
1208             --  Convert unit name into spec name
1209
1210             --  ??? this code seems dubious in presence of pragma
1211             --  Source_File_Name since there is no more direct relationship
1212             --  between unit name and file name.
1213
1214             --  ??? Further, what about alternative subunit naming
1215
1216             Name_Buffer (Name_Len) := 's';
1217             Spec_Name := Name_Find;
1218             File_Name := Get_File_Name (Spec_Name, Subunit => False);
1219
1220             --  Look if File_Name is mentioned in A's sdep list.
1221             --  If not look if the file exists. If it does return True.
1222
1223             for D in
1224               ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep
1225             loop
1226                if Sdep.Table (D).Sfile = File_Name then
1227                   return False;
1228                end if;
1229             end loop;
1230
1231             if Full_Source_Name (File_Name) /= No_File then
1232                Spec_File_Name := File_Name;
1233                return True;
1234             end if;
1235
1236             return False;
1237          end New_Spec;
1238
1239       --  Start of processing for First_New_Spec
1240
1241       begin
1242          U_Chk : for U in
1243            ALIs.Table (A).First_Unit .. ALIs.Table (A).Last_Unit
1244          loop
1245             exit U_Chk when Units.Table (U).Utype = Is_Body_Only
1246                and then New_Spec (Units.Table (U).Uname);
1247
1248             for W in Units.Table (U).First_With
1249                        ..
1250                      Units.Table (U).Last_With
1251             loop
1252                exit U_Chk when
1253                  Withs.Table (W).Afile /= No_File
1254                  and then New_Spec (Withs.Table (W).Uname);
1255             end loop;
1256          end loop U_Chk;
1257
1258          return Spec_File_Name;
1259       end First_New_Spec;
1260
1261       ---------------------------------
1262       -- Data declarations for Check --
1263       ---------------------------------
1264
1265       Full_Lib_File : File_Name_Type;
1266       --  Full name of current library file
1267
1268       Full_Obj_File : File_Name_Type;
1269       --  Full name of the object file corresponding to Lib_File.
1270
1271       Lib_Stamp : Time_Stamp_Type;
1272       --  Time stamp of the current ada library file.
1273
1274       Obj_Stamp : Time_Stamp_Type;
1275       --  Time stamp of the current object file.
1276
1277       Modified_Source : File_Name_Type;
1278       --  The first source in Lib_File whose current time stamp differs
1279       --  from that stored in Lib_File.
1280
1281       New_Spec : File_Name_Type;
1282       --  If Lib_File contains in its W (with) section a body (for a
1283       --  subprogram) for which there exists a spec and the spec did not
1284       --  appear in the Sdep section of Lib_File, New_Spec contains the file
1285       --  name of this new spec.
1286
1287       Source_Name : Name_Id;
1288       Text        : Text_Buffer_Ptr;
1289
1290       Prev_Switch : String_Access;
1291       --  Previous switch processed
1292
1293       Arg : Arg_Id := Arg_Id'First;
1294       --  Current index in Args.Table for a given unit (init to stop warning)
1295
1296       Switch_Found : Boolean;
1297       --  True if a given switch has been found
1298
1299    --  Start of processing for Check
1300
1301    begin
1302       pragma Assert (Lib_File /= No_File);
1303
1304       --  If the ALI file is read-only, set temporarily
1305       --  Check_Object_Consistency to False: we don't care if the object file
1306       --  is not there; presumably, a library will be used for linking.
1307
1308       if Read_Only then
1309          declare
1310             Saved_Check_Object_Consistency : constant Boolean :=
1311                                                Opt.Check_Object_Consistency;
1312          begin
1313             Opt.Check_Object_Consistency := False;
1314             Text := Read_Library_Info (Lib_File);
1315             Opt.Check_Object_Consistency := Saved_Check_Object_Consistency;
1316          end;
1317
1318       else
1319          Text := Read_Library_Info (Lib_File);
1320       end if;
1321
1322       Full_Lib_File := Full_Library_Info_Name;
1323       Full_Obj_File := Full_Object_File_Name;
1324       Lib_Stamp     := Current_Library_File_Stamp;
1325       Obj_Stamp     := Current_Object_File_Stamp;
1326
1327       if Full_Lib_File = No_File then
1328          Verbose_Msg (Lib_File, "being checked ...", Prefix => "  ");
1329       else
1330          Verbose_Msg (Full_Lib_File, "being checked ...", Prefix => "  ");
1331       end if;
1332
1333       ALI     := No_ALI_Id;
1334       O_File  := Full_Obj_File;
1335       O_Stamp := Obj_Stamp;
1336
1337       if Text = null then
1338          if Full_Lib_File = No_File then
1339             Verbose_Msg (Lib_File, "missing.");
1340
1341          elsif Obj_Stamp (Obj_Stamp'First) = ' ' then
1342             Verbose_Msg (Full_Obj_File, "missing.");
1343
1344          else
1345             Verbose_Msg
1346               (Full_Lib_File, "(" & String (Lib_Stamp) & ") newer than",
1347                Full_Obj_File, "(" & String (Obj_Stamp) & ")");
1348          end if;
1349
1350       else
1351          ALI := Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True);
1352          Free (Text);
1353
1354          if ALI = No_ALI_Id then
1355             Verbose_Msg (Full_Lib_File, "incorrectly formatted ALI file");
1356             return;
1357
1358          elsif ALIs.Table (ALI).Ver (1 .. ALIs.Table (ALI).Ver_Len) /=
1359                  Verbose_Library_Version
1360          then
1361             Verbose_Msg (Full_Lib_File, "compiled with old GNAT version");
1362             ALI := No_ALI_Id;
1363             return;
1364          end if;
1365
1366          --  Don't take Ali file into account if it was generated with
1367          --  errors.
1368
1369          if ALIs.Table (ALI).Compile_Errors then
1370             Verbose_Msg (Full_Lib_File, "had errors, must be recompiled");
1371             ALI := No_ALI_Id;
1372             return;
1373          end if;
1374
1375          --  Don't take Ali file into account if it was generated without
1376          --  object.
1377
1378          if Opt.Operating_Mode /= Opt.Check_Semantics
1379            and then ALIs.Table (ALI).No_Object
1380          then
1381             Verbose_Msg (Full_Lib_File, "has no corresponding object");
1382             ALI := No_ALI_Id;
1383             return;
1384          end if;
1385
1386          --  Check for matching compiler switches if needed
1387
1388          if Opt.Check_Switches then
1389
1390             --  First, collect all the switches
1391
1392             Collect_Arguments (Source_File, The_Args);
1393
1394             Prev_Switch := Dummy_Switch;
1395
1396             Get_Name_String (ALIs.Table (ALI).Sfile);
1397
1398             Switches_To_Check.Set_Last (0);
1399
1400             for J in 1 .. Last_Argument loop
1401
1402                --  Skip non switches -c, -I and -o switches
1403
1404                if Arguments (J) (1) = '-'
1405                  and then Arguments (J) (2) /= 'c'
1406                  and then Arguments (J) (2) /= 'o'
1407                  and then Arguments (J) (2) /= 'I'
1408                then
1409                   Normalize_Compiler_Switches
1410                     (Arguments (J).all,
1411                      Normalized_Switches,
1412                      Last_Norm_Switch);
1413
1414                   for K in 1 .. Last_Norm_Switch loop
1415                      Switches_To_Check.Increment_Last;
1416                      Switches_To_Check.Table (Switches_To_Check.Last) :=
1417                        Normalized_Switches (K);
1418                   end loop;
1419                end if;
1420             end loop;
1421
1422             for J in 1 .. Switches_To_Check.Last loop
1423
1424                --  Comparing switches is delicate because gcc reorders
1425                --  a number of switches, according to lang-specs.h, but
1426                --  gnatmake doesn't have the sufficient knowledge to
1427                --  perform the same reordering. Instead, we ignore orders
1428                --  between different "first letter" switches, but keep
1429                --  orders between same switches, e.g -O -O2 is different
1430                --  than -O2 -O, but -g -O is equivalent to -O -g.
1431
1432                if Switches_To_Check.Table (J) (2) /= Prev_Switch (2) or else
1433                    (Prev_Switch'Length >= 6 and then
1434                     Prev_Switch (2 .. 5) = "gnat" and then
1435                     Switches_To_Check.Table (J)'Length >= 6 and then
1436                     Switches_To_Check.Table (J) (2 .. 5) = "gnat" and then
1437                     Prev_Switch (6) /= Switches_To_Check.Table (J) (6))
1438                then
1439                   Prev_Switch := Switches_To_Check.Table (J);
1440                   Arg :=
1441                     Units.Table (ALIs.Table (ALI).First_Unit).First_Arg;
1442                end if;
1443
1444                Switch_Found := False;
1445
1446                for K in Arg ..
1447                  Units.Table (ALIs.Table (ALI).First_Unit).Last_Arg
1448                loop
1449                   if
1450                     Switches_To_Check.Table (J).all = Args.Table (K).all
1451                   then
1452                      Arg := K + 1;
1453                      Switch_Found := True;
1454                      exit;
1455                   end if;
1456                end loop;
1457
1458                if not Switch_Found then
1459                   if Opt.Verbose_Mode then
1460                      Verbose_Msg (ALIs.Table (ALI).Sfile,
1461                                   "switch mismatch """ &
1462                                   Switches_To_Check.Table (J).all & '"');
1463                   end if;
1464
1465                   ALI := No_ALI_Id;
1466                   return;
1467                end if;
1468             end loop;
1469
1470             if Switches_To_Check.Last /=
1471               Integer (Units.Table (ALIs.Table (ALI).First_Unit).Last_Arg -
1472                        Units.Table (ALIs.Table (ALI).First_Unit).First_Arg + 1)
1473             then
1474                if Opt.Verbose_Mode then
1475                   Verbose_Msg (ALIs.Table (ALI).Sfile,
1476                                "different number of switches");
1477
1478                   for K in Units.Table (ALIs.Table (ALI).First_Unit).First_Arg
1479                     .. Units.Table (ALIs.Table (ALI).First_Unit).Last_Arg
1480                   loop
1481                      Write_Str (Args.Table (K).all);
1482                      Write_Char (' ');
1483                   end loop;
1484
1485                   Write_Eol;
1486
1487                   for J in 1 .. Switches_To_Check.Last loop
1488                      Write_Str (Switches_To_Check.Table (J).all);
1489                      Write_Char (' ');
1490                   end loop;
1491
1492                   Write_Eol;
1493                end if;
1494
1495                ALI := No_ALI_Id;
1496                return;
1497             end if;
1498          end if;
1499
1500          --  Get the source files and their message digests. Note that some
1501          --  sources may be missing if ALI is out-of-date.
1502
1503          Set_Source_Table (ALI);
1504
1505          Modified_Source := Time_Stamp_Mismatch (ALI, Read_Only);
1506
1507          if Modified_Source /= No_File then
1508             ALI := No_ALI_Id;
1509
1510             if Opt.Verbose_Mode then
1511                Source_Name := Full_Source_Name (Modified_Source);
1512
1513                if Source_Name /= No_File then
1514                   Verbose_Msg (Source_Name, "time stamp mismatch");
1515                else
1516                   Verbose_Msg (Modified_Source, "missing");
1517                end if;
1518             end if;
1519
1520          else
1521             New_Spec := First_New_Spec (ALI);
1522
1523             if New_Spec /= No_File then
1524                ALI := No_ALI_Id;
1525
1526                if Opt.Verbose_Mode then
1527                   Source_Name := Full_Source_Name (New_Spec);
1528
1529                   if Source_Name /= No_File then
1530                      Verbose_Msg (Source_Name, "new spec");
1531                   else
1532                      Verbose_Msg (New_Spec, "old spec missing");
1533                   end if;
1534                end if;
1535             end if;
1536          end if;
1537       end if;
1538    end Check;
1539
1540    ------------------------
1541    -- Check_For_S_Switch --
1542    ------------------------
1543
1544    procedure Check_For_S_Switch is
1545    begin
1546       --  By default, we generate an object file
1547
1548       Output_Is_Object := True;
1549
1550       for Arg in 1 .. Last_Argument loop
1551          if Arguments (Arg).all = "-S" then
1552             Output_Is_Object := False;
1553
1554          elsif Arguments (Arg).all = "-c" then
1555             Output_Is_Object := True;
1556          end if;
1557       end loop;
1558    end Check_For_S_Switch;
1559
1560    --------------------------
1561    -- Check_Linker_Options --
1562    --------------------------
1563
1564    procedure Check_Linker_Options
1565      (E_Stamp   : Time_Stamp_Type;
1566       O_File    : out File_Name_Type;
1567       O_Stamp   : out Time_Stamp_Type)
1568    is
1569       procedure Check_File (File : File_Name_Type);
1570       --  Update O_File and O_Stamp if the given file is younger than E_Stamp
1571       --  and O_Stamp, or if O_File is No_File and File does not exist.
1572
1573       function Get_Library_File (Name : String) return File_Name_Type;
1574       --  Return the full file name including path of a library based
1575       --  on the name specified with the -l linker option, using the
1576       --  Ada object path. Return No_File if no such file can be found.
1577
1578       type Char_Array is array (Natural) of Character;
1579       type Char_Array_Access is access constant Char_Array;
1580
1581       Template : Char_Array_Access;
1582       pragma Import (C, Template, "__gnat_library_template");
1583
1584       ----------------
1585       -- Check_File --
1586       ----------------
1587
1588       procedure Check_File (File : File_Name_Type) is
1589          Stamp : Time_Stamp_Type;
1590          Name  : File_Name_Type := File;
1591
1592       begin
1593          Get_Name_String (Name);
1594
1595          --  Remove any trailing NUL characters
1596
1597          while Name_Len >= Name_Buffer'First
1598            and then Name_Buffer (Name_Len) = NUL
1599          loop
1600             Name_Len := Name_Len - 1;
1601          end loop;
1602
1603          if Name_Len <= 0 then
1604             return;
1605
1606          elsif Name_Buffer (1) = '-' then
1607
1608             --  Do not check if File is a switch other than "-l"
1609
1610             if Name_Buffer (2) /= 'l' then
1611                return;
1612             end if;
1613
1614             --  The argument is a library switch, get actual name. It
1615             --  is necessary to make a copy of the relevant part of
1616             --  Name_Buffer as Get_Library_Name uses Name_Buffer as well.
1617
1618             declare
1619                Base_Name : constant String := Name_Buffer (3 .. Name_Len);
1620
1621             begin
1622                Name := Get_Library_File (Base_Name);
1623             end;
1624
1625             if Name = No_File then
1626                return;
1627             end if;
1628          end if;
1629
1630          Stamp := File_Stamp (Name);
1631
1632          --  Find the youngest object file that is younger than the
1633          --  executable. If no such file exist, record the first object
1634          --  file that is not found.
1635
1636          if (O_Stamp < Stamp and then E_Stamp < Stamp)
1637            or else (O_File = No_File and then Stamp (Stamp'First) = ' ')
1638          then
1639             O_Stamp := Stamp;
1640             O_File := Name;
1641
1642             --  Strip the trailing NUL if present
1643
1644             Get_Name_String (O_File);
1645
1646             if Name_Buffer (Name_Len) = NUL then
1647                Name_Len := Name_Len - 1;
1648                O_File := Name_Find;
1649             end if;
1650          end if;
1651       end Check_File;
1652
1653       ----------------------
1654       -- Get_Library_Name --
1655       ----------------------
1656
1657       --  See comments in a-adaint.c about template syntax
1658
1659       function Get_Library_File (Name : String) return File_Name_Type is
1660          File : File_Name_Type := No_File;
1661
1662       begin
1663          Name_Len := 0;
1664
1665          for Ptr in Template'Range loop
1666             case Template (Ptr) is
1667                when '*'    =>
1668                   Add_Str_To_Name_Buffer (Name);
1669
1670                when ';'    =>
1671                   File := Full_Lib_File_Name (Name_Find);
1672                   exit when File /= No_File;
1673                   Name_Len := 0;
1674
1675                when NUL    =>
1676                   exit;
1677
1678                when others =>
1679                   Add_Char_To_Name_Buffer (Template (Ptr));
1680             end case;
1681          end loop;
1682
1683          --  The for loop exited because the end of the template
1684          --  was reached. File contains the last possible file name
1685          --  for the library.
1686
1687          if File = No_File and then Name_Len > 0 then
1688             File := Full_Lib_File_Name (Name_Find);
1689          end if;
1690
1691          return File;
1692       end Get_Library_File;
1693
1694    --  Start of processing for Check_Linker_Options
1695
1696    begin
1697       O_File  := No_File;
1698       O_Stamp := (others => ' ');
1699
1700       --  Process linker options from the ALI files.
1701
1702       for Opt in 1 .. Linker_Options.Last loop
1703          Check_File (Linker_Options.Table (Opt).Name);
1704       end loop;
1705
1706       --  Process options given on the command line.
1707
1708       for Opt in Linker_Switches.First .. Linker_Switches.Last loop
1709
1710          --  Check if the previous Opt has one of the two switches
1711          --  that take an extra parameter. (See GCC manual.)
1712
1713          if Opt = Linker_Switches.First
1714            or else (Linker_Switches.Table (Opt - 1).all /= "-u"
1715                       and then
1716                     Linker_Switches.Table (Opt - 1).all /= "-Xlinker"
1717                       and then
1718                     Linker_Switches.Table (Opt - 1).all /= "-L")
1719          then
1720             Name_Len := 0;
1721             Add_Str_To_Name_Buffer (Linker_Switches.Table (Opt).all);
1722             Check_File (Name_Find);
1723          end if;
1724       end loop;
1725
1726    end Check_Linker_Options;
1727
1728    -----------------
1729    -- Check_Steps --
1730    -----------------
1731
1732    procedure Check_Steps is
1733    begin
1734       --  If either -c, -b or -l has been specified, we will not necessarily
1735       --  execute all steps.
1736
1737       if Make_Steps then
1738          Do_Compile_Step := Do_Compile_Step and Compile_Only;
1739          Do_Bind_Step    := Do_Bind_Step    and Bind_Only;
1740          Do_Link_Step    := Do_Link_Step    and Link_Only;
1741
1742          --  If -c has been specified, but not -b, ignore any potential -l
1743
1744          if Do_Compile_Step and then not Do_Bind_Step then
1745             Do_Link_Step := False;
1746          end if;
1747       end if;
1748    end Check_Steps;
1749
1750    -----------------------
1751    -- Collect_Arguments --
1752    -----------------------
1753
1754    procedure Collect_Arguments
1755      (Source_File : File_Name_Type;
1756       Args        : Argument_List)
1757    is
1758    begin
1759       Arguments_Collected := True;
1760       Arguments_Project := No_Project;
1761       Last_Argument := 0;
1762       Add_Arguments (Args);
1763
1764       if Main_Project /= No_Project then
1765          declare
1766             Source_File_Name : constant String :=
1767                                  Get_Name_String (Source_File);
1768             Compiler_Package : Prj.Package_Id;
1769             Switches         : Prj.Variable_Value;
1770             Data             : Project_Data;
1771
1772          begin
1773             Prj.Env.
1774               Get_Reference
1775               (Source_File_Name => Source_File_Name,
1776                Project          => Arguments_Project,
1777                Path             => Arguments_Path_Name);
1778
1779             --  If the source is not a source of a project file,
1780             --  we simply add the saved gcc switches.
1781
1782             if Arguments_Project = No_Project then
1783
1784                Add_Arguments (The_Saved_Gcc_Switches.all);
1785
1786             else
1787                --  We get the project directory for the relative path
1788                --  switches and arguments.
1789
1790                Data := Projects.Table (Arguments_Project);
1791
1792                --  If the source is in an extended project, we go to
1793                --  the ultimate extending project.
1794
1795                while Data.Extended_By /= No_Project loop
1796                   Arguments_Project := Data.Extended_By;
1797                   Data := Projects.Table (Arguments_Project);
1798                end loop;
1799
1800                --  If building a dynamic or relocatable library, compile with
1801                --  PIC option, if it exists.
1802
1803                if Data.Library and then Data.Library_Kind /= Static then
1804                   declare
1805                      PIC : constant String := MLib.Tgt.PIC_Option;
1806
1807                   begin
1808                      if PIC /= "" then
1809                         Add_Arguments ((1 => new String'(PIC)));
1810                      end if;
1811                   end;
1812                end if;
1813
1814                if Data.Dir_Path = null then
1815                   Data.Dir_Path :=
1816                     new String'(Get_Name_String (Data.Display_Directory));
1817                   Projects.Table (Arguments_Project) := Data;
1818                end if;
1819
1820                --  We now look for package Compiler
1821                --  and get the switches from this package.
1822
1823                Compiler_Package :=
1824                  Prj.Util.Value_Of
1825                    (Name        => Name_Compiler,
1826                     In_Packages => Data.Decl.Packages);
1827
1828                if Compiler_Package /= No_Package then
1829
1830                   --  If package Gnatmake.Compiler exists, we get
1831                   --  the specific switches for the current source,
1832                   --  or the global switches, if any.
1833
1834                   Switches := Switches_Of
1835                     (Source_File      => Source_File,
1836                      Source_File_Name => Source_File_Name,
1837                      Naming           => Data.Naming,
1838                      In_Package       => Compiler_Package,
1839                      Allow_ALI        => False);
1840
1841                end if;
1842
1843                case Switches.Kind is
1844
1845                   --  We have a list of switches. We add these switches,
1846                   --  plus the saved gcc switches.
1847
1848                   when List =>
1849
1850                      declare
1851                         Current : String_List_Id := Switches.Values;
1852                         Element : String_Element;
1853                         Number  : Natural := 0;
1854
1855                      begin
1856                         while Current /= Nil_String loop
1857                            Element := String_Elements.Table (Current);
1858                            Number  := Number + 1;
1859                            Current := Element.Next;
1860                         end loop;
1861
1862                         declare
1863                            New_Args : Argument_List (1 .. Number);
1864
1865                         begin
1866                            Current := Switches.Values;
1867
1868                            for Index in New_Args'Range loop
1869                               Element := String_Elements.Table (Current);
1870                               Get_Name_String (Element.Value);
1871                               New_Args (Index) :=
1872                                 new String'(Name_Buffer (1 .. Name_Len));
1873                               Test_If_Relative_Path
1874                                 (New_Args (Index), Parent => Data.Dir_Path);
1875                               Current := Element.Next;
1876                            end loop;
1877
1878                            Add_Arguments
1879                              (Configuration_Pragmas_Switch
1880                                 (Arguments_Project) &
1881                               New_Args & The_Saved_Gcc_Switches.all);
1882                         end;
1883                      end;
1884
1885                      --  We have a single switch. We add this switch,
1886                      --  plus the saved gcc switches.
1887
1888                   when Single =>
1889                      Get_Name_String (Switches.Value);
1890
1891                      declare
1892                         New_Args : Argument_List :=
1893                                      (1 => new String'
1894                                             (Name_Buffer (1 .. Name_Len)));
1895
1896                      begin
1897                         Test_If_Relative_Path
1898                           (New_Args (1), Parent => Data.Dir_Path);
1899                         Add_Arguments
1900                           (Configuration_Pragmas_Switch (Arguments_Project) &
1901                            New_Args & The_Saved_Gcc_Switches.all);
1902                      end;
1903
1904                      --  We have no switches from Gnatmake.Compiler.
1905                      --  We add the saved gcc switches.
1906
1907                   when Undefined =>
1908                      Add_Arguments
1909                        (Configuration_Pragmas_Switch (Arguments_Project) &
1910                         The_Saved_Gcc_Switches.all);
1911                end case;
1912             end if;
1913          end;
1914       end if;
1915
1916       --  Set Output_Is_Object, depending if there is a -S switch.
1917       --  If the bind step is not performed, and there is a -S switch,
1918       --  then we will not check for a valid object file.
1919
1920       Check_For_S_Switch;
1921    end Collect_Arguments;
1922
1923    ---------------------
1924    -- Compile_Sources --
1925    ---------------------
1926
1927    procedure Compile_Sources
1928      (Main_Source           : File_Name_Type;
1929       Args                  : Argument_List;
1930       First_Compiled_File   : out Name_Id;
1931       Most_Recent_Obj_File  : out Name_Id;
1932       Most_Recent_Obj_Stamp : out Time_Stamp_Type;
1933       Main_Unit             : out Boolean;
1934       Compilation_Failures  : out Natural;
1935       Check_Readonly_Files  : Boolean  := False;
1936       Do_Not_Execute        : Boolean  := False;
1937       Force_Compilations    : Boolean  := False;
1938       Keep_Going            : Boolean  := False;
1939       In_Place_Mode         : Boolean  := False;
1940       Initialize_ALI_Data   : Boolean  := True;
1941       Max_Process           : Positive := 1)
1942    is
1943       function Compile
1944         (S    : Name_Id;
1945          L    : Name_Id;
1946          Args : Argument_List) return Process_Id;
1947       --  Compiles S using Args. If S is a GNAT predefined source
1948       --  "-gnatpg" is added to Args. Non blocking call. L corresponds to the
1949       --  expected library file name. Process_Id of the process spawned to
1950       --  execute the compile.
1951
1952       No_Mapping_File : constant Natural := 0;
1953
1954       type Compilation_Data is record
1955          Pid              : Process_Id;
1956          Full_Source_File : File_Name_Type;
1957          Lib_File         : File_Name_Type;
1958          Source_Unit      : Unit_Name_Type;
1959          Mapping_File     : Natural := No_Mapping_File;
1960          Project          : Project_Id := No_Project;
1961          Syntax_Only      : Boolean := False;
1962          Output_Is_Object : Boolean := True;
1963       end record;
1964
1965       Running_Compile : array (1 .. Max_Process) of Compilation_Data;
1966       --  Used to save information about outstanding compilations.
1967
1968       Outstanding_Compiles : Natural := 0;
1969       --  Current number of outstanding compiles
1970
1971       Source_Unit : Unit_Name_Type;
1972       --  Current source unit
1973
1974       Source_File : File_Name_Type;
1975       --  Current source file
1976
1977       Full_Source_File : File_Name_Type;
1978       --  Full name of the current source file
1979
1980       Lib_File : File_Name_Type;
1981       --  Current library file
1982
1983       Full_Lib_File : File_Name_Type;
1984       --  Full name of the current library file
1985
1986       Obj_File : File_Name_Type;
1987       --  Full name of the object file corresponding to Lib_File.
1988
1989       Obj_Stamp : Time_Stamp_Type;
1990       --  Time stamp of the current object file.
1991
1992       Sfile : File_Name_Type;
1993       --  Contains the source file of the units withed by Source_File
1994
1995       ALI : ALI_Id;
1996       --  ALI Id of the current ALI file
1997
1998       Read_Only : Boolean := False;
1999
2000       Compilation_OK  : Boolean;
2001       Need_To_Compile : Boolean;
2002
2003       Pid  : Process_Id;
2004       Text : Text_Buffer_Ptr;
2005
2006       Mfile : Natural := No_Mapping_File;
2007
2008       Need_To_Check_Standard_Library : Boolean :=
2009         Check_Readonly_Files and not Unique_Compile;
2010
2011       Mapping_File_Arg : String_Access;
2012
2013       procedure Add_Process
2014         (Pid    : Process_Id;
2015          Sfile  : File_Name_Type;
2016          Afile  : File_Name_Type;
2017          Uname  : Unit_Name_Type;
2018          Mfile  : Natural := No_Mapping_File);
2019       --  Adds process Pid to the current list of outstanding compilation
2020       --  processes and record the full name of the source file Sfile that
2021       --  we are compiling, the name of its library file Afile and the
2022       --  name of its unit Uname. If Mfile is not equal to No_Mapping_File,
2023       --  it is the index of the mapping file used during compilation in the
2024       --  array The_Mapping_File_Names.
2025
2026       procedure Await_Compile
2027         (Sfile : out File_Name_Type;
2028          Afile : out File_Name_Type;
2029          Uname : out Unit_Name_Type;
2030          OK    : out Boolean);
2031       --  Awaits that an outstanding compilation process terminates. When
2032       --  it does set Sfile to the name of the source file that was compiled
2033       --  Afile to the name of its library file and Uname to the name of its
2034       --  unit. Note that this time stamp can be used to check whether the
2035       --  compilation did generate an object file. OK is set to True if the
2036       --  compilation succeeded. Note that Sfile, Afile and Uname could be
2037       --  resp. No_File, No_File and No_Name  if there were no compilations
2038       --  to wait for.
2039
2040       procedure Collect_Arguments_And_Compile (Source_File : File_Name_Type);
2041       --  Collect arguments from project file (if any) and compile
2042
2043       package Good_ALI is new Table.Table (
2044         Table_Component_Type => ALI_Id,
2045         Table_Index_Type     => Natural,
2046         Table_Low_Bound      => 1,
2047         Table_Initial        => 50,
2048         Table_Increment      => 100,
2049         Table_Name           => "Make.Good_ALI");
2050       --  Contains the set of valid ALI files that have not yet been scanned.
2051
2052       procedure Record_Good_ALI (A : ALI_Id);
2053       --  Records in the previous set the Id of an ALI file.
2054
2055       function Good_ALI_Present return Boolean;
2056       --  Returns True if any ALI file was recorded in the previous set.
2057
2058       function Get_Next_Good_ALI return ALI_Id;
2059       --  Returns the next good ALI_Id record;
2060
2061       procedure Record_Failure
2062         (File  : File_Name_Type;
2063          Unit  : Unit_Name_Type;
2064          Found : Boolean := True);
2065       --  Records in the previous table that the compilation for File failed.
2066       --  If Found is False then the compilation of File failed because we
2067       --  could not find it. Records also Unit when possible.
2068
2069       function Bad_Compilation_Count return Natural;
2070       --  Returns the number of compilation failures.
2071
2072       procedure Get_Mapping_File (Project : Project_Id);
2073       --  Get a mapping file name. If there is one to be reused, reuse it.
2074       --  Otherwise, create a new mapping file.
2075
2076       -----------------
2077       -- Add_Process --
2078       -----------------
2079
2080       procedure Add_Process
2081         (Pid    : Process_Id;
2082          Sfile  : File_Name_Type;
2083          Afile  : File_Name_Type;
2084          Uname  : Unit_Name_Type;
2085          Mfile  : Natural := No_Mapping_File)
2086       is
2087          OC1 : constant Positive := Outstanding_Compiles + 1;
2088
2089       begin
2090          pragma Assert (OC1 <= Max_Process);
2091          pragma Assert (Pid /= Invalid_Pid);
2092
2093          Running_Compile (OC1).Pid              := Pid;
2094          Running_Compile (OC1).Full_Source_File := Sfile;
2095          Running_Compile (OC1).Lib_File         := Afile;
2096          Running_Compile (OC1).Source_Unit      := Uname;
2097          Running_Compile (OC1).Mapping_File     := Mfile;
2098          Running_Compile (OC1).Project          := Arguments_Project;
2099          Running_Compile (OC1).Syntax_Only      := Syntax_Only;
2100          Running_Compile (OC1).Output_Is_Object := Output_Is_Object;
2101
2102          Outstanding_Compiles := OC1;
2103       end Add_Process;
2104
2105       --------------------
2106       -- Await_Compile --
2107       -------------------
2108
2109       procedure Await_Compile
2110         (Sfile  : out File_Name_Type;
2111          Afile  : out File_Name_Type;
2112          Uname  : out File_Name_Type;
2113          OK     : out Boolean)
2114       is
2115          Pid : Process_Id;
2116          Project : Project_Id;
2117
2118       begin
2119          pragma Assert (Outstanding_Compiles > 0);
2120
2121          Sfile := No_File;
2122          Afile := No_File;
2123          Uname := No_Name;
2124          OK    := False;
2125
2126          --  The loop here is a work-around for a problem on VMS; in some
2127          --  circumstances (shared library and several executables, for
2128          --  example), there are child processes other than compilation
2129          --  processes that are received. Until this problem is resolved,
2130          --  we will ignore such processes.
2131
2132          loop
2133             Wait_Process (Pid, OK);
2134
2135             if Pid = Invalid_Pid then
2136                return;
2137             end if;
2138
2139             for J in Running_Compile'First .. Outstanding_Compiles loop
2140                if Pid = Running_Compile (J).Pid then
2141                   Sfile := Running_Compile (J).Full_Source_File;
2142                   Afile := Running_Compile (J).Lib_File;
2143                   Uname := Running_Compile (J).Source_Unit;
2144                   Syntax_Only := Running_Compile (J).Syntax_Only;
2145                   Output_Is_Object := Running_Compile (J).Output_Is_Object;
2146                   Project := Running_Compile (J).Project;
2147
2148                   --  If a mapping file was used by this compilation,
2149                   --  get its file name for reuse by a subsequent compilation
2150
2151                   if Running_Compile (J).Mapping_File /= No_Mapping_File then
2152                      Last_Free_Indices (Project) :=
2153                        Last_Free_Indices (Project) + 1;
2154                      The_Free_Mapping_File_Indices
2155                        (Project, Last_Free_Indices (Project)) :=
2156                        Running_Compile (J).Mapping_File;
2157                   end if;
2158
2159                   --  To actually remove this Pid and related info from
2160                   --  Running_Compile replace its entry with the last valid
2161                   --  entry in Running_Compile.
2162
2163                   if J = Outstanding_Compiles then
2164                      null;
2165
2166                   else
2167                      Running_Compile (J) :=
2168                        Running_Compile (Outstanding_Compiles);
2169                   end if;
2170
2171                   Outstanding_Compiles := Outstanding_Compiles - 1;
2172                   return;
2173                end if;
2174             end loop;
2175
2176             --  This child process was not one of our compilation processes;
2177             --  just ignore it for now.
2178
2179             --  raise Program_Error;
2180          end loop;
2181       end Await_Compile;
2182
2183       ---------------------------
2184       -- Bad_Compilation_Count --
2185       ---------------------------
2186
2187       function Bad_Compilation_Count return Natural is
2188       begin
2189          return Bad_Compilation.Last - Bad_Compilation.First + 1;
2190       end Bad_Compilation_Count;
2191
2192       -----------------------------------
2193       -- Collect_Arguments_And_Compile --
2194       -----------------------------------
2195
2196       procedure Collect_Arguments_And_Compile (Source_File : File_Name_Type) is
2197       begin
2198
2199          --  If arguments have not yet been collected (in Check), collect them
2200          --  now.
2201
2202          if not Arguments_Collected then
2203             Collect_Arguments (Source_File, Args);
2204          end if;
2205
2206          --  If we use mapping file (-P or -C switches), then get one
2207
2208          if Create_Mapping_File then
2209             Get_Mapping_File (Arguments_Project);
2210          end if;
2211
2212          --  If the source is part of a project file, we set the ADA_*_PATHs,
2213          --  check for an eventual library project, and use the full path.
2214
2215          if Arguments_Project /= No_Project then
2216             Prj.Env.Set_Ada_Paths (Arguments_Project, True);
2217
2218             if MLib.Tgt.Support_For_Libraries /= MLib.Tgt.None then
2219                declare
2220                   The_Data : Project_Data :=
2221                     Projects.Table (Arguments_Project);
2222                   Prj      : Project_Id   := Arguments_Project;
2223
2224                begin
2225                   while The_Data.Extended_By /= No_Project loop
2226                      Prj := The_Data.Extended_By;
2227                      The_Data := Projects.Table (Prj);
2228                   end loop;
2229
2230                   if The_Data.Library and then not The_Data.Flag1 then
2231                      --  Add to the Q all sources of the project that
2232                      --  have not been marked
2233
2234                      Insert_Project_Sources
2235                        (The_Project  => Prj,
2236                         All_Projects => False,
2237                         Into_Q       => True);
2238
2239                      --  Now mark the project as processed
2240
2241                      Projects.Table (Prj).Flag1 := True;
2242                   end if;
2243                end;
2244             end if;
2245
2246             --  Change to the object directory of the project file,
2247             --  if necessary.
2248
2249             Change_To_Object_Directory (Arguments_Project);
2250
2251             Pid := Compile (Arguments_Path_Name, Lib_File,
2252                             Arguments (1 .. Last_Argument));
2253
2254          else
2255             --  If this is a source outside of any project file, make sure
2256             --  it will be compiled in the object directory of the main project
2257             --  file.
2258
2259             if Main_Project /= No_Project then
2260                Change_To_Object_Directory (Arguments_Project);
2261             end if;
2262
2263             Pid := Compile (Full_Source_File, Lib_File,
2264                             Arguments (1 .. Last_Argument));
2265          end if;
2266       end Collect_Arguments_And_Compile;
2267
2268       -------------
2269       -- Compile --
2270       -------------
2271
2272       function Compile
2273         (S    : Name_Id;
2274          L    : Name_Id;
2275          Args : Argument_List) return Process_Id
2276       is
2277          Comp_Args : Argument_List (Args'First .. Args'Last + 8);
2278          Comp_Next : Integer := Args'First;
2279          Comp_Last : Integer;
2280
2281          function Ada_File_Name (Name : Name_Id) return Boolean;
2282          --  Returns True if Name is the name of an ada source file
2283          --  (i.e. suffix is .ads or .adb)
2284
2285          -------------------
2286          -- Ada_File_Name --
2287          -------------------
2288
2289          function Ada_File_Name (Name : Name_Id) return Boolean is
2290          begin
2291             Get_Name_String (Name);
2292             return
2293               Name_Len > 4
2294                 and then Name_Buffer (Name_Len - 3 .. Name_Len - 1) = ".ad"
2295                 and then (Name_Buffer (Name_Len) = 'b'
2296                             or else
2297                           Name_Buffer (Name_Len) = 's');
2298          end Ada_File_Name;
2299
2300       --  Start of processing for Compile
2301
2302       begin
2303          Enter_Into_Obsoleted (S);
2304
2305          --  By default, Syntax_Only is False
2306
2307          Syntax_Only := False;
2308
2309          for J in Args'Range loop
2310             if Args (J).all = "-gnats" then
2311
2312                --  If we compile with -gnats, the bind step and the link step
2313                --  are inhibited. Also, we set Syntax_Only to True, so that
2314                --  we don't fail when we don't find the ALI file, after
2315                --  compilation.
2316
2317                Do_Bind_Step := False;
2318                Do_Link_Step := False;
2319                Syntax_Only  := True;
2320
2321             elsif Args (J).all = "-gnatc" then
2322
2323                --  If we compile with -gnatc, the bind step and the link step
2324                --  are inhibited. We set Syntax_Only to False for the case when
2325                --  -gnats was previously specified.
2326
2327                Do_Bind_Step := False;
2328                Do_Link_Step := False;
2329                Syntax_Only  := False;
2330             end if;
2331          end loop;
2332
2333          Comp_Args (Comp_Next) := Comp_Flag;
2334          Comp_Next := Comp_Next + 1;
2335
2336          --  Optimize the simple case where the gcc command line looks like
2337          --     gcc -c -I. ... -I- file.adb  --into->  gcc -c ... file.adb
2338
2339          if Args (Args'First).all = "-I" & Normalized_CWD
2340            and then Args (Args'Last).all = "-I-"
2341            and then S = Strip_Directory (S)
2342          then
2343             Comp_Last := Comp_Next + Args'Length - 3;
2344             Comp_Args (Comp_Next .. Comp_Last) :=
2345               Args (Args'First + 1 .. Args'Last - 1);
2346
2347          else
2348             Comp_Last := Comp_Next + Args'Length - 1;
2349             Comp_Args (Comp_Next .. Comp_Last) := Args;
2350          end if;
2351
2352          --  Set -gnatpg for predefined files (for this purpose the renamings
2353          --  such as Text_IO do not count as predefined). Note that we strip
2354          --  the directory name from the source file name becase the call to
2355          --  Fname.Is_Predefined_File_Name cannot deal with directory prefixes.
2356
2357          declare
2358             Fname : constant File_Name_Type := Strip_Directory (S);
2359
2360          begin
2361             if Is_Predefined_File_Name (Fname, False) then
2362                if Check_Readonly_Files then
2363                   Comp_Last := Comp_Last + 1;
2364                   Comp_Args (Comp_Last) := GNAT_Flag;
2365
2366                else
2367                   Make_Failed
2368                     ("not allowed to compile """ &
2369                      Get_Name_String (Fname) &
2370                      """; use -a switch, or compile file with " &
2371                      """-gnatg"" switch");
2372                end if;
2373             end if;
2374          end;
2375
2376          --  Now check if the file name has one of the suffixes familiar to
2377          --  the gcc driver. If this is not the case then add the ada flag
2378          --  "-x ada".
2379
2380          if not Ada_File_Name (S) and then not Targparm.AAMP_On_Target then
2381             Comp_Last := Comp_Last + 1;
2382             Comp_Args (Comp_Last) := Ada_Flag_1;
2383             Comp_Last := Comp_Last + 1;
2384             Comp_Args (Comp_Last) := Ada_Flag_2;
2385          end if;
2386
2387          if L /= Strip_Directory (L) or else Object_Directory_Path /= null then
2388
2389             --  Build -o argument.
2390
2391             Get_Name_String (L);
2392
2393             for J in reverse 1 .. Name_Len loop
2394                if Name_Buffer (J) = '.' then
2395                   Name_Len := J + Object_Suffix'Length - 1;
2396                   Name_Buffer (J .. Name_Len) := Object_Suffix;
2397                   exit;
2398                end if;
2399             end loop;
2400
2401             Comp_Last := Comp_Last + 1;
2402             Comp_Args (Comp_Last) := Output_Flag;
2403             Comp_Last := Comp_Last + 1;
2404
2405             --  If an object directory was specified, prepend the object file
2406             --  name with this object directory.
2407
2408             if Object_Directory_Path /= null then
2409                Comp_Args (Comp_Last) :=
2410                  new String'(Object_Directory_Path.all &
2411                                Name_Buffer (1 .. Name_Len));
2412
2413             else
2414                Comp_Args (Comp_Last) :=
2415                  new String'(Name_Buffer (1 .. Name_Len));
2416             end if;
2417          end if;
2418
2419          if Create_Mapping_File then
2420             Comp_Last := Comp_Last + 1;
2421             Comp_Args (Comp_Last) := Mapping_File_Arg;
2422          end if;
2423
2424          Get_Name_String (S);
2425
2426          Comp_Last := Comp_Last + 1;
2427          Comp_Args (Comp_Last) := new String'(Name_Buffer (1 .. Name_Len));
2428
2429          GNAT.OS_Lib.Normalize_Arguments (Comp_Args (Args'First .. Comp_Last));
2430
2431          Display (Gcc.all, Comp_Args (Args'First .. Comp_Last));
2432
2433          if Gcc_Path = null then
2434             Make_Failed ("error, unable to locate ", Gcc.all);
2435          end if;
2436
2437          return
2438            GNAT.OS_Lib.Non_Blocking_Spawn
2439              (Gcc_Path.all, Comp_Args (Args'First .. Comp_Last));
2440       end Compile;
2441
2442       ----------------------
2443       -- Get_Mapping_File --
2444       ----------------------
2445
2446       procedure Get_Mapping_File (Project : Project_Id) is
2447       begin
2448          --  If there is a mapping file ready to be reused, reuse it
2449
2450          if Last_Free_Indices (Project) > 0 then
2451             Mfile := The_Free_Mapping_File_Indices
2452                        (Project, Last_Free_Indices (Project));
2453             Last_Free_Indices (Project) := Last_Free_Indices (Project) - 1;
2454
2455          --  Otherwise, create and initialize a new one
2456
2457          else
2458             Init_Mapping_File (Project => Project, File_Index => Mfile);
2459          end if;
2460
2461          --  Put the name in the mapping file argument for the invocation
2462          --  of the compiler.
2463
2464          Free (Mapping_File_Arg);
2465          Mapping_File_Arg :=
2466            new String'("-gnatem=" &
2467                        Get_Name_String
2468                          (The_Mapping_File_Names (Project, Mfile)));
2469
2470       end Get_Mapping_File;
2471
2472       -----------------------
2473       -- Get_Next_Good_ALI --
2474       -----------------------
2475
2476       function Get_Next_Good_ALI return ALI_Id is
2477          ALI : ALI_Id;
2478
2479       begin
2480          pragma Assert (Good_ALI_Present);
2481          ALI := Good_ALI.Table (Good_ALI.Last);
2482          Good_ALI.Decrement_Last;
2483          return ALI;
2484       end Get_Next_Good_ALI;
2485
2486       ----------------------
2487       -- Good_ALI_Present --
2488       ----------------------
2489
2490       function Good_ALI_Present return Boolean is
2491       begin
2492          return Good_ALI.First <= Good_ALI.Last;
2493       end Good_ALI_Present;
2494
2495       --------------------
2496       -- Record_Failure --
2497       --------------------
2498
2499       procedure Record_Failure
2500         (File  : File_Name_Type;
2501          Unit  : Unit_Name_Type;
2502          Found : Boolean := True)
2503       is
2504       begin
2505          Bad_Compilation.Increment_Last;
2506          Bad_Compilation.Table (Bad_Compilation.Last) := (File, Unit, Found);
2507       end Record_Failure;
2508
2509       ---------------------
2510       -- Record_Good_ALI --
2511       ---------------------
2512
2513       procedure Record_Good_ALI (A : ALI_Id) is
2514       begin
2515          Good_ALI.Increment_Last;
2516          Good_ALI.Table (Good_ALI.Last) := A;
2517       end Record_Good_ALI;
2518
2519    --  Start of processing for Compile_Sources
2520
2521    begin
2522       pragma Assert (Args'First = 1);
2523
2524       --  Package and Queue initializations.
2525
2526       Good_ALI.Init;
2527       Output.Set_Standard_Error;
2528
2529       if First_Q_Initialization then
2530          Init_Q;
2531       end if;
2532
2533       if Initialize_ALI_Data then
2534          Initialize_ALI;
2535          Initialize_ALI_Source;
2536       end if;
2537
2538       --  The following two flags affect the behavior of ALI.Set_Source_Table.
2539       --  We set Opt.Check_Source_Files to True to ensure that source file
2540       --  time stamps are checked, and we set Opt.All_Sources to False to
2541       --  avoid checking the presence of the source files listed in the
2542       --  source dependency section of an ali file (which would be a mistake
2543       --  since the ali file may be obsolete).
2544
2545       Opt.Check_Source_Files := True;
2546       Opt.All_Sources        := False;
2547
2548       Insert_Q (Main_Source);
2549       Mark (Main_Source);
2550
2551       First_Compiled_File   := No_File;
2552       Most_Recent_Obj_File  := No_File;
2553       Most_Recent_Obj_Stamp := Empty_Time_Stamp;
2554       Main_Unit             := False;
2555
2556       --  Keep looping until there is no more work to do (the Q is empty)
2557       --  and all the outstanding compilations have terminated
2558
2559       Make_Loop : while not Empty_Q or else Outstanding_Compiles > 0 loop
2560
2561          --  If the user does not want to keep going in case of errors then
2562          --  wait for the remaining outstanding compiles and then exit.
2563
2564          if Bad_Compilation_Count > 0 and then not Keep_Going then
2565             while Outstanding_Compiles > 0 loop
2566                Await_Compile
2567                  (Full_Source_File, Lib_File, Source_Unit, Compilation_OK);
2568
2569                if not Compilation_OK then
2570                   Record_Failure (Full_Source_File, Source_Unit);
2571                end if;
2572             end loop;
2573
2574             exit Make_Loop;
2575          end if;
2576
2577          --  PHASE 1: Check if there is more work that we can do (ie the Q
2578          --  is non empty). If there is, do it only if we have not yet used
2579          --  up all the available processes.
2580
2581          if not Empty_Q and then Outstanding_Compiles < Max_Process then
2582             Extract_From_Q (Source_File, Source_Unit);
2583             Full_Source_File := Osint.Full_Source_Name (Source_File);
2584             Lib_File         := Osint.Lib_File_Name (Source_File);
2585             Full_Lib_File    := Osint.Full_Lib_File_Name (Lib_File);
2586
2587             --  If this source has already been compiled, the executable is
2588             --  obsolete.
2589
2590             if Is_In_Obsoleted (Source_File) then
2591                Executable_Obsolete := True;
2592             end if;
2593
2594             --  If the library file is an Ada library skip it
2595
2596             if Full_Lib_File /= No_File
2597               and then In_Ada_Lib_Dir (Full_Lib_File)
2598             then
2599                Verbose_Msg (Lib_File, "is in an Ada library", Prefix => "  ");
2600
2601             --  If the library file is a read-only library skip it, but only
2602             --  if, when using project files, this library file is in the
2603             --  right object directory (a read-only ALI file in the object
2604             --  directory of a project being extended should not be skipped).
2605
2606             elsif Full_Lib_File /= No_File
2607               and then not Check_Readonly_Files
2608               and then Is_Readonly_Library (Full_Lib_File)
2609               and then Is_In_Object_Directory (Source_File, Full_Lib_File)
2610             then
2611                Verbose_Msg
2612                  (Lib_File, "is a read-only library", Prefix => "  ");
2613
2614             --  The source file that we are checking cannot be located
2615
2616             elsif Full_Source_File = No_File then
2617                Record_Failure (Source_File, Source_Unit, False);
2618
2619             --  Source and library files can be located but are internal
2620             --  files
2621
2622             elsif not Check_Readonly_Files
2623               and then Full_Lib_File /= No_File
2624               and then Is_Internal_File_Name (Source_File)
2625             then
2626
2627                if Force_Compilations then
2628                   Fail
2629                     ("not allowed to compile """ &
2630                      Get_Name_String (Source_File) &
2631                      """; use -a switch, or compile file with " &
2632                      """-gnatg"" switch");
2633                end if;
2634
2635                Verbose_Msg
2636                  (Lib_File, "is an internal library", Prefix => "  ");
2637
2638             --  The source file that we are checking can be located
2639
2640             else
2641                Arguments_Collected := False;
2642
2643                --  Don't waste any time if we have to recompile anyway
2644
2645                Obj_Stamp       := Empty_Time_Stamp;
2646                Need_To_Compile := Force_Compilations;
2647
2648                if not Force_Compilations then
2649                   Read_Only :=
2650                     Full_Lib_File /= No_File
2651                     and then not Check_Readonly_Files
2652                     and then Is_Readonly_Library (Full_Lib_File);
2653                   Check (Source_File, Args, Lib_File, Read_Only,
2654                          ALI, Obj_File, Obj_Stamp);
2655                   Need_To_Compile := (ALI = No_ALI_Id);
2656                end if;
2657
2658                if not Need_To_Compile then
2659
2660                   --  The ALI file is up-to-date. Record its Id.
2661
2662                   Record_Good_ALI (ALI);
2663
2664                   --  Record the time stamp of the most recent object file
2665                   --  as long as no (re)compilations are needed.
2666
2667                   if First_Compiled_File = No_File
2668                     and then (Most_Recent_Obj_File = No_File
2669                               or else Obj_Stamp > Most_Recent_Obj_Stamp)
2670                   then
2671                      Most_Recent_Obj_File  := Obj_File;
2672                      Most_Recent_Obj_Stamp := Obj_Stamp;
2673                   end if;
2674
2675                else
2676                   --  Is this the first file we have to compile?
2677
2678                   if First_Compiled_File = No_File then
2679                      First_Compiled_File  := Full_Source_File;
2680                      Most_Recent_Obj_File := No_File;
2681
2682                      if Do_Not_Execute then
2683                         exit Make_Loop;
2684                      end if;
2685                   end if;
2686
2687                   if In_Place_Mode then
2688
2689                      --  If the library file was not found, then save the
2690                      --  library file near the source file.
2691
2692                      if Full_Lib_File = No_File then
2693                         Get_Name_String (Full_Source_File);
2694
2695                         for J in reverse 1 .. Name_Len loop
2696                            if Name_Buffer (J) = '.' then
2697                               Name_Buffer (J + 1 .. J + 3) := "ali";
2698                               Name_Len := J + 3;
2699                               exit;
2700                            end if;
2701                         end loop;
2702
2703                         Lib_File := Name_Find;
2704
2705                      --  If the library file was found, then save the
2706                      --  library file in the same place.
2707
2708                      else
2709                         Lib_File := Full_Lib_File;
2710                      end if;
2711
2712                   end if;
2713
2714                   --  Start the compilation and record it. We can do this
2715                   --  because there is at least one free process.
2716
2717                   Collect_Arguments_And_Compile (Source_File);
2718
2719                   --  Make sure we could successfully start the compilation
2720
2721                   if Pid = Invalid_Pid then
2722                      Record_Failure (Full_Source_File, Source_Unit);
2723                   else
2724                      Add_Process
2725                        (Pid,
2726                         Full_Source_File,
2727                         Lib_File,
2728                         Source_Unit,
2729                         Mfile);
2730                   end if;
2731                end if;
2732             end if;
2733          end if;
2734
2735          --  PHASE 2: Now check if we should wait for a compilation to
2736          --  finish. This is the case if all the available processes are
2737          --  busy compiling sources or there is nothing else to do
2738          --  (that is the Q is empty and there are no good ALIs to process).
2739
2740          if Outstanding_Compiles = Max_Process
2741            or else (Empty_Q
2742                      and then not Good_ALI_Present
2743                      and then Outstanding_Compiles > 0)
2744          then
2745             Await_Compile
2746               (Full_Source_File, Lib_File, Source_Unit, Compilation_OK);
2747
2748             if not Compilation_OK then
2749                Record_Failure (Full_Source_File, Source_Unit);
2750             end if;
2751
2752             if Compilation_OK or else Keep_Going then
2753
2754                --  Re-read the updated library file
2755
2756                declare
2757                   Saved_Object_Consistency : constant Boolean :=
2758                                                Opt.Check_Object_Consistency;
2759
2760                begin
2761                   --  If compilation was not OK, or if output is not an
2762                   --  object file and we don't do the bind step, don't check
2763                   --  for object consistency.
2764
2765                   Opt.Check_Object_Consistency :=
2766                     Opt.Check_Object_Consistency
2767                     and Compilation_OK
2768                     and (Output_Is_Object or Do_Bind_Step);
2769                   Text := Read_Library_Info (Lib_File);
2770
2771                   --  Restore Check_Object_Consistency to its initial value
2772
2773                   Opt.Check_Object_Consistency := Saved_Object_Consistency;
2774                end;
2775
2776                --  If an ALI file was generated by this compilation, scan
2777                --  the ALI file and record it.
2778                --  If the scan fails, a previous ali file is inconsistent with
2779                --  the unit just compiled.
2780
2781                if Text /= null then
2782                   ALI :=
2783                     Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True);
2784
2785                   if ALI = No_ALI_Id then
2786
2787                      --  Record a failure only if not already done
2788
2789                      if Compilation_OK then
2790                         Inform
2791                           (Lib_File,
2792                            "incompatible ALI file, please recompile");
2793                         Record_Failure (Full_Source_File, Source_Unit);
2794                      end if;
2795                   else
2796                      Free (Text);
2797                      Record_Good_ALI (ALI);
2798                   end if;
2799
2800                --  If we could not read the ALI file that was just generated
2801                --  then there could be a problem reading either the ALI or the
2802                --  corresponding object file (if Opt.Check_Object_Consistency
2803                --  is set Read_Library_Info checks that the time stamp of the
2804                --  object file is more recent than that of the ALI). For an
2805                --  example of problems caught by this test see [6625-009].
2806                --  However, we record a failure only if not already done.
2807
2808                else
2809                   if Compilation_OK and not Syntax_Only then
2810                      Inform
2811                        (Lib_File,
2812                         "WARNING: ALI or object file not found after compile");
2813                      Record_Failure (Full_Source_File, Source_Unit);
2814                   end if;
2815                end if;
2816             end if;
2817          end if;
2818
2819          --  PHASE 3: Check if we recorded good ALI files. If yes process
2820          --  them now in the order in which they have been recorded. There
2821          --  are two occasions in which we record good ali files. The first is
2822          --  in phase 1 when, after scanning an existing ALI file we realize
2823          --  it is up-to-date, the second instance is after a successful
2824          --  compilation.
2825
2826          while Good_ALI_Present loop
2827             ALI := Get_Next_Good_ALI;
2828
2829             --  If we are processing the library file corresponding to the
2830             --  main source file check if this source can be a main unit.
2831
2832             if ALIs.Table (ALI).Sfile = Main_Source then
2833                Main_Unit := ALIs.Table (ALI).Main_Program /= None;
2834             end if;
2835
2836             --  The following adds the standard library (s-stalib) to the
2837             --  list of files to be handled by gnatmake: this file and any
2838             --  files it depends on are always included in every bind,
2839             --  even if they are not in the explicit dependency list.
2840             --  Of course, it is not added if Suppress_Standard_Library
2841             --  is True.
2842
2843             --  However, to avoid annoying output about s-stalib.ali being
2844             --  read only, when "-v" is used, we add the standard library
2845             --  only when "-a" is used.
2846
2847             if Need_To_Check_Standard_Library then
2848                Need_To_Check_Standard_Library := False;
2849
2850                if not Targparm.Suppress_Standard_Library_On_Target then
2851                   declare
2852                      Sfile  : Name_Id;
2853                      Add_It : Boolean := True;
2854
2855                   begin
2856                      Name_Len := Standard_Library_Package_Body_Name'Length;
2857                      Name_Buffer (1 .. Name_Len) :=
2858                        Standard_Library_Package_Body_Name;
2859                      Sfile := Name_Enter;
2860
2861                      --  If we have a special runtime, we add the standard
2862                      --  library only if we can find it.
2863
2864                      if Opt.RTS_Switch then
2865                         Add_It := Find_File (Sfile, Osint.Source) /= No_File;
2866                      end if;
2867
2868                      if Add_It then
2869                         if Is_Marked (Sfile) then
2870                            if Is_In_Obsoleted (Sfile) then
2871                               Executable_Obsolete := True;
2872                            end if;
2873
2874                         else
2875                            Insert_Q (Sfile);
2876                            Mark (Sfile);
2877                         end if;
2878                      end if;
2879                   end;
2880                end if;
2881             end if;
2882
2883             --  Now insert in the Q the unmarked source files (i.e. those
2884             --  which have never been inserted in the Q and hence never
2885             --  considered). Only do that if Unique_Compile is False.
2886
2887             if not Unique_Compile then
2888                for J in
2889                  ALIs.Table (ALI).First_Unit .. ALIs.Table (ALI).Last_Unit
2890                loop
2891                   for K in
2892                     Units.Table (J).First_With .. Units.Table (J).Last_With
2893                   loop
2894                      Sfile := Withs.Table (K).Sfile;
2895                      Add_Dependency (ALIs.Table (ALI).Sfile, Sfile);
2896
2897                      if Is_In_Obsoleted (Sfile) then
2898                         Executable_Obsolete := True;
2899                      end if;
2900
2901                      if Sfile = No_File then
2902                         Debug_Msg ("Skipping generic:", Withs.Table (K).Uname);
2903
2904                      elsif Is_Marked (Sfile) then
2905                         Debug_Msg ("Skipping marked file:", Sfile);
2906
2907                      elsif not Check_Readonly_Files
2908                        and then Is_Internal_File_Name (Sfile)
2909                      then
2910                         Debug_Msg ("Skipping internal file:", Sfile);
2911
2912                      else
2913                         Insert_Q (Sfile, Withs.Table (K).Uname);
2914                         Mark (Sfile);
2915                      end if;
2916                   end loop;
2917                end loop;
2918             end if;
2919          end loop;
2920
2921          if Opt.Display_Compilation_Progress then
2922             Write_Str ("completed ");
2923             Write_Int (Int (Q_Front));
2924             Write_Str (" out of ");
2925             Write_Int (Int (Q.Last));
2926             Write_Str (" (");
2927             Write_Int (Int ((Q_Front * 100) / (Q.Last - Q.First)));
2928             Write_Str ("%)...");
2929             Write_Eol;
2930          end if;
2931       end loop Make_Loop;
2932
2933       Compilation_Failures := Bad_Compilation_Count;
2934
2935       --  Compilation is finished
2936
2937       --  Delete any temporary configuration pragma file
2938
2939       Delete_Temp_Config_Files;
2940
2941    end Compile_Sources;
2942
2943    ----------------------------------
2944    -- Configuration_Pragmas_Switch --
2945    ----------------------------------
2946
2947    function Configuration_Pragmas_Switch
2948      (For_Project : Project_Id) return Argument_List
2949    is
2950       The_Packages : Package_Id;
2951       Gnatmake     : Package_Id;
2952       Compiler     : Package_Id;
2953
2954       Global_Attribute : Variable_Value := Nil_Variable_Value;
2955       Local_Attribute  : Variable_Value := Nil_Variable_Value;
2956
2957       Global_Attribute_Present : Boolean := False;
2958       Local_Attribute_Present  : Boolean := False;
2959
2960       Result : Argument_List (1 .. 3);
2961       Last   : Natural := 0;
2962
2963       function Absolute_Path
2964         (Path    : Name_Id;
2965          Project : Project_Id) return String;
2966       --  Returns an absolute path for a configuration pragmas file.
2967
2968       -------------------
2969       -- Absolute_Path --
2970       -------------------
2971
2972       function Absolute_Path
2973         (Path    : Name_Id;
2974          Project : Project_Id) return String
2975       is
2976       begin
2977          Get_Name_String (Path);
2978
2979          declare
2980             Path_Name : constant String := Name_Buffer (1 .. Name_Len);
2981
2982          begin
2983             if Is_Absolute_Path (Path_Name) then
2984                return Path_Name;
2985
2986             else
2987                declare
2988                   Parent_Directory : constant String :=
2989                     Get_Name_String (Projects.Table (Project).Directory);
2990
2991                begin
2992                   if Parent_Directory (Parent_Directory'Last) =
2993                                                  Directory_Separator
2994                   then
2995                      return Parent_Directory & Path_Name;
2996
2997                   else
2998                      return Parent_Directory & Directory_Separator & Path_Name;
2999                   end if;
3000                end;
3001             end if;
3002          end;
3003       end Absolute_Path;
3004
3005    --  Start of processing for Configuration_Pragmas_Switch
3006
3007    begin
3008       Prj.Env.Create_Config_Pragmas_File (For_Project, Main_Project);
3009
3010       if Projects.Table (For_Project).Config_File_Name /= No_Name then
3011          Temporary_Config_File :=
3012            Projects.Table (For_Project).Config_File_Temp;
3013          Last := 1;
3014          Result (1) :=
3015            new String'
3016                  ("-gnatec=" &
3017                   Get_Name_String
3018                     (Projects.Table (For_Project).Config_File_Name));
3019
3020       else
3021          Temporary_Config_File := False;
3022       end if;
3023
3024       --  Check for attribute Builder'Global_Configuration_Pragmas
3025
3026       The_Packages := Projects.Table (Main_Project).Decl.Packages;
3027       Gnatmake :=
3028         Prj.Util.Value_Of
3029           (Name        => Name_Builder,
3030            In_Packages => The_Packages);
3031
3032       if Gnatmake /= No_Package then
3033          Global_Attribute := Prj.Util.Value_Of
3034            (Variable_Name => Name_Global_Configuration_Pragmas,
3035             In_Variables => Packages.Table (Gnatmake).Decl.Attributes);
3036          Global_Attribute_Present :=
3037            Global_Attribute /= Nil_Variable_Value
3038            and then Get_Name_String (Global_Attribute.Value) /= "";
3039
3040          if Global_Attribute_Present then
3041             declare
3042                Path : constant String :=
3043                         Absolute_Path
3044                           (Global_Attribute.Value, Global_Attribute.Project);
3045             begin
3046                if not Is_Regular_File (Path) then
3047                   Make_Failed
3048                     ("cannot find configuration pragmas file ", Path);
3049                end if;
3050
3051                Last := Last + 1;
3052                Result (Last) := new String'("-gnatec=" &  Path);
3053             end;
3054          end if;
3055       end if;
3056
3057       --  Check for attribute Compiler'Local_Configuration_Pragmas
3058
3059       The_Packages := Projects.Table (For_Project).Decl.Packages;
3060       Compiler :=
3061         Prj.Util.Value_Of
3062           (Name        => Name_Compiler,
3063            In_Packages => The_Packages);
3064
3065       if Compiler /= No_Package then
3066          Local_Attribute := Prj.Util.Value_Of
3067            (Variable_Name => Name_Local_Configuration_Pragmas,
3068             In_Variables => Packages.Table (Compiler).Decl.Attributes);
3069          Local_Attribute_Present :=
3070            Local_Attribute /= Nil_Variable_Value
3071            and then Get_Name_String (Local_Attribute.Value) /= "";
3072
3073          if Local_Attribute_Present then
3074             declare
3075                Path : constant String :=
3076                         Absolute_Path
3077                           (Local_Attribute.Value, Local_Attribute.Project);
3078             begin
3079                if not Is_Regular_File (Path) then
3080                   Make_Failed
3081                     ("cannot find configuration pragmas file ", Path);
3082                end if;
3083
3084                Last := Last + 1;
3085                Result (Last) := new String'("-gnatec=" & Path);
3086             end;
3087          end if;
3088       end if;
3089
3090       return Result (1 .. Last);
3091    end Configuration_Pragmas_Switch;
3092
3093    ---------------
3094    -- Debug_Msg --
3095    ---------------
3096
3097    procedure Debug_Msg (S : String; N : Name_Id) is
3098    begin
3099       if Debug.Debug_Flag_W then
3100          Write_Str ("   ... ");
3101          Write_Str (S);
3102          Write_Str (" ");
3103          Write_Name (N);
3104          Write_Eol;
3105       end if;
3106    end Debug_Msg;
3107
3108    ---------------------------
3109    -- Delete_All_Temp_Files --
3110    ---------------------------
3111
3112    procedure Delete_All_Temp_Files is
3113    begin
3114       if Gnatmake_Called and not Debug.Debug_Flag_N then
3115          Delete_Mapping_Files;
3116          Delete_Temp_Config_Files;
3117          Prj.Env.Delete_All_Path_Files;
3118       end if;
3119    end Delete_All_Temp_Files;
3120
3121    --------------------------
3122    -- Delete_Mapping_Files --
3123    --------------------------
3124
3125    procedure Delete_Mapping_Files is
3126       Success : Boolean;
3127    begin
3128       if not Debug.Debug_Flag_N then
3129          if The_Mapping_File_Names /= null then
3130             for Project in The_Mapping_File_Names'Range (1) loop
3131                for Index in 1 .. Last_Mapping_File_Names (Project) loop
3132                   Delete_File
3133                     (Name => Get_Name_String
3134                                (The_Mapping_File_Names (Project, Index)),
3135                      Success => Success);
3136                end loop;
3137             end loop;
3138          end if;
3139       end if;
3140    end Delete_Mapping_Files;
3141
3142    ------------------------------
3143    -- Delete_Temp_Config_Files --
3144    ------------------------------
3145
3146    procedure Delete_Temp_Config_Files is
3147       Success : Boolean;
3148    begin
3149       if (not Debug.Debug_Flag_N) and Main_Project /= No_Project then
3150          for Project in 1 .. Projects.Last loop
3151             if Projects.Table (Project).Config_File_Temp then
3152                if Opt.Verbose_Mode then
3153                   Write_Str ("Deleting temp configuration file """);
3154                   Write_Str (Get_Name_String
3155                              (Projects.Table (Project).Config_File_Name));
3156                   Write_Line ("""");
3157                end if;
3158
3159                Delete_File
3160                  (Name    => Get_Name_String
3161                   (Projects.Table (Project).Config_File_Name),
3162                   Success => Success);
3163
3164                --  Make sure that we don't have a config file for this
3165                --  project, in case when there are several mains.
3166                --  In this case, we will recreate another config file:
3167                --  we cannot reuse the one that we just deleted!
3168
3169                Projects.Table (Project).Config_Checked   := False;
3170                Projects.Table (Project).Config_File_Name := No_Name;
3171                Projects.Table (Project).Config_File_Temp := False;
3172             end if;
3173          end loop;
3174       end if;
3175    end Delete_Temp_Config_Files;
3176
3177    -------------
3178    -- Display --
3179    -------------
3180
3181    procedure Display (Program : String; Args : Argument_List) is
3182    begin
3183       pragma Assert (Args'First = 1);
3184
3185       if Display_Executed_Programs then
3186          Write_Str (Program);
3187
3188          for J in Args'Range loop
3189
3190             --  Do not display the mapping file argument automatically
3191             --  created when using a project file.
3192
3193             if Main_Project = No_Project
3194               or else Debug.Debug_Flag_N
3195               or else Args (J)'Length < 8
3196               or else
3197                 Args (J)(Args (J)'First .. Args (J)'First + 6) /= "-gnatem"
3198             then
3199                --  When -dn is not specified, do not display the config
3200                --  pragmas switch (-gnatec) for the temporary file created
3201                --  by the project manager (always the first -gnatec switch).
3202                --  Reset Temporary_Config_File to False so that the eventual
3203                --  other -gnatec switches will be displayed.
3204
3205                if (not Debug.Debug_Flag_N)
3206                  and then Temporary_Config_File
3207                  and then Args (J)'Length > 7
3208                  and then Args (J)(Args (J)'First .. Args (J)'First + 6)
3209                             = "-gnatec"
3210                then
3211                   Temporary_Config_File := False;
3212
3213                --  Do not display the -F=mapping_file switch for gnatbind,
3214                --  if -dn is not specified.
3215
3216                elsif Debug.Debug_Flag_N
3217                  or else Args (J)'Length < 4
3218                  or else Args (J)(Args (J)'First .. Args (J)'First + 2) /=
3219                            "-F="
3220                then
3221                   Write_Str (" ");
3222                   Write_Str (Args (J).all);
3223                end if;
3224             end if;
3225          end loop;
3226
3227          Write_Eol;
3228       end if;
3229    end Display;
3230
3231    ----------------------
3232    -- Display_Commands --
3233    ----------------------
3234
3235    procedure Display_Commands (Display : Boolean := True) is
3236    begin
3237       Display_Executed_Programs := Display;
3238    end Display_Commands;
3239
3240    -------------
3241    -- Empty_Q --
3242    -------------
3243
3244    function Empty_Q return Boolean is
3245    begin
3246       if Debug.Debug_Flag_P then
3247          Write_Str ("   Q := [");
3248
3249          for J in Q_Front .. Q.Last - 1 loop
3250             Write_Str (" ");
3251             Write_Name (Q.Table (J).File);
3252             Write_Eol;
3253             Write_Str ("         ");
3254          end loop;
3255
3256          Write_Str ("]");
3257          Write_Eol;
3258       end if;
3259
3260       return Q_Front >= Q.Last;
3261    end Empty_Q;
3262
3263    --------------------------
3264    -- Enter_Into_Obsoleted --
3265    --------------------------
3266
3267    procedure Enter_Into_Obsoleted (F : Name_Id) is
3268       Name  : String := Get_Name_String (F);
3269       First : Natural := Name'Last;
3270       F2    : Name_Id := F;
3271
3272    begin
3273       while First > Name'First
3274         and then Name (First - 1) /= Directory_Separator
3275         and then Name (First - 1) /= '/'
3276       loop
3277          First := First - 1;
3278       end loop;
3279
3280       if First /= Name'First then
3281          Name_Len := 0;
3282          Add_Str_To_Name_Buffer (Name (First .. Name'Last));
3283          F2 := Name_Find;
3284       end if;
3285
3286       Debug_Msg ("New entry in Obsoleted table:", F2);
3287       Obsoleted.Set (F2, True);
3288    end Enter_Into_Obsoleted;
3289
3290    ---------------------
3291    -- Extract_Failure --
3292    ---------------------
3293
3294    procedure Extract_Failure
3295      (File  : out File_Name_Type;
3296       Unit  : out Unit_Name_Type;
3297       Found : out Boolean)
3298    is
3299    begin
3300       File  := Bad_Compilation.Table (Bad_Compilation.Last).File;
3301       Unit  := Bad_Compilation.Table (Bad_Compilation.Last).Unit;
3302       Found := Bad_Compilation.Table (Bad_Compilation.Last).Found;
3303       Bad_Compilation.Decrement_Last;
3304    end Extract_Failure;
3305
3306    --------------------
3307    -- Extract_From_Q --
3308    --------------------
3309
3310    procedure Extract_From_Q
3311      (Source_File : out File_Name_Type;
3312       Source_Unit : out Unit_Name_Type)
3313    is
3314       File : constant File_Name_Type := Q.Table (Q_Front).File;
3315       Unit : constant Unit_Name_Type := Q.Table (Q_Front).Unit;
3316
3317    begin
3318       if Debug.Debug_Flag_Q then
3319          Write_Str ("   Q := Q - [ ");
3320          Write_Name (File);
3321          Write_Str (" ]");
3322          Write_Eol;
3323       end if;
3324
3325       Q_Front := Q_Front + 1;
3326       Source_File := File;
3327       Source_Unit := Unit;
3328    end Extract_From_Q;
3329
3330    -----------------
3331    -- Make_Failed --
3332    -----------------
3333
3334    procedure Make_Failed (S1 : String; S2 : String := ""; S3 : String := "") is
3335    begin
3336       Delete_All_Temp_Files;
3337       Osint.Fail (S1, S2, S3);
3338    end Make_Failed;
3339
3340    --------------
3341    -- Gnatmake --
3342    --------------
3343
3344    procedure Gnatmake is
3345       Main_Source_File : File_Name_Type;
3346       --  The source file containing the main compilation unit
3347
3348       Compilation_Failures : Natural;
3349
3350       Total_Compilation_Failures : Natural := 0;
3351
3352       Is_Main_Unit : Boolean;
3353       --  Set to True by Compile_Sources if the Main_Source_File can be a
3354       --  main unit.
3355
3356       Main_ALI_File : File_Name_Type;
3357       --  The ali file corresponding to Main_Source_File
3358
3359       Executable : File_Name_Type := No_File;
3360       --  The file name of an executable
3361
3362       Non_Std_Executable : Boolean := False;
3363       --  Non_Std_Executable is set to True when there is a possibility
3364       --  that the linker will not choose the correct executable file name.
3365
3366       Current_Work_Dir : constant String_Access :=
3367                                     new String'(Get_Current_Dir);
3368       --  The current working directory, used to modify some relative path
3369       --  switches on the command line when a project file is used.
3370
3371    begin
3372       Gnatmake_Called := True;
3373
3374       Install_Int_Handler (Sigint_Intercepted'Access);
3375
3376       Do_Compile_Step := True;
3377       Do_Bind_Step    := True;
3378       Do_Link_Step    := True;
3379
3380       Obsoleted.Reset;
3381
3382       Make.Initialize;
3383
3384       Bind_Shared := No_Shared_Switch'Access;
3385       Bind_Shared_Known := False;
3386
3387       Failed_Links.Set_Last (0);
3388       Successful_Links.Set_Last (0);
3389
3390       if Hostparm.Java_VM then
3391          Gcc := new String'("jgnat");
3392          Gnatbind := new String'("jgnatbind");
3393          Gnatlink := new String'("jgnatlink");
3394
3395          --  Do not check for an object file (".o") when compiling to
3396          --  Java bytecode since ".class" files are generated instead.
3397
3398          Opt.Check_Object_Consistency := False;
3399       end if;
3400
3401       if Main_Project /= No_Project then
3402
3403          --  If the main project file is a library project file, main(s)
3404          --  cannot be specified on the command line.
3405
3406          if Osint.Number_Of_Files /= 0 then
3407             if Projects.Table (Main_Project).Library
3408               and then not Unique_Compile
3409               and then ((not Make_Steps) or else Bind_Only or else Link_Only)
3410             then
3411                Make_Failed ("cannot specify a main program " &
3412                             "on the command line for a library project file");
3413
3414             else
3415                --  Check that each main on the command line is a source of a
3416                --  project file and, if there are several mains, each of them
3417                --  is a source of the same project file.
3418
3419                Mains.Reset;
3420
3421                declare
3422                   Real_Main_Project : Project_Id := No_Project;
3423                   --  The project of the first main
3424
3425                   Proj : Project_Id := No_Project;
3426                   --  The project of the current main
3427
3428                begin
3429                   --  Check each main
3430
3431                   loop
3432                      declare
3433                         Main : constant String := Mains.Next_Main;
3434                         --  The name specified on the command line may include
3435                         --  directory information.
3436
3437                         File_Name : constant String := Base_Name (Main);
3438                         --  The simple file name of the current main main
3439
3440                      begin
3441                         exit when Main = "";
3442
3443                         --  Get the project of the current main
3444
3445                         Proj := Prj.Env.Project_Of (File_Name, Main_Project);
3446
3447                         --  Fail if the current main is not a source of a
3448                         --  project.
3449
3450                         if Proj = No_Project then
3451                            Make_Failed
3452                              ("""" & Main &
3453                               """ is not a source of any project");
3454
3455                         else
3456                            --  If there is directory information, check that
3457                            --  the source exists and, if it does, that the path
3458                            --  is the actual path of a source of a project.
3459
3460                            if Main /= File_Name then
3461                               declare
3462                                  Data : constant Project_Data :=
3463                                           Projects.Table (Main_Project);
3464
3465                                  Project_Path : constant String :=
3466                                    Prj.Env.File_Name_Of_Library_Unit_Body
3467                                      (Name              => File_Name,
3468                                       Project           => Main_Project,
3469                                       Main_Project_Only => False,
3470                                       Full_Path         => True);
3471                                  Real_Path : String_Access :=
3472                                    Locate_Regular_File
3473                                      (Main &
3474                                       Get_Name_String
3475                                         (Data.Naming.Current_Body_Suffix),
3476                                       "");
3477                               begin
3478                                  if Real_Path = null then
3479                                     Real_Path :=
3480                                       Locate_Regular_File
3481                                         (Main &
3482                                          Get_Name_String
3483                                            (Data.Naming.Current_Spec_Suffix),
3484                                          "");
3485                                  end if;
3486
3487                                  if Real_Path = null then
3488                                     Real_Path :=
3489                                       Locate_Regular_File (Main, "");
3490                                  end if;
3491
3492                                  --  Fail if the file cannot be found
3493
3494                                  if Real_Path = null then
3495                                     Make_Failed
3496                                       ("file """ & Main & """ does not exist");
3497                                  end if;
3498
3499                                  declare
3500                                     Normed_Path : constant String :=
3501                                       Normalize_Pathname
3502                                         (Real_Path.all,
3503                                          Case_Sensitive => False);
3504                                  begin
3505                                     Free (Real_Path);
3506
3507                                     --  Fail if it is not the correct path
3508
3509                                     if Normed_Path /= Project_Path then
3510                                        if Verbose_Mode then
3511                                           Write_Str (Normed_Path);
3512                                           Write_Str (" /= ");
3513                                           Write_Line (Project_Path);
3514                                        end if;
3515
3516                                        Make_Failed
3517                                          ("""" & Main &
3518                                           """ is not a source of any project");
3519                                     end if;
3520                                  end;
3521                               end;
3522                            end if;
3523
3524                            if not Unique_Compile then
3525
3526                               --  Record the project, if it is the first main
3527
3528                               if Real_Main_Project = No_Project then
3529                                  Real_Main_Project := Proj;
3530
3531                               elsif Proj /= Real_Main_Project then
3532
3533                                  --  Fail, as the current main is not a source
3534                                  --  of the same project as the first main.
3535
3536                                  Make_Failed
3537                                    ("""" & Main &
3538                                     """ is not a source of project " &
3539                                     Get_Name_String
3540                                       (Projects.Table
3541                                          (Real_Main_Project).Name));
3542                               end if;
3543                            end if;
3544                         end if;
3545
3546                         --  If -u and -U are not used, we may have mains that
3547                         --  are sources of a project that is not the one
3548                         --  specified with switch -P.
3549
3550                         if not Unique_Compile then
3551                            Main_Project := Real_Main_Project;
3552                         end if;
3553                      end;
3554                   end loop;
3555                end;
3556             end if;
3557
3558          --  If no mains have been specified on the command line,
3559          --  and we are using a project file, we either find the main(s)
3560          --  in the attribute Main of the main project, or we put all
3561          --  the sources of the project file as mains.
3562
3563          else
3564             declare
3565                Value : String_List_Id := Projects.Table (Main_Project).Mains;
3566
3567             begin
3568                --  The attribute Main is an empty list or not specified,
3569                --  or else gnatmake was invoked with the switch "-u".
3570
3571                if Value = Prj.Nil_String or else Unique_Compile then
3572
3573                   if (not Make_Steps) or else Compile_Only
3574                     or else not Projects.Table (Main_Project).Library
3575                   then
3576                      --  First make sure that the binder and the linker
3577                      --  will not be invoked.
3578
3579                      Do_Bind_Step := False;
3580                      Do_Link_Step := False;
3581
3582                      --  Put all the sources in the queue
3583
3584                      Insert_Project_Sources
3585                        (The_Project  => Main_Project,
3586                         All_Projects => Unique_Compile_All_Projects,
3587                         Into_Q       => False);
3588
3589                      --  If there are no sources to compile, we fail
3590
3591                      if Osint.Number_Of_Files = 0 then
3592                         Make_Failed ("no sources to compile");
3593                      end if;
3594                   end if;
3595
3596                else
3597                   --  The attribute Main is not an empty list.
3598                   --  Put all the main subprograms in the list as if there
3599                   --  were specified on the command line. However, if attribute
3600                   --  Languages includes a language other than Ada, only
3601                   --  include the Ada mains; if there is no Ada main, compile
3602                   --  all the sources of the project.
3603
3604                   declare
3605                      Data : Project_Data := Projects.Table (Main_Project);
3606
3607                      Languages : Variable_Value :=
3608                                    Prj.Util.Value_Of
3609                                      (Name_Languages, Data.Decl.Attributes);
3610
3611                      Current : String_List_Id;
3612                      Element : String_Element;
3613
3614                      Foreign_Language  : Boolean := False;
3615                      At_Least_One_Main : Boolean := False;
3616
3617                   begin
3618                      --  First, determine if there is a foreign language in
3619                      --  attribute Languages.
3620
3621                      if not Languages.Default then
3622                         Current := Languages.Values;
3623
3624                         Look_For_Foreign :
3625                         while Current /= Nil_String loop
3626                            Element := String_Elements.Table (Current);
3627                            Get_Name_String (Element.Value);
3628                            To_Lower (Name_Buffer (1 .. Name_Len));
3629
3630                            if Name_Buffer (1 .. Name_Len) /= "ada" then
3631                               Foreign_Language := True;
3632                               exit Look_For_Foreign;
3633                            end if;
3634
3635                            Current := Element.Next;
3636                         end loop Look_For_Foreign;
3637                      end if;
3638
3639                      --  Then, find all mains, or if there is a foreign
3640                      --  language, all the Ada mains.
3641
3642                      while Value /= Prj.Nil_String loop
3643                         Get_Name_String (String_Elements.Table (Value).Value);
3644
3645                         --  To know if a main is an Ada main, get its project.
3646                         --  It should be the project specified on the command
3647                         --  line.
3648
3649                         if (not Foreign_Language) or else
3650                             Prj.Env.Project_Of
3651                               (Name_Buffer (1 .. Name_Len), Main_Project) =
3652                              Main_Project
3653                         then
3654                            At_Least_One_Main := True;
3655                            Osint.Add_File
3656                              (Get_Name_String
3657                                 (String_Elements.Table (Value).Value));
3658                         end if;
3659
3660                         Value := String_Elements.Table (Value).Next;
3661                      end loop;
3662
3663                      --  If we did not get any main, it means that all mains
3664                      --  in attribute Mains are in a foreign language. So,
3665                      --  we put all sources of the main project in the Q.
3666
3667                      if not At_Least_One_Main then
3668
3669                         --  First make sure that the binder and the linker
3670                         --  will not be invoked if -z is not used.
3671
3672                         if not No_Main_Subprogram then
3673                            Do_Bind_Step := False;
3674                            Do_Link_Step := False;
3675                         end if;
3676
3677                         --  Put all the sources in the queue
3678
3679                         Insert_Project_Sources
3680                           (The_Project  => Main_Project,
3681                            All_Projects => Unique_Compile_All_Projects,
3682                            Into_Q       => False);
3683
3684                         --  If there are no sources to compile, we fail
3685
3686                         if Osint.Number_Of_Files = 0 then
3687                            Make_Failed ("no sources to compile");
3688                         end if;
3689                      end if;
3690                   end;
3691
3692                end if;
3693             end;
3694          end if;
3695       end if;
3696
3697       if Opt.Verbose_Mode then
3698          Write_Eol;
3699          Write_Str ("GNATMAKE ");
3700          Write_Str (Gnatvsn.Gnat_Version_String);
3701          Write_Str (" Copyright 1995-2003 Free Software Foundation, Inc.");
3702          Write_Eol;
3703       end if;
3704
3705       if Osint.Number_Of_Files = 0 then
3706          if Main_Project /= No_Project
3707            and then Projects.Table (Main_Project).Library
3708          then
3709             if Do_Bind_Step
3710               and then not Projects.Table (Main_Project).Standalone_Library
3711             then
3712                Make_Failed ("only stand-alone libraries may be bound");
3713             end if;
3714
3715             --  Add the default search directories to be able to find libgnat
3716
3717             Osint.Add_Default_Search_Dirs;
3718
3719             --  And bind and or link the library
3720
3721             MLib.Prj.Build_Library
3722               (For_Project   => Main_Project,
3723                Gnatbind      => Gnatbind.all,
3724                Gnatbind_Path => Gnatbind_Path,
3725                Gcc           => Gcc.all,
3726                Gcc_Path      => Gcc_Path,
3727                Bind          => Bind_Only,
3728                Link          => Link_Only);
3729             Exit_Program (E_Success);
3730
3731          else
3732             --  Output usage information if no files to compile
3733
3734             Usage;
3735             Exit_Program (E_Fatal);
3736          end if;
3737       end if;
3738
3739       --  If -M was specified, behave as if -n was specified
3740
3741       if Opt.List_Dependencies then
3742          Opt.Do_Not_Execute := True;
3743       end if;
3744
3745       --  Note that Osint.Next_Main_Source will always return the (possibly
3746       --  abbreviated file) without any directory information.
3747
3748       Main_Source_File := Next_Main_Source;
3749
3750       Add_Switch ("-I-", Binder, And_Save => True);
3751       Add_Switch ("-I-", Compiler, And_Save => True);
3752
3753       if Main_Project = No_Project then
3754          if Opt.Look_In_Primary_Dir then
3755
3756             Add_Switch
3757               ("-I" &
3758                Normalize_Directory_Name
3759                (Get_Primary_Src_Search_Directory.all).all,
3760                Compiler, Append_Switch => False,
3761                And_Save => False);
3762
3763             Add_Switch ("-aO" & Normalized_CWD,
3764                         Binder,
3765                         Append_Switch => False,
3766                         And_Save => False);
3767          end if;
3768
3769       else
3770          --  If we use a project file, we have already checked that a main
3771          --  specified on the command line with directory information has the
3772          --  path name corresponding to a correct source in the project tree.
3773          --  So, we don't need the directory information to be taken into
3774          --  account by Find_File, and in fact it may lead to take the wrong
3775          --  sources for other compilation units, when there are extending
3776          --  projects.
3777
3778          Opt.Look_In_Primary_Dir := False;
3779       end if;
3780
3781       --  If the user wants a program without a main subprogram, add the
3782       --  appropriate switch to the binder.
3783
3784       if Opt.No_Main_Subprogram then
3785          Add_Switch ("-z", Binder, And_Save => True);
3786       end if;
3787
3788       if Main_Project /= No_Project then
3789
3790          if Projects.Table (Main_Project).Object_Directory = No_Name then
3791             Make_Failed ("no sources to compile");
3792          end if;
3793
3794          --  Change the current directory to the object directory of the main
3795          --  project.
3796
3797          begin
3798             Project_Object_Directory := No_Project;
3799             Change_To_Object_Directory (Main_Project);
3800
3801          exception
3802             when Directory_Error =>
3803
3804                --  This should never happen. But, if it does, display the
3805                --  content of the parent directory of the obj dir.
3806
3807                declare
3808                   Parent : constant Dir_Name_Str :=
3809                     Dir_Name
3810                       (Get_Name_String
3811                            (Projects.Table (Main_Project).Object_Directory));
3812                   Dir : Dir_Type;
3813                   Str : String (1 .. 200);
3814                   Last : Natural;
3815
3816                begin
3817                   Write_Str ("Contents of directory """);
3818                   Write_Str (Parent);
3819                   Write_Line (""":");
3820
3821                   Open (Dir, Parent);
3822
3823                   loop
3824                      Read (Dir, Str, Last);
3825                      exit when Last = 0;
3826                      Write_Str ("   ");
3827                      Write_Line (Str (1 .. Last));
3828                   end loop;
3829
3830                   Close (Dir);
3831
3832                exception
3833                   when X : others =>
3834                      Write_Line ("(unexpected exception)");
3835                      Write_Line (Exception_Information (X));
3836
3837                      if Is_Open (Dir) then
3838                         Close (Dir);
3839                      end if;
3840                end;
3841
3842                Make_Failed ("unable to change working directory to """,
3843                             Get_Name_String
3844                              (Projects.Table (Main_Project).Object_Directory),
3845                             """");
3846          end;
3847
3848          --  Source file lookups should be cached for efficiency.
3849          --  Source files are not supposed to change.
3850
3851          Osint.Source_File_Data (Cache => True);
3852
3853          --  Find the file name of the (first) main unit
3854
3855          declare
3856             Main_Source_File_Name : constant String :=
3857                                       Get_Name_String (Main_Source_File);
3858             Main_Unit_File_Name   : constant String :=
3859                                       Prj.Env.File_Name_Of_Library_Unit_Body
3860                                         (Name    => Main_Source_File_Name,
3861                                          Project => Main_Project,
3862                                          Main_Project_Only =>
3863                                            not Unique_Compile);
3864
3865             The_Packages : constant Package_Id :=
3866               Projects.Table (Main_Project).Decl.Packages;
3867
3868             Builder_Package : constant Prj.Package_Id :=
3869                          Prj.Util.Value_Of
3870                            (Name        => Name_Builder,
3871                             In_Packages => The_Packages);
3872
3873             Binder_Package : constant Prj.Package_Id :=
3874                          Prj.Util.Value_Of
3875                            (Name        => Name_Binder,
3876                             In_Packages => The_Packages);
3877
3878             Linker_Package : constant Prj.Package_Id :=
3879                          Prj.Util.Value_Of
3880                            (Name       => Name_Linker,
3881                             In_Packages => The_Packages);
3882
3883          begin
3884             --  We fail if we cannot find the main source file
3885
3886             if Main_Unit_File_Name = "" then
3887                Make_Failed ('"' & Main_Source_File_Name,
3888                             """ is not a unit of project ",
3889                             Project_File_Name.all & ".");
3890             else
3891                --  Remove any directory information from the main
3892                --  source file name.
3893
3894                declare
3895                   Pos : Natural := Main_Unit_File_Name'Last;
3896
3897                begin
3898                   loop
3899                      exit when Pos < Main_Unit_File_Name'First or else
3900                        Main_Unit_File_Name (Pos) = Directory_Separator;
3901                      Pos := Pos - 1;
3902                   end loop;
3903
3904                   Name_Len := Main_Unit_File_Name'Last - Pos;
3905
3906                   Name_Buffer (1 .. Name_Len) :=
3907                     Main_Unit_File_Name
3908                     (Pos + 1 .. Main_Unit_File_Name'Last);
3909
3910                   Main_Source_File := Name_Find;
3911
3912                   --  We only output the main source file if there is only one
3913
3914                   if Opt.Verbose_Mode and then Osint.Number_Of_Files = 1 then
3915                      Write_Str ("Main source file: """);
3916                      Write_Str (Main_Unit_File_Name
3917                                 (Pos + 1 .. Main_Unit_File_Name'Last));
3918                      Write_Line (""".");
3919                   end if;
3920                end;
3921             end if;
3922
3923             --  If there is a package Builder in the main project file, add
3924             --  the switches from it.
3925
3926             if Builder_Package /= No_Package then
3927
3928                --  If there is only one main, we attempt to get the gnatmake
3929                --  switches for this main (if any). If there are no specific
3930                --  switch for this particular main, get the general gnatmake
3931                --  switches (if any).
3932
3933                if Osint.Number_Of_Files = 1 then
3934                   if Opt.Verbose_Mode then
3935                      Write_Str ("Adding gnatmake switches for """);
3936                      Write_Str (Main_Unit_File_Name);
3937                      Write_Line (""".");
3938                   end if;
3939
3940                   Add_Switches
3941                     (File_Name   => Main_Unit_File_Name,
3942                      The_Package => Builder_Package,
3943                      Program     => None);
3944
3945                else
3946                   --  If there are several mains, we always get the general
3947                   --  gnatmake switches (if any).
3948
3949                   --  Warn the user, if necessary, so that he is not surprized
3950                   --  that specific switches are not taken into account.
3951
3952                   declare
3953                      Defaults : constant Variable_Value :=
3954                        Prj.Util.Value_Of
3955                          (Name                    => Name_Ada,
3956                           Attribute_Or_Array_Name => Name_Default_Switches,
3957                           In_Package              => Builder_Package);
3958
3959                      Switches : constant Array_Element_Id :=
3960                           Prj.Util.Value_Of
3961                              (Name      => Name_Switches,
3962                               In_Arrays =>
3963                                 Packages.Table (Builder_Package).Decl.Arrays);
3964
3965                   begin
3966                      if Defaults /= Nil_Variable_Value then
3967                         if (not Opt.Quiet_Output)
3968                           and then Switches /= No_Array_Element
3969                         then
3970                            Write_Line
3971                              ("Warning: using Builder'Default_Switches" &
3972                               "(""Ada""), as there are several mains");
3973                         end if;
3974
3975                         --  As there is never a source with name " ", we are
3976                         --  guaranteed to always get the general switches.
3977
3978                         Add_Switches
3979                           (File_Name   => " ",
3980                            The_Package => Builder_Package,
3981                            Program     => None);
3982
3983                      elsif (not Opt.Quiet_Output)
3984                        and then Switches /= No_Array_Element
3985                      then
3986                         Write_Line
3987                           ("Warning: using no switches from package Builder," &
3988                            " as there are several mains");
3989                      end if;
3990                   end;
3991                end if;
3992             end if;
3993
3994             Osint.Add_Default_Search_Dirs;
3995
3996             --  Record the current last switch index for table Binder_Switches
3997             --  and Linker_Switches, so that these tables may be reset before
3998             --  for each main, before adding swiches from the project file
3999             --  and from the command line.
4000
4001             Last_Binder_Switch := Binder_Switches.Last;
4002             Last_Linker_Switch := Linker_Switches.Last;
4003
4004             Check_Steps;
4005
4006             --  Add binder switches from the project file for the first main
4007
4008             if Do_Bind_Step and Binder_Package /= No_Package then
4009                if Opt.Verbose_Mode then
4010                   Write_Str ("Adding binder switches for """);
4011                   Write_Str (Main_Unit_File_Name);
4012                   Write_Line (""".");
4013                end if;
4014
4015                Add_Switches
4016                  (File_Name   => Main_Unit_File_Name,
4017                   The_Package => Binder_Package,
4018                   Program     => Binder);
4019             end if;
4020
4021             --  Add linker switches from the project file for the first main
4022
4023             if Do_Link_Step and Linker_Package /= No_Package then
4024                if Opt.Verbose_Mode then
4025                   Write_Str ("Adding linker switches for""");
4026                   Write_Str (Main_Unit_File_Name);
4027                   Write_Line (""".");
4028                end if;
4029
4030                Add_Switches
4031                  (File_Name   => Main_Unit_File_Name,
4032                   The_Package => Linker_Package,
4033                   Program     => Linker);
4034             end if;
4035          end;
4036       end if;
4037
4038       --  Get the target parameters, which are only needed for a couple of
4039       --  cases in gnatmake. Protect against an exception, such as the case
4040       --  of system.ads missing from the library, and fail gracefully.
4041
4042       begin
4043          Targparm.Get_Target_Parameters;
4044
4045       exception
4046          when Unrecoverable_Error =>
4047             Make_Failed ("*** make failed.");
4048       end;
4049
4050       Display_Commands (not Opt.Quiet_Output);
4051
4052       Check_Steps;
4053
4054       if Main_Project /= No_Project then
4055
4056          --  For all library project, if the library file does not exist
4057          --  put all the project sources in the queue, and flag the project
4058          --  so that the library is generated.
4059
4060          if MLib.Tgt.Support_For_Libraries /= MLib.Tgt.None then
4061             for Proj in Projects.First .. Projects.Last loop
4062                if Projects.Table (Proj).Library then
4063                   Projects.Table (Proj).Flag1 :=
4064                     not MLib.Tgt.Library_Exists_For (Proj);
4065
4066                   if Projects.Table (Proj).Flag1 then
4067                      if Opt.Verbose_Mode then
4068                         Write_Str
4069                           ("Library file does not exist for project """);
4070                         Write_Str
4071                           (Get_Name_String (Projects.Table (Proj).Name));
4072                         Write_Line ("""");
4073                      end if;
4074
4075                      Insert_Project_Sources
4076                        (The_Project  => Proj,
4077                         All_Projects => False,
4078                         Into_Q       => True);
4079                   end if;
4080                end if;
4081             end loop;
4082          end if;
4083
4084          --  If a relative path output file has been specified, we add
4085          --  the exec directory.
4086
4087          for J in reverse 1 .. Saved_Linker_Switches.Last - 1 loop
4088             if Saved_Linker_Switches.Table (J).all = Output_Flag.all then
4089                declare
4090                   Exec_File_Name : constant String :=
4091                     Saved_Linker_Switches.Table (J + 1).all;
4092
4093                begin
4094                   if not Is_Absolute_Path (Exec_File_Name) then
4095                      for Index in Exec_File_Name'Range loop
4096                         if Exec_File_Name (Index) = Directory_Separator then
4097                            Make_Failed ("relative executable (""",
4098                                         Exec_File_Name,
4099                                         """) with directory part not " &
4100                                         "allowed when using project files");
4101                         end if;
4102                      end loop;
4103
4104                      Get_Name_String (Projects.Table
4105                                         (Main_Project).Exec_Directory);
4106
4107                      if Name_Buffer (Name_Len) /= Directory_Separator then
4108                         Name_Len := Name_Len + 1;
4109                         Name_Buffer (Name_Len) := Directory_Separator;
4110                      end if;
4111
4112                      Name_Buffer (Name_Len + 1 ..
4113                                     Name_Len + Exec_File_Name'Length) :=
4114                        Exec_File_Name;
4115                      Name_Len := Name_Len + Exec_File_Name'Length;
4116                      Saved_Linker_Switches.Table (J + 1) :=
4117                        new String'(Name_Buffer (1 .. Name_Len));
4118                   end if;
4119                end;
4120
4121                exit;
4122             end if;
4123          end loop;
4124
4125          --  If we are using a project file, for relative paths we add the
4126          --  current working directory for any relative path on the command
4127          --  line and the project directory, for any relative path in the
4128          --  project file.
4129
4130          declare
4131             Dir_Path : constant String_Access :=
4132               new String'(Get_Name_String
4133                             (Projects.Table (Main_Project).Directory));
4134          begin
4135             for J in 1 .. Binder_Switches.Last loop
4136                Test_If_Relative_Path
4137                  (Binder_Switches.Table (J),
4138                   Parent => Dir_Path, Including_L_Switch => False);
4139             end loop;
4140
4141             for J in 1 .. Saved_Binder_Switches.Last loop
4142                Test_If_Relative_Path
4143                  (Saved_Binder_Switches.Table (J),
4144                   Parent => Current_Work_Dir, Including_L_Switch => False);
4145             end loop;
4146
4147             for J in 1 .. Linker_Switches.Last loop
4148                Test_If_Relative_Path
4149                  (Linker_Switches.Table (J), Parent => Dir_Path);
4150             end loop;
4151
4152             for J in 1 .. Saved_Linker_Switches.Last loop
4153                Test_If_Relative_Path
4154                  (Saved_Linker_Switches.Table (J), Parent => Current_Work_Dir);
4155             end loop;
4156
4157             for J in 1 .. Gcc_Switches.Last loop
4158                Test_If_Relative_Path
4159                  (Gcc_Switches.Table (J), Parent => Dir_Path);
4160             end loop;
4161
4162             for J in 1 .. Saved_Gcc_Switches.Last loop
4163                Test_If_Relative_Path
4164                  (Saved_Gcc_Switches.Table (J), Parent => Current_Work_Dir);
4165             end loop;
4166          end;
4167       end if;
4168
4169       --  We now put in the Binder_Switches and Linker_Switches tables,
4170       --  the binder and linker switches of the command line that have been
4171       --  put in the Saved_ tables. If a project file was used, then the
4172       --  command line switches will follow the project file switches.
4173
4174       for J in 1 .. Saved_Binder_Switches.Last loop
4175          Add_Switch
4176            (Saved_Binder_Switches.Table (J),
4177             Binder,
4178             And_Save => False);
4179       end loop;
4180
4181       for J in 1 .. Saved_Linker_Switches.Last loop
4182          Add_Switch
4183            (Saved_Linker_Switches.Table (J),
4184             Linker,
4185             And_Save => False);
4186       end loop;
4187
4188       --  If no project file is used, we just put the gcc switches
4189       --  from the command line in the Gcc_Switches table.
4190
4191       if Main_Project = No_Project then
4192          for J in 1 .. Saved_Gcc_Switches.Last loop
4193             Add_Switch
4194               (Saved_Gcc_Switches.Table (J),
4195                Compiler,
4196               And_Save => False);
4197          end loop;
4198
4199       else
4200          --  And we put the command line gcc switches in the variable
4201          --  The_Saved_Gcc_Switches. They are going to be used later
4202          --  in procedure Compile_Sources.
4203
4204          The_Saved_Gcc_Switches :=
4205            new Argument_List (1 .. Saved_Gcc_Switches.Last + 1);
4206
4207          for J in 1 .. Saved_Gcc_Switches.Last loop
4208             The_Saved_Gcc_Switches (J) := Saved_Gcc_Switches.Table (J);
4209          end loop;
4210
4211          --  We never use gnat.adc when a project file is used
4212
4213          The_Saved_Gcc_Switches (The_Saved_Gcc_Switches'Last) :=
4214            No_gnat_adc;
4215
4216       end if;
4217
4218       --  If there was a --GCC, --GNATBIND or --GNATLINK switch on
4219       --  the command line, then we have to use it, even if there was
4220       --  another switch in the project file.
4221
4222       if Saved_Gcc /= null then
4223          Gcc := Saved_Gcc;
4224       end if;
4225
4226       if Saved_Gnatbind /= null then
4227          Gnatbind := Saved_Gnatbind;
4228       end if;
4229
4230       if Saved_Gnatlink /= null then
4231          Gnatlink := Saved_Gnatlink;
4232       end if;
4233
4234       Gcc_Path       := GNAT.OS_Lib.Locate_Exec_On_Path (Gcc.all);
4235       Gnatbind_Path  := GNAT.OS_Lib.Locate_Exec_On_Path (Gnatbind.all);
4236       Gnatlink_Path  := GNAT.OS_Lib.Locate_Exec_On_Path (Gnatlink.all);
4237
4238       --  If we have specified -j switch both from the project file
4239       --  and on the command line, the one from the command line takes
4240       --  precedence.
4241
4242       if Saved_Maximum_Processes = 0 then
4243          Saved_Maximum_Processes := Opt.Maximum_Processes;
4244       end if;
4245
4246       --  Allocate as many temporary mapping file names as the maximum
4247       --  number of compilation processed, for each possible project.
4248
4249       The_Mapping_File_Names :=
4250         new Temp_File_Names
4251               (No_Project .. Projects.Last, 1 .. Saved_Maximum_Processes);
4252       Last_Mapping_File_Names :=
4253         new Indices'(No_Project .. Projects.Last => 0);
4254
4255       The_Free_Mapping_File_Indices :=
4256         new Free_File_Indices
4257               (No_Project .. Projects.Last, 1 .. Saved_Maximum_Processes);
4258       Last_Free_Indices :=
4259         new Indices'(No_Project .. Projects.Last => 0);
4260
4261       Bad_Compilation.Init;
4262
4263       --  Here is where the make process is started
4264
4265       --  We do the same process for each main
4266
4267       Multiple_Main_Loop : for N_File in 1 .. Osint.Number_Of_Files loop
4268
4269          --  Increase the marking label to be sure to check sources
4270          --  for all executables.
4271
4272          Marking_Label := Marking_Label + 1;
4273
4274          --  Make sure it is not 0, which is the default value for
4275          --  a file that has never been marked.
4276
4277          if Marking_Label = 0 then
4278             Marking_Label := 1;
4279          end if;
4280
4281          --  First, find the executable name and path
4282
4283          Executable          := No_File;
4284          Executable_Obsolete := False;
4285          Non_Std_Executable  := False;
4286
4287          --  Look inside the linker switches to see if the name
4288          --  of the final executable program was specified.
4289
4290          for
4291            J in reverse Linker_Switches.First .. Linker_Switches.Last
4292          loop
4293             if Linker_Switches.Table (J).all = Output_Flag.all then
4294                pragma Assert (J < Linker_Switches.Last);
4295
4296                --  We cannot specify a single executable for several
4297                --  main subprograms!
4298
4299                if Osint.Number_Of_Files > 1 then
4300                   Fail
4301                     ("cannot specify a single executable " &
4302                      "for several mains");
4303                end if;
4304
4305                Name_Len := Linker_Switches.Table (J + 1)'Length;
4306                Name_Buffer (1 .. Name_Len) :=
4307                  Linker_Switches.Table (J + 1).all;
4308
4309                --  Put in canonical case to detect suffixs such as ".EXE" on
4310                --  Windows or VMS.
4311
4312                Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
4313
4314                --  If target has an executable suffix and it has not been
4315                --  specified then it is added here.
4316
4317                if Executable_Suffix'Length /= 0
4318                  and then Name_Buffer
4319                           (Name_Len - Executable_Suffix'Length + 1 .. Name_Len)
4320                              /= Executable_Suffix
4321                then
4322                   --  Get back the original name to keep the case on Windows
4323
4324                   Name_Buffer (1 .. Name_Len) :=
4325                     Linker_Switches.Table (J + 1).all;
4326
4327                   --  Add the executable suffix
4328
4329                   Name_Buffer (Name_Len + 1 ..
4330                                        Name_Len + Executable_Suffix'Length) :=
4331                       Executable_Suffix;
4332                   Name_Len := Name_Len + Executable_Suffix'Length;
4333
4334                else
4335                   --  Get back the original name to keep the case on Windows
4336
4337                   Name_Buffer (1 .. Name_Len) :=
4338                     Linker_Switches.Table (J + 1).all;
4339                end if;
4340
4341                Executable := Name_Enter;
4342
4343                Verbose_Msg (Executable, "final executable");
4344             end if;
4345          end loop;
4346
4347          --  If the name of the final executable program was not
4348          --  specified then construct it from the main input file.
4349
4350          if Executable = No_File then
4351             if Main_Project = No_Project then
4352                Executable :=
4353                  Executable_Name (Strip_Suffix (Main_Source_File));
4354
4355             else
4356                --  If we are using a project file, we attempt to
4357                --  remove the body (or spec) termination of the main
4358                --  subprogram. We find it the the naming scheme of the
4359                --  project file. This will avoid to generate an
4360                --  executable "main.2" for a main subprogram
4361                --  "main.2.ada", when the body termination is ".2.ada".
4362
4363                Executable := Prj.Util.Executable_Of
4364                                         (Main_Project, Main_Source_File);
4365             end if;
4366          end if;
4367
4368          if Main_Project /= No_Project then
4369             declare
4370                Exec_File_Name : constant String :=
4371                  Get_Name_String (Executable);
4372
4373             begin
4374                if not Is_Absolute_Path (Exec_File_Name) then
4375                   for Index in Exec_File_Name'Range loop
4376                      if Exec_File_Name (Index) = Directory_Separator then
4377                         Make_Failed ("relative executable (""",
4378                                            Exec_File_Name,
4379                                            """) with directory part not " &
4380                                            "allowed when using project files");
4381                      end if;
4382                   end loop;
4383
4384                   Get_Name_String (Projects.Table
4385                                            (Main_Project).Exec_Directory);
4386
4387                   if
4388                     Name_Buffer (Name_Len) /= Directory_Separator
4389                   then
4390                      Name_Len := Name_Len + 1;
4391                      Name_Buffer (Name_Len) := Directory_Separator;
4392                   end if;
4393
4394                   Name_Buffer (Name_Len + 1 ..
4395                                        Name_Len + Exec_File_Name'Length) :=
4396                       Exec_File_Name;
4397                   Name_Len := Name_Len + Exec_File_Name'Length;
4398                   Executable := Name_Find;
4399                   Non_Std_Executable := True;
4400                end if;
4401             end;
4402
4403          end if;
4404
4405          if Do_Compile_Step then
4406             Recursive_Compilation_Step : declare
4407                Args : Argument_List (1 .. Gcc_Switches.Last);
4408
4409                First_Compiled_File : Name_Id;
4410                Youngest_Obj_File   : Name_Id;
4411                Youngest_Obj_Stamp  : Time_Stamp_Type;
4412
4413                Executable_Stamp : Time_Stamp_Type;
4414                --  Executable is the final executable program.
4415
4416                Library_Rebuilt : Boolean := False;
4417
4418             begin
4419                for J in 1 .. Gcc_Switches.Last loop
4420                   Args (J) := Gcc_Switches.Table (J);
4421                end loop;
4422
4423                --  Now we invoke Compile_Sources for the current main
4424
4425                Compile_Sources
4426                  (Main_Source           => Main_Source_File,
4427                   Args                  => Args,
4428                   First_Compiled_File   => First_Compiled_File,
4429                   Most_Recent_Obj_File  => Youngest_Obj_File,
4430                   Most_Recent_Obj_Stamp => Youngest_Obj_Stamp,
4431                   Main_Unit             => Is_Main_Unit,
4432                   Compilation_Failures  => Compilation_Failures,
4433                   Check_Readonly_Files  => Opt.Check_Readonly_Files,
4434                   Do_Not_Execute        => Opt.Do_Not_Execute,
4435                   Force_Compilations    => Opt.Force_Compilations,
4436                   In_Place_Mode         => Opt.In_Place_Mode,
4437                   Keep_Going            => Opt.Keep_Going,
4438                   Initialize_ALI_Data   => True,
4439                   Max_Process           => Saved_Maximum_Processes);
4440
4441                if Opt.Verbose_Mode then
4442                   Write_Str ("End of compilation");
4443                   Write_Eol;
4444                end if;
4445
4446                --  Make sure the queue will be reinitialized for the next round
4447
4448                First_Q_Initialization := True;
4449
4450                Total_Compilation_Failures :=
4451                  Total_Compilation_Failures + Compilation_Failures;
4452
4453                if Total_Compilation_Failures /= 0 then
4454                   if Opt.Keep_Going then
4455                      goto Next_Main;
4456
4457                   else
4458                      List_Bad_Compilations;
4459                      raise Compilation_Failed;
4460                   end if;
4461                end if;
4462
4463                --  Regenerate libraries, if any, and if object files
4464                --  have been regenerated.
4465
4466                if Main_Project /= No_Project
4467                  and then MLib.Tgt.Support_For_Libraries /= MLib.Tgt.None
4468                  and then (Do_Bind_Step or Unique_Compile_All_Projects
4469                            or not Compile_Only)
4470                  and then (Do_Link_Step or N_File = Osint.Number_Of_Files)
4471                then
4472                   Library_Projs.Init;
4473
4474                   declare
4475                      Proj2   : Project_Id;
4476                      Depth   : Natural;
4477                      Current : Natural;
4478
4479                   begin
4480                      --  Put in Library_Projs table all library project
4481                      --  file ids when the library need to be rebuilt.
4482
4483                      for Proj1 in Projects.First .. Projects.Last loop
4484
4485                         if Projects.Table (Proj1).Library
4486                           and then not Projects.Table (Proj1).Flag1
4487                         then
4488                            MLib.Prj.Check_Library (Proj1);
4489                         end if;
4490
4491                         if Projects.Table (Proj1).Flag1 then
4492                            Library_Projs.Increment_Last;
4493                            Current := Library_Projs.Last;
4494                            Depth := Projects.Table (Proj1).Depth;
4495
4496                            --  Put the projects in decreasing depth order,
4497                            --  so that if libA depends on libB, libB is first
4498                            --  in order.
4499
4500                            while Current > 1 loop
4501                               Proj2 := Library_Projs.Table (Current - 1);
4502                               exit when Projects.Table (Proj2).Depth >= Depth;
4503                               Library_Projs.Table (Current) := Proj2;
4504                               Current := Current - 1;
4505                            end loop;
4506
4507                            Library_Projs.Table (Current) := Proj1;
4508                            Projects.Table (Proj1).Flag1 := False;
4509                         end if;
4510                      end loop;
4511                   end;
4512
4513                   --  Build the libraries, if any need to be built
4514
4515                   for J in 1 .. Library_Projs.Last loop
4516                      Library_Rebuilt := True;
4517                      MLib.Prj.Build_Library
4518                        (For_Project   => Library_Projs.Table (J),
4519                         Gnatbind      => Gnatbind.all,
4520                         Gnatbind_Path => Gnatbind_Path,
4521                         Gcc           => Gcc.all,
4522                         Gcc_Path      => Gcc_Path);
4523                   end loop;
4524                end if;
4525
4526                if Opt.List_Dependencies then
4527                   if First_Compiled_File /= No_File then
4528                      Inform
4529                        (First_Compiled_File,
4530                         "must be recompiled. Can't generate dependence list.");
4531                   else
4532                      List_Depend;
4533                   end if;
4534
4535                elsif First_Compiled_File = No_File
4536                  and then not Do_Bind_Step
4537                  and then not Opt.Quiet_Output
4538                  and then not Library_Rebuilt
4539                  and then Osint.Number_Of_Files = 1
4540                then
4541                   Inform (Msg => "objects up to date.");
4542
4543                elsif Opt.Do_Not_Execute
4544                  and then First_Compiled_File /= No_File
4545                then
4546                   Write_Name (First_Compiled_File);
4547                   Write_Eol;
4548                end if;
4549
4550                --  Stop after compile step if any of:
4551
4552                --    1) -n (Do_Not_Execute) specified
4553
4554                --    2) -M (List_Dependencies) specified (also sets
4555                --       Do_Not_Execute above, so this is probably superfluous).
4556
4557                --    3) -c (Compile_Only) specified, but not -b (Bind_Only)
4558
4559                --    4) Made unit cannot be a main unit
4560
4561                if (Opt.Do_Not_Execute
4562                    or Opt.List_Dependencies
4563                    or not Do_Bind_Step
4564                    or not Is_Main_Unit)
4565                  and then not No_Main_Subprogram
4566                then
4567                   if Osint.Number_Of_Files = 1 then
4568                      exit Multiple_Main_Loop;
4569
4570                   else
4571                      goto Next_Main;
4572                   end if;
4573                end if;
4574
4575                --  If the objects were up-to-date check if the executable file
4576                --  is also up-to-date. For now always bind and link on the JVM
4577                --  since there is currently no simple way to check the
4578                --  up-to-date status of objects
4579
4580                if not Hostparm.Java_VM
4581                  and then First_Compiled_File = No_File
4582                then
4583                   Executable_Stamp    := File_Stamp (Executable);
4584
4585                   if not Executable_Obsolete then
4586                      Executable_Obsolete :=
4587                        Youngest_Obj_Stamp > Executable_Stamp;
4588                   end if;
4589
4590                   if not Executable_Obsolete then
4591                      for Index in reverse 1 .. Dependencies.Last loop
4592                         if Is_In_Obsoleted
4593                              (Dependencies.Table (Index).Depends_On)
4594                         then
4595                            Enter_Into_Obsoleted
4596                              (Dependencies.Table (Index).This);
4597                         end if;
4598                      end loop;
4599
4600                      Executable_Obsolete := Is_In_Obsoleted (Main_Source_File);
4601                      Dependencies.Init;
4602                   end if;
4603
4604                   if not Executable_Obsolete then
4605
4606                      --  If no Ada object files obsolete the executable, check
4607                      --  for younger or missing linker files.
4608
4609                      Check_Linker_Options
4610                        (Executable_Stamp,
4611                         Youngest_Obj_File,
4612                         Youngest_Obj_Stamp);
4613
4614                      Executable_Obsolete := Youngest_Obj_File /= No_File;
4615                   end if;
4616
4617                   --  Return if the executable is up to date
4618                   --  and otherwise motivate the relink/rebind.
4619
4620                   if not Executable_Obsolete then
4621                      if not Opt.Quiet_Output then
4622                         Inform (Executable, "up to date.");
4623                      end if;
4624
4625                      if Osint.Number_Of_Files = 1 then
4626                         exit Multiple_Main_Loop;
4627
4628                      else
4629                         goto Next_Main;
4630                      end if;
4631                   end if;
4632
4633                   if Executable_Stamp (1) = ' ' then
4634                      Verbose_Msg (Executable, "missing.", Prefix => "  ");
4635
4636                   elsif Youngest_Obj_Stamp (1) = ' ' then
4637                      Verbose_Msg
4638                        (Youngest_Obj_File,
4639                         "missing.",
4640                         Prefix => "  ");
4641
4642                   elsif Youngest_Obj_Stamp > Executable_Stamp then
4643                      Verbose_Msg
4644                        (Youngest_Obj_File,
4645                         "(" & String (Youngest_Obj_Stamp) & ") newer than",
4646                         Executable,
4647                         "(" & String (Executable_Stamp) & ")");
4648
4649                   else
4650                      Verbose_Msg
4651                        (Executable, "needs to be rebuild.",
4652                         Prefix => "  ");
4653
4654                   end if;
4655                end if;
4656             end Recursive_Compilation_Step;
4657          end if;
4658
4659          --  For binding and linking, we need to be in the object directory of
4660          --  the main project.
4661
4662          if Main_Project /= No_Project then
4663             Change_To_Object_Directory (Main_Project);
4664          end if;
4665
4666          --  If we are here, it means that we need to rebuilt the current
4667          --  main. So we set Executable_Obsolete to True to make sure that
4668          --  the subsequent mains will be rebuilt.
4669
4670          Main_ALI_In_Place_Mode_Step : declare
4671             ALI_File : File_Name_Type;
4672             Src_File : File_Name_Type;
4673
4674          begin
4675             Src_File      := Strip_Directory (Main_Source_File);
4676             ALI_File      := Lib_File_Name (Src_File);
4677             Main_ALI_File := Full_Lib_File_Name (ALI_File);
4678
4679             --  When In_Place_Mode, the library file can be located in the
4680             --  Main_Source_File directory which may not be present in the
4681             --  library path. In this case, use the corresponding library file
4682             --  name.
4683
4684             if Main_ALI_File = No_File and then Opt.In_Place_Mode then
4685                Get_Name_String (Get_Directory (Full_Source_Name (Src_File)));
4686                Get_Name_String_And_Append (ALI_File);
4687                Main_ALI_File := Name_Find;
4688                Main_ALI_File := Full_Lib_File_Name (Main_ALI_File);
4689             end if;
4690
4691             if Main_ALI_File = No_File then
4692                Make_Failed ("could not find the main ALI file");
4693             end if;
4694          end Main_ALI_In_Place_Mode_Step;
4695
4696          if Do_Bind_Step then
4697             Bind_Step : declare
4698                Args : Argument_List
4699                         (Binder_Switches.First .. Binder_Switches.Last + 1);
4700                --  The arguments for the invocation of gnatbind
4701
4702                Last_Arg : Natural := Binder_Switches.Last;
4703                --  Index of the last argument in Args
4704
4705                Mapping_FD : File_Descriptor := Invalid_FD;
4706                --  A File Descriptor for an eventual mapping file
4707
4708                Mapping_Path : Name_Id := No_Name;
4709                --  The path name of the mapping file
4710
4711                ALI_Unit : Name_Id := No_Name;
4712                --  The unit name of an ALI file
4713
4714                ALI_Name : Name_Id := No_Name;
4715                --  The file name of the ALI file
4716
4717                ALI_Project  : Project_Id := No_Project;
4718                --  The project of the ALI file
4719
4720                Bytes : Integer;
4721                OK    : Boolean := True;
4722
4723                Status : Boolean;
4724                --  For call to Close
4725
4726             begin
4727                --  If it is the first time the bind step is performed,
4728                --  check if there are shared libraries, so that gnatbind is
4729                --  called with -shared.
4730
4731                if not Bind_Shared_Known then
4732                   if Main_Project /= No_Project
4733                      and then MLib.Tgt.Support_For_Libraries /= MLib.Tgt.None
4734                   then
4735                      for Proj in Projects.First .. Projects.Last loop
4736                         if Projects.Table (Proj).Library and then
4737                           Projects.Table (Proj).Library_Kind /= Static
4738                         then
4739                            Bind_Shared := Shared_Switch'Access;
4740                            exit;
4741                         end if;
4742                      end loop;
4743                   end if;
4744
4745                   Bind_Shared_Known := True;
4746                end if;
4747
4748                --  Get all the binder switches
4749
4750                for J in Binder_Switches.First .. Last_Arg loop
4751                   Args (J) := Binder_Switches.Table (J);
4752                end loop;
4753
4754                if Main_Project /= No_Project then
4755
4756                   --  Put all the source directories in ADA_INCLUDE_PATH,
4757                   --  and all the object directories in ADA_OBJECTS_PATH
4758
4759                   Prj.Env.Set_Ada_Paths (Main_Project, False);
4760
4761                   --  If switch -C was specified, create a binder mapping file
4762
4763                   if Create_Mapping_File then
4764                      Tempdir.Create_Temp_File (Mapping_FD, Mapping_Path);
4765
4766                      if Mapping_FD /= Invalid_FD then
4767
4768                         --  Traverse all units
4769
4770                         for J in Prj.Com.Units.First .. Prj.Com.Units.Last loop
4771                            declare
4772                               Unit : constant Prj.Com.Unit_Data :=
4773                                        Prj.Com.Units.Table (J);
4774                               use Prj.Com;
4775
4776                            begin
4777                               if Unit.Name /= No_Name then
4778
4779                                  --  If there is a body, put it in the mapping
4780
4781                                  if Unit.File_Names (Body_Part).Name /= No_Name
4782                                    and then Unit.File_Names (Body_Part).Project
4783                                                   /= No_Project
4784                                  then
4785                                     Get_Name_String (Unit.Name);
4786                                     Name_Buffer
4787                                       (Name_Len + 1 .. Name_Len + 2) := "%b";
4788                                     Name_Len := Name_Len + 2;
4789                                     ALI_Unit := Name_Find;
4790                                     ALI_Name :=
4791                                       Lib_File_Name
4792                                         (Unit.File_Names (Body_Part).Name);
4793                                     ALI_Project :=
4794                                       Unit.File_Names (Body_Part).Project;
4795
4796                                  --  Otherwise, if there is a spec, put it
4797                                  --  in the mapping.
4798
4799                                  elsif Unit.File_Names (Specification).Name
4800                                                  /= No_Name
4801                                    and then Unit.File_Names
4802                                              (Specification).Project
4803                                                 /= No_Project
4804                                  then
4805                                     Get_Name_String (Unit.Name);
4806                                     Name_Buffer
4807                                       (Name_Len + 1 .. Name_Len + 2) := "%s";
4808                                     Name_Len := Name_Len + 2;
4809                                     ALI_Unit := Name_Find;
4810                                     ALI_Name := Lib_File_Name
4811                                         (Unit.File_Names (Specification).Name);
4812                                     ALI_Project :=
4813                                       Unit.File_Names (Specification).Project;
4814
4815                                  else
4816                                     ALI_Name := No_Name;
4817                                  end if;
4818
4819                                  --  If we have something to put in the mapping
4820                                  --  then we do it now. However, if the project
4821                                  --  is extended, we don't put anything in the
4822                                  --  mapping file, because we do not know where
4823                                  --  the ALI file is: it might be in the ext-
4824                                  --  ended project obj dir as well as in the
4825                                  --  extending project obj dir.
4826
4827                                  if ALI_Name /= No_Name
4828                                     and then Projects.Table
4829                                                (ALI_Project).Extended_By
4830                                                         = No_Project
4831                                     and then Projects.Table
4832                                                (ALI_Project).Extends
4833                                                         = No_Project
4834                                  then
4835                                     --  First line is the unit name
4836
4837                                     Get_Name_String (ALI_Unit);
4838                                     Name_Len := Name_Len + 1;
4839                                     Name_Buffer (Name_Len) := ASCII.LF;
4840                                     Bytes :=
4841                                       Write
4842                                         (Mapping_FD,
4843                                          Name_Buffer (1)'Address,
4844                                          Name_Len);
4845                                     OK := Bytes = Name_Len;
4846
4847                                     if OK then
4848
4849                                        --  Second line it the ALI file name
4850
4851                                        Get_Name_String (ALI_Name);
4852                                        Name_Len := Name_Len + 1;
4853                                        Name_Buffer (Name_Len) := ASCII.LF;
4854                                        Bytes :=
4855                                          Write
4856                                            (Mapping_FD,
4857                                             Name_Buffer (1)'Address,
4858                                             Name_Len);
4859                                        OK := Bytes = Name_Len;
4860                                     end if;
4861
4862                                     if OK then
4863
4864                                        --  Third line it the ALI path name,
4865                                        --  concatenation of the project
4866                                        --  directory with the ALI file name.
4867
4868                                        declare
4869                                           ALI : constant String :=
4870                                                   Get_Name_String (ALI_Name);
4871                                        begin
4872                                           Get_Name_String
4873                                             (Projects.Table (ALI_Project).
4874                                                Object_Directory);
4875
4876                                           if Name_Buffer (Name_Len) /=
4877                                             Directory_Separator
4878                                           then
4879                                              Name_Len := Name_Len + 1;
4880                                              Name_Buffer (Name_Len) :=
4881                                                Directory_Separator;
4882                                           end if;
4883
4884                                           Name_Buffer
4885                                             (Name_Len + 1 ..
4886                                                Name_Len + ALI'Length) := ALI;
4887                                           Name_Len :=
4888                                             Name_Len + ALI'Length + 1;
4889                                           Name_Buffer (Name_Len) := ASCII.LF;
4890                                           Bytes :=
4891                                             Write
4892                                               (Mapping_FD,
4893                                                Name_Buffer (1)'Address,
4894                                                Name_Len);
4895                                           OK := Bytes = Name_Len;
4896                                        end;
4897                                     end if;
4898
4899                                     --  If OK is False, it means we were unable
4900                                     --  to write a line. No point in continuing
4901                                     --  with the other units.
4902
4903                                     exit when not OK;
4904                                  end if;
4905                               end if;
4906                            end;
4907                         end loop;
4908
4909                         Close (Mapping_FD, Status);
4910
4911                         OK := OK and Status;
4912
4913                         --  If the creation of the mapping file was successful,
4914                         --  we add the switch to the arguments of gnatbind.
4915
4916                         if OK then
4917                            Last_Arg := Last_Arg + 1;
4918                            Args (Last_Arg) := new String'
4919                                       ("-F=" & Get_Name_String (Mapping_Path));
4920                         end if;
4921                      end if;
4922                   end if;
4923
4924                end if;
4925
4926                begin
4927                   Bind (Main_ALI_File,
4928                         Bind_Shared.all & Args (Args'First .. Last_Arg));
4929
4930                exception
4931                   when others =>
4932
4933                      --  If -dn was not specified, delete the temporary mapping
4934                      --  file, if one was created.
4935
4936                      if not Debug.Debug_Flag_N
4937                        and then Mapping_Path /= No_Name
4938                      then
4939                         Delete_File (Get_Name_String (Mapping_Path), OK);
4940                      end if;
4941
4942                      --  And reraise the exception
4943
4944                      raise;
4945                end;
4946
4947                --  If -dn was not specified, delete the temporary mapping file,
4948                --  if one was created.
4949
4950                if not Debug.Debug_Flag_N and then Mapping_Path /= No_Name then
4951                   Delete_File (Get_Name_String (Mapping_Path), OK);
4952                end if;
4953             end Bind_Step;
4954          end if;
4955
4956          if Do_Link_Step then
4957             Link_Step : declare
4958                There_Are_Libraries  : Boolean := False;
4959                Linker_Switches_Last : constant Integer := Linker_Switches.Last;
4960                Path_Option : constant String_Access :=
4961                                MLib.Tgt.Linker_Library_Path_Option;
4962                Current : Natural;
4963                Proj2   : Project_Id;
4964                Depth   : Natural;
4965
4966             begin
4967                if not Run_Path_Option then
4968                   Linker_Switches.Increment_Last;
4969                   Linker_Switches.Table (Linker_Switches.Last) :=
4970                     new String'("-R");
4971                end if;
4972
4973                if Main_Project /= No_Project then
4974                   Library_Paths.Set_Last (0);
4975                   Library_Projs.Init;
4976
4977                   if MLib.Tgt.Support_For_Libraries /= MLib.Tgt.None then
4978                      --  Check for library projects
4979
4980                      for Proj1 in 1 .. Projects.Last loop
4981                         if Proj1 /= Main_Project
4982                           and then Projects.Table (Proj1).Library
4983                         then
4984                            --  Add this project to table Library_Projs
4985
4986                            There_Are_Libraries := True;
4987                            Depth := Projects.Table (Proj1).Depth;
4988                            Library_Projs.Increment_Last;
4989                            Current := Library_Projs.Last;
4990
4991                            --  Any project with a greater depth should be
4992                            --  after this project in the list.
4993
4994                            while Current > 1 loop
4995                               Proj2 := Library_Projs.Table (Current - 1);
4996                               exit when Projects.Table (Proj2).Depth <= Depth;
4997                               Library_Projs.Table (Current) := Proj2;
4998                               Current := Current - 1;
4999                            end loop;
5000
5001                            Library_Projs.Table (Current) := Proj1;
5002
5003                            --  If it is not a static library and path option
5004                            --  is set, add it to the Library_Paths table.
5005
5006                            if Projects.Table (Proj1).Library_Kind /= Static
5007                              and then Path_Option /= null
5008                            then
5009                               Library_Paths.Increment_Last;
5010                               Library_Paths.Table (Library_Paths.Last) :=
5011                                 new String'
5012                                   (Get_Name_String
5013                                        (Projects.Table (Proj1).Library_Dir));
5014                            end if;
5015                         end if;
5016                      end loop;
5017
5018                      for Index in 1 .. Library_Projs.Last loop
5019                         --  Add the -L switch
5020
5021                         Linker_Switches.Increment_Last;
5022                         Linker_Switches.Table (Linker_Switches.Last) :=
5023                           new String'("-L" &
5024                                       Get_Name_String
5025                                         (Projects.Table
5026                                            (Library_Projs.Table (Index)).
5027                                               Library_Dir));
5028
5029                         --  Add the -l switch
5030
5031                         Linker_Switches.Increment_Last;
5032                         Linker_Switches.Table (Linker_Switches.Last) :=
5033                           new String'("-l" &
5034                                       Get_Name_String
5035                                         (Projects.Table
5036                                            (Library_Projs.Table (Index)).
5037                                               Library_Name));
5038                      end loop;
5039                   end if;
5040
5041                   if There_Are_Libraries then
5042
5043                      --  If Path_Option is not null, create the switch
5044                      --  ("-Wl,-rpath," or equivalent) with all the non static
5045                      --  library dirs plus the standard GNAT library dir.
5046                      --  We do that only if Run_Path_Option is True
5047                      --  (not disabled by -R switch).
5048
5049                      if Run_Path_Option and Path_Option /= null then
5050                         declare
5051                            Option : String_Access;
5052                            Length : Natural := Path_Option'Length;
5053                            Current : Natural;
5054
5055                         begin
5056                            for Index in
5057                              Library_Paths.First .. Library_Paths.Last
5058                            loop
5059                               --  Add the length of the library dir plus one
5060                               --  for the directory separator.
5061
5062                               Length :=
5063                                 Length +
5064                                 Library_Paths.Table (Index)'Length + 1;
5065                            end loop;
5066
5067                            --  Finally, add the length of the standard GNAT
5068                            --  library dir.
5069
5070                            Length := Length + MLib.Utl.Lib_Directory'Length;
5071                            Option := new String (1 .. Length);
5072                            Option (1 .. Path_Option'Length) := Path_Option.all;
5073                            Current := Path_Option'Length;
5074
5075                            --  Put each library dir followed by a dir separator
5076
5077                            for Index in
5078                              Library_Paths.First .. Library_Paths.Last
5079                            loop
5080                               Option
5081                                 (Current + 1 ..
5082                                    Current +
5083                                    Library_Paths.Table (Index)'Length) :=
5084                                 Library_Paths.Table (Index).all;
5085                               Current :=
5086                                 Current +
5087                                 Library_Paths.Table (Index)'Length + 1;
5088                               Option (Current) := Path_Separator;
5089                            end loop;
5090
5091                            --  Finally put the standard GNAT library dir
5092
5093                            Option
5094                              (Current + 1 ..
5095                                 Current + MLib.Utl.Lib_Directory'Length) :=
5096                              MLib.Utl.Lib_Directory;
5097
5098                            --  And add the switch to the linker switches
5099
5100                            Linker_Switches.Increment_Last;
5101                            Linker_Switches.Table (Linker_Switches.Last) :=
5102                              Option;
5103                         end;
5104                      end if;
5105
5106                   end if;
5107
5108                   --  Put the object directories in ADA_OBJECTS_PATH
5109
5110                   Prj.Env.Set_Ada_Paths (Main_Project, False);
5111
5112                   --  Check for attributes Linker'Linker_Options in projects
5113                   --  other than the main project
5114
5115                   declare
5116                      Linker_Package : Package_Id;
5117                      Options : Variable_Value;
5118
5119                   begin
5120                      Linker_Opts.Init;
5121
5122                      for Index in 1 .. Projects.Last loop
5123                         if Index /= Main_Project then
5124                            Linker_Package :=
5125                              Prj.Util.Value_Of
5126                                (Name => Name_Linker,
5127                                 In_Packages =>
5128                                   Projects.Table (Index).Decl.Packages);
5129                            Options :=
5130                              Prj.Util.Value_Of
5131                                (Name => Name_Ada,
5132                                 Attribute_Or_Array_Name => Name_Linker_Options,
5133                                 In_Package => Linker_Package);
5134
5135                            --  If attribute is present, add the project with
5136                            --  the attribute to table Linker_Opts.
5137
5138                            if Options /= Nil_Variable_Value then
5139                               Linker_Opts.Increment_Last;
5140                               Linker_Opts.Table (Linker_Opts.Last) :=
5141                                 (Project => Index, Options => Options.Values);
5142                            end if;
5143                         end if;
5144                      end loop;
5145                   end;
5146
5147                   declare
5148                      Opt1    : Linker_Options_Data;
5149                      Opt2    : Linker_Options_Data;
5150                      Depth   : Natural;
5151                      Options : String_List_Id;
5152                      Option  : Name_Id;
5153                   begin
5154                      --  Sort the project by increasing depths
5155
5156                      for Index in 1 .. Linker_Opts.Last loop
5157                         Opt1 := Linker_Opts.Table (Index);
5158                         Depth := Projects.Table (Opt1.Project).Depth;
5159
5160                         for J in Index + 1 .. Linker_Opts.Last loop
5161                            Opt2 := Linker_Opts.Table (J);
5162
5163                            if
5164                              Projects.Table (Opt2.Project).Depth < Depth
5165                            then
5166                               Linker_Opts.Table (Index) := Opt2;
5167                               Linker_Opts.Table (J) := Opt1;
5168                               Opt1 := Opt2;
5169                               Depth :=
5170                                 Projects.Table (Opt1.Project).Depth;
5171                            end if;
5172                         end loop;
5173
5174                         --  If Dir_Path has not been computed for this project,
5175                         --  do it now.
5176
5177                         if Projects.Table (Opt1.Project).Dir_Path = null then
5178                            Projects.Table (Opt1.Project).Dir_Path :=
5179                              new String'
5180                                (Get_Name_String
5181                                   (Projects.Table (Opt1.Project). Directory));
5182                         end if;
5183
5184                         Options := Opt1.Options;
5185
5186                         --  Add each of the options to the linker switches
5187
5188                         while Options /= Nil_String loop
5189                            Option := String_Elements.Table (Options).Value;
5190                            Options := String_Elements.Table (Options).Next;
5191                            Linker_Switches.Increment_Last;
5192                            Linker_Switches.Table (Linker_Switches.Last) :=
5193                              new String'(Get_Name_String (Option));
5194
5195                            --  Object files and -L switches specified with
5196                            --  relative paths and must be converted to
5197                            --  absolute paths.
5198
5199                            Test_If_Relative_Path
5200                              (Switch =>
5201                                 Linker_Switches.Table (Linker_Switches.Last),
5202                               Parent => Projects.Table (Opt1.Project).Dir_Path,
5203                               Including_L_Switch => True);
5204                         end loop;
5205                      end loop;
5206                   end;
5207                end if;
5208
5209                declare
5210                   Args : Argument_List
5211                            (Linker_Switches.First .. Linker_Switches.Last + 2);
5212
5213                   Last_Arg : Integer := Linker_Switches.First - 1;
5214                   Skip     : Boolean := False;
5215
5216                begin
5217                   --  Get all the linker switches
5218
5219                   for J in Linker_Switches.First .. Linker_Switches.Last loop
5220                      if Skip then
5221                         Skip := False;
5222
5223                      elsif Non_Std_Executable
5224                        and then Linker_Switches.Table (J).all = "-o"
5225                      then
5226                         Skip := True;
5227
5228                      else
5229                         Last_Arg := Last_Arg + 1;
5230                         Args (Last_Arg) := Linker_Switches.Table (J);
5231                      end if;
5232                   end loop;
5233
5234                   --  If need be, add the -o switch
5235
5236                   if Non_Std_Executable then
5237                      Last_Arg := Last_Arg + 1;
5238                      Args (Last_Arg) := new String'("-o");
5239                      Last_Arg := Last_Arg + 1;
5240                      Args (Last_Arg) :=
5241                        new String'(Get_Name_String (Executable));
5242                   end if;
5243
5244                   --  And invoke the linker
5245
5246                   begin
5247                      Link (Main_ALI_File, Args (Args'First .. Last_Arg));
5248                      Successful_Links.Increment_Last;
5249                      Successful_Links.Table (Successful_Links.Last) :=
5250                        Main_ALI_File;
5251
5252                   exception
5253                      when Link_Failed =>
5254                         if Osint.Number_Of_Files = 1 or not Opt.Keep_Going then
5255                            raise;
5256
5257                         else
5258                            Write_Line ("*** link failed");
5259                            Failed_Links.Increment_Last;
5260                            Failed_Links.Table (Failed_Links.Last) :=
5261                              Main_ALI_File;
5262                         end if;
5263                   end;
5264                end;
5265
5266                Linker_Switches.Set_Last (Linker_Switches_Last);
5267             end Link_Step;
5268          end if;
5269
5270          --  We go to here when we skip the bind and link steps.
5271
5272          <<Next_Main>>
5273
5274          --  We go to the next main, if we did not process the last one
5275
5276          if N_File < Osint.Number_Of_Files then
5277             Main_Source_File := Next_Main_Source;
5278
5279             if Main_Project /= No_Project then
5280
5281                --  Find the file name of the main unit
5282
5283                declare
5284                   Main_Source_File_Name : constant String :=
5285                                             Get_Name_String (Main_Source_File);
5286
5287                   Main_Unit_File_Name : constant String :=
5288                                           Prj.Env.
5289                                             File_Name_Of_Library_Unit_Body
5290                                               (Name => Main_Source_File_Name,
5291                                                Project => Main_Project,
5292                                                Main_Project_Only =>
5293                                                  not Unique_Compile);
5294
5295                   The_Packages : constant Package_Id :=
5296                     Projects.Table (Main_Project).Decl.Packages;
5297
5298                   Binder_Package : constant Prj.Package_Id :=
5299                                Prj.Util.Value_Of
5300                                  (Name        => Name_Binder,
5301                                   In_Packages => The_Packages);
5302
5303                   Linker_Package : constant Prj.Package_Id :=
5304                                Prj.Util.Value_Of
5305                                  (Name       => Name_Linker,
5306                                  In_Packages => The_Packages);
5307
5308                begin
5309                   --  We fail if we cannot find the main source file
5310                   --  as an immediate source of the main project file.
5311
5312                   if Main_Unit_File_Name = "" then
5313                      Make_Failed ('"' & Main_Source_File_Name,
5314                                   """ is not a unit of project ",
5315                                   Project_File_Name.all & ".");
5316
5317                   else
5318                      --  Remove any directory information from the main
5319                      --  source file name.
5320
5321                      declare
5322                         Pos : Natural := Main_Unit_File_Name'Last;
5323
5324                      begin
5325                         loop
5326                            exit when Pos < Main_Unit_File_Name'First
5327                              or else
5328                              Main_Unit_File_Name (Pos) = Directory_Separator;
5329                            Pos := Pos - 1;
5330                         end loop;
5331
5332                         Name_Len := Main_Unit_File_Name'Last - Pos;
5333
5334                         Name_Buffer (1 .. Name_Len) :=
5335                           Main_Unit_File_Name
5336                           (Pos + 1 .. Main_Unit_File_Name'Last);
5337
5338                         Main_Source_File := Name_Find;
5339                      end;
5340                   end if;
5341
5342                   --  We now deal with the binder and linker switches.
5343                   --  If no project file is used, there is nothing to do
5344                   --  because the binder and linker switches are the same
5345                   --  for all mains.
5346
5347                   --  Reset the tables Binder_Switches and Linker_Switches
5348
5349                   Binder_Switches.Set_Last (Last_Binder_Switch);
5350                   Linker_Switches.Set_Last (Last_Linker_Switch);
5351
5352                   --  Add binder switches from the project file for this main,
5353                   --  if any.
5354
5355                   if Do_Bind_Step and Binder_Package /= No_Package then
5356                      if Opt.Verbose_Mode then
5357                         Write_Str ("Adding binder switches for """);
5358                         Write_Str (Main_Unit_File_Name);
5359                         Write_Line (""".");
5360                      end if;
5361
5362                      Add_Switches
5363                        (File_Name   => Main_Unit_File_Name,
5364                         The_Package => Binder_Package,
5365                         Program     => Binder);
5366                   end if;
5367
5368                   --  Add linker switches from the project file for this main,
5369                   --  if any.
5370
5371                   if Do_Link_Step and Linker_Package /= No_Package then
5372                      if Opt.Verbose_Mode then
5373                         Write_Str ("Adding linker switches for""");
5374                         Write_Str (Main_Unit_File_Name);
5375                         Write_Line (""".");
5376                      end if;
5377
5378                      Add_Switches
5379                        (File_Name   => Main_Unit_File_Name,
5380                         The_Package => Linker_Package,
5381                         Program     => Linker);
5382                   end if;
5383
5384                   --  As we are using a project file, for relative paths we add
5385                   --  the current working directory for any relative path on
5386                   --  the command line and the project directory, for any
5387                   --  relative path in the project file.
5388
5389                   declare
5390                      Dir_Path : constant String_Access :=
5391                        new String'(Get_Name_String
5392                                     (Projects.Table (Main_Project).Directory));
5393                   begin
5394                      for
5395                        J in Last_Binder_Switch + 1 .. Binder_Switches.Last
5396                      loop
5397                         Test_If_Relative_Path
5398                           (Binder_Switches.Table (J),
5399                            Parent => Dir_Path, Including_L_Switch => False);
5400                      end loop;
5401
5402                      for
5403                        J in Last_Linker_Switch + 1 .. Linker_Switches.Last
5404                      loop
5405                         Test_If_Relative_Path
5406                           (Linker_Switches.Table (J), Parent => Dir_Path);
5407                      end loop;
5408                   end;
5409
5410                   --  We now put in the Binder_Switches and Linker_Switches
5411                   --  tables, the binder and linker switches of the command
5412                   --  line that have been put in the Saved_ tables.
5413                   --  These switches will follow the project file switches.
5414
5415                   for J in 1 .. Saved_Binder_Switches.Last loop
5416                      Add_Switch
5417                        (Saved_Binder_Switches.Table (J),
5418                         Binder,
5419                         And_Save => False);
5420                   end loop;
5421
5422                   for J in 1 .. Saved_Linker_Switches.Last loop
5423                      Add_Switch
5424                        (Saved_Linker_Switches.Table (J),
5425                         Linker,
5426                         And_Save => False);
5427                   end loop;
5428                end;
5429             end if;
5430          end if;
5431       end loop Multiple_Main_Loop;
5432
5433       if Failed_Links.Last > 0 then
5434          for Index in 1 .. Successful_Links.Last loop
5435             Write_Str ("Linking of """);
5436             Write_Str (Get_Name_String (Successful_Links.Table (Index)));
5437             Write_Line (""" succeeded.");
5438          end loop;
5439
5440          for Index in 1 .. Failed_Links.Last loop
5441             Write_Str ("Linking of """);
5442             Write_Str (Get_Name_String (Failed_Links.Table (Index)));
5443             Write_Line (""" failed.");
5444          end loop;
5445
5446          if Total_Compilation_Failures = 0 then
5447             raise Compilation_Failed;
5448          end if;
5449       end if;
5450
5451       if Total_Compilation_Failures /= 0 then
5452          List_Bad_Compilations;
5453          raise Compilation_Failed;
5454       end if;
5455
5456       --  Delete the temporary mapping file that was created if we are
5457       --  using project files.
5458
5459       if not Debug.Debug_Flag_N then
5460          Delete_Mapping_Files;
5461          Prj.Env.Delete_All_Path_Files;
5462       end if;
5463
5464       Exit_Program (E_Success);
5465
5466    exception
5467       when Bind_Failed =>
5468          Make_Failed ("*** bind failed.");
5469
5470       when Compilation_Failed =>
5471          if not Debug.Debug_Flag_N then
5472             Delete_Mapping_Files;
5473             Prj.Env.Delete_All_Path_Files;
5474          end if;
5475
5476          Exit_Program (E_Fatal);
5477
5478       when Link_Failed =>
5479          Make_Failed ("*** link failed.");
5480
5481       when X : others =>
5482          Write_Line (Exception_Information (X));
5483          Make_Failed ("INTERNAL ERROR. Please report.");
5484
5485    end Gnatmake;
5486
5487    ----------
5488    -- Hash --
5489    ----------
5490
5491    function Hash (F : Name_Id) return Header_Num is
5492    begin
5493       return Header_Num (1 + F mod Max_Header);
5494    end Hash;
5495
5496    --------------------
5497    -- In_Ada_Lib_Dir --
5498    --------------------
5499
5500    function In_Ada_Lib_Dir (File : File_Name_Type) return Boolean is
5501       D : constant Name_Id := Get_Directory (File);
5502       B : constant Byte    := Get_Name_Table_Byte (D);
5503
5504    begin
5505       return (B and Ada_Lib_Dir) /= 0;
5506    end In_Ada_Lib_Dir;
5507
5508    ------------
5509    -- Inform --
5510    ------------
5511
5512    procedure Inform (N : Name_Id := No_Name; Msg : String) is
5513    begin
5514       Osint.Write_Program_Name;
5515
5516       Write_Str (": ");
5517
5518       if N /= No_Name then
5519          Write_Str ("""");
5520          Write_Name (N);
5521          Write_Str (""" ");
5522       end if;
5523
5524       Write_Str (Msg);
5525       Write_Eol;
5526    end Inform;
5527
5528    -----------------------
5529    -- Init_Mapping_File --
5530    -----------------------
5531
5532    procedure Init_Mapping_File
5533      (Project    : Project_Id;
5534       File_Index : in out Natural)
5535    is
5536       FD : File_Descriptor;
5537
5538       Status : Boolean;
5539       --  For call to Close
5540
5541    begin
5542       --  Increase the index of the last mapping file for this project
5543
5544       Last_Mapping_File_Names (Project) :=
5545         Last_Mapping_File_Names (Project) + 1;
5546
5547       --  If there is a project file, call Create_Mapping_File with
5548       --  the project id.
5549
5550       if Project /= No_Project then
5551          Prj.Env.Create_Mapping_File
5552            (Project,
5553             The_Mapping_File_Names
5554               (Project, Last_Mapping_File_Names (Project)));
5555
5556       --  Otherwise, just create an empty file
5557
5558       else
5559          Tempdir.Create_Temp_File
5560            (FD,
5561             The_Mapping_File_Names
5562               (No_Project, Last_Mapping_File_Names (No_Project)));
5563          if FD = Invalid_FD then
5564             Make_Failed ("disk full");
5565          end if;
5566
5567          Close (FD, Status);
5568
5569          if not Status then
5570             Make_Failed ("disk full");
5571          end if;
5572       end if;
5573
5574       --  And return the index of the newly created file
5575
5576       File_Index := Last_Mapping_File_Names (Project);
5577    end Init_Mapping_File;
5578
5579    ------------
5580    -- Init_Q --
5581    ------------
5582
5583    procedure Init_Q is
5584    begin
5585       First_Q_Initialization := False;
5586       Q_Front := Q.First;
5587       Q.Set_Last (Q.First);
5588    end Init_Q;
5589
5590    ----------------
5591    -- Initialize --
5592    ----------------
5593
5594    procedure Initialize is
5595       Next_Arg : Positive;
5596
5597    begin
5598       --  Override default initialization of Check_Object_Consistency
5599       --  since this is normally False for GNATBIND, but is True for
5600       --  GNATMAKE since we do not need to check source consistency
5601       --  again once GNATMAKE has looked at the sources to check.
5602
5603       Opt.Check_Object_Consistency := True;
5604
5605       --  Package initializations. The order of calls is important here.
5606
5607       Output.Set_Standard_Error;
5608
5609       Gcc_Switches.Init;
5610       Binder_Switches.Init;
5611       Linker_Switches.Init;
5612
5613       Csets.Initialize;
5614       Namet.Initialize;
5615
5616       Snames.Initialize;
5617
5618       Prj.Initialize;
5619
5620       Dependencies.Init;
5621
5622       RTS_Specified := null;
5623
5624       Mains.Delete;
5625
5626       Next_Arg := 1;
5627       Scan_Args : while Next_Arg <= Argument_Count loop
5628          Scan_Make_Arg (Argument (Next_Arg), And_Save => True);
5629          Next_Arg := Next_Arg + 1;
5630       end loop Scan_Args;
5631
5632       if Usage_Requested then
5633          Usage;
5634       end if;
5635
5636       --  Test for trailing -P switch
5637
5638       if Project_File_Name_Present and then Project_File_Name = null then
5639          Make_Failed ("project file name missing after -P");
5640
5641       --  Test for trailing -o switch
5642
5643       elsif Opt.Output_File_Name_Present
5644         and then not Output_File_Name_Seen
5645       then
5646          Make_Failed ("output file name missing after -o");
5647
5648       --  Test for trailing -D switch
5649
5650       elsif Opt.Object_Directory_Present
5651         and then not Object_Directory_Seen then
5652          Make_Failed ("object directory missing after -D");
5653       end if;
5654
5655       --  Test for simultaneity of -i and -D
5656
5657       if Object_Directory_Path /= null and then In_Place_Mode then
5658          Make_Failed ("-i and -D cannot be used simutaneously");
5659       end if;
5660
5661       --  Deal with -C= switch
5662
5663       if Gnatmake_Mapping_File /= null then
5664          --  First, check compatibility with other switches
5665
5666          if Project_File_Name /= null then
5667             Make_Failed ("-C= switch is not compatible with -P switch");
5668
5669          elsif Saved_Maximum_Processes > 1 then
5670             Make_Failed ("-C= switch is not compatible with -jnnn switch");
5671          end if;
5672
5673          Fmap.Initialize (Gnatmake_Mapping_File.all);
5674          Add_Switch
5675            ("-gnatem=" & Gnatmake_Mapping_File.all,
5676             Compiler,
5677             And_Save => True);
5678       end if;
5679
5680       if Project_File_Name /= null then
5681
5682          --  A project file was specified by a -P switch
5683
5684          if Opt.Verbose_Mode then
5685             Write_Eol;
5686             Write_Str ("Parsing Project File """);
5687             Write_Str (Project_File_Name.all);
5688             Write_Str (""".");
5689             Write_Eol;
5690          end if;
5691
5692          --  Avoid looking in the current directory for ALI files
5693
5694          --  Opt.Look_In_Primary_Dir := False;
5695
5696          --  Set the project parsing verbosity to whatever was specified
5697          --  by a possible -vP switch.
5698
5699          Prj.Pars.Set_Verbosity (To => Current_Verbosity);
5700
5701          --  Parse the project file.
5702          --  If there is an error, Main_Project will still be No_Project.
5703
5704          Prj.Pars.Parse
5705            (Project           => Main_Project,
5706             Project_File_Name => Project_File_Name.all,
5707             Packages_To_Check => Packages_To_Check_By_Gnatmake);
5708
5709          if Main_Project = No_Project then
5710             Make_Failed ("""", Project_File_Name.all, """ processing failed");
5711          end if;
5712
5713          if Opt.Verbose_Mode then
5714             Write_Eol;
5715             Write_Str ("Parsing of Project File """);
5716             Write_Str (Project_File_Name.all);
5717             Write_Str (""" is finished.");
5718             Write_Eol;
5719          end if;
5720
5721          --  We add the source directories and the object directories
5722          --  to the search paths.
5723
5724          Add_Source_Directories (Main_Project);
5725          Add_Object_Directories (Main_Project);
5726
5727          --  Compute depth of each project
5728
5729          Recursive_Compute_Depth
5730            (Main_Project, Visited => No_Projects, Depth => 0);
5731
5732       else
5733
5734          Osint.Add_Default_Search_Dirs;
5735
5736          --  Source file lookups should be cached for efficiency.
5737          --  Source files are not supposed to change. However, we do that now
5738          --  only if no project file is used; if a project file is used, we
5739          --  do it just after changing the directory to the object directory.
5740
5741          Osint.Source_File_Data (Cache => True);
5742
5743          --  Read gnat.adc file to initialize Fname.UF
5744
5745          Fname.UF.Initialize;
5746
5747          begin
5748             Fname.SF.Read_Source_File_Name_Pragmas;
5749
5750          exception
5751             when Err : SFN_Scan.Syntax_Error_In_GNAT_ADC =>
5752                Make_Failed (Exception_Message (Err));
5753          end;
5754       end if;
5755
5756       --  Make sure no project object directory is recorded
5757
5758       Project_Object_Directory := No_Project;
5759
5760       --  Set the marking label to a value that is not zero
5761
5762       Marking_Label := 1;
5763    end Initialize;
5764
5765    -----------------------------------
5766    -- Insert_Project_Sources_Into_Q --
5767    -----------------------------------
5768
5769    procedure Insert_Project_Sources
5770      (The_Project  : Project_Id;
5771       All_Projects : Boolean;
5772       Into_Q       : Boolean)
5773    is
5774       Put_In_Q : Boolean := Into_Q;
5775       Unit     : Com.Unit_Data;
5776       Sfile    : Name_Id;
5777
5778       Extending : constant Boolean :=
5779                     Projects.Table (The_Project).Extends /= No_Project;
5780
5781       function Check_Project (P : Project_Id) return Boolean;
5782       --  Returns True if P is The_Project or a project extended by
5783       --  The_Project.
5784
5785       -------------------
5786       -- Check_Project --
5787       -------------------
5788
5789       function Check_Project (P : Project_Id) return Boolean is
5790       begin
5791          if All_Projects or P = The_Project then
5792             return True;
5793          elsif Extending then
5794             declare
5795                Data : Project_Data := Projects.Table (The_Project);
5796
5797             begin
5798                loop
5799                   if P = Data.Extends then
5800                      return True;
5801                   end if;
5802
5803                   Data := Projects.Table (Data.Extends);
5804                   exit when Data.Extends = No_Project;
5805                end loop;
5806             end;
5807          end if;
5808
5809          return False;
5810       end Check_Project;
5811
5812    --  Start of processing of Insert_Project_Sources
5813
5814    begin
5815       --  For all the sources in the project files,
5816
5817       for Id in Com.Units.First .. Com.Units.Last loop
5818          Unit  := Com.Units.Table (Id);
5819          Sfile := No_Name;
5820
5821          --  If there is a source for the body, and the body has not been
5822          --  locally removed,
5823
5824          if Unit.File_Names (Com.Body_Part).Name /= No_Name
5825            and then Unit.File_Names (Com.Body_Part).Path /= Slash
5826          then
5827
5828             --  And it is a source for the specified project
5829
5830             if Check_Project (Unit.File_Names (Com.Body_Part).Project) then
5831
5832                --  If we don't have a spec, we cannot consider the source
5833                --  if it is a subunit
5834
5835                if Unit.File_Names (Com.Specification).Name = No_Name then
5836                   declare
5837                      Src_Ind : Source_File_Index;
5838
5839                      --  Here we are cheating a little bit: we don't want to
5840                      --  use Sinput.L, because it depends on the GNAT tree
5841                      --  (Atree, Sinfo, ...). So, we pretend that it is
5842                      --  a project file, and we use Sinput.P.
5843                      --  Source_File_Is_Subunit is just scanning through
5844                      --  the file until it finds one of the reserved words
5845                      --  separate, procedure, function, generic or package.
5846                      --  Fortunately, these Ada reserved words are also
5847                      --  reserved for project files.
5848
5849                   begin
5850                      Src_Ind := Sinput.P.Load_Project_File
5851                                   (Get_Name_String
5852                                      (Unit.File_Names (Com.Body_Part).Path));
5853
5854                      --  If it is a subunit, discard it
5855
5856                      if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
5857                         Sfile := No_Name;
5858
5859                      else
5860                         Sfile := Unit.File_Names (Com.Body_Part).Name;
5861                      end if;
5862                   end;
5863
5864                else
5865                   Sfile := Unit.File_Names (Com.Body_Part).Name;
5866                end if;
5867             end if;
5868
5869          elsif Unit.File_Names (Com.Specification).Name /= No_Name
5870            and then Unit.File_Names (Com.Specification).Path /= Slash
5871            and then Check_Project (Unit.File_Names (Com.Specification).Project)
5872          then
5873             --  If there is no source for the body, but there is a source
5874             --  for the spec which has not been locally removed, then we take
5875             --  this one.
5876
5877             Sfile := Unit.File_Names (Com.Specification).Name;
5878          end if;
5879
5880          --  If Put_In_Q is True, we insert into the Q
5881
5882          if Put_In_Q then
5883
5884             --  For the first source inserted into the Q, we need
5885             --  to initialize the Q, but not for the subsequent sources.
5886
5887             if First_Q_Initialization then
5888                Init_Q;
5889             end if;
5890
5891             --  And of course, we only insert in the Q if the source
5892             --  is not marked.
5893
5894             if Sfile /= No_Name and then not Is_Marked (Sfile) then
5895                if Opt.Verbose_Mode then
5896                   Write_Str ("Adding """);
5897                   Write_Str (Get_Name_String (Sfile));
5898                   Write_Line (""" to the queue");
5899                end if;
5900
5901                Insert_Q (Sfile);
5902                Mark (Sfile);
5903             end if;
5904
5905          elsif Sfile /= No_Name then
5906
5907             --  If Put_In_Q is False, we add the source as it it were
5908             --  specified on the command line, and we set Put_In_Q to True,
5909             --  so that the following sources will be put directly in the
5910             --  queue. This will allow parallel compilation processes if -jx
5911             --  switch is used.
5912
5913             if Opt.Verbose_Mode then
5914                Write_Str ("Adding """);
5915                Write_Str (Get_Name_String (Sfile));
5916                Write_Line (""" as if on the command line");
5917             end if;
5918
5919             Osint.Add_File (Get_Name_String (Sfile));
5920             Put_In_Q := True;
5921          end if;
5922       end loop;
5923    end Insert_Project_Sources;
5924
5925    --------------
5926    -- Insert_Q --
5927    --------------
5928
5929    procedure Insert_Q
5930      (Source_File : File_Name_Type;
5931       Source_Unit : Unit_Name_Type := No_Name)
5932    is
5933    begin
5934       if Debug.Debug_Flag_Q then
5935          Write_Str ("   Q := Q + [ ");
5936          Write_Name (Source_File);
5937          Write_Str (" ] ");
5938          Write_Eol;
5939       end if;
5940
5941       Q.Table (Q.Last).File := Source_File;
5942       Q.Table (Q.Last).Unit := Source_Unit;
5943       Q.Increment_Last;
5944    end Insert_Q;
5945
5946    ----------------------------
5947    -- Is_External_Assignment --
5948    ----------------------------
5949
5950    function Is_External_Assignment (Argv : String) return Boolean is
5951       Start     : Positive := 3;
5952       Finish    : Natural := Argv'Last;
5953       Equal_Pos : Natural;
5954
5955    begin
5956       if Argv'Last < 5 then
5957          return False;
5958
5959       elsif Argv (3) = '"' then
5960          if Argv (Argv'Last) /= '"' or else Argv'Last < 7 then
5961             return False;
5962          else
5963             Start := 4;
5964             Finish := Argv'Last - 1;
5965          end if;
5966       end if;
5967
5968       Equal_Pos := Start;
5969
5970       while Equal_Pos <= Finish and then Argv (Equal_Pos) /= '=' loop
5971          Equal_Pos := Equal_Pos + 1;
5972       end loop;
5973
5974       if Equal_Pos = Start
5975         or else Equal_Pos >= Finish
5976       then
5977          return False;
5978
5979       else
5980          Prj.Ext.Add
5981            (External_Name => Argv (Start .. Equal_Pos - 1),
5982             Value         => Argv (Equal_Pos + 1 .. Finish));
5983          return True;
5984       end if;
5985    end Is_External_Assignment;
5986
5987    ---------------------
5988    -- Is_In_Obsoleted --
5989    ---------------------
5990
5991    function Is_In_Obsoleted (F : Name_Id) return Boolean is
5992    begin
5993       if F = No_File then
5994          return False;
5995
5996       else
5997          declare
5998             Name  : String := Get_Name_String (F);
5999             First : Natural := Name'Last;
6000             F2    : Name_Id := F;
6001
6002          begin
6003             while First > Name'First
6004               and then Name (First - 1) /= Directory_Separator
6005               and then Name (First - 1) /= '/'
6006             loop
6007                First := First - 1;
6008             end loop;
6009
6010             if First /= Name'First then
6011                Name_Len := 0;
6012                Add_Str_To_Name_Buffer (Name (First .. Name'Last));
6013                F2 := Name_Find;
6014             end if;
6015
6016             return Obsoleted.Get (F2);
6017          end;
6018       end if;
6019    end Is_In_Obsoleted;
6020
6021    ----------------------------
6022    -- Is_In_Object_Directory --
6023    ----------------------------
6024
6025    function Is_In_Object_Directory
6026      (Source_File   : File_Name_Type;
6027       Full_Lib_File : File_Name_Type) return Boolean
6028    is
6029    begin
6030       --  There is something to check only when using project files.
6031       --  Otherwise, this function returns True (last line of the function).
6032
6033       if Main_Project /= No_Project then
6034          declare
6035             Source_File_Name : constant String :=
6036                                  Get_Name_String (Source_File);
6037             Saved_Verbosity  : constant Verbosity := Prj.Com.Current_Verbosity;
6038             Project          : Project_Id := No_Project;
6039             Path_Name        : Name_Id := No_Name;
6040             Data             : Project_Data;
6041
6042          begin
6043             --  Call Get_Reference to know the ultimate extending project of
6044             --  the source. Call it with verbosity default to avoid verbose
6045             --  messages.
6046
6047             Prj.Com.Current_Verbosity := Default;
6048             Prj.Env.
6049               Get_Reference
6050               (Source_File_Name => Source_File_Name,
6051                Project          => Project,
6052                Path             => Path_Name);
6053             Prj.Com.Current_Verbosity := Saved_Verbosity;
6054
6055             --  If this source is in a project, check that the ALI file is
6056             --  in its object directory. If it is not, return False, so that
6057             --  the ALI file will not be skipped.
6058
6059             --  If the source is not in an extending project, we fall back to
6060             --  the general case and return True at the end of the function.
6061
6062             if Project /= No_Project
6063               and then Projects.Table (Project).Extends /= No_Project
6064             then
6065                Data := Projects.Table (Project);
6066
6067                declare
6068                   Object_Directory : constant String :=
6069                                        Normalize_Pathname
6070                                          (Get_Name_String
6071                                            (Data.Object_Directory));
6072
6073                   Olast : Natural := Object_Directory'Last;
6074
6075                   Lib_File_Directory : constant String :=
6076                                          Normalize_Pathname (Dir_Name
6077                                            (Get_Name_String (Full_Lib_File)));
6078
6079                   Llast : Natural := Lib_File_Directory'Last;
6080
6081                begin
6082                   --  For directories, Normalize_Pathname may or may not put
6083                   --  a directory separator at the end, depending on its input.
6084                   --  Remove any last directory separator before comparaison.
6085                   --  Returns True only if the two directories are the same.
6086
6087                   if Object_Directory (Olast) = Directory_Separator then
6088                      Olast := Olast - 1;
6089                   end if;
6090
6091                   if Lib_File_Directory (Llast) = Directory_Separator then
6092                      Llast := Llast - 1;
6093                   end if;
6094
6095                   return Object_Directory (Object_Directory'First .. Olast) =
6096                         Lib_File_Directory (Lib_File_Directory'First .. Llast);
6097                end;
6098             end if;
6099          end;
6100       end if;
6101
6102       --  When the source is not in a project file, always return True
6103
6104       return True;
6105    end Is_In_Object_Directory;
6106
6107    ---------------
6108    -- Is_Marked --
6109    ---------------
6110
6111    function Is_Marked (Source_File : File_Name_Type) return Boolean is
6112    begin
6113       return Get_Name_Table_Byte (Source_File) = Marking_Label;
6114    end Is_Marked;
6115
6116    ----------
6117    -- Link --
6118    ----------
6119
6120    procedure Link (ALI_File : File_Name_Type; Args : Argument_List) is
6121       Link_Args : Argument_List (1 .. Args'Length + 1);
6122       Success   : Boolean;
6123
6124    begin
6125       Get_Name_String (ALI_File);
6126       Link_Args (1) := new String'(Name_Buffer (1 .. Name_Len));
6127
6128       Link_Args (2 .. Args'Length + 1) :=  Args;
6129
6130       GNAT.OS_Lib.Normalize_Arguments (Link_Args);
6131
6132       Display (Gnatlink.all, Link_Args);
6133
6134       if Gnatlink_Path = null then
6135          Make_Failed ("error, unable to locate ", Gnatlink.all);
6136       end if;
6137
6138       GNAT.OS_Lib.Spawn (Gnatlink_Path.all, Link_Args, Success);
6139
6140       if not Success then
6141          raise Link_Failed;
6142       end if;
6143    end Link;
6144
6145    ---------------------------
6146    -- List_Bad_Compilations --
6147    ---------------------------
6148
6149    procedure List_Bad_Compilations is
6150    begin
6151       for J in Bad_Compilation.First .. Bad_Compilation.Last loop
6152          if Bad_Compilation.Table (J).File = No_File then
6153             null;
6154          elsif not Bad_Compilation.Table (J).Found then
6155             Inform (Bad_Compilation.Table (J).File, "not found");
6156          else
6157             Inform (Bad_Compilation.Table (J).File, "compilation error");
6158          end if;
6159       end loop;
6160    end List_Bad_Compilations;
6161
6162    -----------------
6163    -- List_Depend --
6164    -----------------
6165
6166    procedure List_Depend is
6167       Lib_Name  : Name_Id;
6168       Obj_Name  : Name_Id;
6169       Src_Name  : Name_Id;
6170
6171       Len       : Natural;
6172       Line_Pos  : Natural;
6173       Line_Size : constant := 77;
6174
6175    begin
6176       Set_Standard_Output;
6177
6178       for A in ALIs.First .. ALIs.Last loop
6179          Lib_Name := ALIs.Table (A).Afile;
6180
6181          --  We have to provide the full library file name in In_Place_Mode
6182
6183          if Opt.In_Place_Mode then
6184             Lib_Name := Full_Lib_File_Name (Lib_Name);
6185          end if;
6186
6187          Obj_Name := Object_File_Name (Lib_Name);
6188          Write_Name (Obj_Name);
6189          Write_Str (" :");
6190
6191          Get_Name_String (Obj_Name);
6192          Len := Name_Len;
6193          Line_Pos := Len + 2;
6194
6195          for D in ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep loop
6196             Src_Name := Sdep.Table (D).Sfile;
6197
6198             if Is_Internal_File_Name (Src_Name)
6199               and then not Check_Readonly_Files
6200             then
6201                null;
6202             else
6203                if not Opt.Quiet_Output then
6204                   Src_Name := Full_Source_Name (Src_Name);
6205                end if;
6206
6207                Get_Name_String (Src_Name);
6208                Len := Name_Len;
6209
6210                if Line_Pos + Len + 1 > Line_Size then
6211                   Write_Str (" \");
6212                   Write_Eol;
6213                   Line_Pos := 0;
6214                end if;
6215
6216                Line_Pos := Line_Pos + Len + 1;
6217
6218                Write_Str (" ");
6219                Write_Name (Src_Name);
6220             end if;
6221          end loop;
6222
6223          Write_Eol;
6224       end loop;
6225
6226       Set_Standard_Error;
6227    end List_Depend;
6228
6229    -----------
6230    -- Mains --
6231    -----------
6232
6233    package body Mains is
6234
6235       package Names is new Table.Table
6236         (Table_Component_Type => File_Name_Type,
6237          Table_Index_Type     => Integer,
6238          Table_Low_Bound      => 1,
6239          Table_Initial        => 10,
6240          Table_Increment      => 100,
6241          Table_Name           => "Make.Mains.Names");
6242       --  The table that stores the main
6243
6244       Current : Natural := 0;
6245       --  The index of the last main retrieved from the table
6246
6247       --------------
6248       -- Add_Main --
6249       --------------
6250
6251       procedure Add_Main (Name : String) is
6252       begin
6253          Name_Len := 0;
6254          Add_Str_To_Name_Buffer (Name);
6255          Names.Increment_Last;
6256          Names.Table (Names.Last) := Name_Find;
6257       end Add_Main;
6258
6259       ------------
6260       -- Delete --
6261       ------------
6262
6263       procedure Delete is
6264       begin
6265          Names.Set_Last (0);
6266          Reset;
6267       end Delete;
6268
6269       ---------------
6270       -- Next_Main --
6271       ---------------
6272
6273       function Next_Main return String is
6274       begin
6275          if Current >= Names.Last then
6276             return "";
6277
6278          else
6279             Current := Current + 1;
6280             return Get_Name_String (Names.Table (Current));
6281          end if;
6282       end Next_Main;
6283
6284       procedure Reset is
6285       begin
6286          Current := 0;
6287       end Reset;
6288
6289    end Mains;
6290
6291    ----------
6292    -- Mark --
6293    ----------
6294
6295    procedure Mark (Source_File : File_Name_Type) is
6296    begin
6297       Set_Name_Table_Byte (Source_File, Marking_Label);
6298    end Mark;
6299
6300    --------------------
6301    -- Mark_Directory --
6302    --------------------
6303
6304    procedure Mark_Directory
6305      (Dir  : String;
6306       Mark : Lib_Mark_Type)
6307    is
6308       N : Name_Id;
6309       B : Byte;
6310
6311    begin
6312       --  Dir last character is supposed to be a directory separator.
6313
6314       Name_Len := Dir'Length;
6315       Name_Buffer (1 .. Name_Len) := Dir;
6316
6317       if not Is_Directory_Separator (Name_Buffer (Name_Len)) then
6318          Name_Len := Name_Len + 1;
6319          Name_Buffer (Name_Len) := Directory_Separator;
6320       end if;
6321
6322       --  Add flags to the already existing flags
6323
6324       N := Name_Find;
6325       B := Get_Name_Table_Byte (N);
6326       Set_Name_Table_Byte (N, B or Mark);
6327    end Mark_Directory;
6328
6329    -----------------------------
6330    -- Recursive_Compute_Depth --
6331    -----------------------------
6332
6333    procedure Recursive_Compute_Depth
6334      (Project : Project_Id;
6335       Visited : Project_Array;
6336       Depth   : Natural)
6337    is
6338       List : Project_List;
6339       Proj : Project_Id;
6340       OK : Boolean;
6341       New_Visited : constant Project_Array := Visited & Project;
6342
6343    begin
6344       --  Nothing to do if there is no project
6345
6346       if Project = No_Project then
6347          return;
6348       end if;
6349
6350       --  If current depth of project is lower than Depth, adjust it
6351
6352       if Projects.Table (Project).Depth < Depth then
6353          Projects.Table (Project).Depth := Depth;
6354       end if;
6355
6356       List := Projects.Table (Project).Imported_Projects;
6357
6358       --  Visit each imported project
6359
6360       while List /= Empty_Project_List loop
6361          Proj := Project_Lists.Table (List).Project;
6362          List := Project_Lists.Table (List).Next;
6363
6364          OK := True;
6365
6366          --  To avoid endless loops due to cycles with limited widts,
6367          --  do not revisit a project that is already in the chain of imports
6368          --  that brought us here.
6369
6370          for J in Visited'Range loop
6371             if Visited (J) = Proj then
6372                OK := False;
6373                exit;
6374             end if;
6375          end loop;
6376
6377          if OK then
6378             Recursive_Compute_Depth
6379               (Project => Proj,
6380                Visited => New_Visited,
6381                Depth => Depth + 1);
6382          end if;
6383       end loop;
6384
6385       --  Visit a project being extended, if any
6386
6387       Recursive_Compute_Depth
6388         (Project => Projects.Table (Project).Extends,
6389          Visited => New_Visited,
6390          Depth => Depth + 1);
6391    end Recursive_Compute_Depth;
6392
6393    -----------------------
6394    -- Sigint_Intercpted --
6395    -----------------------
6396
6397    procedure Sigint_Intercepted is
6398    begin
6399       Write_Line ("*** Interrupted ***");
6400       Delete_All_Temp_Files;
6401       OS_Exit (1);
6402    end Sigint_Intercepted;
6403
6404    -------------------
6405    -- Scan_Make_Arg --
6406    -------------------
6407
6408    procedure Scan_Make_Arg (Argv : String; And_Save : Boolean) is
6409    begin
6410       pragma Assert (Argv'First = 1);
6411
6412       if Argv'Length = 0 then
6413          return;
6414       end if;
6415
6416       --  If the previous switch has set the Project_File_Name_Present
6417       --  flag (that is we have seen a -P alone), then the next argument is
6418       --  the name of the project file.
6419
6420       if Project_File_Name_Present and then Project_File_Name = null then
6421          if Argv (1) = '-' then
6422             Make_Failed ("project file name missing after -P");
6423
6424          else
6425             Project_File_Name_Present := False;
6426             Project_File_Name := new String'(Argv);
6427          end if;
6428
6429       --  If the previous switch has set the Output_File_Name_Present
6430       --  flag (that is we have seen a -o), then the next argument is
6431       --  the name of the output executable.
6432
6433       elsif Opt.Output_File_Name_Present
6434         and then not Output_File_Name_Seen
6435       then
6436          Output_File_Name_Seen := True;
6437
6438          if Argv (1) = '-' then
6439             Make_Failed ("output file name missing after -o");
6440
6441          else
6442             Add_Switch ("-o", Linker, And_Save => And_Save);
6443
6444             --  Automatically add the executable suffix if it has not been
6445             --  specified explicitly.
6446
6447             if Executable_Suffix'Length /= 0
6448               and then (Argv'Length <= Executable_Suffix'Length
6449                         or else Argv (Argv'Last - Executable_Suffix'Length + 1
6450                                         .. Argv'Last) /= Executable_Suffix)
6451             then
6452                Add_Switch
6453                  (Argv & Executable_Suffix,
6454                   Linker,
6455                   And_Save => And_Save);
6456             else
6457                Add_Switch (Argv, Linker, And_Save => And_Save);
6458             end if;
6459          end if;
6460
6461       --  If the previous switch has set the Object_Directory_Present flag
6462       --  (that is we have seen a -D), then the next argument is
6463       --  the path name of the object directory..
6464
6465       elsif Opt.Object_Directory_Present
6466         and then not Object_Directory_Seen
6467       then
6468          Object_Directory_Seen := True;
6469
6470          if Argv (1) = '-' then
6471             Make_Failed ("object directory path name missing after -D");
6472
6473          elsif not Is_Directory (Argv) then
6474             Make_Failed ("cannot find object directory """, Argv, """");
6475
6476          else
6477             Add_Lib_Search_Dir (Argv);
6478
6479             --  Specify the object directory to the binder
6480
6481             Add_Switch ("-aO" & Argv, Binder, And_Save => And_Save);
6482
6483             --  Record the object directory. Make sure it ends with a directory
6484             --  separator.
6485
6486             if Argv (Argv'Last) = Directory_Separator then
6487                Object_Directory_Path := new String'(Argv);
6488
6489             else
6490                Object_Directory_Path :=
6491                  new String'(Argv & Directory_Separator);
6492             end if;
6493          end if;
6494
6495       --  Then check if we are dealing with -cargs/-bargs/-largs/-margs
6496
6497       elsif Argv = "-bargs"
6498               or else
6499             Argv = "-cargs"
6500               or else
6501             Argv = "-largs"
6502               or else
6503             Argv = "-margs"
6504       then
6505          case Argv (2) is
6506             when 'c' => Program_Args := Compiler;
6507             when 'b' => Program_Args := Binder;
6508             when 'l' => Program_Args := Linker;
6509             when 'm' => Program_Args := None;
6510
6511             when others =>
6512                raise Program_Error;
6513          end case;
6514
6515       --  A special test is needed for the -o switch within a -largs
6516       --  since that is another way to specify the name of the final
6517       --  executable.
6518
6519       elsif Program_Args = Linker
6520         and then Argv = "-o"
6521       then
6522          Make_Failed ("switch -o not allowed within a -largs. " &
6523                       "Use -o directly.");
6524
6525       --  Check to see if we are reading switches after a -cargs,
6526       --  -bargs or -largs switch. If yes save it.
6527
6528       elsif Program_Args /= None then
6529
6530          --  Check to see if we are reading -I switches in order
6531          --  to take into account in the src & lib search directories.
6532
6533          if Argv'Length > 2 and then Argv (1 .. 2) = "-I" then
6534             if Argv (3 .. Argv'Last) = "-" then
6535                Opt.Look_In_Primary_Dir := False;
6536
6537             elsif Program_Args = Compiler then
6538                if Argv (3 .. Argv'Last) /= "-" then
6539                   Add_Src_Search_Dir (Argv (3 .. Argv'Last));
6540                end if;
6541
6542             elsif Program_Args = Binder then
6543                Add_Lib_Search_Dir (Argv (3 .. Argv'Last));
6544             end if;
6545          end if;
6546
6547          Add_Switch (Argv, Program_Args, And_Save => And_Save);
6548
6549       --  Handle non-default compiler, binder, linker, and handle --RTS switch
6550
6551       elsif Argv'Length > 2 and then Argv (1 .. 2) = "--" then
6552          if Argv'Length > 6
6553            and then Argv (1 .. 6) = "--GCC="
6554          then
6555             declare
6556                Program_Args : constant Argument_List_Access :=
6557                                 Argument_String_To_List
6558                                   (Argv (7 .. Argv'Last));
6559
6560             begin
6561                if And_Save then
6562                   Saved_Gcc := new String'(Program_Args.all (1).all);
6563                else
6564                   Gcc := new String'(Program_Args.all (1).all);
6565                end if;
6566
6567                for J in 2 .. Program_Args.all'Last loop
6568                   Add_Switch
6569                     (Program_Args.all (J).all,
6570                      Compiler,
6571                      And_Save => And_Save);
6572                end loop;
6573             end;
6574
6575          elsif Argv'Length > 11
6576            and then Argv (1 .. 11) = "--GNATBIND="
6577          then
6578             declare
6579                Program_Args : constant Argument_List_Access :=
6580                                 Argument_String_To_List
6581                                   (Argv (12 .. Argv'Last));
6582
6583             begin
6584                if And_Save then
6585                   Saved_Gnatbind := new String'(Program_Args.all (1).all);
6586                else
6587                   Gnatbind := new String'(Program_Args.all (1).all);
6588                end if;
6589
6590                for J in 2 .. Program_Args.all'Last loop
6591                   Add_Switch
6592                     (Program_Args.all (J).all, Binder, And_Save => And_Save);
6593                end loop;
6594             end;
6595
6596          elsif Argv'Length > 11
6597            and then Argv (1 .. 11) = "--GNATLINK="
6598          then
6599             declare
6600                Program_Args : constant Argument_List_Access :=
6601                                 Argument_String_To_List
6602                                   (Argv (12 .. Argv'Last));
6603             begin
6604                if And_Save then
6605                   Saved_Gnatlink := new String'(Program_Args.all (1).all);
6606                else
6607                   Gnatlink := new String'(Program_Args.all (1).all);
6608                end if;
6609
6610                for J in 2 .. Program_Args.all'Last loop
6611                   Add_Switch (Program_Args.all (J).all, Linker);
6612                end loop;
6613             end;
6614
6615          elsif Argv'Length >= 5 and then
6616            Argv (1 .. 5) = "--RTS"
6617          then
6618             Add_Switch (Argv, Compiler, And_Save => And_Save);
6619             Add_Switch (Argv, Binder, And_Save => And_Save);
6620
6621             if Argv'Length <= 6 or else Argv (6) /= '=' then
6622                Make_Failed ("missing path for --RTS");
6623
6624             else
6625                --  Check that this is the first time we see this switch or
6626                --  if it is not the first time, the same path is specified.
6627
6628                if RTS_Specified = null then
6629                   RTS_Specified := new String'(Argv (7 .. Argv'Last));
6630
6631                elsif RTS_Specified.all /= Argv (7 .. Argv'Last) then
6632                   Make_Failed ("--RTS cannot be specified multiple times");
6633                end if;
6634
6635                --  Valid --RTS switch
6636
6637                Opt.No_Stdinc := True;
6638                Opt.No_Stdlib := True;
6639                Opt.RTS_Switch := True;
6640
6641                declare
6642                   Src_Path_Name : constant String_Ptr :=
6643                                     Get_RTS_Search_Dir
6644                                       (Argv (7 .. Argv'Last), Include);
6645
6646                   Lib_Path_Name : constant String_Ptr :=
6647                                     Get_RTS_Search_Dir
6648                                       (Argv (7 .. Argv'Last), Objects);
6649
6650                begin
6651                   if Src_Path_Name /= null and then
6652                     Lib_Path_Name /= null
6653                   then
6654                      --  Set the RTS_*_Path_Name variables, so that the correct
6655                      --  directories will be set when
6656                      --  Osint.Add_Default_Search_Dirs will be called later.
6657
6658                      RTS_Src_Path_Name := Src_Path_Name;
6659                      RTS_Lib_Path_Name := Lib_Path_Name;
6660
6661                   elsif  Src_Path_Name = null
6662                     and Lib_Path_Name = null then
6663                      Make_Failed ("RTS path not valid: missing " &
6664                                   "adainclude and adalib directories");
6665
6666                   elsif Src_Path_Name = null then
6667                      Make_Failed ("RTS path not valid: missing adainclude " &
6668                                   "directory");
6669
6670                   elsif  Lib_Path_Name = null then
6671                      Make_Failed ("RTS path not valid: missing adalib " &
6672                                   "directory");
6673                   end if;
6674                end;
6675             end if;
6676
6677          else
6678             Make_Failed ("unknown switch: ", Argv);
6679          end if;
6680
6681       --  If we have seen a regular switch process it
6682
6683       elsif Argv (1) = '-' then
6684
6685          if Argv'Length = 1 then
6686             Make_Failed ("switch character cannot be followed by a blank");
6687
6688          --  -I-
6689
6690          elsif Argv (2 .. Argv'Last) = "I-" then
6691             Opt.Look_In_Primary_Dir := False;
6692
6693          --  Forbid  -?-  or  -??-  where ? is any character
6694
6695          elsif (Argv'Length = 3 and then Argv (3) = '-')
6696            or else (Argv'Length = 4 and then Argv (4) = '-')
6697          then
6698             Make_Failed ("trailing ""-"" at the end of ", Argv, " forbidden.");
6699
6700          --  -Idir
6701
6702          elsif Argv (2) = 'I' then
6703             Add_Src_Search_Dir (Argv (3 .. Argv'Last));
6704             Add_Lib_Search_Dir (Argv (3 .. Argv'Last));
6705             Add_Switch (Argv, Compiler, And_Save => And_Save);
6706             Add_Switch (Argv, Binder, And_Save => And_Save);
6707
6708          --  -aIdir (to gcc this is like a -I switch)
6709
6710          elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aI" then
6711             Add_Src_Search_Dir (Argv (4 .. Argv'Last));
6712             Add_Switch ("-I" & Argv (4 .. Argv'Last),
6713                         Compiler,
6714                         And_Save => And_Save);
6715             Add_Switch (Argv, Binder, And_Save => And_Save);
6716
6717          --  -aOdir
6718
6719          elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aO" then
6720             Add_Lib_Search_Dir (Argv (4 .. Argv'Last));
6721             Add_Switch (Argv, Binder, And_Save => And_Save);
6722
6723          --  -aLdir (to gnatbind this is like a -aO switch)
6724
6725          elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aL" then
6726             Mark_Directory (Argv (4 .. Argv'Last), Ada_Lib_Dir);
6727             Add_Lib_Search_Dir (Argv (4 .. Argv'Last));
6728             Add_Switch ("-aO" & Argv (4 .. Argv'Last),
6729                         Binder,
6730                         And_Save => And_Save);
6731
6732          --  -Adir (to gnatbind this is like a -aO switch, to gcc like a -I)
6733
6734          elsif Argv (2) = 'A' then
6735             Mark_Directory (Argv (3 .. Argv'Last), Ada_Lib_Dir);
6736             Add_Src_Search_Dir (Argv (3 .. Argv'Last));
6737             Add_Lib_Search_Dir (Argv (3 .. Argv'Last));
6738             Add_Switch ("-I"  & Argv (3 .. Argv'Last),
6739                         Compiler,
6740                         And_Save => And_Save);
6741             Add_Switch ("-aO" & Argv (3 .. Argv'Last),
6742                         Binder,
6743                         And_Save => And_Save);
6744
6745          --  -Ldir
6746
6747          elsif Argv (2) = 'L' then
6748             Add_Switch (Argv, Linker, And_Save => And_Save);
6749
6750          --  For -gxxxxx,-pg,-mxxx: give the switch to both the compiler and
6751          --  the linker (except for -gnatxxx which is only for the compiler)
6752
6753          elsif
6754            (Argv (2) = 'g' and then (Argv'Last < 5
6755                                        or else Argv (2 .. 5) /= "gnat"))
6756              or else Argv (2 .. Argv'Last) = "pg"
6757              or else (Argv (2) = 'm' and then Argv'Last > 2)
6758          then
6759             Add_Switch (Argv, Compiler, And_Save => And_Save);
6760             Add_Switch (Argv, Linker, And_Save => And_Save);
6761
6762          --  -C=<mapping file>
6763
6764          elsif Argv'Last > 2 and then Argv (2) = 'C' then
6765             if And_Save then
6766                if Argv (3) /= '=' or else Argv'Last <= 3 then
6767                   Make_Failed ("illegal switch ", Argv);
6768                end if;
6769
6770                Gnatmake_Mapping_File := new String'(Argv (4 .. Argv'Last));
6771             end if;
6772
6773          --  -D
6774
6775          elsif Argv'Last = 2 and then Argv (2) = 'D' then
6776             if Project_File_Name /= null then
6777                Make_Failed ("-D cannot be used in conjunction with a " &
6778                             "project file");
6779
6780             else
6781                Scan_Make_Switches (Argv);
6782             end if;
6783
6784          --  -d
6785
6786          elsif Argv (2) = 'd'
6787            and then Argv'Last = 2
6788          then
6789             Opt.Display_Compilation_Progress := True;
6790
6791          --  -i
6792
6793          elsif Argv'Last = 2 and then Argv (2) = 'i' then
6794             if Project_File_Name /= null then
6795                Make_Failed ("-i cannot be used in conjunction with a " &
6796                             "project file");
6797
6798             else
6799                Scan_Make_Switches (Argv);
6800             end if;
6801
6802          --  -j (need to save the result)
6803
6804          elsif Argv (2) = 'j' then
6805             Scan_Make_Switches (Argv);
6806
6807             if And_Save then
6808                Saved_Maximum_Processes := Maximum_Processes;
6809             end if;
6810
6811          --  -m
6812
6813          elsif Argv (2) = 'm'
6814            and then Argv'Last = 2
6815          then
6816             Opt.Minimal_Recompilation := True;
6817
6818          --  -u
6819
6820          elsif Argv (2) = 'u'
6821            and then Argv'Last = 2
6822          then
6823             Unique_Compile   := True;
6824             Opt.Compile_Only := True;
6825             Do_Bind_Step     := False;
6826             Do_Link_Step     := False;
6827
6828          --  -U
6829
6830          elsif Argv (2) = 'U'
6831            and then Argv'Last = 2
6832          then
6833             Unique_Compile_All_Projects := True;
6834             Unique_Compile   := True;
6835             Opt.Compile_Only := True;
6836             Do_Bind_Step     := False;
6837             Do_Link_Step     := False;
6838
6839          --  -Pprj or -P prj (only once, and only on the command line)
6840
6841          elsif Argv (2) = 'P' then
6842             if Project_File_Name /= null then
6843                Make_Failed ("cannot have several project files specified");
6844
6845             elsif Object_Directory_Path /= null then
6846                Make_Failed ("-D cannot be used in conjunction with a " &
6847                             "project file");
6848
6849             elsif In_Place_Mode then
6850                Make_Failed ("-i cannot be used in conjunction with a " &
6851                             "project file");
6852
6853             elsif not And_Save then
6854
6855                --  It could be a tool other than gnatmake (i.e, gnatdist)
6856                --  or a -P switch inside a project file.
6857
6858                Fail
6859                  ("either the tool is not ""project-aware"" or " &
6860                   "a project file is specified inside a project file");
6861
6862             elsif Argv'Last = 2 then
6863
6864                --  -P is used alone: the project file name is the next option
6865
6866                Project_File_Name_Present := True;
6867
6868             else
6869                Project_File_Name := new String'(Argv (3 .. Argv'Last));
6870             end if;
6871
6872          --  -vPx  (verbosity of the parsing of the project files)
6873
6874          elsif Argv'Last = 4
6875            and then Argv (2 .. 3) = "vP"
6876            and then Argv (4) in '0' .. '2'
6877          then
6878             if And_Save then
6879                case Argv (4) is
6880                   when '0' =>
6881                      Current_Verbosity := Prj.Default;
6882                   when '1' =>
6883                      Current_Verbosity := Prj.Medium;
6884                   when '2' =>
6885                      Current_Verbosity := Prj.High;
6886                   when others =>
6887                      null;
6888                end case;
6889             end if;
6890
6891          --  -Xext=val  (External assignment)
6892
6893          elsif Argv (2) = 'X'
6894            and then Is_External_Assignment (Argv)
6895          then
6896             --  Is_External_Assignment has side effects
6897             --  when it returns True;
6898
6899             null;
6900
6901          --  If -gnath is present, then generate the usage information
6902          --  right now and do not pass this option on to the compiler calls.
6903
6904          elsif Argv = "-gnath" then
6905             Usage;
6906
6907          --  If -gnatc is specified, make sure the bind step and the link
6908          --  step are not executed.
6909
6910          elsif Argv'Length >= 6 and then Argv (2 .. 6) = "gnatc" then
6911
6912             --  If -gnatc is specified, make sure the bind step and the link
6913             --  step are not executed.
6914
6915             Add_Switch (Argv, Compiler, And_Save => And_Save);
6916             Opt.Operating_Mode := Opt.Check_Semantics;
6917             Opt.Check_Object_Consistency := False;
6918             Opt.Compile_Only             := True;
6919             Do_Bind_Step                 := False;
6920             Do_Link_Step                 := False;
6921
6922          elsif Argv (2 .. Argv'Last) = "nostdlib" then
6923
6924             --  Don't pass -nostdlib to gnatlink, it will disable
6925             --  linking with all standard library files.
6926
6927             Opt.No_Stdlib := True;
6928
6929             Add_Switch (Argv, Compiler, And_Save => And_Save);
6930             Add_Switch (Argv, Binder, And_Save => And_Save);
6931
6932          elsif Argv (2 .. Argv'Last) = "nostdinc" then
6933
6934             --  Pass -nostdinc to the Compiler and to gnatbind
6935
6936             Opt.No_Stdinc := True;
6937             Add_Switch (Argv, Compiler, And_Save => And_Save);
6938             Add_Switch (Argv, Binder, And_Save => And_Save);
6939
6940             --  By default all switches with more than one character
6941             --  or one character switches which are not in 'a' .. 'z'
6942             --  (except 'C', 'F', and 'M') are passed to the compiler,
6943             --  unless we are dealing with a debug switch (starts with 'd')
6944
6945          elsif Argv (2) /= 'd'
6946            and then Argv (2 .. Argv'Last) /= "C"
6947            and then Argv (2 .. Argv'Last) /= "F"
6948            and then Argv (2 .. Argv'Last) /= "M"
6949            and then (Argv'Length > 2 or else Argv (2) not in 'a' .. 'z')
6950          then
6951             Add_Switch (Argv, Compiler, And_Save => And_Save);
6952
6953          --  All other options are handled by Scan_Make_Switches
6954
6955          else
6956             Scan_Make_Switches (Argv);
6957          end if;
6958
6959       --  If not a switch it must be a file name
6960
6961       else
6962          Add_File (Argv);
6963          Mains.Add_Main (Argv);
6964       end if;
6965    end Scan_Make_Arg;
6966
6967    -----------------
6968    -- Switches_Of --
6969    -----------------
6970
6971    function Switches_Of
6972      (Source_File      : Name_Id;
6973       Source_File_Name : String;
6974       Naming           : Naming_Data;
6975       In_Package       : Package_Id;
6976       Allow_ALI        : Boolean) return Variable_Value
6977    is
6978       Switches : Variable_Value;
6979
6980       Defaults : constant Array_Element_Id :=
6981                    Prj.Util.Value_Of
6982                      (Name      => Name_Default_Switches,
6983                       In_Arrays =>
6984                       Packages.Table (In_Package).Decl.Arrays);
6985
6986       Switches_Array : constant Array_Element_Id :=
6987                          Prj.Util.Value_Of
6988                            (Name      => Name_Switches,
6989                             In_Arrays =>
6990                               Packages.Table (In_Package).Decl.Arrays);
6991
6992    begin
6993       Switches :=
6994         Prj.Util.Value_Of
6995         (Index => Source_File,
6996          In_Array => Switches_Array);
6997
6998       if Switches = Nil_Variable_Value then
6999          declare
7000             Name        : String (1 .. Source_File_Name'Length + 3);
7001             Last        : Positive := Source_File_Name'Length;
7002             Spec_Suffix : constant String :=
7003                             Get_Name_String (Naming.Current_Spec_Suffix);
7004             Body_Suffix : constant String :=
7005                             Get_Name_String (Naming.Current_Body_Suffix);
7006             Truncated   : Boolean := False;
7007
7008          begin
7009             Name (1 .. Last) := Source_File_Name;
7010
7011             if Last > Body_Suffix'Length
7012                and then Name (Last - Body_Suffix'Length + 1 .. Last) =
7013                                                                   Body_Suffix
7014             then
7015                Truncated := True;
7016                Last := Last - Body_Suffix'Length;
7017             end if;
7018
7019             if not Truncated
7020               and then Last > Spec_Suffix'Length
7021               and then Name (Last - Spec_Suffix'Length + 1 .. Last) =
7022                                                                  Spec_Suffix
7023             then
7024                Truncated := True;
7025                Last := Last - Spec_Suffix'Length;
7026             end if;
7027
7028             if Truncated then
7029                Name_Len := Last;
7030                Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
7031                Switches :=
7032                  Prj.Util.Value_Of
7033                  (Index => Name_Find,
7034                   In_Array => Switches_Array);
7035
7036                if Switches = Nil_Variable_Value
7037                  and then Allow_ALI
7038                then
7039                   Last := Source_File_Name'Length;
7040
7041                   while Name (Last) /= '.' loop
7042                      Last := Last - 1;
7043                   end loop;
7044
7045                   Name (Last + 1 .. Last + 3) := "ali";
7046                   Name_Len := Last + 3;
7047                   Name_Buffer (1 .. Name_Len) := Name (1 .. Name_Len);
7048                   Switches :=
7049                     Prj.Util.Value_Of
7050                        (Index => Name_Find,
7051                         In_Array => Switches_Array);
7052                end if;
7053             end if;
7054          end;
7055       end if;
7056
7057       if Switches = Nil_Variable_Value then
7058          Switches := Prj.Util.Value_Of
7059                                 (Index => Name_Ada, In_Array => Defaults);
7060       end if;
7061
7062       return Switches;
7063    end Switches_Of;
7064
7065    ---------------------------
7066    -- Test_If_Relative_Path --
7067    ---------------------------
7068
7069    procedure Test_If_Relative_Path
7070      (Switch             : in out String_Access;
7071       Parent             : String_Access;
7072       Including_L_Switch : Boolean := True)
7073    is
7074    begin
7075       if Switch /= null then
7076
7077          declare
7078             Sw : String (1 .. Switch'Length);
7079             Start : Positive;
7080
7081          begin
7082             Sw := Switch.all;
7083
7084             if Sw (1) = '-' then
7085                if Sw'Length >= 3
7086                  and then (Sw (2) = 'A'
7087                            or else Sw (2) = 'I'
7088                            or else (Including_L_Switch and then Sw (2) = 'L'))
7089                then
7090                   Start := 3;
7091
7092                   if Sw = "-I-" then
7093                      return;
7094                   end if;
7095
7096                elsif Sw'Length >= 4
7097                  and then (Sw (2 .. 3) = "aL"
7098                            or else Sw (2 .. 3) = "aO"
7099                            or else Sw (2 .. 3) = "aI")
7100                then
7101                   Start := 4;
7102
7103                else
7104                   return;
7105                end if;
7106
7107                --  Because relative path arguments to --RTS= may be relative
7108                --  to the search directory prefix, those relative path
7109                --  arguments are not converted.
7110
7111                if not Is_Absolute_Path (Sw (Start .. Sw'Last)) then
7112                   if Parent = null or else Parent'Length = 0 then
7113                      Make_Failed
7114                        ("relative search path switches (""",
7115                         Sw,
7116                         """) are not allowed");
7117
7118                   else
7119                      Switch :=
7120                        new String'
7121                          (Sw (1 .. Start - 1) &
7122                           Parent.all &
7123                           Directory_Separator &
7124                           Sw (Start .. Sw'Last));
7125                   end if;
7126                end if;
7127
7128             else
7129                if not Is_Absolute_Path (Sw) then
7130                   if Parent = null or else Parent'Length = 0 then
7131                      Make_Failed
7132                        ("relative paths (""", Sw, """) are not allowed");
7133
7134                   else
7135                      Switch :=
7136                        new String'(Parent.all & Directory_Separator & Sw);
7137                   end if;
7138                end if;
7139             end if;
7140          end;
7141       end if;
7142    end Test_If_Relative_Path;
7143
7144    -----------
7145    -- Usage --
7146    -----------
7147
7148    procedure Usage is
7149    begin
7150       if Usage_Needed then
7151          Usage_Needed := False;
7152          Makeusg;
7153       end if;
7154    end Usage;
7155
7156    -----------------
7157    -- Verbose_Msg --
7158    -----------------
7159
7160    procedure Verbose_Msg
7161      (N1     : Name_Id;
7162       S1     : String;
7163       N2     : Name_Id := No_Name;
7164       S2     : String  := "";
7165       Prefix : String := "  -> ")
7166    is
7167    begin
7168       if not Opt.Verbose_Mode then
7169          return;
7170       end if;
7171
7172       Write_Str (Prefix);
7173       Write_Str ("""");
7174       Write_Name (N1);
7175       Write_Str (""" ");
7176       Write_Str (S1);
7177
7178       if N2 /= No_Name then
7179          Write_Str (" """);
7180          Write_Name (N2);
7181          Write_Str (""" ");
7182       end if;
7183
7184       Write_Str (S2);
7185       Write_Eol;
7186    end Verbose_Msg;
7187
7188 begin
7189    Prj.Com.Fail := Make_Failed'Access;
7190    MLib.Fail    := Make_Failed'Access;
7191    --  Make sure that in case of failure, the temp files will be deleted
7192 end Make;