1aexcept.adb, [...]: Merge header, formatting and other trivial changes from ACT.
[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-2002 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 Ada.Exceptions;   use Ada.Exceptions;
28 with Ada.Command_Line; use Ada.Command_Line;
29
30 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
31
32 with ALI;      use ALI;
33 with ALI.Util; use ALI.Util;
34 with Csets;
35 with Debug;
36 with Fname;    use Fname;
37 with Fname.SF; use Fname.SF;
38 with Fname.UF; use Fname.UF;
39 with Gnatvsn;  use Gnatvsn;
40 with Hostparm; use Hostparm;
41 with Makeusg;
42 with MLib.Prj;
43 with MLib.Tgt;
44 with MLib.Utl;
45 with Namet;    use Namet;
46 with Opt;      use Opt;
47 with Osint.M;  use Osint.M;
48 with Osint;    use Osint;
49 with Gnatvsn;
50 with Output;   use Output;
51 with Prj;      use Prj;
52 with Prj.Com;
53 with Prj.Env;
54 with Prj.Ext;
55 with Prj.Pars;
56 with Prj.Util;
57 with SFN_Scan;
58 with Sinput.L;
59 with Snames;   use Snames;
60 with Stringt;  use Stringt;
61 with Switch;   use Switch;
62 with Switch.M; use Switch.M;
63 with Targparm;
64
65 with System.WCh_Con; use System.WCh_Con;
66
67 package body Make is
68
69    use ASCII;
70    --  Make control characters visible
71
72    Standard_Library_Package_Body_Name : constant String := "s-stalib.adb";
73    --  Every program depends on this package, that must then be checked,
74    --  especially when -f and -a are used.
75
76    -------------------------
77    -- Note on terminology --
78    -------------------------
79
80    --  In this program, we use the phrase "termination" of a file name to
81    --  refer to the suffix that appears after the unit name portion. Very
82    --  often this is simply the extension, but in some cases, the sequence
83    --  may be more complex, for example in main.1.ada, the termination in
84    --  this name is ".1.ada" and in main_.ada the termination is "_.ada".
85
86    -------------------------------------
87    -- Queue (Q) Manipulation Routines --
88    -------------------------------------
89
90    --  The Q is used in Compile_Sources below. Its implementation uses the
91    --  GNAT generic package Table (basically an extensible array). Q_Front
92    --  points to the first valid element in the Q, whereas Q.First is the first
93    --  element ever enqueued, while Q.Last - 1 is the last element in the Q.
94    --
95    --        +---+--------------+---+---+---+-----------+---+--------
96    --    Q   |   |  ........    |   |   |   | .......   |   |
97    --        +---+--------------+---+---+---+-----------+---+--------
98    --          ^                  ^                       ^
99    --       Q.First             Q_Front               Q.Last - 1
100    --
101    --  The elements comprised between Q.First and Q_Front - 1 are the
102    --  elements that have been enqueued and then dequeued, while the
103    --  elements between Q_Front and Q.Last - 1 are the elements currently
104    --  in the Q. When the Q is initialized Q_Front = Q.First = Q.Last.
105    --  After Compile_Sources has terminated its execution, Q_Front = Q.Last
106    --  and the elements contained between Q.Front and Q.Last-1 are those that
107    --  were explored and thus marked by Compile_Sources. Whenever the Q is
108    --  reinitialized, the elements between Q.First and Q.Last - 1 are unmarked.
109
110    procedure Init_Q;
111    --  Must be called to (re)initialize the Q.
112
113    procedure Insert_Q
114      (Source_File : File_Name_Type;
115       Source_Unit : Unit_Name_Type := No_Name);
116    --  Inserts Source_File at the end of Q. Provide Source_Unit when
117    --  possible for external use (gnatdist).
118
119    function Empty_Q return Boolean;
120    --  Returns True if Q is empty.
121
122    procedure Extract_From_Q
123      (Source_File : out File_Name_Type;
124       Source_Unit : out Unit_Name_Type);
125    --  Extracts the first element from the Q.
126
127    procedure Insert_Project_Sources
128      (The_Project : Project_Id;
129       Into_Q      : Boolean);
130    --  If Into_Q is True, insert all sources of the project file that are not
131    --  already marked into the Q. If Into_Q is False, call Osint.Add_File for
132    --  all sources of the project file.
133
134    First_Q_Initialization : Boolean := True;
135    --  Will be set to false after Init_Q has been called once.
136
137    Q_Front : Natural;
138    --  Points to the first valid element in the Q.
139
140    Unique_Compile : Boolean := False;
141
142    type Q_Record is record
143       File : File_Name_Type;
144       Unit : Unit_Name_Type;
145    end record;
146    --  File is the name of the file to compile. Unit is for gnatdist
147    --  use in order to easily get the unit name of a file to compile
148    --  when its name is krunched or declared in gnat.adc.
149
150    package Q is new Table.Table (
151      Table_Component_Type => Q_Record,
152      Table_Index_Type     => Natural,
153      Table_Low_Bound      => 0,
154      Table_Initial        => 4000,
155      Table_Increment      => 100,
156      Table_Name           => "Make.Q");
157    --  This is the actual Q.
158
159    --  The following instantiations and variables are necessary to save what
160    --  is found on the command line, in case there is a project file specified.
161
162    package Saved_Gcc_Switches is new Table.Table (
163      Table_Component_Type => String_Access,
164      Table_Index_Type     => Integer,
165      Table_Low_Bound      => 1,
166      Table_Initial        => 20,
167      Table_Increment      => 100,
168      Table_Name           => "Make.Saved_Gcc_Switches");
169
170    package Saved_Binder_Switches is new Table.Table (
171      Table_Component_Type => String_Access,
172      Table_Index_Type     => Integer,
173      Table_Low_Bound      => 1,
174      Table_Initial        => 20,
175      Table_Increment      => 100,
176      Table_Name           => "Make.Saved_Binder_Switches");
177
178    package Saved_Linker_Switches is new Table.Table
179      (Table_Component_Type => String_Access,
180       Table_Index_Type     => Integer,
181       Table_Low_Bound      => 1,
182       Table_Initial        => 20,
183       Table_Increment      => 100,
184       Table_Name           => "Make.Saved_Linker_Switches");
185
186    package Saved_Make_Switches is new Table.Table
187      (Table_Component_Type => String_Access,
188       Table_Index_Type     => Integer,
189       Table_Low_Bound      => 1,
190       Table_Initial        => 20,
191       Table_Increment      => 100,
192       Table_Name           => "Make.Saved_Make_Switches");
193
194    package Switches_To_Check is new Table.Table (
195      Table_Component_Type => String_Access,
196      Table_Index_Type     => Integer,
197      Table_Low_Bound      => 1,
198      Table_Initial        => 20,
199      Table_Increment      => 100,
200      Table_Name           => "Make.Switches_To_Check");
201
202    Normalized_Switches : Argument_List_Access := new Argument_List (1 .. 10);
203    Last_Norm_Switch    : Natural := 0;
204
205    Saved_Maximum_Processes : Natural := 0;
206    Saved_WC_Encoding_Method : WC_Encoding_Method := WC_Encoding_Method'First;
207    Saved_WC_Encoding_Method_Set : Boolean := False;
208
209    type Arg_List_Ref is access Argument_List;
210    The_Saved_Gcc_Switches : Arg_List_Ref;
211
212    Project_File_Name : String_Access  := null;
213    Current_Verbosity : Prj.Verbosity  := Prj.Default;
214    Main_Project      : Prj.Project_Id := No_Project;
215
216    procedure Add_Source_Dir (N : String);
217    --  Call Add_Src_Search_Dir.
218    --  Output one line when in verbose mode.
219
220    procedure Add_Source_Directories is
221      new Prj.Env.For_All_Source_Dirs (Action => Add_Source_Dir);
222
223    procedure Add_Object_Dir (N : String);
224    --  Call Add_Lib_Search_Dir.
225    --  Output one line when in verbose mode.
226
227    procedure Add_Object_Directories is
228      new Prj.Env.For_All_Object_Dirs (Action => Add_Object_Dir);
229
230    type Bad_Compilation_Info is record
231       File  : File_Name_Type;
232       Unit  : Unit_Name_Type;
233       Found : Boolean;
234    end record;
235    --  File is the name of the file for which a compilation failed.
236    --  Unit is for gnatdist use in order to easily get the unit name
237    --  of a file when its name is krunched or declared in gnat.adc.
238    --  Found is False if the compilation failed because the file could
239    --  not be found.
240
241    package Bad_Compilation is new Table.Table (
242      Table_Component_Type => Bad_Compilation_Info,
243      Table_Index_Type     => Natural,
244      Table_Low_Bound      => 1,
245      Table_Initial        => 20,
246      Table_Increment      => 100,
247      Table_Name           => "Make.Bad_Compilation");
248    --  Full name of all the source files for which compilation fails.
249
250    Original_Ada_Include_Path : constant String_Access :=
251                                  Getenv ("ADA_INCLUDE_PATH");
252    Original_Ada_Objects_Path : constant String_Access :=
253                                  Getenv ("ADA_OBJECTS_PATH");
254    Current_Ada_Include_Path  : String_Access := null;
255    Current_Ada_Objects_Path  : String_Access := null;
256
257    Max_Line_Length : constant := 127;
258    --  Maximum number of characters per line, when displaying a path
259
260    Do_Compile_Step : Boolean := True;
261    Do_Bind_Step    : Boolean := True;
262    Do_Link_Step    : Boolean := True;
263    --  Flags to indicate what step should be executed.
264    --  Can be set to False with the switches -c, -b and -l.
265    --  These flags are reset to True for each invokation of procedure Gnatmake.
266
267    ----------------------
268    -- Marking Routines --
269    ----------------------
270
271    procedure Mark (Source_File : File_Name_Type);
272    --  Mark Source_File. Marking is used to signal that Source_File has
273    --  already been inserted in the Q.
274
275    function Is_Marked (Source_File : File_Name_Type) return Boolean;
276    --  Returns True if Source_File was previously marked.
277
278    -------------------
279    -- Misc Routines --
280    -------------------
281
282    procedure List_Depend;
283    --  Prints to standard output the list of object dependencies. This list
284    --  can be used directly in a Makefile. A call to Compile_Sources must
285    --  precede the call to List_Depend. Also because this routine uses the
286    --  ALI files that were originally loaded and scanned by Compile_Sources,
287    --  no additional ALI files should be scanned between the two calls (i.e.
288    --  between the call to Compile_Sources and List_Depend.)
289
290    procedure Inform (N : Name_Id := No_Name; Msg : String);
291    --  Prints out the program name followed by a colon, N and S.
292
293    procedure List_Bad_Compilations;
294    --  Prints out the list of all files for which the compilation failed.
295
296    procedure Verbose_Msg
297      (N1     : Name_Id;
298       S1     : String;
299       N2     : Name_Id := No_Name;
300       S2     : String  := "";
301       Prefix : String  := "  -> ");
302    --  If the verbose flag (Verbose_Mode) is set then print Prefix to standard
303    --  output followed by N1 and S1. If N2 /= No_Name then N2 is then printed
304    --  after S1. S2 is printed last. Both N1 and N2 are printed in quotation
305    --  marks.
306
307    Usage_Needed : Boolean := True;
308    --  Flag used to make sure Makeusg is call at most once
309
310    procedure Usage;
311    --  Call Makeusg, if Usage_Needed is True.
312    --  Set Usage_Needed to False.
313
314    -----------------------
315    -- Gnatmake Routines --
316    -----------------------
317
318    subtype Lib_Mark_Type is Byte;
319    --  ??? this needs a comment
320
321    Ada_Lib_Dir : constant Lib_Mark_Type := 1;
322    --  ??? this needs a comment
323
324    --  Note that the notion of GNAT lib dir is no longer used. The code
325    --  related to it has not been removed to give an idea on how to use
326    --  the directory prefix marking mechanism.
327
328    --  An Ada library directory is a directory containing ali and object
329    --  files but no source files for the bodies (the specs can be in the
330    --  same or some other directory). These directories are specified
331    --  in the Gnatmake command line with the switch "-Adir" (to specify the
332    --  spec location -Idir cab be used).  Gnatmake skips the missing sources
333    --  whose ali are in Ada library directories. For an explanation of why
334    --  Gnatmake behaves that way, see the spec of Make.Compile_Sources.
335    --  The directory lookup penalty is incurred every single time this
336    --  routine is called.
337
338    function Is_External_Assignment (Argv : String) return Boolean;
339    --  Verify that an external assignment switch is syntactically correct.
340    --  Correct forms are
341    --      -Xname=value
342    --      -X"name=other value"
343    --  Assumptions: 'First = 1, Argv (1 .. 2) = "-X"
344    --  When this function returns True, the external assignment has
345    --  been entered by a call to Prj.Ext.Add, so that in a project
346    --  file, External ("name") will return "value".
347
348    function In_Ada_Lib_Dir  (File : File_Name_Type) return Boolean;
349    --  Get directory prefix of this file and get lib mark stored in name
350    --  table for this directory. Then check if an Ada lib mark has been set.
351
352    procedure Mark_Directory
353      (Dir  : String;
354       Mark : Lib_Mark_Type);
355    --  Store Dir in name table and set lib mark as name info to identify
356    --  Ada libraries.
357
358    function Object_File_Name (Source : String) return String;
359    --  Returns the object file name suitable for switch -o.
360
361    procedure Set_Ada_Paths
362      (For_Project         : Prj.Project_Id;
363       Including_Libraries : Boolean);
364    --  Set, if necessary, env. variables ADA_INCLUDE_PATH and
365    --  ADA_OBJECTS_PATH.
366    --
367    --  Note: this will modify these environment variables only
368    --  for the current gnatmake process and all of its children
369    --  (invocations of the compiler, the binder and the linker).
370    --  The caller process ADA_INCLUDE_PATH and ADA_OBJECTS_PATH are
371    --  not affected.
372
373    function Switches_Of
374      (Source_File      : Name_Id;
375       Source_File_Name : String;
376       Naming           : Naming_Data;
377       In_Package       : Package_Id;
378       Allow_ALI        : Boolean)
379       return             Variable_Value;
380    --  Return the switches for the source file in the specified package
381    --  of a project file. If the Source_File ends with a standard GNAT
382    --  extension (".ads" or ".adb"), try first the full name, then the
383    --  name without the extension, then, if Allow_ALI is True, the name with
384    --  the extension ".ali". If there is no switches for either names, try the
385    --  default switches for Ada. If all failed, return No_Variable_Value.
386
387    procedure Test_If_Relative_Path
388      (Switch : in out String_Access;
389       Parent : String_Access);
390    --  Test if Switch is a relative search path switch.
391    --  If it is, fail if Parent is null, otherwise prepend the path with
392    --  Parent. This subprogram is only called when using project files.
393
394    procedure Set_Library_For
395      (Project             : Project_Id;
396       There_Are_Libraries : in out Boolean);
397    --  If Project is a library project, add the correct
398    --  -L and -l switches to the linker invocation.
399
400    procedure Set_Libraries is
401       new For_Every_Project_Imported (Boolean, Set_Library_For);
402    --  Add the -L and -l switches to the linker for all
403    --  of the library projects.
404
405    ----------------------------------------------------
406    -- Compiler, Binder & Linker Data and Subprograms --
407    ----------------------------------------------------
408
409    Gcc             : String_Access := Program_Name ("gcc");
410    Gnatbind        : String_Access := Program_Name ("gnatbind");
411    Gnatlink        : String_Access := Program_Name ("gnatlink");
412    --  Default compiler, binder, linker programs
413
414    Saved_Gcc       : String_Access := null;
415    Saved_Gnatbind  : String_Access := null;
416    Saved_Gnatlink  : String_Access := null;
417    --  Given by the command line. Will be used, if non null.
418
419    Gcc_Path        : String_Access :=
420                        GNAT.OS_Lib.Locate_Exec_On_Path (Gcc.all);
421    Gnatbind_Path   : String_Access :=
422                        GNAT.OS_Lib.Locate_Exec_On_Path (Gnatbind.all);
423    Gnatlink_Path   : String_Access :=
424                        GNAT.OS_Lib.Locate_Exec_On_Path (Gnatlink.all);
425    --  Path for compiler, binder, linker programs, defaulted now for gnatdist.
426    --  Changed later if overridden on command line.
427
428    Comp_Flag         : constant String_Access := new String'("-c");
429    Output_Flag       : constant String_Access := new String'("-o");
430    Ada_Flag_1        : constant String_Access := new String'("-x");
431    Ada_Flag_2        : constant String_Access := new String'("ada");
432    No_gnat_adc       : constant String_Access := new String'("-gnatA");
433    GNAT_Flag         : constant String_Access := new String'("-gnatpg");
434    Do_Not_Check_Flag : constant String_Access := new String'("-x");
435
436    Object_Suffix     : constant String := Get_Object_Suffix.all;
437    Executable_Suffix : constant String := Get_Executable_Suffix.all;
438
439    Syntax_Only : Boolean := False;
440    --  Set to True when compiling with -gnats
441
442    Display_Executed_Programs : Boolean := True;
443    --  Set to True if name of commands should be output on stderr.
444
445    Output_File_Name_Seen : Boolean := False;
446    --  Set to True after having scanned the file_name for
447    --  switch "-o file_name"
448
449    type Make_Program_Type is (None, Compiler, Binder, Linker);
450
451    Program_Args : Make_Program_Type := None;
452    --  Used to indicate if we are scanning gnatmake, gcc, gnatbind, or gnatbind
453    --  options within the gnatmake command line.
454    --  Used in Scan_Make_Arg only, but must be a global variable.
455
456    procedure Add_Switches
457      (The_Package : Package_Id;
458       File_Name   : String;
459       Program     : Make_Program_Type);
460    procedure Add_Switch
461      (S             : String_Access;
462       Program       : Make_Program_Type;
463       Append_Switch : Boolean := True;
464       And_Save      : Boolean := True);
465    procedure Add_Switch
466      (S             : String;
467       Program       : Make_Program_Type;
468       Append_Switch : Boolean := True;
469       And_Save      : Boolean := True);
470    --  Make invokes one of three programs (the compiler, the binder or the
471    --  linker). For the sake of convenience, some program specific switches
472    --  can be passed directly on the gnatmake commande line. This procedure
473    --  records these switches so that gnamake can pass them to the right
474    --  program.  S is the switch to be added at the end of the command line
475    --  for Program if Append_Switch is True. If Append_Switch is False S is
476    --  added at the beginning of the command line.
477
478    procedure Check
479      (Lib_File  : File_Name_Type;
480       ALI       : out ALI_Id;
481       O_File    : out File_Name_Type;
482       O_Stamp   : out Time_Stamp_Type);
483    --  Determines whether the library file Lib_File is up-to-date or not. The
484    --  full name (with path information) of the object file corresponding to
485    --  Lib_File is returned in O_File. Its time stamp is saved in O_Stamp.
486    --  ALI is the ALI_Id corresponding to Lib_File. If Lib_File in not
487    --  up-to-date, then the corresponding source file needs to be recompiled.
488    --  In this case ALI = No_ALI_Id.
489
490    procedure Check_Linker_Options
491      (E_Stamp : Time_Stamp_Type;
492       O_File  : out File_Name_Type;
493       O_Stamp : out Time_Stamp_Type);
494    --  Checks all linker options for linker files that are newer
495    --  than E_Stamp. If such objects are found, the youngest object
496    --  is returned in O_File and its stamp in O_Stamp.
497    --
498    --  If no obsolete linker files were found, the first missing
499    --  linker file is returned in O_File and O_Stamp is empty.
500    --  Otherwise O_File is No_File.
501
502    procedure Display (Program : String; Args : Argument_List);
503    --  Displays Program followed by the arguments in Args if variable
504    --  Display_Executed_Programs is set. The lower bound of Args must be 1.
505
506    type Temp_File_Names is array (Positive range <>) of Temp_File_Name;
507
508    type Temp_Files_Ptr is access Temp_File_Names;
509
510    The_Mapping_File_Names : Temp_Files_Ptr;
511    Last_Mapping_File_Name : Natural := 0;
512
513    procedure Delete_Mapping_Files;
514    --  Delete all temporary mapping files
515
516    procedure Init_Mapping_File (File_Name : in out Temp_File_Name);
517    --  Create a new temporary mapping file, and fill it with the project file
518    --  mappings, when using project file(s)
519
520    --------------------
521    -- Add_Object_Dir --
522    --------------------
523
524    procedure Add_Object_Dir (N : String) is
525    begin
526       Add_Lib_Search_Dir (N);
527
528       if Opt.Verbose_Mode then
529          Write_Str ("Adding object directory """);
530          Write_Str (N);
531          Write_Str (""".");
532          Write_Eol;
533       end if;
534    end Add_Object_Dir;
535
536    --------------------
537    -- Add_Source_Dir --
538    --------------------
539
540    procedure Add_Source_Dir (N : String) is
541    begin
542       Add_Src_Search_Dir (N);
543
544       if Opt.Verbose_Mode then
545          Write_Str ("Adding source directory """);
546          Write_Str (N);
547          Write_Str (""".");
548          Write_Eol;
549       end if;
550    end Add_Source_Dir;
551
552    ----------------
553    -- Add_Switch --
554    ----------------
555
556    procedure Add_Switch
557      (S             : String_Access;
558       Program       : Make_Program_Type;
559       Append_Switch : Boolean := True;
560       And_Save      : Boolean := True)
561    is
562       generic
563          with package T is new Table.Table (<>);
564       procedure Generic_Position (New_Position : out Integer);
565       --  Generic procedure that chooses a position for S in T at the
566       --  beginning or the end, depending on the boolean Append_Switch.
567
568
569       ----------------------
570       -- Generic_Position --
571       ----------------------
572
573       procedure  Generic_Position (New_Position : out Integer) is
574       begin
575          T.Increment_Last;
576
577          if Append_Switch then
578             New_Position := Integer (T.Last);
579          else
580             for J in reverse T.Table_Index_Type'Succ (T.First) .. T.Last loop
581                T.Table (J) := T.Table (T.Table_Index_Type'Pred (J));
582             end loop;
583
584             New_Position := Integer (T.First);
585          end if;
586       end Generic_Position;
587
588       procedure Gcc_Switches_Pos    is new Generic_Position (Gcc_Switches);
589       procedure Binder_Switches_Pos is new Generic_Position (Binder_Switches);
590       procedure Linker_Switches_Pos is new Generic_Position (Linker_Switches);
591
592       procedure Saved_Gcc_Switches_Pos is new
593         Generic_Position (Saved_Gcc_Switches);
594
595       procedure Saved_Binder_Switches_Pos is new
596         Generic_Position (Saved_Binder_Switches);
597
598       procedure Saved_Linker_Switches_Pos is new
599         Generic_Position (Saved_Linker_Switches);
600
601       New_Position : Integer;
602
603    --  Start of processing for Add_Switch
604
605    begin
606       if And_Save then
607          case Program is
608             when Compiler =>
609                Saved_Gcc_Switches_Pos (New_Position);
610                Saved_Gcc_Switches.Table (New_Position) := S;
611
612             when Binder   =>
613                Saved_Binder_Switches_Pos (New_Position);
614                Saved_Binder_Switches.Table (New_Position) := S;
615
616             when Linker   =>
617                Saved_Linker_Switches_Pos (New_Position);
618                Saved_Linker_Switches.Table (New_Position) := S;
619
620             when None =>
621                raise Program_Error;
622          end case;
623
624       else
625          case Program is
626             when Compiler =>
627                Gcc_Switches_Pos (New_Position);
628                Gcc_Switches.Table (New_Position) := S;
629
630             when Binder   =>
631                Binder_Switches_Pos (New_Position);
632                Binder_Switches.Table (New_Position) := S;
633
634             when Linker   =>
635                Linker_Switches_Pos (New_Position);
636                Linker_Switches.Table (New_Position) := S;
637
638             when None =>
639                raise Program_Error;
640          end case;
641       end if;
642    end Add_Switch;
643
644    procedure Add_Switch
645      (S             : String;
646       Program       : Make_Program_Type;
647       Append_Switch : Boolean := True;
648       And_Save      : Boolean := True)
649    is
650    begin
651       Add_Switch (S             => new String'(S),
652                   Program       => Program,
653                   Append_Switch => Append_Switch,
654                   And_Save      => And_Save);
655    end Add_Switch;
656
657    ------------------
658    -- Add_Switches --
659    ------------------
660
661    procedure Add_Switches
662      (The_Package : Package_Id;
663       File_Name   : String;
664       Program     : Make_Program_Type)
665    is
666       Switches      : Variable_Value;
667       Switch_List   : String_List_Id;
668       Element       : String_Element;
669
670    begin
671       if File_Name'Length > 0 then
672          Name_Len := File_Name'Length;
673          Name_Buffer (1 .. Name_Len) := File_Name;
674          Switches :=
675            Switches_Of
676            (Source_File      => Name_Find,
677             Source_File_Name => File_Name,
678             Naming           => Projects.Table (Main_Project).Naming,
679             In_Package       => The_Package,
680             Allow_ALI        =>
681               Program = Binder or else Program = Linker);
682
683          case Switches.Kind is
684             when Undefined =>
685                null;
686
687             when List =>
688                Program_Args := Program;
689
690                Switch_List := Switches.Values;
691
692                while Switch_List /= Nil_String loop
693                   Element := String_Elements.Table (Switch_List);
694                   String_To_Name_Buffer (Element.Value);
695
696                   if Name_Len > 0 then
697                      if Opt.Verbose_Mode then
698                         Write_Str ("   Adding ");
699                         Write_Line (Name_Buffer (1 .. Name_Len));
700                      end if;
701
702                      Scan_Make_Arg
703                        (Name_Buffer (1 .. Name_Len),
704                         And_Save => False);
705                   end if;
706
707                   Switch_List := Element.Next;
708                end loop;
709
710             when Single =>
711                Program_Args := Program;
712                String_To_Name_Buffer (Switches.Value);
713
714                if Name_Len > 0 then
715                   if Opt.Verbose_Mode then
716                      Write_Str ("   Adding ");
717                      Write_Line (Name_Buffer (1 .. Name_Len));
718                   end if;
719
720                   Scan_Make_Arg
721                     (Name_Buffer (1 .. Name_Len), And_Save => False);
722                end if;
723          end case;
724       end if;
725    end Add_Switches;
726
727    ----------
728    -- Bind --
729    ----------
730
731    procedure Bind (ALI_File : File_Name_Type; Args : Argument_List) is
732       Bind_Args : Argument_List (1 .. Args'Last + 2);
733       Bind_Last : Integer;
734       Success   : Boolean;
735
736    begin
737       pragma Assert (Args'First = 1);
738
739       --  Optimize the simple case where the gnatbind command line looks like
740       --     gnatbind -aO. -I- file.ali   --into->   gnatbind file.adb
741
742       if Args'Length = 2
743         and then Args (Args'First).all = "-aO" & Normalized_CWD
744         and then Args (Args'Last).all = "-I-"
745         and then ALI_File = Strip_Directory (ALI_File)
746       then
747          Bind_Last := Args'First - 1;
748
749       else
750          Bind_Last := Args'Last;
751          Bind_Args (Args'Range) := Args;
752       end if;
753
754       --  It is completely pointless to re-check source file time stamps.
755       --  This has been done already by gnatmake
756
757       Bind_Last := Bind_Last + 1;
758       Bind_Args (Bind_Last) := Do_Not_Check_Flag;
759
760       Get_Name_String (ALI_File);
761
762       Bind_Last := Bind_Last + 1;
763       Bind_Args (Bind_Last) := new String'(Name_Buffer (1 .. Name_Len));
764
765       GNAT.OS_Lib.Normalize_Arguments (Bind_Args (Args'First .. Bind_Last));
766
767       Display (Gnatbind.all, Bind_Args (Args'First .. Bind_Last));
768
769       if Gnatbind_Path = null then
770          Osint.Fail ("error, unable to locate " & Gnatbind.all);
771       end if;
772
773       GNAT.OS_Lib.Spawn
774         (Gnatbind_Path.all, Bind_Args (Args'First .. Bind_Last), Success);
775
776       if not Success then
777          raise Bind_Failed;
778       end if;
779    end Bind;
780
781    -----------
782    -- Check --
783    -----------
784
785    procedure Check
786      (Lib_File  : File_Name_Type;
787       ALI       : out ALI_Id;
788       O_File    : out File_Name_Type;
789       O_Stamp   : out Time_Stamp_Type)
790    is
791       function First_New_Spec (A : ALI_Id) return File_Name_Type;
792       --  Looks in the with table entries of A and returns the spec file name
793       --  of the first withed unit (subprogram) for which no spec existed when
794       --  A was generated but for which there exists one now, implying that A
795       --  is now obsolete. If no such unit is found No_File is returned.
796       --  Otherwise the spec file name of the unit is returned.
797       --
798       --  **WARNING** in the event of Uname format modifications, one *MUST*
799       --  make sure this function is also updated.
800       --
801       --  Note: This function should really be in ali.adb and use Uname
802       --  services, but this causes the whole compiler to be dragged along
803       --  for gnatbind and gnatmake.
804
805       --------------------
806       -- First_New_Spec --
807       --------------------
808
809       function First_New_Spec (A : ALI_Id) return File_Name_Type is
810          Spec_File_Name : File_Name_Type := No_File;
811
812          function New_Spec (Uname : Unit_Name_Type) return Boolean;
813          --  Uname is the name of the spec or body of some ada unit.
814          --  This function returns True if the Uname is the name of a body
815          --  which has a spec not mentioned inali file A. If True is returned
816          --  Spec_File_Name above is set to the name of this spec file.
817
818          --------------
819          -- New_Spec --
820          --------------
821
822          function New_Spec (Uname : Unit_Name_Type) return Boolean is
823             Spec_Name : Unit_Name_Type;
824             File_Name : File_Name_Type;
825
826          begin
827             --  Test whether Uname is the name of a body unit (ie ends with %b)
828
829             Get_Name_String (Uname);
830             pragma
831               Assert (Name_Len > 2 and then Name_Buffer (Name_Len - 1) = '%');
832
833             if Name_Buffer (Name_Len) /= 'b' then
834                return False;
835             end if;
836
837             --  Convert unit name into spec name
838
839             --  ??? this code seems dubious in presence of pragma
840             --  Source_File_Name since there is no more direct relationship
841             --  between unit name and file name.
842
843             --  ??? Further, what about alternative subunit naming
844
845             Name_Buffer (Name_Len) := 's';
846             Spec_Name := Name_Find;
847             File_Name := Get_File_Name (Spec_Name, Subunit => False);
848
849             --  Look if File_Name is mentioned in A's sdep list.
850             --  If not look if the file exists. If it does return True.
851
852             for D in
853               ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep
854             loop
855                if Sdep.Table (D).Sfile = File_Name then
856                   return False;
857                end if;
858             end loop;
859
860             if Full_Source_Name (File_Name) /= No_File then
861                Spec_File_Name := File_Name;
862                return True;
863             end if;
864
865             return False;
866          end New_Spec;
867
868       --  Start of processing for First_New_Spec
869
870       begin
871          U_Chk : for U in
872            ALIs.Table (A).First_Unit .. ALIs.Table (A).Last_Unit
873          loop
874             exit U_Chk when Units.Table (U).Utype = Is_Body_Only
875                and then New_Spec (Units.Table (U).Uname);
876
877             for W in Units.Table (U).First_With
878                        ..
879                      Units.Table (U).Last_With
880             loop
881                exit U_Chk when
882                  Withs.Table (W).Afile /= No_File
883                  and then New_Spec (Withs.Table (W).Uname);
884             end loop;
885          end loop U_Chk;
886
887          return Spec_File_Name;
888       end First_New_Spec;
889
890       ---------------------------------
891       -- Data declarations for Check --
892       ---------------------------------
893
894       Full_Lib_File : File_Name_Type;
895       --  Full name of current library file
896
897       Full_Obj_File : File_Name_Type;
898       --  Full name of the object file corresponding to Lib_File.
899
900       Lib_Stamp : Time_Stamp_Type;
901       --  Time stamp of the current ada library file.
902
903       Obj_Stamp : Time_Stamp_Type;
904       --  Time stamp of the current object file.
905
906       Modified_Source : File_Name_Type;
907       --  The first source in Lib_File whose current time stamp differs
908       --  from that stored in Lib_File.
909
910       New_Spec : File_Name_Type;
911       --  If Lib_File contains in its W (with) section a body (for a
912       --  subprogram) for which there exists a spec and the spec did not
913       --  appear in the Sdep section of Lib_File, New_Spec contains the file
914       --  name of this new spec.
915
916       Source_Name : Name_Id;
917       Text        : Text_Buffer_Ptr;
918
919       Prev_Switch : Character;
920       --  First character of previous switch processed
921
922       Arg : Arg_Id := Arg_Id'First;
923       --  Current index in Args.Table for a given unit (init to stop warning)
924
925       Switch_Found : Boolean;
926       --  True if a given switch has been found
927
928       Num_Args : Integer;
929       --  Number of compiler arguments processed
930
931    --  Start of processing for Check
932
933    begin
934       pragma Assert (Lib_File /= No_File);
935
936       Text          := Read_Library_Info (Lib_File);
937       Full_Lib_File := Full_Library_Info_Name;
938       Full_Obj_File := Full_Object_File_Name;
939       Lib_Stamp     := Current_Library_File_Stamp;
940       Obj_Stamp     := Current_Object_File_Stamp;
941
942       if Full_Lib_File = No_File then
943          Verbose_Msg (Lib_File, "being checked ...", Prefix => "  ");
944       else
945          Verbose_Msg (Full_Lib_File, "being checked ...", Prefix => "  ");
946       end if;
947
948       ALI     := No_ALI_Id;
949       O_File  := Full_Obj_File;
950       O_Stamp := Obj_Stamp;
951
952       if Text = null then
953          if Full_Lib_File = No_File then
954             Verbose_Msg (Lib_File, "missing.");
955
956          elsif Obj_Stamp (Obj_Stamp'First) = ' ' then
957             Verbose_Msg (Full_Obj_File, "missing.");
958
959          else
960             Verbose_Msg
961               (Full_Lib_File, "(" & String (Lib_Stamp) & ") newer than",
962                Full_Obj_File, "(" & String (Obj_Stamp) & ")");
963          end if;
964
965       else
966          ALI := Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True);
967          Free (Text);
968
969          if ALI = No_ALI_Id then
970             Verbose_Msg (Full_Lib_File, "incorrectly formatted ALI file");
971             return;
972
973          elsif ALIs.Table (ALI).Ver (1 .. ALIs.Table (ALI).Ver_Len) /=
974                                                           Library_Version
975          then
976             Verbose_Msg (Full_Lib_File, "compiled with old GNAT version");
977             ALI := No_ALI_Id;
978             return;
979          end if;
980
981          --  Don't take Ali file into account if it was generated without
982          --  object.
983
984          if Opt.Operating_Mode /= Opt.Check_Semantics
985            and then ALIs.Table (ALI).No_Object
986          then
987             Verbose_Msg (Full_Lib_File, "has no corresponding object");
988             ALI := No_ALI_Id;
989             return;
990          end if;
991
992          --  Check for matching compiler switches if needed
993
994          if Opt.Check_Switches then
995             Prev_Switch := ASCII.Nul;
996             Num_Args    := 0;
997
998             Get_Name_String (ALIs.Table (ALI).Sfile);
999
1000             Switches_To_Check.Set_Last (0);
1001
1002             for J in Gcc_Switches.First .. Gcc_Switches.Last loop
1003
1004                --  Skip non switches, -I and -o switches
1005
1006                if Gcc_Switches.Table (J) (1) = '-'
1007                  and then Gcc_Switches.Table (J) (2) /= 'o'
1008                  and then Gcc_Switches.Table (J) (2) /= 'I'
1009                then
1010                   Normalize_Compiler_Switches
1011                     (Gcc_Switches.Table (J).all,
1012                      Normalized_Switches,
1013                      Last_Norm_Switch);
1014
1015                   for K in 1 .. Last_Norm_Switch loop
1016                      Switches_To_Check.Increment_Last;
1017                      Switches_To_Check.Table (Switches_To_Check.Last) :=
1018                        Normalized_Switches (K);
1019                   end loop;
1020                end if;
1021             end loop;
1022
1023             for J in 1 .. Switches_To_Check.Last loop
1024
1025                --  Comparing switches is delicate because gcc reorders
1026                --  a number of switches, according to lang-specs.h, but
1027                --  gnatmake doesn't have the sufficient knowledge to
1028                --  perform the same reordering. Instead, we ignore orders
1029                --  between different "first letter" switches, but keep
1030                --  orders between same switches, e.g -O -O2 is different
1031                --  than -O2 -O, but -g -O is equivalent to -O -g.
1032
1033                if Switches_To_Check.Table (J) (2) /= Prev_Switch then
1034                   Prev_Switch := Switches_To_Check.Table (J) (2);
1035                   Arg :=
1036                     Units.Table (ALIs.Table (ALI).First_Unit).First_Arg;
1037                end if;
1038
1039                Switch_Found := False;
1040
1041                for K in Arg ..
1042                  Units.Table (ALIs.Table (ALI).First_Unit).Last_Arg
1043                loop
1044                   Num_Args := Num_Args + 1;
1045
1046                   if
1047                     Switches_To_Check.Table (J).all = Args.Table (K).all
1048                   then
1049                      Arg := K + 1;
1050                      Switch_Found := True;
1051                      exit;
1052                   end if;
1053                end loop;
1054
1055                if not Switch_Found then
1056                   if Opt.Verbose_Mode then
1057                      Verbose_Msg (ALIs.Table (ALI).Sfile,
1058                                   "switch mismatch");
1059                   end if;
1060
1061                   ALI := No_ALI_Id;
1062                   return;
1063                end if;
1064             end loop;
1065
1066             if Num_Args /=
1067               Integer (Units.Table (ALIs.Table (ALI).First_Unit).Last_Arg -
1068                        Units.Table (ALIs.Table (ALI).First_Unit).First_Arg + 1)
1069             then
1070                if Opt.Verbose_Mode then
1071                   Verbose_Msg (ALIs.Table (ALI).Sfile,
1072                     "different number of switches");
1073                end if;
1074
1075                ALI := No_ALI_Id;
1076                return;
1077             end if;
1078          end if;
1079
1080          --  Get the source files and their time stamps. Note that some
1081          --  sources may be missing if ALI is out-of-date.
1082
1083          Set_Source_Table (ALI);
1084
1085          Modified_Source := Time_Stamp_Mismatch (ALI);
1086
1087          if Modified_Source /= No_File then
1088             ALI := No_ALI_Id;
1089
1090             if Opt.Verbose_Mode then
1091                Source_Name := Full_Source_Name (Modified_Source);
1092
1093                if Source_Name /= No_File then
1094                   Verbose_Msg (Source_Name, "time stamp mismatch");
1095                else
1096                   Verbose_Msg (Modified_Source, "missing");
1097                end if;
1098             end if;
1099
1100          else
1101             New_Spec := First_New_Spec (ALI);
1102
1103             if New_Spec /= No_File then
1104                ALI := No_ALI_Id;
1105
1106                if Opt.Verbose_Mode then
1107                   Source_Name := Full_Source_Name (New_Spec);
1108
1109                   if Source_Name /= No_File then
1110                      Verbose_Msg (Source_Name, "new spec");
1111                   else
1112                      Verbose_Msg (New_Spec, "old spec missing");
1113                   end if;
1114                end if;
1115             end if;
1116          end if;
1117       end if;
1118    end Check;
1119
1120    --------------------------
1121    -- Check_Linker_Options --
1122    --------------------------
1123
1124    procedure Check_Linker_Options
1125      (E_Stamp   : Time_Stamp_Type;
1126       O_File    : out File_Name_Type;
1127       O_Stamp   : out Time_Stamp_Type)
1128    is
1129       procedure Check_File (File : File_Name_Type);
1130       --  Update O_File and O_Stamp if the given file is younger than E_Stamp
1131       --  and O_Stamp, or if O_File is No_File and File does not exist.
1132
1133       function Get_Library_File (Name : String) return File_Name_Type;
1134       --  Return the full file name including path of a library based
1135       --  on the name specified with the -l linker option, using the
1136       --  Ada object path. Return No_File if no such file can be found.
1137
1138       type Char_Array is array (Natural) of Character;
1139       type Char_Array_Access is access constant Char_Array;
1140
1141       Template : Char_Array_Access;
1142       pragma Import (C, Template, "__gnat_library_template");
1143
1144       ----------------
1145       -- Check_File --
1146       ----------------
1147
1148       procedure Check_File (File : File_Name_Type) is
1149          Stamp : Time_Stamp_Type;
1150          Name  : File_Name_Type := File;
1151
1152       begin
1153          Get_Name_String (Name);
1154
1155          --  Remove any trailing NUL characters
1156
1157          while Name_Len >= Name_Buffer'First
1158            and then Name_Buffer (Name_Len) = NUL
1159          loop
1160             Name_Len := Name_Len - 1;
1161          end loop;
1162
1163          if Name_Len <= 0 then
1164             return;
1165
1166          elsif Name_Buffer (1) = '-' then
1167
1168             --  Do not check if File is a switch other than "-l"
1169
1170             if Name_Buffer (2) /= 'l' then
1171                return;
1172             end if;
1173
1174             --  The argument is a library switch, get actual name. It
1175             --  is necessary to make a copy of the relevant part of
1176             --  Name_Buffer as Get_Library_Name uses Name_Buffer as well.
1177
1178             declare
1179                Base_Name : constant String := Name_Buffer (3 .. Name_Len);
1180
1181             begin
1182                Name := Get_Library_File (Base_Name);
1183             end;
1184
1185             if Name = No_File then
1186                return;
1187             end if;
1188          end if;
1189
1190          Stamp := File_Stamp (Name);
1191
1192          --  Find the youngest object file that is younger than the
1193          --  executable. If no such file exist, record the first object
1194          --  file that is not found.
1195
1196          if (O_Stamp < Stamp and then E_Stamp < Stamp)
1197            or else (O_File = No_File and then Stamp (Stamp'First) = ' ')
1198          then
1199             O_Stamp := Stamp;
1200             O_File := Name;
1201
1202             --  Strip the trailing NUL if present
1203
1204             Get_Name_String (O_File);
1205
1206             if Name_Buffer (Name_Len) = NUL then
1207                Name_Len := Name_Len - 1;
1208                O_File := Name_Find;
1209             end if;
1210          end if;
1211       end Check_File;
1212
1213       ----------------------
1214       -- Get_Library_Name --
1215       ----------------------
1216
1217       --  See comments in a-adaint.c about template syntax
1218
1219       function Get_Library_File (Name : String) return File_Name_Type is
1220          File : File_Name_Type := No_File;
1221
1222       begin
1223          Name_Len := 0;
1224
1225          for Ptr in Template'Range loop
1226             case Template (Ptr) is
1227                when '*'    =>
1228                   Add_Str_To_Name_Buffer (Name);
1229
1230                when ';'    =>
1231                   File := Full_Lib_File_Name (Name_Find);
1232                   exit when File /= No_File;
1233                   Name_Len := 0;
1234
1235                when NUL    =>
1236                   exit;
1237
1238                when others =>
1239                   Add_Char_To_Name_Buffer (Template (Ptr));
1240             end case;
1241          end loop;
1242
1243          --  The for loop exited because the end of the template
1244          --  was reached. File contains the last possible file name
1245          --  for the library.
1246
1247          if File = No_File and then Name_Len > 0 then
1248             File := Full_Lib_File_Name (Name_Find);
1249          end if;
1250
1251          return File;
1252       end Get_Library_File;
1253
1254    --  Start of processing for Check_Linker_Options
1255
1256    begin
1257       O_File  := No_File;
1258       O_Stamp := (others => ' ');
1259
1260       --  Process linker options from the ALI files.
1261
1262       for Opt in 1 .. Linker_Options.Last loop
1263          Check_File (Linker_Options.Table (Opt).Name);
1264       end loop;
1265
1266       --  Process options given on the command line.
1267
1268       for Opt in Linker_Switches.First .. Linker_Switches.Last loop
1269
1270          --  Check if the previous Opt has one of the two switches
1271          --  that take an extra parameter. (See GCC manual.)
1272
1273          if Opt = Linker_Switches.First
1274            or else (Linker_Switches.Table (Opt - 1).all /= "-u"
1275                       and then
1276                     Linker_Switches.Table (Opt - 1).all /= "-Xlinker")
1277          then
1278             Name_Len := 0;
1279             Add_Str_To_Name_Buffer (Linker_Switches.Table (Opt).all);
1280             Check_File (Name_Find);
1281          end if;
1282       end loop;
1283
1284    end Check_Linker_Options;
1285
1286    ---------------------
1287    -- Compile_Sources --
1288    ---------------------
1289
1290    procedure Compile_Sources
1291      (Main_Source           : File_Name_Type;
1292       Args                  : Argument_List;
1293       First_Compiled_File   : out Name_Id;
1294       Most_Recent_Obj_File  : out Name_Id;
1295       Most_Recent_Obj_Stamp : out Time_Stamp_Type;
1296       Main_Unit             : out Boolean;
1297       Compilation_Failures  : out Natural;
1298       Check_Readonly_Files  : Boolean  := False;
1299       Do_Not_Execute        : Boolean  := False;
1300       Force_Compilations    : Boolean  := False;
1301       Keep_Going            : Boolean  := False;
1302       In_Place_Mode         : Boolean  := False;
1303       Initialize_ALI_Data   : Boolean  := True;
1304       Max_Process           : Positive := 1)
1305    is
1306       function Compile
1307         (S    : Name_Id;
1308          L    : Name_Id;
1309          Args : Argument_List)
1310          return Process_Id;
1311       --  Compiles S using Args. If S is a GNAT predefined source
1312       --  "-gnatpg" is added to Args. Non blocking call. L corresponds to the
1313       --  expected library file name. Process_Id of the process spawned to
1314       --  execute the compile.
1315
1316       No_Mapping_File : constant Temp_File_Name := (others => ' ');
1317
1318       type Compilation_Data is record
1319          Pid              : Process_Id;
1320          Full_Source_File : File_Name_Type;
1321          Lib_File         : File_Name_Type;
1322          Source_Unit      : Unit_Name_Type;
1323          Mapping_File     : Temp_File_Name := No_Mapping_File;
1324          Use_Mapping_File : Boolean        := False;
1325          Syntax_Only      : Boolean        := False;
1326       end record;
1327
1328       Running_Compile : array (1 .. Max_Process) of Compilation_Data;
1329       --  Used to save information about outstanding compilations.
1330
1331       Outstanding_Compiles : Natural := 0;
1332       --  Current number of outstanding compiles
1333
1334       Source_Unit : Unit_Name_Type;
1335       --  Current source unit
1336
1337       Source_File : File_Name_Type;
1338       --  Current source file
1339
1340       Full_Source_File : File_Name_Type;
1341       --  Full name of the current source file
1342
1343       Lib_File : File_Name_Type;
1344       --  Current library file
1345
1346       Full_Lib_File : File_Name_Type;
1347       --  Full name of the current library file
1348
1349       Obj_File : File_Name_Type;
1350       --  Full name of the object file corresponding to Lib_File.
1351
1352       Obj_Stamp : Time_Stamp_Type;
1353       --  Time stamp of the current object file.
1354
1355       Sfile : File_Name_Type;
1356       --  Contains the source file of the units withed by Source_File
1357
1358       ALI : ALI_Id;
1359       --  ALI Id of the current ALI file
1360
1361       Compilation_OK  : Boolean;
1362       Need_To_Compile : Boolean;
1363
1364       Pid  : Process_Id;
1365       Text : Text_Buffer_Ptr;
1366
1367       Mfile : Temp_File_Name := No_Mapping_File;
1368
1369       Data : Prj.Project_Data;
1370
1371       Arg_Index : Natural;
1372       --  Index in Special_Args.Table of a given compilation file
1373
1374       Need_To_Check_Standard_Library : Boolean := Check_Readonly_Files;
1375
1376       Mapping_File_Arg : constant String_Access := new String'
1377         (1 => '-', 2 => 'g', 3 => 'n', 4 => 'a', 5 => 't', 6 => 'e', 7 => 'm',
1378          8 .. 7 + Mfile'Length => ' ');
1379
1380       procedure Add_Process
1381         (Pid    : Process_Id;
1382          Sfile  : File_Name_Type;
1383          Afile  : File_Name_Type;
1384          Uname  : Unit_Name_Type;
1385          Mfile  : Temp_File_Name := No_Mapping_File;
1386          UMfile : Boolean        := False);
1387       --  Adds process Pid to the current list of outstanding compilation
1388       --  processes and record the full name of the source file Sfile that
1389       --  we are compiling, the name of its library file Afile and the
1390       --  name of its unit Uname.
1391
1392       procedure Await_Compile
1393         (Sfile : out File_Name_Type;
1394          Afile : out File_Name_Type;
1395          Uname : out Unit_Name_Type;
1396          OK    : out Boolean);
1397       --  Awaits that an outstanding compilation process terminates. When
1398       --  it does set Sfile to the name of the source file that was compiled
1399       --  Afile to the name of its library file and Uname to the name of its
1400       --  unit. Note that this time stamp can be used to check whether the
1401       --  compilation did generate an object file. OK is set to True if the
1402       --  compilation succeeded. Note that Sfile, Afile and Uname could be
1403       --  resp. No_File, No_File and No_Name  if there were no compilations
1404       --  to wait for.
1405
1406       procedure Collect_Arguments_And_Compile (Source_File : File_Name_Type);
1407       --  Collect arguments from project file (if any) and compile
1408
1409       package Good_ALI is new Table.Table (
1410         Table_Component_Type => ALI_Id,
1411         Table_Index_Type     => Natural,
1412         Table_Low_Bound      => 1,
1413         Table_Initial        => 50,
1414         Table_Increment      => 100,
1415         Table_Name           => "Make.Good_ALI");
1416       --  Contains the set of valid ALI files that have not yet been scanned.
1417
1418       procedure Record_Good_ALI (A : ALI_Id);
1419       --  Records in the previous set the Id of an ALI file.
1420
1421       function Good_ALI_Present return Boolean;
1422       --  Returns True if any ALI file was recorded in the previous set.
1423
1424       function Get_Next_Good_ALI return ALI_Id;
1425       --  Returns the next good ALI_Id record;
1426
1427       procedure Record_Failure
1428         (File  : File_Name_Type;
1429          Unit  : Unit_Name_Type;
1430          Found : Boolean := True);
1431       --  Records in the previous table that the compilation for File failed.
1432       --  If Found is False then the compilation of File failed because we
1433       --  could not find it. Records also Unit when possible.
1434
1435       function Bad_Compilation_Count return Natural;
1436       --  Returns the number of compilation failures.
1437
1438       procedure Debug_Msg (S : String; N : Name_Id);
1439       --  If Debug.Debug_Flag_W is set outputs string S followed by name N.
1440
1441       function Configuration_Pragmas_Switch
1442         (For_Project : Project_Id)
1443          return        Argument_List;
1444       --  Return an argument list of one element, if there is a configuration
1445       --  pragmas file to be specified for For_Project,
1446       --  otherwise return an empty argument list.
1447
1448       procedure Get_Mapping_File;
1449       --  Get a mapping file name. If there is one to be reused, reuse it.
1450       --  Otherwise, create a new mapping file.
1451
1452       -----------------
1453       -- Add_Process --
1454       -----------------
1455
1456       procedure Add_Process
1457         (Pid    : Process_Id;
1458          Sfile  : File_Name_Type;
1459          Afile  : File_Name_Type;
1460          Uname  : Unit_Name_Type;
1461          Mfile  : Temp_File_Name := No_Mapping_File;
1462          UMfile : Boolean        := False)
1463       is
1464          OC1 : constant Positive := Outstanding_Compiles + 1;
1465
1466       begin
1467          pragma Assert (OC1 <= Max_Process);
1468          pragma Assert (Pid /= Invalid_Pid);
1469
1470          Running_Compile (OC1).Pid              := Pid;
1471          Running_Compile (OC1).Full_Source_File := Sfile;
1472          Running_Compile (OC1).Lib_File         := Afile;
1473          Running_Compile (OC1).Source_Unit      := Uname;
1474          Running_Compile (OC1).Mapping_File     := Mfile;
1475          Running_Compile (OC1).Use_Mapping_File := UMfile;
1476          Running_Compile (OC1).Syntax_Only      := Syntax_Only;
1477
1478          Outstanding_Compiles := OC1;
1479       end Add_Process;
1480
1481       --------------------
1482       -- Await_Compile --
1483       -------------------
1484
1485       procedure Await_Compile
1486         (Sfile  : out File_Name_Type;
1487          Afile  : out File_Name_Type;
1488          Uname  : out File_Name_Type;
1489          OK     : out Boolean)
1490       is
1491          Pid : Process_Id;
1492
1493       begin
1494          pragma Assert (Outstanding_Compiles > 0);
1495
1496          Sfile := No_File;
1497          Afile := No_File;
1498          Uname := No_Name;
1499          OK    := False;
1500
1501          Wait_Process (Pid, OK);
1502
1503          if Pid = Invalid_Pid then
1504             return;
1505          end if;
1506
1507          for J in Running_Compile'First .. Outstanding_Compiles loop
1508             if Pid = Running_Compile (J).Pid then
1509                Sfile := Running_Compile (J).Full_Source_File;
1510                Afile := Running_Compile (J).Lib_File;
1511                Uname := Running_Compile (J).Source_Unit;
1512                Syntax_Only := Running_Compile (J).Syntax_Only;
1513
1514                --  If a mapping file was used by this compilation,
1515                --  get its file name for reuse by a subsequent compilation
1516
1517                if Running_Compile (J).Use_Mapping_File then
1518                   Last_Mapping_File_Name := Last_Mapping_File_Name + 1;
1519                   The_Mapping_File_Names (Last_Mapping_File_Name) :=
1520                     Running_Compile (J).Mapping_File;
1521                end if;
1522
1523                --  To actually remove this Pid and related info from
1524                --  Running_Compile replace its entry with the last valid
1525                --  entry in Running_Compile.
1526
1527                if J = Outstanding_Compiles then
1528                   null;
1529
1530                else
1531                   Running_Compile (J) :=
1532                     Running_Compile (Outstanding_Compiles);
1533                end if;
1534
1535                Outstanding_Compiles := Outstanding_Compiles - 1;
1536                return;
1537             end if;
1538          end loop;
1539
1540          raise Program_Error;
1541       end Await_Compile;
1542
1543       ---------------------------
1544       -- Bad_Compilation_Count --
1545       ---------------------------
1546
1547       function Bad_Compilation_Count return Natural is
1548       begin
1549          return Bad_Compilation.Last - Bad_Compilation.First + 1;
1550       end Bad_Compilation_Count;
1551
1552       -----------------------------------
1553       -- Collect_Arguments_And_Compile --
1554       -----------------------------------
1555
1556       procedure Collect_Arguments_And_Compile (Source_File : File_Name_Type) is
1557       begin
1558
1559          --  If we use mapping file (-P or -C switches), then get one
1560
1561          if Create_Mapping_File then
1562             Get_Mapping_File;
1563          end if;
1564
1565          --  If no project file is used, then just call Compile with
1566          --  the specified Args.
1567
1568          if Main_Project = No_Project then
1569             Pid := Compile (Full_Source_File, Lib_File, Args);
1570
1571          --  A project file was used
1572
1573          else
1574             --  First check if the current source is an immediate
1575             --  source of a project file.
1576
1577             if Opt.Verbose_Mode then
1578                Write_Eol;
1579                Write_Line ("Establishing Project context.");
1580             end if;
1581
1582             declare
1583                Source_File_Name : constant String :=
1584                                     Get_Name_String (Source_File);
1585                Current_Project  : Prj.Project_Id;
1586                Path_Name        : File_Name_Type := Source_File;
1587                Compiler_Package : Prj.Package_Id;
1588                Switches         : Prj.Variable_Value;
1589                Object_File      : String_Access;
1590
1591             begin
1592                if Opt.Verbose_Mode then
1593                   Write_Str ("Checking if the Project File exists for """);
1594                   Write_Str (Source_File_Name);
1595                   Write_Line (""".");
1596                end if;
1597
1598                Prj.Env.
1599                  Get_Reference
1600                  (Source_File_Name => Source_File_Name,
1601                   Project          => Current_Project,
1602                   Path             => Path_Name);
1603
1604                if Current_Project = No_Project then
1605
1606                   --  The current source is not an immediate source of any
1607                   --  project file. Call Compile with the specified Args plus
1608                   --  the saved gcc switches.
1609
1610                   if Opt.Verbose_Mode then
1611                      Write_Str ("No Project File.");
1612                      Write_Eol;
1613                   end if;
1614
1615                   Pid := Compile
1616                     (Full_Source_File,
1617                      Lib_File,
1618                      Args & The_Saved_Gcc_Switches.all);
1619
1620                --  We now know the project of the current source
1621
1622                else
1623                   --  Set ADA_INCLUDE_PATH and ADA_OBJECTS_PATH if the project
1624                   --  has changed.
1625
1626                   --  Note: this will modify these environment variables only
1627                   --  for the current gnatmake process and all of its children
1628                   --  (invocations of the compiler, the binder and the linker).
1629
1630                   --  The caller's ADA_INCLUDE_PATH and ADA_OBJECTS_PATH are
1631                   --  not affected.
1632
1633                   Set_Ada_Paths (Current_Project, True);
1634
1635                   Data := Projects.Table (Current_Project);
1636
1637                   --  Check if it is a library project that needs to be
1638                   --  processed, only if it is not the main project.
1639
1640                   if MLib.Tgt.Libraries_Are_Supported
1641                     and then Current_Project /= Main_Project
1642                     and then Data.Library
1643                     and then not Data.Flag1
1644                   then
1645                      --  Add to the Q all sources of the project that have
1646                      --  not been marked
1647
1648                      Insert_Project_Sources
1649                        (The_Project => Current_Project, Into_Q => True);
1650
1651                      --  Now mark the project as processed
1652
1653                      Data.Flag1 := True;
1654                      Projects.Table (Current_Project).Flag1 := True;
1655                   end if;
1656
1657                   Get_Name_String (Data.Object_Directory);
1658
1659                   if Name_Buffer (Name_Len) = '/'
1660                     or else Name_Buffer (Name_Len) = Directory_Separator
1661                   then
1662                      Object_File :=
1663                        new String'
1664                         (Name_Buffer (1 .. Name_Len) &
1665                          Object_File_Name (Source_File_Name));
1666
1667                   else
1668                      Object_File :=
1669                        new String'
1670                         (Name_Buffer (1 .. Name_Len) &
1671                          Directory_Separator &
1672                          Object_File_Name (Source_File_Name));
1673                   end if;
1674
1675                   if Opt.Verbose_Mode then
1676                      Write_Str ("Project file is """);
1677                      Write_Str (Get_Name_String (Data.Name));
1678                      Write_Str (""".");
1679                      Write_Eol;
1680                   end if;
1681
1682                   --  We know look for package Compiler
1683                   --  and get the switches from this package.
1684
1685                   if Opt.Verbose_Mode then
1686                      Write_Str ("Checking package Compiler.");
1687                      Write_Eol;
1688                   end if;
1689
1690                   Compiler_Package :=
1691                     Prj.Util.Value_Of
1692                     (Name        => Name_Compiler,
1693                      In_Packages => Data.Decl.Packages);
1694
1695                   if Compiler_Package /= No_Package then
1696
1697                      if Opt.Verbose_Mode then
1698                         Write_Str ("Getting the switches.");
1699                         Write_Eol;
1700                      end if;
1701
1702                      --  If package Gnatmake.Compiler exists, we get
1703                      --  the specific switches for the current source,
1704                      --  or the global switches, if any.
1705
1706                      Switches := Switches_Of
1707                        (Source_File      => Source_File,
1708                         Source_File_Name => Source_File_Name,
1709                         Naming           =>
1710                           Projects.Table (Current_Project).Naming,
1711                         In_Package       => Compiler_Package,
1712                         Allow_ALI        => False);
1713
1714                   end if;
1715
1716                   case Switches.Kind is
1717
1718                      --  We have a list of switches. We add to Args
1719                      --  these switches, plus the saved gcc switches.
1720
1721                      when List =>
1722
1723                         declare
1724                            Current : String_List_Id := Switches.Values;
1725                            Element : String_Element;
1726                            Number  : Natural := 0;
1727
1728                         begin
1729                            while Current /= Nil_String loop
1730                               Element := String_Elements.Table (Current);
1731                               Number  := Number + 1;
1732                               Current := Element.Next;
1733                            end loop;
1734
1735                            declare
1736                               New_Args : Argument_List (1 .. Number);
1737
1738                            begin
1739                               Current := Switches.Values;
1740
1741                               for Index in New_Args'Range loop
1742                                  Element := String_Elements.Table (Current);
1743                                  String_To_Name_Buffer (Element.Value);
1744                                  New_Args (Index) :=
1745                                    new String' (Name_Buffer (1 .. Name_Len));
1746                                  Test_If_Relative_Path
1747                                    (New_Args (Index), Parent => null);
1748                                  Current := Element.Next;
1749                               end loop;
1750
1751                               Pid := Compile
1752                                 (Path_Name,
1753                                  Lib_File,
1754                                  Args & Output_Flag & Object_File &
1755                                  Configuration_Pragmas_Switch
1756                                                     (Current_Project) &
1757                                  New_Args & The_Saved_Gcc_Switches.all);
1758                            end;
1759                         end;
1760
1761                      --  We have a single switch. We add to Args
1762                      --  this switch, plus the saved gcc switches.
1763
1764                      when Single =>
1765                         String_To_Name_Buffer (Switches.Value);
1766
1767                         declare
1768                            New_Args : Argument_List :=
1769                                         (1 => new String'
1770                                                 (Name_Buffer (1 .. Name_Len)));
1771
1772                         begin
1773                            Test_If_Relative_Path
1774                              (New_Args (1), Parent => null);
1775                            Pid := Compile
1776                              (Path_Name,
1777                               Lib_File,
1778                               Args &
1779                               Output_Flag &
1780                               Object_File &
1781                               New_Args &
1782                               Configuration_Pragmas_Switch (Current_Project) &
1783                                 The_Saved_Gcc_Switches.all);
1784                         end;
1785
1786                      --  We have no switches from Gnatmake.Compiler.
1787                      --  We add to Args the saved gcc switches.
1788
1789                      when Undefined =>
1790                         if Opt.Verbose_Mode then
1791                            Write_Str ("There are no switches.");
1792                            Write_Eol;
1793                         end if;
1794
1795                         Pid := Compile
1796                           (Path_Name,
1797                            Lib_File,
1798                            Args & Output_Flag & Object_File &
1799                            Configuration_Pragmas_Switch (Current_Project) &
1800                            The_Saved_Gcc_Switches.all);
1801                   end case;
1802                end if;
1803             end;
1804          end if;
1805       end Collect_Arguments_And_Compile;
1806
1807       -------------
1808       -- Compile --
1809       -------------
1810
1811       function Compile (S : Name_Id; L : Name_Id; Args : Argument_List)
1812         return Process_Id
1813       is
1814          Comp_Args : Argument_List (Args'First .. Args'Last + 8);
1815          Comp_Next : Integer := Args'First;
1816          Comp_Last : Integer;
1817
1818          function Ada_File_Name (Name : Name_Id) return Boolean;
1819          --  Returns True if Name is the name of an ada source file
1820          --  (i.e. suffix is .ads or .adb)
1821
1822          -------------------
1823          -- Ada_File_Name --
1824          -------------------
1825
1826          function Ada_File_Name (Name : Name_Id) return Boolean is
1827          begin
1828             Get_Name_String (Name);
1829             return
1830               Name_Len > 4
1831                 and then Name_Buffer (Name_Len - 3 .. Name_Len - 1) = ".ad"
1832                 and then (Name_Buffer (Name_Len) = 'b'
1833                             or else
1834                           Name_Buffer (Name_Len) = 's');
1835          end Ada_File_Name;
1836
1837       --  Start of processing for Compile
1838
1839       begin
1840          --  By default, Syntax_Only is False
1841
1842          Syntax_Only := False;
1843
1844          for J in Args'Range loop
1845             if Args (J).all = "-gnats" then
1846
1847                --  If we compile with -gnats, the bind step and the link step
1848                --  are inhibited. Also, we set Syntax_Only to True, so that
1849                --  we don't fail when we don't find the ALI file, after
1850                --  compilation.
1851
1852                Do_Bind_Step := False;
1853                Do_Link_Step := False;
1854                Syntax_Only  := True;
1855
1856             elsif Args (J).all = "-gnatc" then
1857
1858                --  If we compile with -gnatc, the bind step and the link step
1859                --  are inhibited. We set Syntax_Only to True for the case when
1860                --  -gnats was previously specified.
1861
1862                Do_Bind_Step := False;
1863                Do_Link_Step := False;
1864                Syntax_Only  := False;
1865             end if;
1866          end loop;
1867
1868          Comp_Args (Comp_Next) := Comp_Flag;
1869          Comp_Next := Comp_Next + 1;
1870
1871          --  Optimize the simple case where the gcc command line looks like
1872          --     gcc -c -I. ... -I- file.adb  --into->  gcc -c ... file.adb
1873
1874          if Args (Args'First).all = "-I" & Normalized_CWD
1875            and then Args (Args'Last).all = "-I-"
1876            and then S = Strip_Directory (S)
1877          then
1878             Comp_Last := Comp_Next + Args'Length - 3;
1879             Comp_Args (Comp_Next .. Comp_Last) :=
1880               Args (Args'First + 1 .. Args'Last - 1);
1881
1882          else
1883             Comp_Last := Comp_Next + Args'Length - 1;
1884             Comp_Args (Comp_Next .. Comp_Last) := Args;
1885          end if;
1886
1887          --  Set -gnatpg for predefined files (for this purpose the renamings
1888          --  such as Text_IO do not count as predefined). Note that we strip
1889          --  the directory name from the source file name becase the call to
1890          --  Fname.Is_Predefined_File_Name cannot deal with directory prefixes.
1891
1892          declare
1893             Fname : constant File_Name_Type := Strip_Directory (S);
1894
1895          begin
1896             if Is_Predefined_File_Name (Fname, False) then
1897                if Check_Readonly_Files then
1898                   Comp_Last := Comp_Last + 1;
1899                   Comp_Args (Comp_Last) := GNAT_Flag;
1900
1901                else
1902                   Fail
1903                     ("not allowed to compile """ &
1904                      Get_Name_String (Fname) &
1905                      """; use -a switch.");
1906                end if;
1907             end if;
1908          end;
1909
1910          --  Now check if the file name has one of the suffixes familiar to
1911          --  the gcc driver. If this is not the case then add the ada flag
1912          --  "-x ada".
1913
1914          if not Ada_File_Name (S) then
1915             Comp_Last := Comp_Last + 1;
1916             Comp_Args (Comp_Last) := Ada_Flag_1;
1917             Comp_Last := Comp_Last + 1;
1918             Comp_Args (Comp_Last) := Ada_Flag_2;
1919          end if;
1920
1921          if L /= Strip_Directory (L) then
1922
1923             --  Build -o argument.
1924
1925             Get_Name_String (L);
1926
1927             for J in reverse 1 .. Name_Len loop
1928                if Name_Buffer (J) = '.' then
1929                   Name_Len := J + Object_Suffix'Length - 1;
1930                   Name_Buffer (J .. Name_Len) := Object_Suffix;
1931                   exit;
1932                end if;
1933             end loop;
1934
1935             Comp_Last := Comp_Last + 1;
1936             Comp_Args (Comp_Last) := Output_Flag;
1937             Comp_Last := Comp_Last + 1;
1938             Comp_Args (Comp_Last) := new String'(Name_Buffer (1 .. Name_Len));
1939          end if;
1940
1941          if Create_Mapping_File then
1942             Comp_Last := Comp_Last + 1;
1943             Comp_Args (Comp_Last) := Mapping_File_Arg;
1944          end if;
1945
1946          Get_Name_String (S);
1947
1948          Comp_Last := Comp_Last + 1;
1949          Comp_Args (Comp_Last) := new String'(Name_Buffer (1 .. Name_Len));
1950
1951          GNAT.OS_Lib.Normalize_Arguments (Comp_Args (Args'First .. Comp_Last));
1952
1953          Display (Gcc.all, Comp_Args (Args'First .. Comp_Last));
1954
1955          if Gcc_Path = null then
1956             Osint.Fail ("error, unable to locate " & Gcc.all);
1957          end if;
1958
1959          return
1960            GNAT.OS_Lib.Non_Blocking_Spawn
1961              (Gcc_Path.all, Comp_Args (Args'First .. Comp_Last));
1962       end Compile;
1963
1964       ----------------------------------
1965       -- Configuration_Pragmas_Switch --
1966       ----------------------------------
1967
1968       function Configuration_Pragmas_Switch
1969         (For_Project : Project_Id)
1970          return        Argument_List
1971       is
1972       begin
1973          Prj.Env.Create_Config_Pragmas_File (For_Project, Main_Project);
1974
1975          if Projects.Table (For_Project).Config_File_Name /= No_Name then
1976             return
1977               (1 => new String'("-gnatec" &
1978                     Get_Name_String
1979                       (Projects.Table (For_Project).Config_File_Name)));
1980
1981          else
1982             return (1 .. 0 => null);
1983          end if;
1984       end Configuration_Pragmas_Switch;
1985
1986       ---------------
1987       -- Debug_Msg --
1988       ---------------
1989
1990       procedure Debug_Msg (S : String; N : Name_Id) is
1991       begin
1992          if Debug.Debug_Flag_W then
1993             Write_Str ("   ... ");
1994             Write_Str (S);
1995             Write_Str (" ");
1996             Write_Name (N);
1997             Write_Eol;
1998          end if;
1999       end Debug_Msg;
2000
2001       ----------------------
2002       -- Get_Mapping_File --
2003       ----------------------
2004
2005       procedure Get_Mapping_File is
2006       begin
2007          --  If there is a mapping file ready to be reused, reuse it
2008
2009          if Last_Mapping_File_Name > 0 then
2010             Mfile := The_Mapping_File_Names (Last_Mapping_File_Name);
2011             Last_Mapping_File_Name := Last_Mapping_File_Name - 1;
2012
2013          --  Otherwise, create and initialize a new one
2014
2015          else
2016             Init_Mapping_File (File_Name => Mfile);
2017          end if;
2018
2019          --  Put the name in the mapping file argument for the invocation
2020          --  of the compiler.
2021
2022          Mapping_File_Arg (8 .. Mapping_File_Arg'Last) := Mfile;
2023
2024       end Get_Mapping_File;
2025
2026       -----------------------
2027       -- Get_Next_Good_ALI --
2028       -----------------------
2029
2030       function Get_Next_Good_ALI return ALI_Id is
2031          ALI : ALI_Id;
2032
2033       begin
2034          pragma Assert (Good_ALI_Present);
2035          ALI := Good_ALI.Table (Good_ALI.Last);
2036          Good_ALI.Decrement_Last;
2037          return ALI;
2038       end Get_Next_Good_ALI;
2039
2040       ----------------------
2041       -- Good_ALI_Present --
2042       ----------------------
2043
2044       function Good_ALI_Present return Boolean is
2045       begin
2046          return Good_ALI.First <= Good_ALI.Last;
2047       end Good_ALI_Present;
2048
2049       --------------------
2050       -- Record_Failure --
2051       --------------------
2052
2053       procedure Record_Failure
2054         (File  : File_Name_Type;
2055          Unit  : Unit_Name_Type;
2056          Found : Boolean := True)
2057       is
2058       begin
2059          Bad_Compilation.Increment_Last;
2060          Bad_Compilation.Table (Bad_Compilation.Last) := (File, Unit, Found);
2061       end Record_Failure;
2062
2063       ---------------------
2064       -- Record_Good_ALI --
2065       ---------------------
2066
2067       procedure Record_Good_ALI (A : ALI_Id) is
2068       begin
2069          Good_ALI.Increment_Last;
2070          Good_ALI.Table (Good_ALI.Last) := A;
2071       end Record_Good_ALI;
2072
2073    --  Start of processing for Compile_Sources
2074
2075    begin
2076       pragma Assert (Args'First = 1);
2077
2078       --  Package and Queue initializations.
2079
2080       Good_ALI.Init;
2081       Output.Set_Standard_Error;
2082       Init_Q;
2083
2084       if Initialize_ALI_Data then
2085          Initialize_ALI;
2086          Initialize_ALI_Source;
2087       end if;
2088
2089       --  The following two flags affect the behavior of ALI.Set_Source_Table.
2090       --  We set Opt.Check_Source_Files to True to ensure that source file
2091       --  time stamps are checked, and we set Opt.All_Sources to False to
2092       --  avoid checking the presence of the source files listed in the
2093       --  source dependency section of an ali file (which would be a mistake
2094       --  since the ali file may be obsolete).
2095
2096       Opt.Check_Source_Files := True;
2097       Opt.All_Sources        := False;
2098
2099       --  If the main source is marked, there is nothing to compile.
2100       --  This can happen when we have several main subprograms.
2101       --  For the first main, we always insert in the Q.
2102
2103       if not Is_Marked (Main_Source) then
2104          Insert_Q (Main_Source);
2105          Mark (Main_Source);
2106       end if;
2107
2108       First_Compiled_File  := No_File;
2109       Most_Recent_Obj_File := No_File;
2110       Main_Unit            := False;
2111
2112       --  Keep looping until there is no more work to do (the Q is empty)
2113       --  and all the outstanding compilations have terminated
2114
2115       Make_Loop : while not Empty_Q or else Outstanding_Compiles > 0 loop
2116
2117          --  If the user does not want to keep going in case of errors then
2118          --  wait for the remaining outstanding compiles and then exit.
2119
2120          if Bad_Compilation_Count > 0 and then not Keep_Going then
2121             while Outstanding_Compiles > 0 loop
2122                Await_Compile
2123                  (Full_Source_File, Lib_File, Source_Unit, Compilation_OK);
2124
2125                if not Compilation_OK then
2126                   Record_Failure (Full_Source_File, Source_Unit);
2127                end if;
2128             end loop;
2129
2130             exit Make_Loop;
2131          end if;
2132
2133          --  PHASE 1: Check if there is more work that we can do (ie the Q
2134          --  is non empty). If there is, do it only if we have not yet used
2135          --  up all the available processes.
2136
2137          if not Empty_Q and then Outstanding_Compiles < Max_Process then
2138             Extract_From_Q (Source_File, Source_Unit);
2139             Full_Source_File := Osint.Full_Source_Name (Source_File);
2140             Lib_File         := Osint.Lib_File_Name (Source_File);
2141             Full_Lib_File    := Osint.Full_Lib_File_Name (Lib_File);
2142
2143             --  If the library file is an Ada library skip it
2144
2145             if Full_Lib_File /= No_File
2146               and then In_Ada_Lib_Dir (Full_Lib_File)
2147             then
2148                Verbose_Msg (Lib_File, "is in an Ada library", Prefix => "  ");
2149
2150             --  If the library file is a read-only library skip it
2151
2152             elsif Full_Lib_File /= No_File
2153               and then not Check_Readonly_Files
2154               and then Is_Readonly_Library (Full_Lib_File)
2155             then
2156                Verbose_Msg
2157                  (Lib_File, "is a read-only library", Prefix => "  ");
2158
2159             --  The source file that we are checking cannot be located
2160
2161             elsif Full_Source_File = No_File then
2162                Record_Failure (Source_File, Source_Unit, False);
2163
2164             --  Source and library files can be located but are internal
2165             --  files
2166
2167             elsif not Check_Readonly_Files
2168               and then Full_Lib_File /= No_File
2169               and then Is_Internal_File_Name (Source_File)
2170             then
2171
2172                if Force_Compilations then
2173                   Fail
2174                     ("not allowed to compile """ &
2175                      Get_Name_String (Source_File) &
2176                      """; use -a switch.");
2177                end if;
2178
2179                Verbose_Msg
2180                  (Lib_File, "is an internal library", Prefix => "  ");
2181
2182             --  The source file that we are checking can be located
2183
2184             else
2185                --  Don't waste any time if we have to recompile anyway
2186
2187                Obj_Stamp       := Empty_Time_Stamp;
2188                Need_To_Compile := Force_Compilations;
2189
2190                if not Force_Compilations then
2191                   Check (Lib_File, ALI, Obj_File, Obj_Stamp);
2192                   Need_To_Compile := (ALI = No_ALI_Id);
2193                end if;
2194
2195                if not Need_To_Compile then
2196
2197                   --  The ALI file is up-to-date. Record its Id.
2198
2199                   Record_Good_ALI (ALI);
2200
2201                   --  Record the time stamp of the most recent object file
2202                   --  as long as no (re)compilations are needed.
2203
2204                   if First_Compiled_File = No_File
2205                     and then (Most_Recent_Obj_File = No_File
2206                               or else Obj_Stamp > Most_Recent_Obj_Stamp)
2207                   then
2208                      Most_Recent_Obj_File  := Obj_File;
2209                      Most_Recent_Obj_Stamp := Obj_Stamp;
2210                   end if;
2211
2212                else
2213                   --  Is this the first file we have to compile?
2214
2215                   if First_Compiled_File = No_File then
2216                      First_Compiled_File  := Full_Source_File;
2217                      Most_Recent_Obj_File := No_File;
2218
2219                      if Do_Not_Execute then
2220                         exit Make_Loop;
2221                      end if;
2222                   end if;
2223
2224                   if In_Place_Mode then
2225
2226                      --  If the library file was not found, then save the
2227                      --  library file near the source file.
2228
2229                      if Full_Lib_File = No_File then
2230                         Get_Name_String (Full_Source_File);
2231
2232                         for J in reverse 1 .. Name_Len loop
2233                            if Name_Buffer (J) = '.' then
2234                               Name_Buffer (J + 1 .. J + 3) := "ali";
2235                               Name_Len := J + 3;
2236                               exit;
2237                            end if;
2238                         end loop;
2239
2240                         Lib_File := Name_Find;
2241
2242                      --  If the library file was found, then save the
2243                      --  library file in the same place.
2244
2245                      else
2246                         Lib_File := Full_Lib_File;
2247                      end if;
2248
2249                   end if;
2250
2251                   --  Check for special compilation flags
2252
2253                   Arg_Index := 0;
2254
2255                   --  Start the compilation and record it. We can do this
2256                   --  because there is at least one free process.
2257
2258                   Collect_Arguments_And_Compile (Source_File);
2259
2260                   --  Make sure we could successfully start the compilation
2261
2262                   if Pid = Invalid_Pid then
2263                      Record_Failure (Full_Source_File, Source_Unit);
2264                   else
2265                      Add_Process
2266                        (Pid,
2267                         Full_Source_File,
2268                         Lib_File,
2269                         Source_Unit,
2270                         Mfile,
2271                         Create_Mapping_File);
2272                   end if;
2273                end if;
2274             end if;
2275          end if;
2276
2277          --  PHASE 2: Now check if we should wait for a compilation to
2278          --  finish. This is the case if all the available processes are
2279          --  busy compiling sources or there is nothing else to do
2280          --  (that is the Q is empty and there are no good ALIs to process).
2281
2282          if Outstanding_Compiles = Max_Process
2283            or else (Empty_Q
2284                      and then not Good_ALI_Present
2285                      and then Outstanding_Compiles > 0)
2286          then
2287             Await_Compile
2288               (Full_Source_File, Lib_File, Source_Unit, Compilation_OK);
2289
2290             if not Compilation_OK then
2291                Record_Failure (Full_Source_File, Source_Unit);
2292             end if;
2293
2294             if Compilation_OK or else Keep_Going then
2295
2296                --  Re-read the updated library file
2297
2298                declare
2299                   Saved_Object_Consistency : constant Boolean :=
2300                                                Opt.Check_Object_Consistency;
2301
2302                begin
2303                   --  If compilation was not OK, don't check object
2304                   --  consistency.
2305
2306                   Opt.Check_Object_Consistency :=
2307                     Opt.Check_Object_Consistency and Compilation_OK;
2308                   Text := Read_Library_Info (Lib_File);
2309
2310                   --  Restore Check_Object_Consistency to its initial value
2311
2312                   Opt.Check_Object_Consistency := Saved_Object_Consistency;
2313                end;
2314
2315                --  If no ALI file was generated by this compilation nothing
2316                --  more to do, otherwise scan the ali file and record it.
2317                --  If the scan fails, a previous ali file is inconsistent with
2318                --  the unit just compiled.
2319
2320                if Text /= null then
2321                   ALI :=
2322                     Scan_ALI (Lib_File, Text, Ignore_ED => False, Err => True);
2323
2324                   if ALI = No_ALI_Id then
2325
2326                      --  Record a failure only if not already done
2327
2328                      if Compilation_OK then
2329                         Inform
2330                           (Lib_File,
2331                            "incompatible ALI file, please recompile");
2332                         Record_Failure (Full_Source_File, Source_Unit);
2333                      end if;
2334                   else
2335                      Free (Text);
2336                      Record_Good_ALI (ALI);
2337                   end if;
2338
2339                --  If we could not read the ALI file that was just generated
2340                --  then there could be a problem reading either the ALI or the
2341                --  corresponding object file (if Opt.Check_Object_Consistency
2342                --  is set Read_Library_Info checks that the time stamp of the
2343                --  object file is more recent than that of the ALI). For an
2344                --  example of problems caught by this test see [6625-009].
2345                --  However, we record a failure only if not already done.
2346
2347                else
2348                   if Compilation_OK and not Syntax_Only then
2349                      Inform
2350                        (Lib_File,
2351                         "WARNING: ALI or object file not found after compile");
2352                      Record_Failure (Full_Source_File, Source_Unit);
2353                   end if;
2354                end if;
2355             end if;
2356          end if;
2357
2358          exit Make_Loop when Unique_Compile;
2359
2360          --  PHASE 3: Check if we recorded good ALI files. If yes process
2361          --  them now in the order in which they have been recorded. There
2362          --  are two occasions in which we record good ali files. The first is
2363          --  in phase 1 when, after scanning an existing ALI file we realise
2364          --  it is up-to-date, the second instance is after a successful
2365          --  compilation.
2366
2367          while Good_ALI_Present loop
2368             ALI := Get_Next_Good_ALI;
2369
2370             --  If we are processing the library file corresponding to the
2371             --  main source file check if this source can be a main unit.
2372
2373             if ALIs.Table (ALI).Sfile = Main_Source then
2374                Main_Unit := ALIs.Table (ALI).Main_Program /= None;
2375             end if;
2376
2377             --  The following adds the standard library (s-stalib) to the
2378             --  list of files to be handled by gnatmake: this file and any
2379             --  files it depends on are always included in every bind,
2380             --  except in No_Run_Time mode, even if they are not
2381             --  in the explicit dependency list.
2382
2383             --  However, to avoid annoying output about s-stalib.ali being
2384             --  read only, when "-v" is used, we add the standard library
2385             --  only when "-a" is used.
2386
2387             if Need_To_Check_Standard_Library then
2388                Need_To_Check_Standard_Library := False;
2389
2390                if not ALIs.Table (ALI).No_Run_Time then
2391                   declare
2392                      Sfile  : Name_Id;
2393                      Add_It : Boolean := True;
2394
2395                   begin
2396                      Name_Len := Standard_Library_Package_Body_Name'Length;
2397                      Name_Buffer (1 .. Name_Len) :=
2398                        Standard_Library_Package_Body_Name;
2399                      Sfile := Name_Enter;
2400
2401                      --  If we have a special runtime, we add the standard
2402                      --  library only if we can find it.
2403
2404                      if Opt.RTS_Switch then
2405                         Add_It := Find_File (Sfile, Osint.Source) /= No_File;
2406                      end if;
2407
2408                      if Add_It and then not Is_Marked (Sfile) then
2409                         Insert_Q (Sfile);
2410                         Mark (Sfile);
2411                      end if;
2412                   end;
2413                end if;
2414             end if;
2415
2416             --  Now insert in the Q the unmarked source files (i.e. those
2417             --  which have neever been inserted in the Q and hence never
2418             --  considered).
2419
2420             for J in
2421               ALIs.Table (ALI).First_Unit .. ALIs.Table (ALI).Last_Unit
2422             loop
2423                for K in
2424                  Units.Table (J).First_With .. Units.Table (J).Last_With
2425                loop
2426                   Sfile := Withs.Table (K).Sfile;
2427
2428                   if Sfile = No_File then
2429                      Debug_Msg ("Skipping generic:", Withs.Table (K).Uname);
2430
2431                   elsif Is_Marked (Sfile) then
2432                      Debug_Msg ("Skipping marked file:", Sfile);
2433
2434                   elsif not Check_Readonly_Files
2435                     and then Is_Internal_File_Name (Sfile)
2436                   then
2437                      Debug_Msg ("Skipping internal file:", Sfile);
2438
2439                   else
2440                      Insert_Q (Sfile, Withs.Table (K).Uname);
2441                      Mark (Sfile);
2442                   end if;
2443                end loop;
2444             end loop;
2445          end loop;
2446
2447          if Opt.Display_Compilation_Progress then
2448             Write_Str ("completed ");
2449             Write_Int (Int (Q_Front));
2450             Write_Str (" out of ");
2451             Write_Int (Int (Q.Last));
2452             Write_Str (" (");
2453             Write_Int (Int ((Q_Front * 100) / (Q.Last - Q.First)));
2454             Write_Str ("%)...");
2455             Write_Eol;
2456          end if;
2457       end loop Make_Loop;
2458
2459       Compilation_Failures := Bad_Compilation_Count;
2460
2461       --  Compilation is finished
2462
2463       --  Delete any temporary configuration pragma file
2464
2465       if Main_Project /= No_Project then
2466          declare
2467             Success : Boolean;
2468
2469          begin
2470             for Project in 1 .. Projects.Last loop
2471                if Projects.Table (Project).Config_File_Temp then
2472                   if Opt.Verbose_Mode then
2473                      Write_Str ("Deleting temp configuration file """);
2474                      Write_Str (Get_Name_String
2475                                 (Projects.Table (Project).Config_File_Name));
2476                      Write_Line ("""");
2477                   end if;
2478
2479                   Delete_File
2480                     (Name    => Get_Name_String
2481                                   (Projects.Table (Project).Config_File_Name),
2482                      Success => Success);
2483
2484                   --  Make sure that we don't have a config file for this
2485                   --  project, in case when there are several mains.
2486                   --  In this case, we will recreate another config file:
2487                   --  we cannot reuse the one that we just deleted!
2488
2489                   Projects.Table (Project).Config_Checked   := False;
2490                   Projects.Table (Project).Config_File_Name := No_Name;
2491                   Projects.Table (Project).Config_File_Temp := False;
2492                end if;
2493             end loop;
2494          end;
2495       end if;
2496    end Compile_Sources;
2497
2498    --------------------------
2499    -- Delete_Mapping_Files --
2500    --------------------------
2501
2502    procedure Delete_Mapping_Files is
2503       Success : Boolean;
2504
2505    begin
2506       for Index in 1 .. Last_Mapping_File_Name loop
2507          Delete_File
2508            (Name => The_Mapping_File_Names (Index), Success => Success);
2509       end loop;
2510    end Delete_Mapping_Files;
2511
2512    -------------
2513    -- Display --
2514    -------------
2515
2516    procedure Display (Program : String; Args : Argument_List) is
2517    begin
2518       pragma Assert (Args'First = 1);
2519
2520       if Display_Executed_Programs then
2521          Write_Str (Program);
2522
2523          for J in Args'Range loop
2524
2525             --  Do not display the mapping file argument automatically
2526             --  created when using a project file.
2527
2528             if Main_Project = No_Project
2529               or else Args (J)'Length /= 7 + Temp_File_Name'Length
2530               or else Args (J)'First /= 1
2531               or else Args (J)(1 .. 7) /= "-gnatem"
2532             then
2533                Write_Str (" ");
2534                Write_Str (Args (J).all);
2535             end if;
2536          end loop;
2537
2538          Write_Eol;
2539       end if;
2540    end Display;
2541
2542    ----------------------
2543    -- Display_Commands --
2544    ----------------------
2545
2546    procedure Display_Commands (Display : Boolean := True) is
2547    begin
2548       Display_Executed_Programs := Display;
2549    end Display_Commands;
2550
2551    -------------
2552    -- Empty_Q --
2553    -------------
2554
2555    function Empty_Q return Boolean is
2556    begin
2557       if Debug.Debug_Flag_P then
2558          Write_Str ("   Q := [");
2559
2560          for J in Q_Front .. Q.Last - 1 loop
2561             Write_Str (" ");
2562             Write_Name (Q.Table (J).File);
2563             Write_Eol;
2564             Write_Str ("         ");
2565          end loop;
2566
2567          Write_Str ("]");
2568          Write_Eol;
2569       end if;
2570
2571       return Q_Front >= Q.Last;
2572    end Empty_Q;
2573
2574    ---------------------
2575    -- Extract_Failure --
2576    ---------------------
2577
2578    procedure Extract_Failure
2579      (File  : out File_Name_Type;
2580       Unit  : out Unit_Name_Type;
2581       Found : out Boolean)
2582    is
2583    begin
2584       File  := Bad_Compilation.Table (Bad_Compilation.Last).File;
2585       Unit  := Bad_Compilation.Table (Bad_Compilation.Last).Unit;
2586       Found := Bad_Compilation.Table (Bad_Compilation.Last).Found;
2587       Bad_Compilation.Decrement_Last;
2588    end Extract_Failure;
2589
2590    --------------------
2591    -- Extract_From_Q --
2592    --------------------
2593
2594    procedure Extract_From_Q
2595      (Source_File : out File_Name_Type;
2596       Source_Unit : out Unit_Name_Type)
2597    is
2598       File : constant File_Name_Type := Q.Table (Q_Front).File;
2599       Unit : constant Unit_Name_Type := Q.Table (Q_Front).Unit;
2600
2601    begin
2602       if Debug.Debug_Flag_Q then
2603          Write_Str ("   Q := Q - [ ");
2604          Write_Name (File);
2605          Write_Str (" ]");
2606          Write_Eol;
2607       end if;
2608
2609       Q_Front := Q_Front + 1;
2610       Source_File := File;
2611       Source_Unit := Unit;
2612    end Extract_From_Q;
2613
2614    --------------
2615    -- Gnatmake --
2616    --------------
2617
2618    procedure Gnatmake is
2619       Main_Source_File : File_Name_Type;
2620       --  The source file containing the main compilation unit
2621
2622       Compilation_Failures : Natural;
2623
2624       Total_Compilation_Failures : Natural := 0;
2625
2626       Is_Main_Unit : Boolean;
2627       --  Set to True by Compile_Sources if the Main_Source_File can be a
2628       --  main unit.
2629
2630       Main_ALI_File : File_Name_Type;
2631       --  The ali file corresponding to Main_Source_File
2632
2633       Executable : File_Name_Type := No_File;
2634       --  The file name of an executable
2635
2636       Non_Std_Executable : Boolean := False;
2637       --  Non_Std_Executable is set to True when there is a possibility
2638       --  that the linker will not choose the correct executable file name.
2639
2640       Executable_Obsolete : Boolean := False;
2641       --  Executable_Obsolete is set to True for the first obsolete main
2642       --  and is never reset to False. Any subsequent main will always
2643       --  be rebuild (if we rebuild mains), even in the case when it is not
2644       --  really necessary, because it is too hard to decide.
2645
2646       Current_Work_Dir : constant String_Access :=
2647                                     new String'(Get_Current_Dir);
2648       --  The current working directory, used to modify some relative path
2649       --  switches on the command line when a project file is used.
2650
2651    begin
2652       Do_Compile_Step := True;
2653       Do_Bind_Step    := True;
2654       Do_Link_Step    := True;
2655
2656       Make.Initialize;
2657
2658       if Hostparm.Java_VM then
2659          Gcc := new String'("jgnat");
2660          Gnatbind := new String'("jgnatbind");
2661          Gnatlink := new String '("jgnatlink");
2662
2663          --  Do not check for an object file (".o") when compiling to
2664          --  Java bytecode since ".class" files are generated instead.
2665
2666          Opt.Check_Object_Consistency := False;
2667       end if;
2668
2669       if Opt.Verbose_Mode then
2670          Targparm.Get_Target_Parameters;
2671
2672          Write_Eol;
2673          Write_Str ("GNATMAKE ");
2674
2675          if Targparm.High_Integrity_Mode_On_Target then
2676             Write_Str ("Pro High Integrity ");
2677          end if;
2678
2679          Write_Str (Gnatvsn.Gnat_Version_String);
2680          Write_Str (" Copyright 1995-2002 Free Software Foundation, Inc.");
2681          Write_Eol;
2682       end if;
2683
2684       --  If no mains have been specified on the command line,
2685       --  and we are using a project file, we either find the main(s)
2686       --  in the attribute Main of the main project, or we put all
2687       --  the sources of the project file as mains.
2688
2689       if Main_Project /= No_Project and then Osint.Number_Of_Files = 0 then
2690          Name_Len := 4;
2691          Name_Buffer (1 .. 4) := "main";
2692
2693          declare
2694             Main_Id : constant Name_Id := Name_Find;
2695
2696             Mains : constant Prj.Variable_Value :=
2697                       Prj.Util.Value_Of
2698                         (Variable_Name => Main_Id,
2699                          In_Variables  =>
2700                            Projects.Table (Main_Project).Decl.Attributes);
2701
2702             Value : String_List_Id := Mains.Values;
2703
2704          begin
2705             --  The attribute Main is an empty list or not specified,
2706             --  or else gnatmake was invoked with the switch "-u".
2707
2708             if Value = Prj.Nil_String or else Unique_Compile then
2709
2710                --  First make sure that the binder and the linker
2711                --  will not be invoked.
2712
2713                Do_Bind_Step := False;
2714                Do_Link_Step := False;
2715
2716                --  Set Unique_Compile if it was not already set
2717
2718                Unique_Compile := True;
2719
2720                --  Put all the sources in the queue
2721
2722                Insert_Project_Sources
2723                  (The_Project => Main_Project, Into_Q => False);
2724
2725             else
2726                --  The attribute Main is not an empty list.
2727                --  Put all the main subprograms in the list as if there were
2728                --  specified on the command line.
2729
2730                while Value /= Prj.Nil_String loop
2731                   String_To_Name_Buffer (String_Elements.Table (Value).Value);
2732                   Osint.Add_File (Name_Buffer (1 .. Name_Len));
2733                   Value := String_Elements.Table (Value).Next;
2734                end loop;
2735
2736             end if;
2737          end;
2738
2739       end if;
2740
2741       --  Output usage information if no files. Note that this can happen
2742       --  in the case of a project file that contains only subunits.
2743
2744       if Osint.Number_Of_Files = 0 then
2745          Makeusg;
2746          Exit_Program (E_Fatal);
2747
2748       end if;
2749
2750       --  If -M was specified, behave as if -n was specified
2751
2752       if Opt.List_Dependencies then
2753          Opt.Do_Not_Execute := True;
2754       end if;
2755
2756       --  Note that Osint.Next_Main_Source will always return the (possibly
2757       --  abbreviated file) without any directory information.
2758
2759       Main_Source_File := Next_Main_Source;
2760
2761       if Project_File_Name = null then
2762          Add_Switch ("-I-", Compiler, And_Save => True);
2763          Add_Switch ("-I-", Binder, And_Save => True);
2764
2765          if Opt.Look_In_Primary_Dir then
2766
2767             Add_Switch
2768               ("-I" &
2769                Normalize_Directory_Name
2770                (Get_Primary_Src_Search_Directory.all).all,
2771                Compiler, Append_Switch => False,
2772                And_Save => False);
2773
2774             Add_Switch ("-aO" & Normalized_CWD,
2775                         Binder,
2776                         Append_Switch => False,
2777                         And_Save => False);
2778          end if;
2779
2780       end if;
2781
2782       --  If the user wants a program without a main subprogram, add the
2783       --  appropriate switch to the binder.
2784
2785       if Opt.No_Main_Subprogram then
2786          Add_Switch ("-z", Binder, And_Save => True);
2787       end if;
2788
2789       if Main_Project /= No_Project then
2790
2791          Change_Dir
2792            (Get_Name_String (Projects.Table (Main_Project).Object_Directory));
2793
2794          --  Find the file name of the main unit
2795
2796          declare
2797             Main_Source_File_Name : constant String :=
2798                                       Get_Name_String (Main_Source_File);
2799             Main_Unit_File_Name   : constant String :=
2800                                       Prj.Env.File_Name_Of_Library_Unit_Body
2801                                         (Name    => Main_Source_File_Name,
2802                                          Project => Main_Project);
2803
2804             The_Packages : constant Package_Id :=
2805               Projects.Table (Main_Project).Decl.Packages;
2806
2807             Gnatmake : constant Prj.Package_Id :=
2808                          Prj.Util.Value_Of
2809                            (Name        => Name_Builder,
2810                             In_Packages => The_Packages);
2811
2812             Binder_Package : constant Prj.Package_Id :=
2813                          Prj.Util.Value_Of
2814                            (Name        => Name_Binder,
2815                             In_Packages => The_Packages);
2816
2817             Linker_Package : constant Prj.Package_Id :=
2818                          Prj.Util.Value_Of
2819                            (Name       => Name_Linker,
2820                            In_Packages => The_Packages);
2821
2822          begin
2823             --  We fail if we cannot find the main source file
2824             --  as an immediate source of the main project file.
2825
2826             if Main_Unit_File_Name = "" then
2827                Fail ('"' & Main_Source_File_Name  &
2828                      """ is not a unit of project " &
2829                      Project_File_Name.all & ".");
2830             else
2831                --  Remove any directory information from the main
2832                --  source file name.
2833
2834                declare
2835                   Pos : Natural := Main_Unit_File_Name'Last;
2836
2837                begin
2838                   loop
2839                      exit when Pos < Main_Unit_File_Name'First or else
2840                        Main_Unit_File_Name (Pos) = Directory_Separator;
2841                      Pos := Pos - 1;
2842                   end loop;
2843
2844                   Name_Len := Main_Unit_File_Name'Last - Pos;
2845
2846                   Name_Buffer (1 .. Name_Len) :=
2847                     Main_Unit_File_Name
2848                     (Pos + 1 .. Main_Unit_File_Name'Last);
2849
2850                   Main_Source_File := Name_Find;
2851
2852                   --  We only output the main source file if there is only one
2853
2854                   if Opt.Verbose_Mode and then Osint.Number_Of_Files = 1 then
2855                      Write_Str ("Main source file: """);
2856                      Write_Str (Main_Unit_File_Name
2857                                 (Pos + 1 .. Main_Unit_File_Name'Last));
2858                      Write_Line (""".");
2859                   end if;
2860                end;
2861             end if;
2862
2863             --  If there is a package gnatmake in the main project file, add
2864             --  the switches from it. We also add the switches from packages
2865             --  gnatbind and gnatlink, if any.
2866
2867             if Gnatmake /= No_Package then
2868
2869                --  If there is only one main, we attempt to get the gnatmake
2870                --  switches for this main (if any). If there are no specific
2871                --  switch for this particular main, get the general gnatmake
2872                --  switches (if any).
2873
2874                if Osint.Number_Of_Files = 1 then
2875                   if Opt.Verbose_Mode then
2876                      Write_Str ("Adding gnatmake switches for """);
2877                      Write_Str (Main_Unit_File_Name);
2878                      Write_Line (""".");
2879                   end if;
2880
2881                   Add_Switches
2882                     (File_Name   => Main_Unit_File_Name,
2883                      The_Package => Gnatmake,
2884                      Program     => None);
2885
2886                else
2887                   --  If there are several mains, we always get the general
2888                   --  gnatmake switches (if any).
2889
2890                   --  Note: As there is never a source with name " ",
2891                   --  we are guaranteed to always get the gneneral switches.
2892
2893                   Add_Switches
2894                     (File_Name   => " ",
2895                      The_Package => Gnatmake,
2896                      Program     => None);
2897                end if;
2898
2899             end if;
2900
2901             if Binder_Package /= No_Package then
2902
2903                --  If there is only one main, we attempt to get the gnatbind
2904                --  switches for this main (if any). If there are no specific
2905                --  switch for this particular main, get the general gnatbind
2906                --  switches (if any).
2907
2908                if Osint.Number_Of_Files = 1 then
2909                   if Opt.Verbose_Mode then
2910                      Write_Str ("Adding binder switches for """);
2911                      Write_Str (Main_Unit_File_Name);
2912                      Write_Line (""".");
2913                   end if;
2914
2915                   Add_Switches
2916                     (File_Name   => Main_Unit_File_Name,
2917                      The_Package => Binder_Package,
2918                      Program     => Binder);
2919
2920                else
2921                   --  If there are several mains, we always get the general
2922                   --  gnatbind switches (if any).
2923
2924                   --  Note: As there is never a source with name " ",
2925                   --  we are guaranteed to always get the gneneral switches.
2926
2927                   Add_Switches
2928                     (File_Name   => " ",
2929                      The_Package => Binder_Package,
2930                      Program     => Binder);
2931                end if;
2932
2933             end if;
2934
2935             if Linker_Package /= No_Package then
2936
2937                --  If there is only one main, we attempt to get the
2938                --  gnatlink switches for this main (if any). If there are
2939                --  no specific switch for this particular main, we get the
2940                --  general gnatlink switches (if any).
2941
2942                if Osint.Number_Of_Files = 1 then
2943                   if Opt.Verbose_Mode then
2944                      Write_Str ("Adding linker switches for""");
2945                      Write_Str (Main_Unit_File_Name);
2946                      Write_Line (""".");
2947                   end if;
2948
2949                   Add_Switches
2950                     (File_Name   => Main_Unit_File_Name,
2951                      The_Package => Linker_Package,
2952                      Program     => Linker);
2953
2954                else
2955                   --  If there are several mains, we always get the general
2956                   --  gnatlink switches (if any).
2957
2958                   --  Note: As there is never a source with name " ",
2959                   --  we are guaranteed to always get the general switches.
2960
2961                   Add_Switches
2962                     (File_Name   => " ",
2963                      The_Package => Linker_Package,
2964                      Program     => Linker);
2965                end if;
2966             end if;
2967          end;
2968       end if;
2969
2970       Display_Commands (not Opt.Quiet_Output);
2971
2972       --  If we are using a project file, relative paths are forbidden in the
2973       --  project file, but we add the current working directory for any
2974       --  relative path on the command line.
2975
2976       if Main_Project /= No_Project then
2977
2978          for J in 1 .. Binder_Switches.Last loop
2979             Test_If_Relative_Path
2980               (Binder_Switches.Table (J), Parent => null);
2981          end loop;
2982
2983          for J in 1 .. Saved_Binder_Switches.Last loop
2984             Test_If_Relative_Path
2985               (Saved_Binder_Switches.Table (J), Parent => Current_Work_Dir);
2986          end loop;
2987
2988          for J in 1 .. Linker_Switches.Last loop
2989             Test_If_Relative_Path
2990               (Linker_Switches.Table (J), Parent => null);
2991          end loop;
2992
2993          for J in 1 .. Saved_Linker_Switches.Last loop
2994             Test_If_Relative_Path
2995               (Saved_Linker_Switches.Table (J), Parent => Current_Work_Dir);
2996          end loop;
2997
2998          for J in 1 .. Gcc_Switches.Last loop
2999             Test_If_Relative_Path
3000               (Gcc_Switches.Table (J), Parent => null);
3001          end loop;
3002
3003          for J in 1 .. Saved_Gcc_Switches.Last loop
3004             Test_If_Relative_Path
3005               (Saved_Gcc_Switches.Table (J), Parent => Current_Work_Dir);
3006          end loop;
3007       end if;
3008
3009       --  We now put in the Binder_Switches and Linker_Switches tables,
3010       --  the binder and linker switches of the command line that have been
3011       --  put in the Saved_ tables. If a project file was used, then the
3012       --  command line switches will follow the project file switches.
3013
3014       for J in 1 .. Saved_Binder_Switches.Last loop
3015          Add_Switch
3016            (Saved_Binder_Switches.Table (J),
3017             Binder,
3018             And_Save => False);
3019       end loop;
3020
3021       for J in 1 .. Saved_Linker_Switches.Last loop
3022          Add_Switch
3023            (Saved_Linker_Switches.Table (J),
3024             Linker,
3025             And_Save => False);
3026       end loop;
3027
3028       --  If no project file is used, we just put the gcc switches
3029       --  from the command line in the Gcc_Switches table.
3030
3031       if Main_Project = No_Project then
3032          for J in 1 .. Saved_Gcc_Switches.Last loop
3033             Add_Switch
3034               (Saved_Gcc_Switches.Table (J),
3035                Compiler,
3036               And_Save => False);
3037          end loop;
3038
3039       else
3040          --  And we put the command line gcc switches in the variable
3041          --  The_Saved_Gcc_Switches. They are going to be used later
3042          --  in procedure Compile_Sources.
3043
3044          The_Saved_Gcc_Switches :=
3045            new Argument_List (1 .. Saved_Gcc_Switches.Last + 1);
3046
3047          for J in 1 .. Saved_Gcc_Switches.Last loop
3048             The_Saved_Gcc_Switches (J) := Saved_Gcc_Switches.Table (J);
3049          end loop;
3050
3051          --  We never use gnat.adc when a project file is used
3052
3053          The_Saved_Gcc_Switches (The_Saved_Gcc_Switches'Last) :=
3054            No_gnat_adc;
3055
3056       end if;
3057
3058       --  If there was a --GCC, --GNATBIND or --GNATLINK switch on
3059       --  the command line, then we have to use it, even if there was
3060       --  another switch in the project file.
3061
3062       if Saved_Gcc /= null then
3063          Gcc := Saved_Gcc;
3064       end if;
3065
3066       if Saved_Gnatbind /= null then
3067          Gnatbind := Saved_Gnatbind;
3068       end if;
3069
3070       if Saved_Gnatlink /= null then
3071          Gnatlink := Saved_Gnatlink;
3072       end if;
3073
3074       Gcc_Path       := GNAT.OS_Lib.Locate_Exec_On_Path (Gcc.all);
3075       Gnatbind_Path  := GNAT.OS_Lib.Locate_Exec_On_Path (Gnatbind.all);
3076       Gnatlink_Path  := GNAT.OS_Lib.Locate_Exec_On_Path (Gnatlink.all);
3077
3078       --  If we have specified -j switch both from the project file
3079       --  and on the command line, the one from the command line takes
3080       --  precedence.
3081
3082       if Saved_Maximum_Processes = 0 then
3083          Saved_Maximum_Processes := Opt.Maximum_Processes;
3084       end if;
3085
3086       --  Allocate as many temporary mapping file names as the maximum
3087       --  number of compilation processed.
3088
3089       The_Mapping_File_Names :=
3090         new Temp_File_Names (1 .. Saved_Maximum_Processes);
3091
3092       --  If either -c, -b or -l has been specified, we will not necessarily
3093       --  execute all steps.
3094
3095       if Compile_Only or else Bind_Only or else Link_Only then
3096          Do_Compile_Step := Do_Compile_Step and Compile_Only;
3097          Do_Bind_Step    := Do_Bind_Step    and Bind_Only;
3098          Do_Link_Step    := Do_Link_Step    and Link_Only;
3099
3100          --  If -c has been specified, but not -b, ignore any potential -l
3101
3102          if Do_Compile_Step and then not Do_Bind_Step then
3103             Do_Link_Step := False;
3104          end if;
3105       end if;
3106
3107       Bad_Compilation.Init;
3108
3109       --  Here is where the make process is started
3110
3111       --  We do the same process for each main
3112
3113       Multiple_Main_Loop : for N_File in 1 .. Osint.Number_Of_Files loop
3114
3115          if Do_Compile_Step then
3116             Recursive_Compilation_Step : declare
3117                Args : Argument_List (1 .. Gcc_Switches.Last);
3118
3119                First_Compiled_File : Name_Id;
3120
3121                Youngest_Obj_File   : Name_Id;
3122                Youngest_Obj_Stamp  : Time_Stamp_Type;
3123
3124                Executable_Stamp    : Time_Stamp_Type;
3125                --  Executable is the final executable program.
3126
3127             begin
3128                Executable         := No_File;
3129                Non_Std_Executable := False;
3130
3131                for J in 1 .. Gcc_Switches.Last loop
3132                   Args (J) := Gcc_Switches.Table (J);
3133                end loop;
3134
3135                --  Look inside the linker switches to see if the name
3136                --  of the final executable program was specified.
3137
3138                for
3139                  J in reverse Linker_Switches.First .. Linker_Switches.Last
3140                loop
3141                   if Linker_Switches.Table (J).all = Output_Flag.all then
3142                      pragma Assert (J < Linker_Switches.Last);
3143
3144                      --  We cannot specify a single executable for several
3145                      --  main subprograms!
3146
3147                      if Osint.Number_Of_Files > 1 then
3148                         Fail
3149                            ("cannot specify a single executable " &
3150                             "for several mains");
3151                      end if;
3152
3153                      Name_Len := Linker_Switches.Table (J + 1)'Length;
3154                      Name_Buffer (1 .. Name_Len) :=
3155                        Linker_Switches.Table (J + 1).all;
3156
3157                      --  If target has an executable suffix and it has not been
3158                      --  specified then it is added here.
3159
3160                      if Executable_Suffix'Length /= 0
3161                        and then Linker_Switches.Table (J + 1)
3162                                  (Name_Len - Executable_Suffix'Length + 1
3163                                   .. Name_Len) /= Executable_Suffix
3164                      then
3165                         Name_Buffer (Name_Len + 1 ..
3166                                      Name_Len + Executable_Suffix'Length) :=
3167                           Executable_Suffix;
3168                         Name_Len := Name_Len + Executable_Suffix'Length;
3169                      end if;
3170
3171                      Executable := Name_Enter;
3172
3173                      Verbose_Msg (Executable, "final executable");
3174                   end if;
3175                end loop;
3176
3177                --  If the name of the final executable program was not
3178                --  specified then construct it from the main input file.
3179
3180                if Executable = No_File then
3181                   if Main_Project = No_Project then
3182                      Executable :=
3183                        Executable_Name (Strip_Suffix (Main_Source_File));
3184
3185                   else
3186                      --  If we are using a project file, we attempt to
3187                      --  remove the body (or spec) termination of the main
3188                      --  subprogram. We find it the the naming scheme of the
3189                      --  project file. This will avoid to generate an
3190                      --  executable "main.2" for a main subprogram
3191                      --  "main.2.ada", when the body termination is ".2.ada".
3192
3193                      declare
3194                         Body_Append : constant String :=
3195                                         Get_Name_String
3196                                           (Projects.Table
3197                                            (Main_Project).
3198                                             Naming.Current_Impl_Suffix);
3199
3200                         Spec_Append : constant String :=
3201                                         Get_Name_String
3202                                           (Projects.Table
3203                                             (Main_Project).
3204                                               Naming.Current_Spec_Suffix);
3205
3206                      begin
3207                         Get_Name_String (Main_Source_File);
3208
3209                         if Name_Len > Body_Append'Length
3210                           and then Name_Buffer
3211                              (Name_Len - Body_Append'Length + 1 .. Name_Len) =
3212                                            Body_Append
3213                         then
3214                            --  We have found the body termination. We remove it
3215                            --  add the executable termination, if any.
3216
3217                            Name_Len := Name_Len - Body_Append'Length;
3218                            Executable := Executable_Name (Name_Find);
3219
3220                         elsif Name_Len > Spec_Append'Length
3221                           and then
3222                             Name_Buffer
3223                               (Name_Len - Spec_Append'Length + 1 .. Name_Len) =
3224                                                                    Spec_Append
3225                         then
3226                            --  We have found the spec termination. We remove
3227                            --  it, add the executable termination, if any.
3228
3229                            Name_Len := Name_Len - Spec_Append'Length;
3230                            Executable := Executable_Name (Name_Find);
3231
3232                         else
3233                            Executable :=
3234                              Executable_Name (Strip_Suffix (Main_Source_File));
3235                         end if;
3236
3237                      end;
3238                   end if;
3239                end if;
3240
3241                if Main_Project /= No_Project then
3242                   declare
3243                      Exec_File_Name : constant String :=
3244                        Get_Name_String (Executable);
3245
3246                   begin
3247                      if not Is_Absolute_Path (Exec_File_Name) then
3248                         for Index in Exec_File_Name'Range loop
3249                            if Exec_File_Name (Index) = Directory_Separator then
3250                               Fail ("relative executable (""" &
3251                                     Exec_File_Name &
3252                                     """) with directory part not allowed " &
3253                                     "when using project files");
3254                            end if;
3255                         end loop;
3256
3257                         Get_Name_String (Projects.Table
3258                                          (Main_Project).Exec_Directory);
3259
3260                         if
3261                           Name_Buffer (Name_Len) /= Directory_Separator
3262                         then
3263                            Name_Len := Name_Len + 1;
3264                            Name_Buffer (Name_Len) := Directory_Separator;
3265                         end if;
3266
3267                         Name_Buffer (Name_Len + 1 ..
3268                                      Name_Len + Exec_File_Name'Length) :=
3269                           Exec_File_Name;
3270                         Name_Len := Name_Len + Exec_File_Name'Length;
3271                         Executable := Name_Find;
3272                         Non_Std_Executable := True;
3273                      end if;
3274                   end;
3275
3276                end if;
3277
3278                --  Now we invoke Compile_Sources for the current main
3279
3280                Compile_Sources
3281                  (Main_Source           => Main_Source_File,
3282                   Args                  => Args,
3283                   First_Compiled_File   => First_Compiled_File,
3284                   Most_Recent_Obj_File  => Youngest_Obj_File,
3285                   Most_Recent_Obj_Stamp => Youngest_Obj_Stamp,
3286                   Main_Unit             => Is_Main_Unit,
3287                   Compilation_Failures  => Compilation_Failures,
3288                   Check_Readonly_Files  => Opt.Check_Readonly_Files,
3289                   Do_Not_Execute        => Opt.Do_Not_Execute,
3290                   Force_Compilations    => Opt.Force_Compilations,
3291                   In_Place_Mode         => Opt.In_Place_Mode,
3292                   Keep_Going            => Opt.Keep_Going,
3293                   Initialize_ALI_Data   => True,
3294                   Max_Process           => Saved_Maximum_Processes);
3295
3296                if Opt.Verbose_Mode then
3297                   Write_Str ("End of compilation");
3298                   Write_Eol;
3299                end if;
3300
3301                Total_Compilation_Failures :=
3302                  Total_Compilation_Failures + Compilation_Failures;
3303
3304                if Total_Compilation_Failures /= 0 then
3305                   if Opt.Keep_Going then
3306                      goto Next_Main;
3307
3308                   else
3309                      List_Bad_Compilations;
3310                      raise Compilation_Failed;
3311                   end if;
3312                end if;
3313
3314                --  Regenerate libraries, if any and if object files
3315                --  have been regenerated
3316
3317                if Main_Project /= No_Project
3318                  and then MLib.Tgt.Libraries_Are_Supported
3319                then
3320
3321                   for Proj in Projects.First .. Projects.Last loop
3322
3323                      if Proj /= Main_Project
3324                        and then Projects.Table (Proj).Flag1
3325                      then
3326                         MLib.Prj.Build_Library (For_Project => Proj);
3327                      end if;
3328
3329                   end loop;
3330
3331                end if;
3332
3333                if Opt.List_Dependencies then
3334                   if First_Compiled_File /= No_File then
3335                      Inform
3336                        (First_Compiled_File,
3337                         "must be recompiled. Can't generate dependence list.");
3338                   else
3339                      List_Depend;
3340                   end if;
3341
3342                elsif First_Compiled_File = No_File
3343                  and then not Do_Bind_Step
3344                  and then not Opt.Quiet_Output
3345                  and then Osint.Number_Of_Files = 1
3346                then
3347                   if Unique_Compile then
3348                      Inform (Msg => "object up to date.");
3349                   else
3350                      Inform (Msg => "objects up to date.");
3351                   end if;
3352
3353                elsif Opt.Do_Not_Execute
3354                  and then First_Compiled_File /= No_File
3355                then
3356                   Write_Name (First_Compiled_File);
3357                   Write_Eol;
3358                end if;
3359
3360                --  Stop after compile step if any of:
3361
3362                --    1) -n (Do_Not_Execute) specified
3363
3364                --    2) -M (List_Dependencies) specified (also sets
3365                --       Do_Not_Execute above, so this is probably superfluous).
3366
3367                --    3) -c (Compile_Only) specified, but not -b (Bind_Only)
3368
3369                --    4) Made unit cannot be a main unit
3370
3371                if (Opt.Do_Not_Execute
3372                    or Opt.List_Dependencies
3373                    or not Do_Bind_Step
3374                    or not Is_Main_Unit)
3375                  and then not No_Main_Subprogram
3376                then
3377                   if Osint.Number_Of_Files = 1 then
3378                      exit Multiple_Main_Loop;
3379
3380                   else
3381                      goto Next_Main;
3382                   end if;
3383                end if;
3384
3385                --  If the objects were up-to-date check if the executable file
3386                --  is also up-to-date. For now always bind and link on the JVM
3387                --  since there is currently no simple way to check the
3388                --  up-to-date status of objects
3389
3390                if not Hostparm.Java_VM
3391                  and then First_Compiled_File = No_File
3392                then
3393                   Executable_Stamp    := File_Stamp (Executable);
3394
3395                   --  Once Executable_Obsolete is set to True, it is never
3396                   --  reset to False, because it is too hard to accurately
3397                   --  decide if a subsequent main need to be rebuilt or not.
3398
3399                   Executable_Obsolete :=
3400                     Executable_Obsolete
3401                       or else Youngest_Obj_Stamp > Executable_Stamp;
3402
3403                   if not Executable_Obsolete then
3404
3405                      --  If no Ada object files obsolete the executable, check
3406                      --  for younger or missing linker files.
3407
3408                      Check_Linker_Options
3409                        (Executable_Stamp,
3410                         Youngest_Obj_File,
3411                         Youngest_Obj_Stamp);
3412
3413                      Executable_Obsolete := Youngest_Obj_File /= No_File;
3414                   end if;
3415
3416                   --  Return if the executable is up to date
3417                   --  and otherwise motivate the relink/rebind.
3418
3419                   if not Executable_Obsolete then
3420                      if not Opt.Quiet_Output then
3421                         Inform (Executable, "up to date.");
3422                      end if;
3423
3424                      if Osint.Number_Of_Files = 1 then
3425                         exit Multiple_Main_Loop;
3426
3427                      else
3428                         goto Next_Main;
3429                      end if;
3430                   end if;
3431
3432                   if Executable_Stamp (1) = ' ' then
3433                      Verbose_Msg (Executable, "missing.", Prefix => "  ");
3434
3435                   elsif Youngest_Obj_Stamp (1) = ' ' then
3436                      Verbose_Msg
3437                        (Youngest_Obj_File,
3438                         "missing.",
3439                         Prefix => "  ");
3440
3441                   elsif Youngest_Obj_Stamp > Executable_Stamp then
3442                      Verbose_Msg
3443                        (Youngest_Obj_File,
3444                         "(" & String (Youngest_Obj_Stamp) & ") newer than",
3445                         Executable,
3446                         "(" & String (Executable_Stamp) & ")");
3447
3448                   else
3449                      Verbose_Msg
3450                        (Executable, "needs to be rebuild.",
3451                         Prefix => "  ");
3452
3453                   end if;
3454                end if;
3455             end Recursive_Compilation_Step;
3456          end if;
3457
3458          --  If we are here, it means that we need to rebuilt the current
3459          --  main. So we set Executable_Obsolete to True to make sure that
3460          --  the subsequent mains will be rebuilt.
3461
3462          Executable_Obsolete := True;
3463
3464          Main_ALI_In_Place_Mode_Step :
3465          declare
3466             ALI_File : File_Name_Type;
3467             Src_File : File_Name_Type;
3468
3469          begin
3470             Src_File      := Strip_Directory (Main_Source_File);
3471             ALI_File      := Lib_File_Name (Src_File);
3472             Main_ALI_File := Full_Lib_File_Name (ALI_File);
3473
3474             --  When In_Place_Mode, the library file can be located in the
3475             --  Main_Source_File directory which may not be present in the
3476             --  library path. In this case, use the corresponding library file
3477             --  name.
3478
3479             if Main_ALI_File = No_File and then Opt.In_Place_Mode then
3480                Get_Name_String (Get_Directory (Full_Source_Name (Src_File)));
3481                Get_Name_String_And_Append (ALI_File);
3482                Main_ALI_File := Name_Find;
3483                Main_ALI_File := Full_Lib_File_Name (Main_ALI_File);
3484             end if;
3485
3486             if Main_ALI_File = No_File then
3487                Fail ("could not find the main ALI file");
3488             end if;
3489
3490          end Main_ALI_In_Place_Mode_Step;
3491
3492          if Do_Bind_Step then
3493             Bind_Step : declare
3494                Args : Argument_List
3495                         (Binder_Switches.First .. Binder_Switches.Last);
3496
3497             begin
3498                --  Get all the binder switches
3499
3500                for J in Binder_Switches.First .. Binder_Switches.Last loop
3501                   Args (J) := Binder_Switches.Table (J);
3502                end loop;
3503
3504                if Main_Project /= No_Project then
3505
3506                   --  Put all the source directories in ADA_INCLUDE_PATH,
3507                   --  and all the object directories in ADA_OBJECTS_PATH
3508
3509                   Set_Ada_Paths (Main_Project, False);
3510                end if;
3511
3512                Bind (Main_ALI_File, Args);
3513             end Bind_Step;
3514          end if;
3515
3516          if Do_Link_Step then
3517
3518             Link_Step : declare
3519                There_Are_Libraries  : Boolean := False;
3520                Linker_Switches_Last : constant Integer := Linker_Switches.Last;
3521
3522             begin
3523                if Main_Project /= No_Project then
3524
3525                   if MLib.Tgt.Libraries_Are_Supported then
3526                      Set_Libraries (Main_Project, There_Are_Libraries);
3527                   end if;
3528
3529                   if There_Are_Libraries then
3530
3531                      --  Add -L<lib_dir> -lgnarl -lgnat -Wl,-rpath,<lib_dir>
3532
3533                      Linker_Switches.Increment_Last;
3534                      Linker_Switches.Table (Linker_Switches.Last) :=
3535                        new String'("-L" & MLib.Utl.Lib_Directory);
3536                      Linker_Switches.Increment_Last;
3537                      Linker_Switches.Table (Linker_Switches.Last) :=
3538                        new String'("-lgnarl");
3539                      Linker_Switches.Increment_Last;
3540                      Linker_Switches.Table (Linker_Switches.Last) :=
3541                        new String'("-lgnat");
3542
3543                      declare
3544                         Option : constant String_Access :=
3545                                    MLib.Tgt.Linker_Library_Path_Option
3546                                      (MLib.Utl.Lib_Directory);
3547
3548                      begin
3549                         if Option /= null then
3550                            Linker_Switches.Increment_Last;
3551                            Linker_Switches.Table (Linker_Switches.Last) :=
3552                              Option;
3553                         end if;
3554                      end;
3555                   end if;
3556
3557                   --  Put the object directories in ADA_OBJECTS_PATH
3558
3559                   Set_Ada_Paths (Main_Project, False);
3560                end if;
3561
3562                declare
3563                   Args : Argument_List
3564                            (Linker_Switches.First .. Linker_Switches.Last + 2);
3565
3566                   Last_Arg : Integer := Linker_Switches.First - 1;
3567                   Skip     : Boolean := False;
3568
3569                begin
3570                   --  Get all the linker switches
3571
3572                   for J in Linker_Switches.First .. Linker_Switches.Last loop
3573                      if Skip then
3574                         Skip := False;
3575
3576                      elsif Non_Std_Executable
3577                        and then Linker_Switches.Table (J).all = "-o"
3578                      then
3579                         Skip := True;
3580
3581                      else
3582                         Last_Arg := Last_Arg + 1;
3583                         Args (Last_Arg) := Linker_Switches.Table (J);
3584                      end if;
3585
3586                   end loop;
3587
3588                   --  And invoke the linker
3589
3590                   if Non_Std_Executable then
3591                      Last_Arg := Last_Arg + 1;
3592                      Args (Last_Arg) := new String'("-o");
3593                      Last_Arg := Last_Arg + 1;
3594                      Args (Last_Arg) :=
3595                        new String'(Get_Name_String (Executable));
3596                      Link (Main_ALI_File, Args (Args'First .. Last_Arg));
3597
3598                   else
3599                      Link
3600                        (Main_ALI_File,
3601                         Args (Args'First .. Last_Arg));
3602                   end if;
3603
3604                end;
3605
3606                Linker_Switches.Set_Last (Linker_Switches_Last);
3607             end Link_Step;
3608          end if;
3609
3610          --  We go to here when we skip the bind and link steps.
3611
3612          <<Next_Main>>
3613
3614          --  We go to the next main, if we did not process the last one
3615
3616          if N_File < Osint.Number_Of_Files then
3617             Main_Source_File := Next_Main_Source;
3618
3619             if Main_Project /= No_Project then
3620
3621                --  Find the file name of the main unit
3622
3623                declare
3624                   Main_Source_File_Name : constant String :=
3625                                             Get_Name_String (Main_Source_File);
3626
3627                   Main_Unit_File_Name : constant String :=
3628                                           Prj.Env.
3629                                             File_Name_Of_Library_Unit_Body
3630                                               (Name => Main_Source_File_Name,
3631                                                Project => Main_Project);
3632
3633                begin
3634                   --  We fail if we cannot find the main source file
3635                   --  as an immediate source of the main project file.
3636
3637                   if Main_Unit_File_Name = "" then
3638                      Fail ('"' & Main_Source_File_Name  &
3639                            """ is not a unit of project " &
3640                            Project_File_Name.all & ".");
3641
3642                   else
3643                      --  Remove any directory information from the main
3644                      --  source file name.
3645
3646                      declare
3647                         Pos : Natural := Main_Unit_File_Name'Last;
3648
3649                      begin
3650                         loop
3651                            exit when Pos < Main_Unit_File_Name'First
3652                              or else
3653                              Main_Unit_File_Name (Pos) = Directory_Separator;
3654                            Pos := Pos - 1;
3655                         end loop;
3656
3657                         Name_Len := Main_Unit_File_Name'Last - Pos;
3658
3659                         Name_Buffer (1 .. Name_Len) :=
3660                           Main_Unit_File_Name
3661                           (Pos + 1 .. Main_Unit_File_Name'Last);
3662
3663                         Main_Source_File := Name_Find;
3664                      end;
3665                   end if;
3666                end;
3667             end if;
3668          end if;
3669       end loop Multiple_Main_Loop;
3670
3671       if Total_Compilation_Failures /= 0 then
3672          List_Bad_Compilations;
3673          raise Compilation_Failed;
3674       end if;
3675
3676       --  Delete the temporary mapping file that was created if we are
3677       --  using project files.
3678
3679       Delete_Mapping_Files;
3680
3681       Exit_Program (E_Success);
3682
3683    exception
3684       when Bind_Failed =>
3685          Delete_Mapping_Files;
3686          Osint.Fail ("*** bind failed.");
3687
3688       when Compilation_Failed =>
3689          Delete_Mapping_Files;
3690          Exit_Program (E_Fatal);
3691
3692       when Link_Failed =>
3693          Delete_Mapping_Files;
3694          Osint.Fail ("*** link failed.");
3695
3696       when X : others =>
3697          Delete_Mapping_Files;
3698          Write_Line (Exception_Information (X));
3699          Osint.Fail ("INTERNAL ERROR. Please report.");
3700
3701    end Gnatmake;
3702
3703    --------------------
3704    -- In_Ada_Lib_Dir --
3705    --------------------
3706
3707    function In_Ada_Lib_Dir (File : File_Name_Type) return Boolean is
3708       D : constant Name_Id := Get_Directory (File);
3709       B : constant Byte    := Get_Name_Table_Byte (D);
3710
3711    begin
3712       return (B and Ada_Lib_Dir) /= 0;
3713    end In_Ada_Lib_Dir;
3714
3715    ------------
3716    -- Inform --
3717    ------------
3718
3719    procedure Inform (N : Name_Id := No_Name; Msg : String) is
3720    begin
3721       Osint.Write_Program_Name;
3722
3723       Write_Str (": ");
3724
3725       if N /= No_Name then
3726          Write_Str ("""");
3727          Write_Name (N);
3728          Write_Str (""" ");
3729       end if;
3730
3731       Write_Str (Msg);
3732       Write_Eol;
3733    end Inform;
3734
3735    -----------------------
3736    -- Init_Mapping_File --
3737    -----------------------
3738
3739    procedure Init_Mapping_File (File_Name : in out Temp_File_Name) is
3740       FD : File_Descriptor;
3741    begin
3742       if Main_Project /= No_Project then
3743          Prj.Env.Create_Mapping_File (File_Name);
3744
3745       else
3746          Create_Temp_File (FD, File_Name);
3747
3748          if FD = Invalid_FD then
3749             Fail ("disk full");
3750          end if;
3751
3752          Close (FD);
3753       end if;
3754    end Init_Mapping_File;
3755
3756    ------------
3757    -- Init_Q --
3758    ------------
3759
3760    procedure Init_Q is
3761    begin
3762       First_Q_Initialization := False;
3763       Q_Front := Q.First;
3764       Q.Set_Last (Q.First);
3765    end Init_Q;
3766
3767    ----------------
3768    -- Initialize --
3769    ----------------
3770
3771    procedure Initialize is
3772       Next_Arg : Positive;
3773
3774    begin
3775       --  Override default initialization of Check_Object_Consistency
3776       --  since this is normally False for GNATBIND, but is True for
3777       --  GNATMAKE since we do not need to check source consistency
3778       --  again once GNATMAKE has looked at the sources to check.
3779
3780       Opt.Check_Object_Consistency := True;
3781
3782       --  Package initializations. The order of calls is important here.
3783
3784       Output.Set_Standard_Error;
3785
3786       Gcc_Switches.Init;
3787       Binder_Switches.Init;
3788       Linker_Switches.Init;
3789
3790       Csets.Initialize;
3791       Namet.Initialize;
3792
3793       Snames.Initialize;
3794
3795       Prj.Initialize;
3796
3797       Next_Arg := 1;
3798       Scan_Args : while Next_Arg <= Argument_Count loop
3799          Scan_Make_Arg (Argument (Next_Arg), And_Save => True);
3800          Next_Arg := Next_Arg + 1;
3801       end loop Scan_Args;
3802
3803       if Usage_Requested then
3804          Makeusg;
3805       end if;
3806
3807       --  Test for trailing -o switch
3808
3809       if Opt.Output_File_Name_Present
3810         and then not Output_File_Name_Seen
3811       then
3812          Fail ("output file name missing after -o");
3813       end if;
3814
3815       if Project_File_Name /= null then
3816
3817          --  A project file was specified by a -P switch
3818
3819          if Opt.Verbose_Mode then
3820             Write_Eol;
3821             Write_Str ("Parsing Project File """);
3822             Write_Str (Project_File_Name.all);
3823             Write_Str (""".");
3824             Write_Eol;
3825          end if;
3826
3827          --  Avoid looking in the current directory for ALI files
3828
3829          --  Opt.Look_In_Primary_Dir := False;
3830
3831          --  Set the project parsing verbosity to whatever was specified
3832          --  by a possible -vP switch.
3833
3834          Prj.Pars.Set_Verbosity (To => Current_Verbosity);
3835
3836          --  Parse the project file.
3837          --  If there is an error, Main_Project will still be No_Project.
3838
3839          Prj.Pars.Parse
3840            (Project           => Main_Project,
3841             Project_File_Name => Project_File_Name.all);
3842
3843          if Main_Project = No_Project then
3844             Fail ("""" & Project_File_Name.all &
3845                   """ processing failed");
3846          end if;
3847
3848          if Opt.Verbose_Mode then
3849             Write_Eol;
3850             Write_Str ("Parsing of Project File """);
3851             Write_Str (Project_File_Name.all);
3852             Write_Str (""" is finished.");
3853             Write_Eol;
3854          end if;
3855
3856          --  We add the source directories and the object directories
3857          --  to the search paths.
3858
3859          Add_Source_Directories (Main_Project);
3860          Add_Object_Directories (Main_Project);
3861
3862       end if;
3863
3864       Osint.Add_Default_Search_Dirs;
3865
3866       --  Mark the GNAT libraries if needed.
3867
3868       --  Source file lookups should be cached for efficiency.
3869       --  Source files are not supposed to change.
3870
3871       Osint.Source_File_Data (Cache => True);
3872
3873       --  Read gnat.adc file to initialize Fname.UF
3874
3875       Fname.UF.Initialize;
3876
3877       begin
3878          Fname.SF.Read_Source_File_Name_Pragmas;
3879
3880       exception
3881          when Err : SFN_Scan.Syntax_Error_In_GNAT_ADC =>
3882             Osint.Fail (Exception_Message (Err));
3883       end;
3884    end Initialize;
3885
3886    -----------------------------------
3887    -- Insert_Project_Sources_Into_Q --
3888    -----------------------------------
3889
3890    procedure Insert_Project_Sources
3891      (The_Project : Project_Id;
3892       Into_Q      : Boolean)
3893    is
3894       Unit  : Com.Unit_Data;
3895       Sfile : Name_Id;
3896
3897    begin
3898       --  For all the sources in the project files,
3899
3900       for Id in Com.Units.First .. Com.Units.Last loop
3901          Unit  := Com.Units.Table (Id);
3902          Sfile := No_Name;
3903
3904          --  If there is a source for the body,
3905
3906          if Unit.File_Names (Com.Body_Part).Name /= No_Name then
3907
3908             --  And it is a source of the specified project
3909
3910             if Unit.File_Names (Com.Body_Part).Project = The_Project then
3911
3912                --  If we don't have a spec, we cannot consider the source
3913                --  if it is a subunit
3914
3915                if Unit.File_Names (Com.Specification).Name = No_Name then
3916                   declare
3917                      Src_Ind : Source_File_Index;
3918
3919                   begin
3920                      Src_Ind := Sinput.L.Load_Source_File
3921                                   (Unit.File_Names (Com.Body_Part).Name);
3922
3923                      --  If it is a subunit, discard it
3924
3925                      if Sinput.L.Source_File_Is_Subunit (Src_Ind) then
3926                         Sfile := No_Name;
3927
3928                      else
3929                         Sfile := Unit.File_Names (Com.Body_Part).Name;
3930                      end if;
3931                   end;
3932
3933                else
3934                   Sfile := Unit.File_Names (Com.Body_Part).Name;
3935                end if;
3936             end if;
3937
3938          elsif Unit.File_Names (Com.Specification).Name /= No_Name
3939            and then Unit.File_Names (Com.Specification).Project = The_Project
3940          then
3941             --  If there is no source for the body, but there is a source
3942             --  for the spec, then we take this one.
3943
3944             Sfile := Unit.File_Names (Com.Specification).Name;
3945          end if;
3946
3947          --  If Into_Q is True, we insert into the Q
3948
3949          if Into_Q then
3950
3951             --  For the first source inserted into the Q, we need
3952             --  to initialize the Q, but not for the subsequent sources.
3953
3954             if First_Q_Initialization then
3955                Init_Q;
3956             end if;
3957
3958             --  And of course, we only insert in the Q if the source
3959             --  is not marked.
3960
3961             if Sfile /= No_Name and then not Is_Marked (Sfile) then
3962                Insert_Q (Sfile);
3963                Mark (Sfile);
3964             end if;
3965
3966          elsif Sfile /= No_Name then
3967
3968             --  If Into_Q is False, we add the source as it it were
3969             --  specified on the command line.
3970
3971             Osint.Add_File (Get_Name_String (Sfile));
3972          end if;
3973       end loop;
3974    end Insert_Project_Sources;
3975
3976    --------------
3977    -- Insert_Q --
3978    --------------
3979
3980    procedure Insert_Q
3981      (Source_File : File_Name_Type;
3982       Source_Unit : Unit_Name_Type := No_Name)
3983    is
3984    begin
3985       if Debug.Debug_Flag_Q then
3986          Write_Str ("   Q := Q + [ ");
3987          Write_Name (Source_File);
3988          Write_Str (" ] ");
3989          Write_Eol;
3990       end if;
3991
3992       Q.Table (Q.Last).File := Source_File;
3993       Q.Table (Q.Last).Unit := Source_Unit;
3994       Q.Increment_Last;
3995    end Insert_Q;
3996
3997    ----------------------------
3998    -- Is_External_Assignment --
3999    ----------------------------
4000
4001    function Is_External_Assignment (Argv : String) return Boolean is
4002       Start     : Positive := 3;
4003       Finish    : Natural := Argv'Last;
4004       Equal_Pos : Natural;
4005
4006    begin
4007       if Argv'Last < 5 then
4008          return False;
4009
4010       elsif Argv (3) = '"' then
4011          if Argv (Argv'Last) /= '"' or else Argv'Last < 7 then
4012             return False;
4013          else
4014             Start := 4;
4015             Finish := Argv'Last - 1;
4016          end if;
4017       end if;
4018
4019       Equal_Pos := Start;
4020
4021       while Equal_Pos <= Finish and then Argv (Equal_Pos) /= '=' loop
4022          Equal_Pos := Equal_Pos + 1;
4023       end loop;
4024
4025       if Equal_Pos = Start
4026         or else Equal_Pos >= Finish
4027       then
4028          return False;
4029
4030       else
4031          Prj.Ext.Add
4032            (External_Name => Argv (Start .. Equal_Pos - 1),
4033             Value         => Argv (Equal_Pos + 1 .. Finish));
4034          return True;
4035       end if;
4036    end Is_External_Assignment;
4037
4038    ---------------
4039    -- Is_Marked --
4040    ---------------
4041
4042    function Is_Marked (Source_File : File_Name_Type) return Boolean is
4043    begin
4044       return Get_Name_Table_Byte (Source_File) /= 0;
4045    end Is_Marked;
4046
4047    ----------
4048    -- Link --
4049    ----------
4050
4051    procedure Link (ALI_File : File_Name_Type; Args : Argument_List) is
4052       Link_Args : Argument_List (Args'First .. Args'Last + 1);
4053       Success   : Boolean;
4054
4055    begin
4056       Link_Args (Args'Range) :=  Args;
4057
4058       Get_Name_String (ALI_File);
4059       Link_Args (Args'Last + 1) := new String'(Name_Buffer (1 .. Name_Len));
4060
4061       GNAT.OS_Lib.Normalize_Arguments (Link_Args);
4062
4063       Display (Gnatlink.all, Link_Args);
4064
4065       if Gnatlink_Path = null then
4066          Osint.Fail ("error, unable to locate " & Gnatlink.all);
4067       end if;
4068
4069       GNAT.OS_Lib.Spawn (Gnatlink_Path.all, Link_Args, Success);
4070
4071       if not Success then
4072          raise Link_Failed;
4073       end if;
4074    end Link;
4075
4076    ---------------------------
4077    -- List_Bad_Compilations --
4078    ---------------------------
4079
4080    procedure List_Bad_Compilations is
4081    begin
4082       for J in Bad_Compilation.First .. Bad_Compilation.Last loop
4083          if Bad_Compilation.Table (J).File = No_File then
4084             null;
4085          elsif not Bad_Compilation.Table (J).Found then
4086             Inform (Bad_Compilation.Table (J).File, "not found");
4087          else
4088             Inform (Bad_Compilation.Table (J).File, "compilation error");
4089          end if;
4090       end loop;
4091    end List_Bad_Compilations;
4092
4093    -----------------
4094    -- List_Depend --
4095    -----------------
4096
4097    procedure List_Depend is
4098       Lib_Name  : Name_Id;
4099       Obj_Name  : Name_Id;
4100       Src_Name  : Name_Id;
4101
4102       Len       : Natural;
4103       Line_Pos  : Natural;
4104       Line_Size : constant := 77;
4105
4106    begin
4107       Set_Standard_Output;
4108
4109       for A in ALIs.First .. ALIs.Last loop
4110          Lib_Name := ALIs.Table (A).Afile;
4111
4112          --  We have to provide the full library file name in In_Place_Mode
4113
4114          if Opt.In_Place_Mode then
4115             Lib_Name := Full_Lib_File_Name (Lib_Name);
4116          end if;
4117
4118          Obj_Name := Object_File_Name (Lib_Name);
4119          Write_Name (Obj_Name);
4120          Write_Str (" :");
4121
4122          Get_Name_String (Obj_Name);
4123          Len := Name_Len;
4124          Line_Pos := Len + 2;
4125
4126          for D in ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep loop
4127             Src_Name := Sdep.Table (D).Sfile;
4128
4129             if Is_Internal_File_Name (Src_Name)
4130               and then not Check_Readonly_Files
4131             then
4132                null;
4133             else
4134                if not Opt.Quiet_Output then
4135                   Src_Name := Full_Source_Name (Src_Name);
4136                end if;
4137
4138                Get_Name_String (Src_Name);
4139                Len := Name_Len;
4140
4141                if Line_Pos + Len + 1 > Line_Size then
4142                   Write_Str (" \");
4143                   Write_Eol;
4144                   Line_Pos := 0;
4145                end if;
4146
4147                Line_Pos := Line_Pos + Len + 1;
4148
4149                Write_Str (" ");
4150                Write_Name (Src_Name);
4151             end if;
4152          end loop;
4153
4154          Write_Eol;
4155       end loop;
4156
4157       Set_Standard_Error;
4158    end List_Depend;
4159
4160    ----------
4161    -- Mark --
4162    ----------
4163
4164    procedure Mark (Source_File : File_Name_Type) is
4165    begin
4166       Set_Name_Table_Byte (Source_File, 1);
4167    end Mark;
4168
4169    --------------------
4170    -- Mark_Directory --
4171    --------------------
4172
4173    procedure Mark_Directory
4174      (Dir  : String;
4175       Mark : Lib_Mark_Type)
4176    is
4177       N : Name_Id;
4178       B : Byte;
4179
4180    begin
4181       --  Dir last character is supposed to be a directory separator.
4182
4183       Name_Len := Dir'Length;
4184       Name_Buffer (1 .. Name_Len) := Dir;
4185
4186       if not Is_Directory_Separator (Name_Buffer (Name_Len)) then
4187          Name_Len := Name_Len + 1;
4188          Name_Buffer (Name_Len) := Directory_Separator;
4189       end if;
4190
4191       --  Add flags to the already existing flags
4192
4193       N := Name_Find;
4194       B := Get_Name_Table_Byte (N);
4195       Set_Name_Table_Byte (N, B or Mark);
4196    end Mark_Directory;
4197
4198    ----------------------
4199    -- Object_File_Name --
4200    ----------------------
4201
4202    function Object_File_Name (Source : String) return String is
4203    begin
4204       --  If the source name has an extension, then replace it with
4205       --  the object suffix.
4206
4207       for Index in reverse Source'First + 1 .. Source'Last loop
4208          if Source (Index) = '.' then
4209             return Source (Source'First .. Index - 1) & Object_Suffix;
4210          end if;
4211       end loop;
4212
4213       --  If there is no dot, or if it is the first character, just add the
4214       --  object suffix.
4215
4216       return Source & Object_Suffix;
4217    end Object_File_Name;
4218
4219    -------------------
4220    -- Scan_Make_Arg --
4221    -------------------
4222
4223    procedure Scan_Make_Arg (Argv : String; And_Save : Boolean) is
4224    begin
4225       pragma Assert (Argv'First = 1);
4226
4227       if Argv'Length = 0 then
4228          return;
4229       end if;
4230
4231       --  If the previous switch has set the Output_File_Name_Present
4232       --  flag (that is we have seen a -o), then the next argument is
4233       --  the name of the output executable.
4234
4235       if Opt.Output_File_Name_Present and then not Output_File_Name_Seen then
4236          Output_File_Name_Seen := True;
4237
4238          if Argv (1) = '-' then
4239             Fail ("output file name missing after -o");
4240
4241          else
4242             Add_Switch ("-o", Linker, And_Save => And_Save);
4243
4244             --  Automatically add the executable suffix if it has not been
4245             --  specified explicitly.
4246
4247             if Executable_Suffix'Length /= 0
4248               and then Argv (Argv'Last - Executable_Suffix'Length + 1
4249                              .. Argv'Last) /= Executable_Suffix
4250             then
4251                Add_Switch
4252                  (Argv & Executable_Suffix,
4253                   Linker,
4254                   And_Save => And_Save);
4255             else
4256                Add_Switch (Argv, Linker, And_Save => And_Save);
4257             end if;
4258          end if;
4259
4260       --  Then check if we are dealing with -cargs/-bargs/-largs
4261
4262       elsif Argv = "-bargs"
4263               or else
4264             Argv = "-cargs"
4265               or else
4266             Argv = "-largs"
4267               or else
4268             Argv = "-margs"
4269       then
4270          case Argv (2) is
4271             when 'c' => Program_Args := Compiler;
4272             when 'b' => Program_Args := Binder;
4273             when 'l' => Program_Args := Linker;
4274             when 'm' => Program_Args := None;
4275
4276             when others =>
4277                raise Program_Error;
4278          end case;
4279
4280       --  A special test is needed for the -o switch within a -largs
4281       --  since that is another way to specify the name of the final
4282       --  executable.
4283
4284       elsif Program_Args = Linker
4285         and then Argv = "-o"
4286       then
4287          Fail ("switch -o not allowed within a -largs. Use -o directly.");
4288
4289       --  Check to see if we are reading switches after a -cargs,
4290       --  -bargs or -largs switch. If yes save it.
4291
4292       elsif Program_Args /= None then
4293
4294          --  Check to see if we are reading -I switches in order
4295          --  to take into account in the src & lib search directories.
4296
4297          if Argv'Length > 2 and then Argv (1 .. 2) = "-I" then
4298             if Argv (3 .. Argv'Last) = "-" then
4299                Opt.Look_In_Primary_Dir := False;
4300
4301             elsif Program_Args = Compiler then
4302                if Argv (3 .. Argv'Last) /= "-" then
4303                   Add_Src_Search_Dir (Argv (3 .. Argv'Last));
4304
4305                end if;
4306
4307             elsif Program_Args = Binder then
4308                Add_Lib_Search_Dir (Argv (3 .. Argv'Last));
4309
4310             end if;
4311          end if;
4312
4313          Add_Switch (Argv, Program_Args, And_Save => And_Save);
4314
4315       --  Handle non-default compiler, binder, linker, and handle --RTS switch
4316
4317       elsif Argv'Length > 2 and then Argv (1 .. 2) = "--" then
4318          if Argv'Length > 6
4319            and then Argv (1 .. 6) = "--GCC="
4320          then
4321             declare
4322                Program_Args : Argument_List_Access :=
4323                                 Argument_String_To_List
4324                                   (Argv (7 .. Argv'Last));
4325
4326             begin
4327                if And_Save then
4328                   Saved_Gcc := new String'(Program_Args.all (1).all);
4329                else
4330                   Gcc := new String'(Program_Args.all (1).all);
4331                end if;
4332
4333                for J in 2 .. Program_Args.all'Last loop
4334                   Add_Switch
4335                     (Program_Args.all (J).all,
4336                      Compiler,
4337                      And_Save => And_Save);
4338                end loop;
4339             end;
4340
4341          elsif Argv'Length > 11
4342            and then Argv (1 .. 11) = "--GNATBIND="
4343          then
4344             declare
4345                Program_Args : Argument_List_Access :=
4346                                 Argument_String_To_List
4347                                   (Argv (12 .. Argv'Last));
4348
4349             begin
4350                if And_Save then
4351                   Saved_Gnatbind := new String'(Program_Args.all (1).all);
4352                else
4353                   Gnatbind := new String'(Program_Args.all (1).all);
4354                end if;
4355
4356                for J in 2 .. Program_Args.all'Last loop
4357                   Add_Switch
4358                     (Program_Args.all (J).all, Binder, And_Save => And_Save);
4359                end loop;
4360             end;
4361
4362          elsif Argv'Length > 11
4363            and then Argv (1 .. 11) = "--GNATLINK="
4364          then
4365             declare
4366                Program_Args : Argument_List_Access :=
4367                                 Argument_String_To_List
4368                                   (Argv (12 .. Argv'Last));
4369             begin
4370                if And_Save then
4371                   Saved_Gnatlink := new String'(Program_Args.all (1).all);
4372                else
4373                   Gnatlink := new String'(Program_Args.all (1).all);
4374                end if;
4375
4376                for J in 2 .. Program_Args.all'Last loop
4377                   Add_Switch (Program_Args.all (J).all, Linker);
4378                end loop;
4379             end;
4380
4381          elsif Argv'Length >= 5 and then
4382            Argv (1 .. 5) = "--RTS"
4383          then
4384             Add_Switch (Argv, Compiler, And_Save => And_Save);
4385             Add_Switch (Argv, Binder, And_Save => And_Save);
4386
4387             if Argv'Length <= 6 or else Argv (6) /= '=' then
4388                Osint.Fail ("missing path for --RTS");
4389
4390             else
4391                --  Valid --RTS switch
4392
4393                Opt.No_Stdinc := True;
4394                Opt.No_Stdlib := True;
4395                Opt.RTS_Switch := True;
4396
4397                declare
4398                   Src_Path_Name : String_Ptr :=
4399                                     Get_RTS_Search_Dir
4400                                       (Argv (7 .. Argv'Last), Include);
4401                   Lib_Path_Name : String_Ptr :=
4402                                     Get_RTS_Search_Dir
4403                                       (Argv (7 .. Argv'Last), Objects);
4404
4405                begin
4406                   if Src_Path_Name /= null and then
4407                     Lib_Path_Name /= null
4408                   then
4409                      Add_Search_Dirs (Src_Path_Name, Include);
4410                      Add_Search_Dirs (Lib_Path_Name, Objects);
4411
4412                   elsif  Src_Path_Name = null
4413                     and Lib_Path_Name = null then
4414                      Osint.Fail ("RTS path not valid: missing " &
4415                                  "adainclude and adalib directories");
4416
4417                   elsif Src_Path_Name = null then
4418                      Osint.Fail ("RTS path not valid: missing " &
4419                                  "adainclude directory");
4420
4421                   elsif  Lib_Path_Name = null then
4422                      Osint.Fail ("RTS path not valid: missing " &
4423                                  "adalib directory");
4424                   end if;
4425                end;
4426             end if;
4427
4428          else
4429             Fail ("unknown switch: ", Argv);
4430          end if;
4431
4432       --  If we have seen a regular switch process it
4433
4434       elsif Argv (1) = '-' then
4435
4436          if Argv'Length = 1 then
4437             Fail ("switch character cannot be followed by a blank");
4438
4439          --  -I-
4440
4441          elsif Argv (2 .. Argv'Last) = "I-" then
4442             Opt.Look_In_Primary_Dir := False;
4443
4444          --  Forbid  -?-  or  -??-  where ? is any character
4445
4446          elsif (Argv'Length = 3 and then Argv (3) = '-')
4447            or else (Argv'Length = 4 and then Argv (4) = '-')
4448          then
4449             Fail ("trailing ""-"" at the end of ", Argv, " forbidden.");
4450
4451          --  -Idir
4452
4453          elsif Argv (2) = 'I' then
4454             Add_Src_Search_Dir (Argv (3 .. Argv'Last));
4455             Add_Lib_Search_Dir (Argv (3 .. Argv'Last));
4456             Add_Switch (Argv, Compiler, And_Save => And_Save);
4457             Add_Switch ("-aO" & Argv (3 .. Argv'Last),
4458                         Binder,
4459                         And_Save => And_Save);
4460
4461             --  No need to pass any source dir to the binder
4462             --  since gnatmake call it with the -x flag
4463             --  (ie do not check source time stamp)
4464
4465          --  -aIdir (to gcc this is like a -I switch)
4466
4467          elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aI" then
4468             Add_Src_Search_Dir (Argv (4 .. Argv'Last));
4469             Add_Switch ("-I" & Argv (4 .. Argv'Last),
4470                         Compiler,
4471                         And_Save => And_Save);
4472
4473          --  -aOdir
4474
4475          elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aO" then
4476             Add_Lib_Search_Dir (Argv (4 .. Argv'Last));
4477             Add_Switch (Argv, Binder, And_Save => And_Save);
4478
4479          --  -aLdir (to gnatbind this is like a -aO switch)
4480
4481          elsif Argv'Length >= 3 and then Argv (2 .. 3) = "aL" then
4482             Mark_Directory (Argv (4 .. Argv'Last), Ada_Lib_Dir);
4483             Add_Lib_Search_Dir (Argv (4 .. Argv'Last));
4484             Add_Switch ("-aO" & Argv (4 .. Argv'Last),
4485                         Binder,
4486                         And_Save => And_Save);
4487
4488          --  -Adir (to gnatbind this is like a -aO switch, to gcc like a -I)
4489
4490          elsif Argv (2) = 'A' then
4491             Mark_Directory (Argv (3 .. Argv'Last), Ada_Lib_Dir);
4492             Add_Src_Search_Dir (Argv (3 .. Argv'Last));
4493             Add_Lib_Search_Dir (Argv (3 .. Argv'Last));
4494             Add_Switch ("-I"  & Argv (3 .. Argv'Last),
4495                         Compiler,
4496                         And_Save => And_Save);
4497             Add_Switch ("-aO" & Argv (3 .. Argv'Last),
4498                         Binder,
4499                         And_Save => And_Save);
4500
4501          --  -Ldir
4502
4503          elsif Argv (2) = 'L' then
4504             Add_Switch (Argv, Linker, And_Save => And_Save);
4505
4506          --  For -gxxxxx,-pg : give the switch to both the compiler and the
4507          --  linker (except for -gnatxxx which is only for the compiler)
4508
4509          elsif
4510            (Argv (2) = 'g' and then (Argv'Last < 5
4511                                        or else Argv (2 .. 5) /= "gnat"))
4512              or else Argv (2 .. Argv'Last) = "pg"
4513          then
4514             Add_Switch (Argv, Compiler, And_Save => And_Save);
4515             Add_Switch (Argv, Linker, And_Save => And_Save);
4516
4517          --  -d
4518
4519          elsif Argv (2) = 'd'
4520            and then Argv'Last = 2
4521          then
4522             Opt.Display_Compilation_Progress := True;
4523
4524          --  -j (need to save the result)
4525
4526          elsif Argv (2) = 'j' then
4527             Scan_Make_Switches (Argv);
4528
4529             if And_Save then
4530                Saved_Maximum_Processes := Maximum_Processes;
4531             end if;
4532
4533          --  -m
4534
4535          elsif Argv (2) = 'm'
4536            and then Argv'Last = 2
4537          then
4538             Opt.Minimal_Recompilation := True;
4539
4540          --  -u
4541
4542          elsif Argv (2) = 'u'
4543            and then Argv'Last = 2
4544          then
4545             Unique_Compile   := True;
4546             Opt.Compile_Only := True;
4547             Do_Bind_Step     := False;
4548             Do_Link_Step     := False;
4549
4550          --  -Pprj (only once, and only on the command line)
4551
4552          elsif Argv'Last > 2
4553            and then Argv (2) = 'P'
4554          then
4555             if Project_File_Name /= null then
4556                Fail ("cannot have several project files specified");
4557
4558             elsif not And_Save then
4559
4560                --  It could be a tool other than gnatmake (i.e, gnatdist)
4561                --  or a -P switch inside a project file.
4562
4563                Fail
4564                  ("either the tool is not ""project-aware"" or " &
4565                   "a project file is specified inside a project file");
4566
4567             else
4568                Project_File_Name := new String' (Argv (3 .. Argv'Last));
4569             end if;
4570
4571          --  -S (Assemble)
4572
4573          --  Since no object file is created, don't check object
4574          --  consistency.
4575
4576          elsif Argv (2) = 'S'
4577            and then Argv'Last = 2
4578          then
4579             Opt.Check_Object_Consistency := False;
4580             Add_Switch (Argv, Compiler, And_Save => And_Save);
4581
4582          --  -vPx  (verbosity of the parsing of the project files)
4583
4584          elsif Argv'Last = 4
4585            and then Argv (2 .. 3) = "vP"
4586            and then Argv (4) in '0' .. '2'
4587          then
4588             if And_Save then
4589                case Argv (4) is
4590                   when '0' =>
4591                      Current_Verbosity := Prj.Default;
4592                   when '1' =>
4593                      Current_Verbosity := Prj.Medium;
4594                   when '2' =>
4595                      Current_Verbosity := Prj.High;
4596                   when others =>
4597                      null;
4598                end case;
4599             end if;
4600
4601          --  -Wx (need to save the result)
4602
4603          elsif Argv (2) = 'W' then
4604             Scan_Make_Switches (Argv);
4605
4606             if And_Save then
4607                Saved_WC_Encoding_Method := Wide_Character_Encoding_Method;
4608                Saved_WC_Encoding_Method_Set := True;
4609             end if;
4610
4611          --  -Xext=val  (External assignment)
4612
4613          elsif Argv (2) = 'X'
4614            and then Is_External_Assignment (Argv)
4615          then
4616             --  Is_External_Assignment has side effects
4617             --  when it returns True;
4618
4619             null;
4620
4621          --  If -gnath is present, then generate the usage information
4622          --  right now and do not pass this option on to the compiler calls.
4623
4624          elsif Argv = "-gnath" then
4625             Usage;
4626
4627          --  If -gnatc is specified, make sure the bind step and the link
4628          --  step are not executed.
4629
4630          elsif Argv'Length >= 6 and then Argv (2 .. 6) = "gnatc" then
4631
4632             --  If -gnatc is specified, make sure the bind step and the link
4633             --  step are not executed.
4634
4635             Add_Switch (Argv, Compiler, And_Save => And_Save);
4636             Opt.Operating_Mode := Opt.Check_Semantics;
4637             Opt.Check_Object_Consistency := False;
4638             Opt.Compile_Only             := True;
4639             Do_Bind_Step                 := False;
4640             Do_Link_Step                 := False;
4641
4642          elsif Argv (2 .. Argv'Last) = "nostdlib" then
4643
4644             --  Don't pass -nostdlib to gnatlink, it will disable
4645             --  linking with all standard library files.
4646
4647             Opt.No_Stdlib := True;
4648             Add_Switch (Argv, Binder, And_Save => And_Save);
4649
4650          elsif Argv (2 .. Argv'Last) = "nostdinc" then
4651
4652             --  Pass -nostdinv to the Compiler and to gnatbind
4653
4654             Opt.No_Stdinc := True;
4655             Add_Switch (Argv, Compiler, And_Save => And_Save);
4656             Add_Switch (Argv, Binder, And_Save => And_Save);
4657
4658             --  By default all switches with more than one character
4659             --  or one character switches which are not in 'a' .. 'z'
4660             --  (except 'C' and 'M') are passed to the compiler, unless we are
4661             --  dealing with a debug switch (starts with 'd')
4662
4663          elsif Argv (2) /= 'd'
4664            and then Argv (2 .. Argv'Last) /= "M"
4665            and then Argv (2 .. Argv'Last) /= "C"
4666            and then (Argv'Length > 2 or else Argv (2) not in 'a' .. 'z')
4667          then
4668             Add_Switch (Argv, Compiler, And_Save => And_Save);
4669
4670          --  All other options are handled by Scan_Make_Switches
4671
4672          else
4673             Scan_Make_Switches (Argv);
4674          end if;
4675
4676       --  If not a switch it must be a file name
4677
4678       else
4679          Add_File (Argv);
4680       end if;
4681    end Scan_Make_Arg;
4682
4683    -------------------
4684    -- Set_Ada_Paths --
4685    -------------------
4686
4687    procedure Set_Ada_Paths
4688      (For_Project         : Prj.Project_Id;
4689       Including_Libraries : Boolean)
4690    is
4691       New_Ada_Include_Path : constant String_Access :=
4692                                Prj.Env.Ada_Include_Path (For_Project);
4693
4694       New_Ada_Objects_Path : constant String_Access :=
4695                                Prj.Env.Ada_Objects_Path
4696                                  (For_Project, Including_Libraries);
4697
4698    begin
4699       --  If ADA_INCLUDE_PATH needs to be changed (we are not using the same
4700       --  project file), set the new ADA_INCLUDE_PATH
4701
4702       if New_Ada_Include_Path /= Current_Ada_Include_Path then
4703          Current_Ada_Include_Path := New_Ada_Include_Path;
4704
4705          if Original_Ada_Include_Path'Length = 0 then
4706             Setenv ("ADA_INCLUDE_PATH",
4707                     New_Ada_Include_Path.all);
4708
4709          else
4710             --  If there existed an ADA_INCLUDE_PATH at the invocation of
4711             --  gnatmake, concatenate new ADA_INCLUDE_PATH with the original.
4712
4713             Setenv ("ADA_INCLUDE_PATH",
4714                     Original_Ada_Include_Path.all &
4715                     Path_Separator &
4716                     New_Ada_Include_Path.all);
4717          end if;
4718
4719          if Opt.Verbose_Mode then
4720             declare
4721                Include_Path : constant String_Access :=
4722                  Getenv ("ADA_INCLUDE_PATH");
4723
4724             begin
4725                --  Display the new ADA_INCLUDE_PATH
4726
4727                Write_Str ("ADA_INCLUDE_PATH = """);
4728                Prj.Util.Write_Str
4729                  (S          => Include_Path.all,
4730                   Max_Length => Max_Line_Length,
4731                   Separator  => Path_Separator);
4732                Write_Str ("""");
4733                Write_Eol;
4734             end;
4735          end if;
4736       end if;
4737
4738       --  If ADA_OBJECTS_PATH needs to be changed (we are not using the same
4739       --  project file), set the new ADA_OBJECTS_PATH
4740
4741       if New_Ada_Objects_Path /= Current_Ada_Objects_Path then
4742          Current_Ada_Objects_Path := New_Ada_Objects_Path;
4743
4744          if Original_Ada_Objects_Path'Length = 0 then
4745             Setenv ("ADA_OBJECTS_PATH",
4746                     New_Ada_Objects_Path.all);
4747
4748          else
4749             --  If there existed an ADA_OBJECTS_PATH at the invocation of
4750             --  gnatmake, concatenate new ADA_OBJECTS_PATH with the original.
4751
4752             Setenv ("ADA_OBJECTS_PATH",
4753                     Original_Ada_Objects_Path.all &
4754                     Path_Separator &
4755                     New_Ada_Objects_Path.all);
4756          end if;
4757
4758          if Opt.Verbose_Mode then
4759             declare
4760                Objects_Path : constant String_Access :=
4761                  Getenv ("ADA_OBJECTS_PATH");
4762
4763             begin
4764                --  Display the new ADA_OBJECTS_PATH
4765
4766                Write_Str ("ADA_OBJECTS_PATH = """);
4767                Prj.Util.Write_Str
4768                  (S          => Objects_Path.all,
4769                   Max_Length => Max_Line_Length,
4770                   Separator  => Path_Separator);
4771                Write_Str ("""");
4772                Write_Eol;
4773             end;
4774          end if;
4775       end if;
4776
4777    end Set_Ada_Paths;
4778
4779    ---------------------
4780    -- Set_Library_For --
4781    ---------------------
4782
4783    procedure Set_Library_For
4784      (Project             : Project_Id;
4785       There_Are_Libraries : in out Boolean)
4786    is
4787    begin
4788       --  Case of library project
4789
4790       if Projects.Table (Project).Library then
4791          There_Are_Libraries := True;
4792
4793          --  Add the -L switch
4794
4795          Linker_Switches.Increment_Last;
4796          Linker_Switches.Table (Linker_Switches.Last) :=
4797            new String'("-L" &
4798                        Get_Name_String
4799                        (Projects.Table (Project).Library_Dir));
4800
4801          --  Add the -l switch
4802
4803          Linker_Switches.Increment_Last;
4804          Linker_Switches.Table (Linker_Switches.Last) :=
4805            new String'("-l" &
4806                        Get_Name_String
4807                        (Projects.Table (Project).Library_Name));
4808
4809          --  Add the Wl,-rpath switch if library non static
4810
4811          if Projects.Table (Project).Library_Kind /= Static then
4812             declare
4813                Option : constant String_Access :=
4814                           MLib.Tgt.Linker_Library_Path_Option
4815                             (Get_Name_String
4816                               (Projects.Table (Project).Library_Dir));
4817
4818             begin
4819                if Option /= null then
4820                   Linker_Switches.Increment_Last;
4821                   Linker_Switches.Table (Linker_Switches.Last) :=
4822                     Option;
4823                end if;
4824
4825             end;
4826
4827          end if;
4828
4829       end if;
4830    end Set_Library_For;
4831
4832    -----------------
4833    -- Switches_Of --
4834    -----------------
4835
4836    function Switches_Of
4837      (Source_File      : Name_Id;
4838       Source_File_Name : String;
4839       Naming           : Naming_Data;
4840       In_Package       : Package_Id;
4841       Allow_ALI        : Boolean)
4842       return             Variable_Value
4843    is
4844       Switches : Variable_Value;
4845
4846       Defaults : constant Array_Element_Id :=
4847                    Prj.Util.Value_Of
4848                      (Name      => Name_Default_Switches,
4849                       In_Arrays =>
4850                       Packages.Table (In_Package).Decl.Arrays);
4851
4852       Switches_Array : constant Array_Element_Id :=
4853                          Prj.Util.Value_Of
4854                            (Name      => Name_Switches,
4855                             In_Arrays =>
4856                               Packages.Table (In_Package).Decl.Arrays);
4857
4858    begin
4859       Switches :=
4860         Prj.Util.Value_Of
4861         (Index => Source_File,
4862          In_Array => Switches_Array);
4863
4864       if Switches = Nil_Variable_Value then
4865          declare
4866             Name        : String (1 .. Source_File_Name'Length + 3);
4867             Last        : Positive := Source_File_Name'Length;
4868             Spec_Suffix : constant String :=
4869                             Get_Name_String (Naming.Current_Spec_Suffix);
4870             Impl_Suffix : constant String :=
4871                             Get_Name_String (Naming.Current_Impl_Suffix);
4872             Truncated   : Boolean := False;
4873
4874          begin
4875             Name (1 .. Last) := Source_File_Name;
4876
4877             if Last > Impl_Suffix'Length
4878                and then Name (Last - Impl_Suffix'Length + 1 .. Last) =
4879                                                                   Impl_Suffix
4880             then
4881                Truncated := True;
4882                Last := Last - Impl_Suffix'Length;
4883             end if;
4884
4885             if not Truncated
4886               and then Last > Spec_Suffix'Length
4887               and then Name (Last - Spec_Suffix'Length + 1 .. Last) =
4888                                                                  Spec_Suffix
4889             then
4890                Truncated := True;
4891                Last := Last - Spec_Suffix'Length;
4892             end if;
4893
4894             if Truncated then
4895                Name_Len := Last;
4896                Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
4897                Switches :=
4898                  Prj.Util.Value_Of
4899                  (Index => Name_Find,
4900                   In_Array => Switches_Array);
4901
4902                if Switches = Nil_Variable_Value
4903                  and then Allow_ALI
4904                then
4905                   Last := Source_File_Name'Length;
4906
4907                   while Name (Last) /= '.' loop
4908                      Last := Last - 1;
4909                   end loop;
4910
4911                   Name (Last + 1 .. Last + 3) := "ali";
4912                   Name_Len := Last + 3;
4913                   Name_Buffer (1 .. Name_Len) := Name (1 .. Name_Len);
4914                   Switches :=
4915                     Prj.Util.Value_Of
4916                        (Index => Name_Find,
4917                         In_Array => Switches_Array);
4918                end if;
4919             end if;
4920          end;
4921       end if;
4922
4923       if Switches = Nil_Variable_Value then
4924          Switches := Prj.Util.Value_Of
4925                                 (Index => Name_Ada, In_Array => Defaults);
4926       end if;
4927
4928       return Switches;
4929    end Switches_Of;
4930
4931    ---------------------------
4932    -- Test_If_Relative_Path --
4933    ---------------------------
4934
4935    procedure Test_If_Relative_Path
4936      (Switch : in out String_Access;
4937       Parent : String_Access)
4938    is
4939    begin
4940       if Switch /= null then
4941
4942          declare
4943             Sw : String (1 .. Switch'Length);
4944             Start : Positive;
4945
4946          begin
4947             Sw := Switch.all;
4948
4949             if Sw (1) = '-' then
4950                if Sw'Length >= 3
4951                  and then (Sw (2) = 'A'
4952                            or else Sw (2) = 'I'
4953                            or else Sw (2) = 'L')
4954                then
4955                   Start := 3;
4956
4957                   if Sw = "-I-" then
4958                      return;
4959                   end if;
4960
4961                elsif Sw'Length >= 4
4962                  and then (Sw (2 .. 3) = "aL"
4963                            or else Sw (2 .. 3) = "aO"
4964                            or else Sw (2 .. 3) = "aI")
4965                then
4966                   Start := 4;
4967
4968                elsif Sw'Length >= 7
4969                  and then Sw (2 .. 6) = "-RTS="
4970                then
4971                   Start := 7;
4972                else
4973                   return;
4974                end if;
4975
4976                if not Is_Absolute_Path (Sw (Start .. Sw'Last)) then
4977                   if Parent = null then
4978                      Fail ("relative search path switches (""" & Sw &
4979                            """) are not allowed inside project files");
4980
4981                   else
4982                      Switch :=
4983                        new String'
4984                          (Sw (1 .. Start - 1) &
4985                           Parent.all &
4986                           Directory_Separator &
4987                           Sw (Start .. Sw'Last));
4988                   end if;
4989                end if;
4990             end if;
4991          end;
4992       end if;
4993    end Test_If_Relative_Path;
4994
4995    -----------
4996    -- Usage --
4997    -----------
4998
4999    procedure Usage is
5000    begin
5001       if Usage_Needed then
5002          Usage_Needed := False;
5003          Makeusg;
5004       end if;
5005    end Usage;
5006
5007    -----------------
5008    -- Verbose_Msg --
5009    -----------------
5010
5011    procedure Verbose_Msg
5012      (N1     : Name_Id;
5013       S1     : String;
5014       N2     : Name_Id := No_Name;
5015       S2     : String  := "";
5016       Prefix : String := "  -> ")
5017    is
5018    begin
5019       if not Opt.Verbose_Mode then
5020          return;
5021       end if;
5022
5023       Write_Str (Prefix);
5024       Write_Str ("""");
5025       Write_Name (N1);
5026       Write_Str (""" ");
5027       Write_Str (S1);
5028
5029       if N2 /= No_Name then
5030          Write_Str (" """);
5031          Write_Name (N2);
5032          Write_Str (""" ");
5033       end if;
5034
5035       Write_Str (S2);
5036       Write_Eol;
5037    end Verbose_Msg;
5038
5039 end Make;