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