OSDN Git Service

2011-08-05 Yannick Moy <moy@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / prj-conf.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                             P R J . C O N F                             --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --            Copyright (C) 2006-2011, 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 3,  or (at your option) any later ver- --
14 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17 -- for  more details.  You should have  received  a copy of the GNU General --
18 -- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license.          --
20 --                                                                          --
21 -- GNAT was originally developed  by the GNAT team at  New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
23 --                                                                          --
24 ------------------------------------------------------------------------------
25
26 with Hostparm;
27 with Makeutl;  use Makeutl;
28 with MLib.Tgt;
29 with Opt;      use Opt;
30 with Output;   use Output;
31 with Prj.Env;
32 with Prj.Err;
33 with Prj.Part;
34 with Prj.PP;
35 with Prj.Proc; use Prj.Proc;
36 with Prj.Tree; use Prj.Tree;
37 with Prj.Util; use Prj.Util;
38 with Prj;      use Prj;
39 with Snames;   use Snames;
40
41 with Ada.Directories; use Ada.Directories;
42 with Ada.Exceptions;  use Ada.Exceptions;
43
44 with GNAT.Case_Util; use GNAT.Case_Util;
45 with GNAT.HTable;    use GNAT.HTable;
46
47 package body Prj.Conf is
48
49    Auto_Cgpr : constant String := "auto.cgpr";
50
51    Default_Name : constant String := "default.cgpr";
52    --  Default configuration file that will be used if found
53
54    Config_Project_Env_Var : constant String := "GPR_CONFIG";
55    --  Name of the environment variable that provides the name of the
56    --  configuration file to use.
57
58    Gprconfig_Name : constant String := "gprconfig";
59
60    package RTS_Languages is new GNAT.HTable.Simple_HTable
61      (Header_Num => Prj.Header_Num,
62       Element    => Name_Id,
63       No_Element => No_Name,
64       Key        => Name_Id,
65       Hash       => Prj.Hash,
66       Equal      => "=");
67    --  Stores the runtime names for the various languages. This is in general
68    --  set from a --RTS command line option.
69
70    -----------------------
71    -- Local_Subprograms --
72    -----------------------
73
74    procedure Add_Attributes
75      (Project_Tree : Project_Tree_Ref;
76       Conf_Decl    : Declarations;
77       User_Decl    : in out Declarations);
78    --  Process the attributes in the config declarations.
79    --  For single string values, if the attribute is not declared in the user
80    --  declarations, declare it with the value in the config declarations.
81    --  For string list values, prepend the value in the user declarations with
82    --  the value in the config declarations.
83
84    function Check_Target
85      (Config_File        : Prj.Project_Id;
86       Autoconf_Specified : Boolean;
87       Project_Tree       : Prj.Project_Tree_Ref;
88       Target             : String := "") return Boolean;
89    --  Check that the config file's target matches Target.
90    --  Target should be set to the empty string when the user did not specify
91    --  a target. If the target in the configuration file is invalid, this
92    --  function will raise Invalid_Config with an appropriate message.
93    --  Autoconf_Specified should be set to True if the user has used
94    --  autoconf.
95
96    function Locate_Config_File (Name : String) return String_Access;
97    --  Search for Name in the config files directory. Return full path if
98    --  found, or null otherwise.
99
100    procedure Raise_Invalid_Config (Msg : String);
101    pragma No_Return (Raise_Invalid_Config);
102    --  Raises exception Invalid_Config with given message
103
104    procedure Apply_Config_File
105      (Config_File  : Prj.Project_Id;
106       Project_Tree : Prj.Project_Tree_Ref);
107    --  Apply the configuration file settings to all the projects in the
108    --  project tree. The Project_Tree must have been parsed first, and
109    --  processed through the first phase so that all its projects are known.
110    --
111    --  Currently, this will add new attributes and packages in the various
112    --  projects, so that when the second phase of the processing is performed
113    --  these attributes are automatically taken into account.
114
115    --------------------
116    -- Add_Attributes --
117    --------------------
118
119    procedure Add_Attributes
120      (Project_Tree : Project_Tree_Ref;
121       Conf_Decl    : Declarations;
122       User_Decl    : in out Declarations)
123    is
124       Shared : constant Shared_Project_Tree_Data_Access := Project_Tree.Shared;
125       Conf_Attr_Id       : Variable_Id;
126       Conf_Attr          : Variable;
127       Conf_Array_Id      : Array_Id;
128       Conf_Array         : Array_Data;
129       Conf_Array_Elem_Id : Array_Element_Id;
130       Conf_Array_Elem    : Array_Element;
131       Conf_List          : String_List_Id;
132       Conf_List_Elem     : String_Element;
133
134       User_Attr_Id       : Variable_Id;
135       User_Attr          : Variable;
136       User_Array_Id      : Array_Id;
137       User_Array         : Array_Data;
138       User_Array_Elem_Id : Array_Element_Id;
139       User_Array_Elem    : Array_Element;
140
141    begin
142       Conf_Attr_Id := Conf_Decl.Attributes;
143       User_Attr_Id := User_Decl.Attributes;
144       while Conf_Attr_Id /= No_Variable loop
145          Conf_Attr := Shared.Variable_Elements.Table (Conf_Attr_Id);
146          User_Attr := Shared.Variable_Elements.Table (User_Attr_Id);
147
148          if not Conf_Attr.Value.Default then
149             if User_Attr.Value.Default then
150
151                --  No attribute declared in user project file: just copy the
152                --  value of the configuration attribute.
153
154                User_Attr.Value := Conf_Attr.Value;
155                Shared.Variable_Elements.Table (User_Attr_Id) := User_Attr;
156
157             elsif User_Attr.Value.Kind = List
158               and then Conf_Attr.Value.Values /= Nil_String
159             then
160                --  List attribute declared in both the user project and the
161                --  configuration project: prepend the user list with the
162                --  configuration list.
163
164                declare
165                   Conf_List : String_List_Id := Conf_Attr.Value.Values;
166                   Conf_Elem : String_Element;
167                   User_List : constant String_List_Id :=
168                                 User_Attr.Value.Values;
169                   New_List : String_List_Id;
170                   New_Elem : String_Element;
171
172                begin
173                   --  Create new list
174
175                   String_Element_Table.Increment_Last
176                     (Shared.String_Elements);
177                   New_List :=
178                     String_Element_Table.Last (Shared.String_Elements);
179
180                   --  Value of attribute is new list
181
182                   User_Attr.Value.Values := New_List;
183                   Shared.Variable_Elements.Table (User_Attr_Id) := User_Attr;
184
185                   loop
186                      --  Get each element of configuration list
187
188                      Conf_Elem := Shared.String_Elements.Table (Conf_List);
189                      New_Elem  := Conf_Elem;
190                      Conf_List := Conf_Elem.Next;
191
192                      if Conf_List = Nil_String then
193
194                         --  If it is the last element in the list, connect to
195                         --  first element of user list, and we are done.
196
197                         New_Elem.Next := User_List;
198                         Shared.String_Elements.Table (New_List) := New_Elem;
199                         exit;
200
201                      else
202                         --  If it is not the last element in the list, add to
203                         --  new list.
204
205                         String_Element_Table.Increment_Last
206                           (Shared.String_Elements);
207                         New_Elem.Next :=
208                           String_Element_Table.Last (Shared.String_Elements);
209                         Shared.String_Elements.Table (New_List) := New_Elem;
210                         New_List := New_Elem.Next;
211                      end if;
212                   end loop;
213                end;
214             end if;
215          end if;
216
217          Conf_Attr_Id := Conf_Attr.Next;
218          User_Attr_Id := User_Attr.Next;
219       end loop;
220
221       Conf_Array_Id := Conf_Decl.Arrays;
222       while Conf_Array_Id /= No_Array loop
223          Conf_Array := Shared.Arrays.Table (Conf_Array_Id);
224
225          User_Array_Id := User_Decl.Arrays;
226          while User_Array_Id /= No_Array loop
227             User_Array := Shared.Arrays.Table (User_Array_Id);
228             exit when User_Array.Name = Conf_Array.Name;
229             User_Array_Id := User_Array.Next;
230          end loop;
231
232          --  If this associative array does not exist in the user project file,
233          --  do a shallow copy of the full associative array.
234
235          if User_Array_Id = No_Array then
236             Array_Table.Increment_Last (Shared.Arrays);
237             User_Array := Conf_Array;
238             User_Array.Next := User_Decl.Arrays;
239             User_Decl.Arrays := Array_Table.Last (Shared.Arrays);
240             Shared.Arrays.Table (User_Decl.Arrays) := User_Array;
241
242          --  Otherwise, check each array element
243
244          else
245             Conf_Array_Elem_Id := Conf_Array.Value;
246             while Conf_Array_Elem_Id /= No_Array_Element loop
247                Conf_Array_Elem :=
248                  Shared.Array_Elements.Table (Conf_Array_Elem_Id);
249
250                User_Array_Elem_Id := User_Array.Value;
251                while User_Array_Elem_Id /= No_Array_Element loop
252                   User_Array_Elem :=
253                     Shared.Array_Elements.Table (User_Array_Elem_Id);
254                   exit when User_Array_Elem.Index = Conf_Array_Elem.Index;
255                   User_Array_Elem_Id := User_Array_Elem.Next;
256                end loop;
257
258                --  If the array element doesn't exist in the user array, insert
259                --  a shallow copy of the conf array element in the user array.
260
261                if User_Array_Elem_Id = No_Array_Element then
262                   Array_Element_Table.Increment_Last (Shared.Array_Elements);
263                   User_Array_Elem := Conf_Array_Elem;
264                   User_Array_Elem.Next := User_Array.Value;
265                   User_Array.Value :=
266                     Array_Element_Table.Last (Shared.Array_Elements);
267                   Shared.Array_Elements.Table (User_Array.Value) :=
268                     User_Array_Elem;
269                   Shared.Arrays.Table (User_Array_Id) := User_Array;
270
271                --  Otherwise, if the value is a string list, prepend the conf
272                --  array element value to the array element.
273
274                elsif Conf_Array_Elem.Value.Kind = List then
275                   Conf_List := Conf_Array_Elem.Value.Values;
276
277                   if Conf_List /= Nil_String then
278                      declare
279                         Link     : constant String_List_Id :=
280                                      User_Array_Elem.Value.Values;
281                         Previous : String_List_Id := Nil_String;
282                         Next     : String_List_Id;
283
284                      begin
285                         loop
286                            Conf_List_Elem :=
287                              Shared.String_Elements.Table (Conf_List);
288                            String_Element_Table.Increment_Last
289                              (Shared.String_Elements);
290                            Next :=
291                              String_Element_Table.Last
292                                (Shared.String_Elements);
293                            Shared.String_Elements.Table (Next) :=
294                              Conf_List_Elem;
295
296                            if Previous = Nil_String then
297                               User_Array_Elem.Value.Values := Next;
298                               Shared.Array_Elements.Table
299                                 (User_Array_Elem_Id) := User_Array_Elem;
300
301                            else
302                               Shared.String_Elements.Table
303                                 (Previous).Next := Next;
304                            end if;
305
306                            Previous := Next;
307
308                            Conf_List := Conf_List_Elem.Next;
309
310                            if Conf_List = Nil_String then
311                               Shared.String_Elements.Table (Previous).Next :=
312                                 Link;
313                               exit;
314                            end if;
315                         end loop;
316                      end;
317                   end if;
318                end if;
319
320                Conf_Array_Elem_Id := Conf_Array_Elem.Next;
321             end loop;
322          end if;
323
324          Conf_Array_Id := Conf_Array.Next;
325       end loop;
326    end Add_Attributes;
327
328    ------------------------------------
329    -- Add_Default_GNAT_Naming_Scheme --
330    ------------------------------------
331
332    procedure Add_Default_GNAT_Naming_Scheme
333      (Config_File  : in out Project_Node_Id;
334       Project_Tree : Project_Node_Tree_Ref)
335    is
336       procedure Create_Attribute
337         (Name  : Name_Id;
338          Value : String;
339          Index : String := "";
340          Pkg   : Project_Node_Id := Empty_Node);
341
342       ----------------------
343       -- Create_Attribute --
344       ----------------------
345
346       procedure Create_Attribute
347         (Name  : Name_Id;
348          Value : String;
349          Index : String := "";
350          Pkg   : Project_Node_Id := Empty_Node)
351       is
352          Attr : Project_Node_Id;
353          pragma Unreferenced (Attr);
354
355          Expr   : Name_Id         := No_Name;
356          Val    : Name_Id         := No_Name;
357          Parent : Project_Node_Id := Config_File;
358
359       begin
360          if Index /= "" then
361             Name_Len := Index'Length;
362             Name_Buffer (1 .. Name_Len) := Index;
363             Val := Name_Find;
364          end if;
365
366          if Pkg /= Empty_Node then
367             Parent := Pkg;
368          end if;
369
370          Name_Len := Value'Length;
371          Name_Buffer (1 .. Name_Len) := Value;
372          Expr := Name_Find;
373
374          Attr := Create_Attribute
375            (Tree       => Project_Tree,
376             Prj_Or_Pkg => Parent,
377             Name       => Name,
378             Index_Name => Val,
379             Kind       => Prj.Single,
380             Value      => Create_Literal_String (Expr, Project_Tree));
381       end Create_Attribute;
382
383       --  Local variables
384
385       Name   : Name_Id;
386       Naming : Project_Node_Id;
387
388    --  Start of processing for Add_Default_GNAT_Naming_Scheme
389
390    begin
391       if Config_File = Empty_Node then
392
393          --  Create a dummy config file is none was found
394
395          Name_Len := Auto_Cgpr'Length;
396          Name_Buffer (1 .. Name_Len) := Auto_Cgpr;
397          Name := Name_Find;
398
399          --  An invalid project name to avoid conflicts with user-created ones
400
401          Name_Len := 5;
402          Name_Buffer (1 .. Name_Len) := "_auto";
403
404          Config_File :=
405            Create_Project
406              (In_Tree        => Project_Tree,
407               Name           => Name_Find,
408               Full_Path      => Path_Name_Type (Name),
409               Is_Config_File => True);
410
411          --  Setup library support
412
413          case MLib.Tgt.Support_For_Libraries is
414             when None =>
415                null;
416
417             when Static_Only =>
418                Create_Attribute (Name_Library_Support, "static_only");
419
420             when Full =>
421                Create_Attribute (Name_Library_Support, "full");
422          end case;
423
424          if MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported then
425             Create_Attribute (Name_Library_Auto_Init_Supported, "true");
426          else
427             Create_Attribute (Name_Library_Auto_Init_Supported, "false");
428          end if;
429
430          --  Setup Ada support (Ada is the default language here, since this
431          --  is only called when no config file existed initially, ie for
432          --  gnatmake).
433
434          Create_Attribute (Name_Default_Language, "ada");
435
436          Naming := Create_Package (Project_Tree, Config_File, "naming");
437          Create_Attribute (Name_Spec_Suffix, ".ads", "ada",     Pkg => Naming);
438          Create_Attribute (Name_Separate_Suffix, ".adb", "ada", Pkg => Naming);
439          Create_Attribute (Name_Body_Suffix, ".adb", "ada",     Pkg => Naming);
440          Create_Attribute (Name_Dot_Replacement, "-",           Pkg => Naming);
441          Create_Attribute (Name_Casing,          "lowercase",   Pkg => Naming);
442
443          if Current_Verbosity = High then
444             Write_Line ("Automatically generated (in-memory) config file");
445             Prj.PP.Pretty_Print
446               (Project                => Config_File,
447                In_Tree                => Project_Tree,
448                Backward_Compatibility => False);
449          end if;
450       end if;
451    end Add_Default_GNAT_Naming_Scheme;
452
453    -----------------------
454    -- Apply_Config_File --
455    -----------------------
456
457    procedure Apply_Config_File
458      (Config_File  : Prj.Project_Id;
459       Project_Tree : Prj.Project_Tree_Ref)
460    is
461       Shared : constant Shared_Project_Tree_Data_Access := Project_Tree.Shared;
462
463       Conf_Decl    : constant Declarations := Config_File.Decl;
464       Conf_Pack_Id : Package_Id;
465       Conf_Pack    : Package_Element;
466
467       User_Decl    : Declarations;
468       User_Pack_Id : Package_Id;
469       User_Pack    : Package_Element;
470       Proj         : Project_List;
471
472    begin
473       Debug_Output ("Applying config file to a project tree");
474
475       Proj := Project_Tree.Projects;
476       while Proj /= null loop
477          if Proj.Project /= Config_File then
478             User_Decl := Proj.Project.Decl;
479             Add_Attributes
480               (Project_Tree      => Project_Tree,
481                Conf_Decl         => Conf_Decl,
482                User_Decl         => User_Decl);
483
484             Conf_Pack_Id := Conf_Decl.Packages;
485             while Conf_Pack_Id /= No_Package loop
486                Conf_Pack := Shared.Packages.Table (Conf_Pack_Id);
487
488                User_Pack_Id := User_Decl.Packages;
489                while User_Pack_Id /= No_Package loop
490                   User_Pack := Shared.Packages.Table (User_Pack_Id);
491                   exit when User_Pack.Name = Conf_Pack.Name;
492                   User_Pack_Id := User_Pack.Next;
493                end loop;
494
495                if User_Pack_Id = No_Package then
496                   Package_Table.Increment_Last (Shared.Packages);
497                   User_Pack := Conf_Pack;
498                   User_Pack.Next := User_Decl.Packages;
499                   User_Decl.Packages := Package_Table.Last (Shared.Packages);
500                   Shared.Packages.Table (User_Decl.Packages) := User_Pack;
501
502                else
503                   Add_Attributes
504                     (Project_Tree      => Project_Tree,
505                      Conf_Decl         => Conf_Pack.Decl,
506                      User_Decl         =>
507                        Shared.Packages.Table (User_Pack_Id).Decl);
508                end if;
509
510                Conf_Pack_Id := Conf_Pack.Next;
511             end loop;
512
513             Proj.Project.Decl := User_Decl;
514
515             --  For aggregate projects, we need to apply the config to all
516             --  their aggregated trees as well.
517
518             if Proj.Project.Qualifier = Aggregate then
519                declare
520                   List : Aggregated_Project_List :=
521                     Proj.Project.Aggregated_Projects;
522                begin
523                   while List /= null loop
524                      Debug_Output
525                        ("Recursively apply config to aggregated tree",
526                         List.Project.Name);
527                      Apply_Config_File
528                        (Config_File,
529                         Project_Tree      => List.Tree);
530                      List := List.Next;
531                   end loop;
532                end;
533             end if;
534          end if;
535
536          Proj := Proj.Next;
537       end loop;
538    end Apply_Config_File;
539
540    ------------------
541    -- Check_Target --
542    ------------------
543
544    function Check_Target
545      (Config_File  : Project_Id;
546       Autoconf_Specified : Boolean;
547       Project_Tree : Prj.Project_Tree_Ref;
548       Target       : String := "") return Boolean
549    is
550       Shared : constant Shared_Project_Tree_Data_Access := Project_Tree.Shared;
551       Variable : constant Variable_Value :=
552                    Value_Of
553                      (Name_Target, Config_File.Decl.Attributes, Shared);
554       Tgt_Name : Name_Id := No_Name;
555       OK       : Boolean;
556
557    begin
558       if Variable /= Nil_Variable_Value and then not Variable.Default then
559          Tgt_Name := Variable.Value;
560       end if;
561
562       if Target = "" then
563          OK := not Autoconf_Specified or else Tgt_Name = No_Name;
564       else
565          OK := Tgt_Name /= No_Name
566                  and then Target = Get_Name_String (Tgt_Name);
567       end if;
568
569       if not OK then
570          if Autoconf_Specified then
571             if Verbose_Mode then
572                Write_Line ("inconsistent targets, performing autoconf");
573             end if;
574
575             return False;
576
577          else
578             if Tgt_Name /= No_Name then
579                Raise_Invalid_Config
580                  ("invalid target name """
581                   & Get_Name_String (Tgt_Name) & """ in configuration");
582             else
583                Raise_Invalid_Config
584                  ("no target specified in configuration file");
585             end if;
586          end if;
587       end if;
588
589       return True;
590    end Check_Target;
591
592    --------------------------------------
593    -- Get_Or_Create_Configuration_File --
594    --------------------------------------
595
596    procedure Get_Or_Create_Configuration_File
597      (Project                    : Project_Id;
598       Project_Tree               : Project_Tree_Ref;
599       Project_Node_Tree          : Prj.Tree.Project_Node_Tree_Ref;
600       Env                        : in out Prj.Tree.Environment;
601       Allow_Automatic_Generation : Boolean;
602       Config_File_Name           : String := "";
603       Autoconf_Specified         : Boolean;
604       Target_Name                : String := "";
605       Normalized_Hostname        : String;
606       Packages_To_Check          : String_List_Access := null;
607       Config                     : out Prj.Project_Id;
608       Config_File_Path           : out String_Access;
609       Automatically_Generated    : out Boolean;
610       On_Load_Config             : Config_File_Hook := null)
611    is
612       Shared : constant Shared_Project_Tree_Data_Access := Project_Tree.Shared;
613
614       At_Least_One_Compiler_Command : Boolean := False;
615       --  Set to True if at least one attribute Ide'Compiler_Command is
616       --  specified for one language of the system.
617
618       function Default_File_Name return String;
619       --  Return the name of the default config file that should be tested
620
621       procedure Do_Autoconf;
622       --  Generate a new config file through gprconfig. In case of error, this
623       --  raises the Invalid_Config exception with an appropriate message
624
625       function Get_Config_Switches return Argument_List_Access;
626       --  Return the --config switches to use for gprconfig
627
628       function Might_Have_Sources (Project : Project_Id) return Boolean;
629       --  True if the specified project might have sources (ie the user has not
630       --  explicitly specified it. We haven't checked the file system, nor do
631       --  we need to at this stage.
632
633       -----------------------
634       -- Default_File_Name --
635       -----------------------
636
637       function Default_File_Name return String is
638          Ada_RTS : constant String := Runtime_Name_For (Name_Ada);
639          Tmp     : String_Access;
640
641       begin
642          if Target_Name /= "" then
643             if Ada_RTS /= "" then
644                return Target_Name & '-' & Ada_RTS
645                  & Config_Project_File_Extension;
646             else
647                return Target_Name & Config_Project_File_Extension;
648             end if;
649
650          elsif Ada_RTS /= "" then
651             return Ada_RTS & Config_Project_File_Extension;
652
653          else
654             Tmp := Getenv (Config_Project_Env_Var);
655
656             declare
657                T : constant String := Tmp.all;
658
659             begin
660                Free (Tmp);
661
662                if T'Length = 0 then
663                   return Default_Name;
664                else
665                   return T;
666                end if;
667             end;
668          end if;
669       end Default_File_Name;
670
671       ------------------------
672       -- Might_Have_Sources --
673       ------------------------
674
675       function Might_Have_Sources (Project : Project_Id) return Boolean is
676          Variable : Variable_Value;
677
678       begin
679          Variable :=
680            Value_Of
681              (Name_Source_Dirs,
682               Project.Decl.Attributes,
683               Shared);
684
685          if Variable = Nil_Variable_Value
686            or else Variable.Default
687            or else Variable.Values /= Nil_String
688          then
689             Variable :=
690               Value_Of
691                 (Name_Source_Files,
692                  Project.Decl.Attributes,
693                  Shared);
694             return Variable = Nil_Variable_Value
695               or else Variable.Default
696               or else Variable.Values /= Nil_String;
697
698          else
699             return False;
700          end if;
701       end Might_Have_Sources;
702
703       -------------------------
704       -- Get_Config_Switches --
705       -------------------------
706
707       function Get_Config_Switches return Argument_List_Access is
708          package Language_Htable is new GNAT.HTable.Simple_HTable
709            (Header_Num => Prj.Header_Num,
710             Element    => Name_Id,
711             No_Element => No_Name,
712             Key        => Name_Id,
713             Hash       => Prj.Hash,
714             Equal      => "=");
715          --  Hash table to keep the languages used in the project tree
716
717          IDE : constant Package_Id :=
718                  Value_Of (Name_Ide, Project.Decl.Packages, Shared);
719
720          Prj_Iter : Project_List;
721          List     : String_List_Id;
722          Elem     : String_Element;
723          Lang     : Name_Id;
724          Variable : Variable_Value;
725          Name     : Name_Id;
726          Count    : Natural;
727          Result   : Argument_List_Access;
728
729          Check_Default : Boolean;
730
731       begin
732          Prj_Iter := Project_Tree.Projects;
733          while Prj_Iter /= null loop
734             if Might_Have_Sources (Prj_Iter.Project) then
735                Variable :=
736                  Value_Of
737                    (Name_Languages,
738                     Prj_Iter.Project.Decl.Attributes,
739                     Shared);
740
741                if Variable = Nil_Variable_Value
742                  or else Variable.Default
743                then
744                   --  Languages is not declared. If it is not an extending
745                   --  project, or if it extends a project with no Languages,
746                   --  check for Default_Language.
747
748                   Check_Default := Prj_Iter.Project.Extends = No_Project;
749
750                   if not Check_Default then
751                      Variable :=
752                        Value_Of
753                          (Name_Languages,
754                           Prj_Iter.Project.Extends.Decl.Attributes,
755                           Shared);
756                      Check_Default :=
757                        Variable /= Nil_Variable_Value
758                          and then Variable.Values = Nil_String;
759                   end if;
760
761                   if Check_Default then
762                      Variable :=
763                        Value_Of
764                          (Name_Default_Language,
765                           Prj_Iter.Project.Decl.Attributes,
766                           Shared);
767
768                      if Variable /= Nil_Variable_Value
769                        and then not Variable.Default
770                      then
771                         Get_Name_String (Variable.Value);
772                         To_Lower (Name_Buffer (1 .. Name_Len));
773                         Lang := Name_Find;
774                         Language_Htable.Set (Lang, Lang);
775
776                      else
777                         --  If no default language is declared, default to Ada
778
779                         Language_Htable.Set (Name_Ada, Name_Ada);
780                      end if;
781                   end if;
782
783                elsif Variable.Values /= Nil_String then
784
785                   --  Attribute Languages is declared with a non empty
786                   --  list: put all the languages in Language_HTable.
787
788                   List := Variable.Values;
789                   while List /= Nil_String loop
790                      Elem := Shared.String_Elements.Table (List);
791
792                      Get_Name_String (Elem.Value);
793                      To_Lower (Name_Buffer (1 .. Name_Len));
794                      Lang := Name_Find;
795                      Language_Htable.Set (Lang, Lang);
796
797                      List := Elem.Next;
798                   end loop;
799                end if;
800             end if;
801
802             Prj_Iter := Prj_Iter.Next;
803          end loop;
804
805          Name  := Language_Htable.Get_First;
806          Count := 0;
807          while Name /= No_Name loop
808             Count := Count + 1;
809             Name := Language_Htable.Get_Next;
810          end loop;
811
812          Result := new String_List (1 .. Count);
813
814          Count := 1;
815          Name  := Language_Htable.Get_First;
816          while Name /= No_Name loop
817             --  Check if IDE'Compiler_Command is declared for the language.
818             --  If it is, use its value to invoke gprconfig.
819
820             Variable :=
821               Value_Of
822                 (Name,
823                  Attribute_Or_Array_Name => Name_Compiler_Command,
824                  In_Package              => IDE,
825                  Shared                  => Shared,
826                  Force_Lower_Case_Index  => True);
827
828             declare
829                Config_Command : constant String :=
830                  "--config=" & Get_Name_String (Name);
831
832                Runtime_Name   : constant String :=
833                  Runtime_Name_For (Name);
834
835             begin
836                if Variable = Nil_Variable_Value
837                  or else Length_Of_Name (Variable.Value) = 0
838                then
839                   Result (Count) :=
840                     new String'(Config_Command & ",," & Runtime_Name);
841
842                else
843                   At_Least_One_Compiler_Command := True;
844
845                   declare
846                      Compiler_Command : constant String :=
847                        Get_Name_String (Variable.Value);
848
849                   begin
850                      if Is_Absolute_Path (Compiler_Command) then
851                         Result (Count) :=
852                           new String'
853                             (Config_Command & ",," & Runtime_Name & "," &
854                              Containing_Directory (Compiler_Command) & "," &
855                              Simple_Name (Compiler_Command));
856                      else
857                         Result (Count) :=
858                           new String'
859                             (Config_Command & ",," & Runtime_Name & ",," &
860                              Compiler_Command);
861                      end if;
862                   end;
863                end if;
864             end;
865
866             Count := Count + 1;
867             Name  := Language_Htable.Get_Next;
868          end loop;
869
870          return Result;
871       end Get_Config_Switches;
872
873       -----------------
874       -- Do_Autoconf --
875       -----------------
876
877       procedure Do_Autoconf is
878          Obj_Dir : constant Variable_Value :=
879                      Value_Of
880                        (Name_Object_Dir,
881                         Project.Decl.Attributes,
882                         Shared);
883
884          Gprconfig_Path  : String_Access;
885          Success         : Boolean;
886
887       begin
888          Gprconfig_Path := Locate_Exec_On_Path (Gprconfig_Name);
889
890          if Gprconfig_Path = null then
891             Raise_Invalid_Config
892               ("could not locate gprconfig for auto-configuration");
893          end if;
894
895          --  First, find the object directory of the user's project
896
897          if Obj_Dir = Nil_Variable_Value or else Obj_Dir.Default then
898             Get_Name_String (Project.Directory.Display_Name);
899
900          else
901             if Is_Absolute_Path (Get_Name_String (Obj_Dir.Value)) then
902                Get_Name_String (Obj_Dir.Value);
903
904             else
905                Name_Len := 0;
906                Add_Str_To_Name_Buffer
907                  (Get_Name_String (Project.Directory.Display_Name));
908                Add_Str_To_Name_Buffer (Get_Name_String (Obj_Dir.Value));
909             end if;
910          end if;
911
912          if Subdirs /= null then
913             Add_Char_To_Name_Buffer (Directory_Separator);
914             Add_Str_To_Name_Buffer (Subdirs.all);
915          end if;
916
917          for J in 1 .. Name_Len loop
918             if Name_Buffer (J) = '/' then
919                Name_Buffer (J) := Directory_Separator;
920             end if;
921          end loop;
922
923          declare
924             Obj_Dir         : constant String := Name_Buffer (1 .. Name_Len);
925             Config_Switches : Argument_List_Access;
926             Args            : Argument_List (1 .. 5);
927             Arg_Last         : Positive;
928
929             Obj_Dir_Exists : Boolean := True;
930
931          begin
932             --  Check if the object directory exists. If Setup_Projects is True
933             --  (-p) and directory does not exist, attempt to create it.
934             --  Otherwise, if directory does not exist, fail without calling
935             --  gprconfig.
936
937             if not Is_Directory (Obj_Dir)
938               and then (Setup_Projects or else Subdirs /= null)
939             then
940                begin
941                   Create_Path (Obj_Dir);
942
943                   if not Quiet_Output then
944                      Write_Str ("object directory """);
945                      Write_Str (Obj_Dir);
946                      Write_Line (""" created");
947                   end if;
948
949                exception
950                   when others =>
951                      Raise_Invalid_Config
952                        ("could not create object directory " & Obj_Dir);
953                end;
954             end if;
955
956             if not Is_Directory (Obj_Dir) then
957                case Env.Flags.Require_Obj_Dirs is
958                   when Error =>
959                      Raise_Invalid_Config
960                        ("object directory " & Obj_Dir & " does not exist");
961                   when Warning =>
962                      Prj.Err.Error_Msg
963                        (Env.Flags,
964                         "?object directory " & Obj_Dir & " does not exist");
965                      Obj_Dir_Exists := False;
966                   when Silent =>
967                      null;
968                end case;
969             end if;
970
971             --  If no switch --RTS have been specified on the command line,
972             --  look for --RTS switches in the Builder switches.
973
974             if RTS_Languages.Get_First = No_Name then
975                declare
976                   Builder : constant Package_Id :=
977                     Value_Of (Name_Builder, Project.Decl.Packages, Shared);
978                   Switch_Array_Id : Array_Element_Id;
979
980                   procedure Check_RTS_Switches;
981                   --  Take into account eventual switches --RTS in
982                   --  Switch_Array_Id.
983
984                   ------------------------
985                   -- Check_RTS_SWitches --
986                   ------------------------
987
988                   procedure Check_RTS_Switches is
989                      Switch_Array : Array_Element;
990
991                      Switch_List   : String_List_Id := Nil_String;
992                      Switch : String_Element;
993
994                      Lang      : Name_Id;
995                      Lang_Last : Positive;
996                   begin
997                      while Switch_Array_Id /= No_Array_Element loop
998                         Switch_Array :=
999                           Shared.Array_Elements.Table (Switch_Array_Id);
1000                            Switch_List := Switch_Array.Value.Values;
1001
1002                         while Switch_List /= Nil_String loop
1003                            Switch :=
1004                              Shared.String_Elements.Table (Switch_List);
1005
1006                            if Switch.Value /= No_Name then
1007                               Get_Name_String (Switch.Value);
1008
1009                               if Name_Len >= 7 and then
1010                                 Name_Buffer (1 .. 5) = "--RTS"
1011                               then
1012                                  if Name_Buffer (6) = '=' then
1013                                     if not Runtime_Name_Set_For (Name_Ada) then
1014                                        Set_Runtime_For
1015                                          (Name_Ada,
1016                                           Name_Buffer (7 .. Name_Len));
1017                                     end if;
1018
1019                                  elsif Name_Len > 7 and then
1020                                    Name_Buffer (6) = ':' and then
1021                                    Name_Buffer (7) /= '='
1022                                  then
1023                                     Lang_Last := 7;
1024                                     while Lang_Last < Name_Len and then
1025                                       Name_Buffer (Lang_Last + 1) /= '='
1026                                     loop
1027                                        Lang_Last := Lang_Last + 1;
1028                                     end loop;
1029
1030                                     if
1031                                       Name_Buffer (Lang_Last + 1) = '='
1032                                     then
1033                                        declare
1034                                           RTS : constant String :=
1035                                             Name_Buffer (Lang_Last + 2 ..
1036                                                            Name_Len);
1037                                        begin
1038                                           Name_Buffer (1 .. Lang_Last - 6)
1039                                             := Name_Buffer (7 .. Lang_Last);
1040                                           Name_Len := Lang_Last - 6;
1041                                           To_Lower
1042                                             (Name_Buffer (1 .. Name_Len));
1043                                           Lang := Name_Find;
1044
1045                                           if
1046                                           not Runtime_Name_Set_For (Lang)
1047                                           then
1048                                              Set_Runtime_For (Lang, RTS);
1049                                           end if;
1050                                        end;
1051                                     end if;
1052                                  end if;
1053                               end if;
1054                            end if;
1055
1056                            Switch_List := Switch.Next;
1057                         end loop;
1058
1059                         Switch_Array_Id := Switch_Array.Next;
1060                      end loop;
1061                   end Check_RTS_Switches;
1062
1063                begin
1064                   if Builder /= No_Package then
1065                      Switch_Array_Id :=
1066                        Value_Of
1067                          (Name      => Name_Switches,
1068                           In_Arrays =>
1069                             Shared.Packages.Table (Builder).Decl.Arrays,
1070                           Shared    => Shared);
1071                      Check_RTS_Switches;
1072
1073                      Switch_Array_Id :=
1074                        Value_Of
1075                          (Name      => Name_Default_Switches,
1076                           In_Arrays =>
1077                             Shared.Packages.Table (Builder).Decl.Arrays,
1078                           Shared    => Shared);
1079                      Check_RTS_Switches;
1080                   end if;
1081                end;
1082             end if;
1083
1084             --  Get the config switches. This should be done only now, as some
1085             --  runtimes may have been found if the Builder switches.
1086
1087             Config_Switches := Get_Config_Switches;
1088
1089             --  Invoke gprconfig
1090
1091             Args (1) := new String'("--batch");
1092             Args (2) := new String'("-o");
1093
1094             --  If no config file was specified, set the auto.cgpr one
1095
1096             if Config_File_Name = "" then
1097                if Obj_Dir_Exists then
1098                   Args (3) :=
1099                     new String'(Obj_Dir & Directory_Separator & Auto_Cgpr);
1100
1101                else
1102                   declare
1103                      Path_FD   : File_Descriptor;
1104                      Path_Name : Path_Name_Type;
1105
1106                   begin
1107                      Prj.Env.Create_Temp_File
1108                        (Shared    => Project_Tree.Shared,
1109                         Path_FD   => Path_FD,
1110                         Path_Name => Path_Name,
1111                         File_Use  => "configuration file");
1112
1113                      if Path_FD /= Invalid_FD then
1114                         Args (3) := new String'(Get_Name_String (Path_Name));
1115                         GNAT.OS_Lib.Close (Path_FD);
1116
1117                      else
1118                         --  We'll have an error message later on
1119
1120                         Args (3) :=
1121                           new String'
1122                             (Obj_Dir & Directory_Separator & Auto_Cgpr);
1123                      end if;
1124                   end;
1125                end if;
1126             else
1127                Args (3) := new String'(Config_File_Name);
1128             end if;
1129
1130             if Normalized_Hostname = "" then
1131                Arg_Last := 3;
1132             else
1133                if Target_Name = "" then
1134                   if At_Least_One_Compiler_Command then
1135                      Args (4) := new String'("--target=all");
1136
1137                   else
1138                      Args (4) :=
1139                        new String'("--target=" & Normalized_Hostname);
1140                   end if;
1141
1142                else
1143                   Args (4) := new String'("--target=" & Target_Name);
1144                end if;
1145
1146                Arg_Last := 4;
1147             end if;
1148
1149             if not Verbose_Mode then
1150                Arg_Last := Arg_Last + 1;
1151                Args (Arg_Last) := new String'("-q");
1152             end if;
1153
1154             if Verbose_Mode then
1155                Write_Str (Gprconfig_Name);
1156
1157                for J in 1 .. Arg_Last loop
1158                   Write_Char (' ');
1159                   Write_Str (Args (J).all);
1160                end loop;
1161
1162                for J in Config_Switches'Range loop
1163                   Write_Char (' ');
1164                   Write_Str (Config_Switches (J).all);
1165                end loop;
1166
1167                Write_Eol;
1168
1169             elsif not Quiet_Output then
1170                --  Display no message if we are creating auto.cgpr, unless in
1171                --  verbose mode
1172
1173                if Config_File_Name /= ""
1174                  or else Verbose_Mode
1175                then
1176                   Write_Str ("creating ");
1177                   Write_Str (Simple_Name (Args (3).all));
1178                   Write_Eol;
1179                end if;
1180             end if;
1181
1182             Spawn (Gprconfig_Path.all, Args (1 .. Arg_Last) &
1183                    Config_Switches.all,
1184                    Success);
1185
1186             Free (Config_Switches);
1187
1188             Config_File_Path := Locate_Config_File (Args (3).all);
1189
1190             if Config_File_Path = null then
1191                Raise_Invalid_Config
1192                  ("could not create " & Args (3).all);
1193             end if;
1194
1195             for F in Args'Range loop
1196                Free (Args (F));
1197             end loop;
1198          end;
1199       end Do_Autoconf;
1200
1201       Success             : Boolean;
1202       Config_Project_Node : Project_Node_Id := Empty_Node;
1203
1204    begin
1205       pragma Assert (Prj.Env.Is_Initialized (Env.Project_Path));
1206
1207       Free (Config_File_Path);
1208       Config := No_Project;
1209
1210       if Config_File_Name /= "" then
1211          Config_File_Path := Locate_Config_File (Config_File_Name);
1212       else
1213          Config_File_Path := Locate_Config_File (Default_File_Name);
1214       end if;
1215
1216       if Config_File_Path = null then
1217          if (not Allow_Automatic_Generation) and then
1218             Config_File_Name /= ""
1219          then
1220             Raise_Invalid_Config
1221               ("could not locate main configuration project "
1222                & Config_File_Name);
1223          end if;
1224       end if;
1225
1226       Automatically_Generated :=
1227         Allow_Automatic_Generation and then Config_File_Path = null;
1228
1229       <<Process_Config_File>>
1230
1231       if Automatically_Generated then
1232          if Hostparm.OpenVMS then
1233
1234             --  There is no gprconfig on VMS
1235
1236             Raise_Invalid_Config
1237               ("could not locate any configuration project file");
1238
1239          else
1240             --  This might raise an Invalid_Config exception
1241
1242             Do_Autoconf;
1243          end if;
1244
1245       --  If the config file is not auto-generated, warn if there is any --RTS
1246       --  switch on the command line.
1247
1248       elsif RTS_Languages.Get_First /= No_Name and then
1249         Opt.Warning_Mode /= Opt.Suppress
1250       then
1251          Write_Line
1252            ("warning: --RTS is taken into account only in auto-configuration");
1253       end if;
1254
1255       --  Parse the configuration file
1256
1257       if Verbose_Mode and then Config_File_Path /= null then
1258          Write_Str  ("Checking configuration ");
1259          Write_Line (Config_File_Path.all);
1260       end if;
1261
1262       if On_Load_Config /= null then
1263          On_Load_Config
1264            (Config_File       => Config_Project_Node,
1265             Project_Node_Tree => Project_Node_Tree);
1266
1267       elsif Config_File_Path /= null then
1268          Prj.Part.Parse
1269            (In_Tree                => Project_Node_Tree,
1270             Project                => Config_Project_Node,
1271             Project_File_Name      => Config_File_Path.all,
1272             Errout_Handling        => Prj.Part.Finalize_If_Error,
1273             Packages_To_Check      => Packages_To_Check,
1274             Current_Directory      => Current_Directory,
1275             Is_Config_File         => True,
1276             Env                    => Env);
1277       else
1278          Config_Project_Node := Empty_Node;
1279       end if;
1280
1281       if Config_Project_Node /= Empty_Node then
1282          Prj.Proc.Process_Project_Tree_Phase_1
1283            (In_Tree                => Project_Tree,
1284             Project                => Config,
1285             Success                => Success,
1286             From_Project_Node      => Config_Project_Node,
1287             From_Project_Node_Tree => Project_Node_Tree,
1288             Env                    => Env,
1289             Reset_Tree             => False);
1290       end if;
1291
1292       if Config_Project_Node = Empty_Node
1293         or else Config = No_Project
1294       then
1295          Raise_Invalid_Config
1296            ("processing of configuration project """
1297             & Config_File_Path.all & """ failed");
1298       end if;
1299
1300       --  Check that the target of the configuration file is the one the user
1301       --  specified on the command line. We do not need to check that when in
1302       --  auto-conf mode, since the appropriate target was passed to gprconfig.
1303
1304       if not Automatically_Generated
1305         and then not
1306           Check_Target (Config, Autoconf_Specified, Project_Tree, Target_Name)
1307       then
1308          Automatically_Generated := True;
1309          goto Process_Config_File;
1310       end if;
1311    end Get_Or_Create_Configuration_File;
1312
1313    ------------------------
1314    -- Locate_Config_File --
1315    ------------------------
1316
1317    function Locate_Config_File (Name : String) return String_Access is
1318       Prefix_Path : constant String := Executable_Prefix_Path;
1319    begin
1320       if Prefix_Path'Length /= 0 then
1321          return Locate_Regular_File
1322            (Name,
1323             "." & Path_Separator &
1324             Prefix_Path & "share" & Directory_Separator & "gpr");
1325       else
1326          return Locate_Regular_File (Name, ".");
1327       end if;
1328    end Locate_Config_File;
1329
1330    ------------------------------------
1331    -- Parse_Project_And_Apply_Config --
1332    ------------------------------------
1333
1334    procedure Parse_Project_And_Apply_Config
1335      (Main_Project               : out Prj.Project_Id;
1336       User_Project_Node          : out Prj.Tree.Project_Node_Id;
1337       Config_File_Name           : String := "";
1338       Autoconf_Specified         : Boolean;
1339       Project_File_Name          : String;
1340       Project_Tree               : Prj.Project_Tree_Ref;
1341       Project_Node_Tree          : Prj.Tree.Project_Node_Tree_Ref;
1342       Env                        : in out Prj.Tree.Environment;
1343       Packages_To_Check          : String_List_Access;
1344       Allow_Automatic_Generation : Boolean := True;
1345       Automatically_Generated    : out Boolean;
1346       Config_File_Path           : out String_Access;
1347       Target_Name                : String := "";
1348       Normalized_Hostname        : String;
1349       On_Load_Config             : Config_File_Hook := null)
1350    is
1351    begin
1352       pragma Assert (Prj.Env.Is_Initialized (Env.Project_Path));
1353
1354       --  Parse the user project tree
1355
1356       Prj.Initialize (Project_Tree);
1357
1358       Main_Project      := No_Project;
1359       Automatically_Generated := False;
1360
1361       Prj.Part.Parse
1362         (In_Tree                => Project_Node_Tree,
1363          Project                => User_Project_Node,
1364          Project_File_Name      => Project_File_Name,
1365          Errout_Handling        => Prj.Part.Finalize_If_Error,
1366          Packages_To_Check      => Packages_To_Check,
1367          Current_Directory      => Current_Directory,
1368          Is_Config_File         => False,
1369          Env                    => Env);
1370
1371       if User_Project_Node = Empty_Node then
1372          User_Project_Node := Empty_Node;
1373          return;
1374       end if;
1375
1376       Process_Project_And_Apply_Config
1377         (Main_Project               => Main_Project,
1378          User_Project_Node          => User_Project_Node,
1379          Config_File_Name           => Config_File_Name,
1380          Autoconf_Specified         => Autoconf_Specified,
1381          Project_Tree               => Project_Tree,
1382          Project_Node_Tree          => Project_Node_Tree,
1383          Env                        => Env,
1384          Packages_To_Check          => Packages_To_Check,
1385          Allow_Automatic_Generation => Allow_Automatic_Generation,
1386          Automatically_Generated    => Automatically_Generated,
1387          Config_File_Path           => Config_File_Path,
1388          Target_Name                => Target_Name,
1389          Normalized_Hostname        => Normalized_Hostname,
1390          On_Load_Config             => On_Load_Config);
1391    end Parse_Project_And_Apply_Config;
1392
1393    --------------------------------------
1394    -- Process_Project_And_Apply_Config --
1395    --------------------------------------
1396
1397    procedure Process_Project_And_Apply_Config
1398      (Main_Project               : out Prj.Project_Id;
1399       User_Project_Node          : Prj.Tree.Project_Node_Id;
1400       Config_File_Name           : String := "";
1401       Autoconf_Specified         : Boolean;
1402       Project_Tree               : Prj.Project_Tree_Ref;
1403       Project_Node_Tree          : Prj.Tree.Project_Node_Tree_Ref;
1404       Env                        : in out Prj.Tree.Environment;
1405       Packages_To_Check          : String_List_Access;
1406       Allow_Automatic_Generation : Boolean := True;
1407       Automatically_Generated    : out Boolean;
1408       Config_File_Path           : out String_Access;
1409       Target_Name                : String := "";
1410       Normalized_Hostname        : String;
1411       On_Load_Config             : Config_File_Hook := null;
1412       Reset_Tree                 : Boolean := True)
1413    is
1414       Shared : constant Shared_Project_Tree_Data_Access := Project_Tree.Shared;
1415       Main_Config_Project : Project_Id;
1416       Success : Boolean;
1417
1418    begin
1419       Main_Project := No_Project;
1420       Automatically_Generated := False;
1421
1422       Process_Project_Tree_Phase_1
1423         (In_Tree                => Project_Tree,
1424          Project                => Main_Project,
1425          Success                => Success,
1426          From_Project_Node      => User_Project_Node,
1427          From_Project_Node_Tree => Project_Node_Tree,
1428          Env                    => Env,
1429          Reset_Tree             => Reset_Tree);
1430
1431       if not Success then
1432          Main_Project := No_Project;
1433          return;
1434       end if;
1435
1436       if Project_Tree.Source_Info_File_Name /= null then
1437          if not Is_Absolute_Path (Project_Tree.Source_Info_File_Name.all) then
1438             declare
1439                Obj_Dir : constant Variable_Value :=
1440                  Value_Of
1441                    (Name_Object_Dir,
1442                     Main_Project.Decl.Attributes,
1443                     Shared);
1444
1445             begin
1446                if Obj_Dir = Nil_Variable_Value or else Obj_Dir.Default then
1447                   Get_Name_String (Main_Project.Directory.Display_Name);
1448
1449                else
1450                   if Is_Absolute_Path (Get_Name_String (Obj_Dir.Value)) then
1451                      Get_Name_String (Obj_Dir.Value);
1452
1453                   else
1454                      Name_Len := 0;
1455                      Add_Str_To_Name_Buffer
1456                        (Get_Name_String (Main_Project.Directory.Display_Name));
1457                      Add_Str_To_Name_Buffer (Get_Name_String (Obj_Dir.Value));
1458                   end if;
1459                end if;
1460
1461                Add_Char_To_Name_Buffer (Directory_Separator);
1462                Add_Str_To_Name_Buffer (Project_Tree.Source_Info_File_Name.all);
1463                Free (Project_Tree.Source_Info_File_Name);
1464                Project_Tree.Source_Info_File_Name :=
1465                  new String'(Name_Buffer (1 .. Name_Len));
1466             end;
1467          end if;
1468
1469          Read_Source_Info_File (Project_Tree);
1470       end if;
1471
1472       --  Find configuration file
1473
1474       Get_Or_Create_Configuration_File
1475         (Config                     => Main_Config_Project,
1476          Project                    => Main_Project,
1477          Project_Tree               => Project_Tree,
1478          Project_Node_Tree          => Project_Node_Tree,
1479          Env                        => Env,
1480          Allow_Automatic_Generation => Allow_Automatic_Generation,
1481          Config_File_Name           => Config_File_Name,
1482          Autoconf_Specified         => Autoconf_Specified,
1483          Target_Name                => Target_Name,
1484          Normalized_Hostname        => Normalized_Hostname,
1485          Packages_To_Check          => Packages_To_Check,
1486          Config_File_Path           => Config_File_Path,
1487          Automatically_Generated    => Automatically_Generated,
1488          On_Load_Config             => On_Load_Config);
1489
1490       Apply_Config_File (Main_Config_Project, Project_Tree);
1491
1492       --  Finish processing the user's project
1493
1494       Prj.Proc.Process_Project_Tree_Phase_2
1495         (In_Tree                    => Project_Tree,
1496          Project                    => Main_Project,
1497          Success                    => Success,
1498          From_Project_Node          => User_Project_Node,
1499          From_Project_Node_Tree     => Project_Node_Tree,
1500          Env                        => Env);
1501
1502       if Success then
1503          if Project_Tree.Source_Info_File_Name /= null and then
1504             not Project_Tree.Source_Info_File_Exists
1505          then
1506             Write_Source_Info_File (Project_Tree);
1507          end if;
1508
1509       else
1510          Main_Project := No_Project;
1511       end if;
1512    end Process_Project_And_Apply_Config;
1513
1514    --------------------------
1515    -- Raise_Invalid_Config --
1516    --------------------------
1517
1518    procedure Raise_Invalid_Config (Msg : String) is
1519    begin
1520       Raise_Exception (Invalid_Config'Identity, Msg);
1521    end Raise_Invalid_Config;
1522
1523    ----------------------
1524    -- Runtime_Name_For --
1525    ----------------------
1526
1527    function Runtime_Name_For (Language : Name_Id) return String is
1528    begin
1529       if RTS_Languages.Get (Language) /= No_Name then
1530          return Get_Name_String (RTS_Languages.Get (Language));
1531       else
1532          return "";
1533       end if;
1534    end Runtime_Name_For;
1535
1536    --------------------------
1537    -- Runtime_Name_Set_For --
1538    --------------------------
1539
1540    function Runtime_Name_Set_For (Language : Name_Id) return Boolean is
1541    begin
1542       return RTS_Languages.Get (Language) /= No_Name;
1543    end Runtime_Name_Set_For;
1544
1545    ---------------------
1546    -- Set_Runtime_For --
1547    ---------------------
1548
1549    procedure Set_Runtime_For (Language : Name_Id; RTS_Name : String) is
1550    begin
1551       Name_Len := RTS_Name'Length;
1552       Name_Buffer (1 .. Name_Len) := RTS_Name;
1553       RTS_Languages.Set (Language, Name_Find);
1554    end Set_Runtime_For;
1555
1556 end Prj.Conf;