OSDN Git Service

Minor reformatting.
[pf3gnuchains/gcc-fork.git] / gcc / ada / prj-env.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                              P R J . E N V                               --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 2001-2009, 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 Fmap;
27 with Opt;
28 with Osint;    use Osint;
29 with Output;   use Output;
30 with Prj.Com;  use Prj.Com;
31 with Tempdir;
32
33 package body Prj.Env is
34
35    Buffer_Initial : constant := 1_000;
36    --  Initial size of Buffer
37
38    -----------------------
39    -- Local Subprograms --
40    -----------------------
41
42    package Source_Path_Table is new GNAT.Dynamic_Tables
43      (Table_Component_Type => Name_Id,
44       Table_Index_Type     => Natural,
45       Table_Low_Bound      => 1,
46       Table_Initial        => 50,
47       Table_Increment      => 100);
48    --  A table to store the source dirs before creating the source path file
49
50    package Object_Path_Table is new GNAT.Dynamic_Tables
51      (Table_Component_Type => Path_Name_Type,
52       Table_Index_Type     => Natural,
53       Table_Low_Bound      => 1,
54       Table_Initial        => 50,
55       Table_Increment      => 100);
56    --  A table to store the object dirs, before creating the object path file
57
58    procedure Add_To_Buffer
59      (S           : String;
60       Buffer      : in out String_Access;
61       Buffer_Last : in out Natural);
62    --  Add a string to Buffer, extending Buffer if needed
63
64    procedure Add_To_Path
65      (Source_Dirs : String_List_Id;
66       In_Tree     : Project_Tree_Ref;
67       Buffer      : in out String_Access;
68       Buffer_Last : in out Natural);
69    --  Add to Ada_Path_Buffer all the source directories in string list
70    --  Source_Dirs, if any.
71
72    procedure Add_To_Path
73      (Dir         : String;
74       Buffer      : in out String_Access;
75       Buffer_Last : in out Natural);
76    --  If Dir is not already in the global variable Ada_Path_Buffer, add it.
77    --  If Buffer_Last /= 0, prepend a Path_Separator character to Path.
78
79    procedure Add_To_Source_Path
80      (Source_Dirs  : String_List_Id;
81       In_Tree      : Project_Tree_Ref;
82       Source_Paths : in out Source_Path_Table.Instance);
83    --  Add to Ada_Path_B all the source directories in string list
84    --  Source_Dirs, if any. Increment Ada_Path_Length.
85
86    procedure Add_To_Object_Path
87      (Object_Dir   : Path_Name_Type;
88       Object_Paths : in out Object_Path_Table.Instance);
89    --  Add Object_Dir to object path table. Make sure it is not duplicate
90    --  and it is the last one in the current table.
91
92    procedure Set_Path_File_Var (Name : String; Value : String);
93    --  Call Setenv, after calling To_Host_File_Spec
94
95    function Ultimate_Extension_Of
96      (Project : Project_Id) return Project_Id;
97    --  Return a project that is either Project or an extended ancestor of
98    --  Project that itself is not extended.
99
100    procedure Create_Temp_File
101      (In_Tree   : Project_Tree_Ref;
102       Path_FD   : out File_Descriptor;
103       Path_Name : out Path_Name_Type;
104       File_Use  : String);
105    --  Create a temporary file, and fail with an error if it could not be
106    --  created.
107
108    ----------------------
109    -- Ada_Include_Path --
110    ----------------------
111
112    function Ada_Include_Path
113      (Project   : Project_Id;
114       In_Tree   : Project_Tree_Ref;
115       Recursive : Boolean := False) return String
116    is
117       Buffer      : String_Access;
118       Buffer_Last : Natural := 0;
119
120       procedure Add (Project : Project_Id; Dummy : in out Boolean);
121       --  Add source dirs of Project to the path
122
123       ---------
124       -- Add --
125       ---------
126
127       procedure Add (Project : Project_Id; Dummy : in out Boolean) is
128          pragma Unreferenced (Dummy);
129       begin
130          Add_To_Path (Project.Source_Dirs, In_Tree, Buffer, Buffer_Last);
131       end Add;
132
133       procedure For_All_Projects is
134         new For_Every_Project_Imported (Boolean, Add);
135
136       Dummy : Boolean := False;
137
138    --  Start of processing for Ada_Include_Path
139
140    begin
141       if Recursive then
142
143          --  If it is the first time we call this function for
144          --  this project, compute the source path
145
146          if Project.Ada_Include_Path = null then
147             Buffer := new String (1 .. 4096);
148             For_All_Projects (Project, Dummy);
149             Project.Ada_Include_Path := new String'(Buffer (1 .. Buffer_Last));
150             Free (Buffer);
151          end if;
152
153          return Project.Ada_Include_Path.all;
154
155       else
156          Buffer := new String (1 .. 4096);
157          Add_To_Path (Project.Source_Dirs, In_Tree, Buffer, Buffer_Last);
158
159          declare
160             Result : constant String := Buffer (1 .. Buffer_Last);
161          begin
162             Free (Buffer);
163             return Result;
164          end;
165       end if;
166    end Ada_Include_Path;
167
168    ----------------------
169    -- Ada_Objects_Path --
170    ----------------------
171
172    function Ada_Objects_Path
173      (Project             : Project_Id;
174       Including_Libraries : Boolean := True) return String_Access
175    is
176       Buffer      : String_Access;
177       Buffer_Last : Natural := 0;
178
179       procedure Add (Project : Project_Id; Dummy : in out Boolean);
180       --  Add all the object directories of a project to the path
181
182       ---------
183       -- Add --
184       ---------
185
186       procedure Add (Project : Project_Id; Dummy : in out Boolean) is
187          pragma Unreferenced (Dummy);
188          Path : constant Path_Name_Type :=
189                   Get_Object_Directory
190                     (Project,
191                      Including_Libraries => Including_Libraries,
192                      Only_If_Ada         => False);
193       begin
194          if Path /= No_Path then
195             Add_To_Path (Get_Name_String (Path), Buffer, Buffer_Last);
196          end if;
197       end Add;
198
199       procedure For_All_Projects is
200         new For_Every_Project_Imported (Boolean, Add);
201
202       Dummy : Boolean := False;
203
204    --  Start of processing for Ada_Objects_Path
205
206    begin
207       --  If it is the first time we call this function for
208       --  this project, compute the objects path
209
210       if Project.Ada_Objects_Path = null then
211          Buffer := new String (1 .. 4096);
212          For_All_Projects (Project, Dummy);
213
214          Project.Ada_Objects_Path := new String'(Buffer (1 .. Buffer_Last));
215          Free (Buffer);
216       end if;
217
218       return Project.Ada_Objects_Path;
219    end Ada_Objects_Path;
220
221    -------------------
222    -- Add_To_Buffer --
223    -------------------
224
225    procedure Add_To_Buffer
226      (S           : String;
227       Buffer      : in out String_Access;
228       Buffer_Last : in out Natural)
229    is
230       Last : constant Natural := Buffer_Last + S'Length;
231
232    begin
233       while Last > Buffer'Last loop
234          declare
235             New_Buffer : constant String_Access :=
236                            new String (1 .. 2 * Buffer'Last);
237          begin
238             New_Buffer (1 .. Buffer_Last) := Buffer (1 .. Buffer_Last);
239             Free (Buffer);
240             Buffer := New_Buffer;
241          end;
242       end loop;
243
244       Buffer (Buffer_Last + 1 .. Last) := S;
245       Buffer_Last := Last;
246    end Add_To_Buffer;
247
248    ------------------------
249    -- Add_To_Object_Path --
250    ------------------------
251
252    procedure Add_To_Object_Path
253      (Object_Dir   : Path_Name_Type;
254       Object_Paths : in out Object_Path_Table.Instance)
255    is
256    begin
257       --  Check if the directory is already in the table
258
259       for Index in Object_Path_Table.First ..
260                    Object_Path_Table.Last (Object_Paths)
261       loop
262
263          --  If it is, remove it, and add it as the last one
264
265          if Object_Paths.Table (Index) = Object_Dir then
266             for Index2 in Index + 1 ..
267                           Object_Path_Table.Last (Object_Paths)
268             loop
269                Object_Paths.Table (Index2 - 1) := Object_Paths.Table (Index2);
270             end loop;
271
272             Object_Paths.Table
273               (Object_Path_Table.Last (Object_Paths)) := Object_Dir;
274             return;
275          end if;
276       end loop;
277
278       --  The directory is not already in the table, add it
279
280       Object_Path_Table.Append (Object_Paths, Object_Dir);
281    end Add_To_Object_Path;
282
283    -----------------
284    -- Add_To_Path --
285    -----------------
286
287    procedure Add_To_Path
288      (Source_Dirs : String_List_Id;
289       In_Tree     : Project_Tree_Ref;
290       Buffer      : in out String_Access;
291       Buffer_Last : in out Natural)
292    is
293       Current    : String_List_Id := Source_Dirs;
294       Source_Dir : String_Element;
295    begin
296       while Current /= Nil_String loop
297          Source_Dir := In_Tree.String_Elements.Table (Current);
298          Add_To_Path (Get_Name_String (Source_Dir.Display_Value),
299                       Buffer, Buffer_Last);
300          Current := Source_Dir.Next;
301       end loop;
302    end Add_To_Path;
303
304    procedure Add_To_Path
305      (Dir         : String;
306       Buffer      : in out String_Access;
307       Buffer_Last : in out Natural)
308    is
309       Len        : Natural;
310       New_Buffer : String_Access;
311       Min_Len    : Natural;
312
313       function Is_Present (Path : String; Dir : String) return Boolean;
314       --  Return True if Dir is part of Path
315
316       ----------------
317       -- Is_Present --
318       ----------------
319
320       function Is_Present (Path : String; Dir : String) return Boolean is
321          Last : constant Integer := Path'Last - Dir'Length + 1;
322
323       begin
324          for J in Path'First .. Last loop
325
326             --  Note: the order of the conditions below is important, since
327             --  it ensures a minimal number of string comparisons.
328
329             if (J = Path'First
330                 or else Path (J - 1) = Path_Separator)
331               and then
332                 (J + Dir'Length > Path'Last
333                  or else Path (J + Dir'Length) = Path_Separator)
334               and then Dir = Path (J .. J + Dir'Length - 1)
335             then
336                return True;
337             end if;
338          end loop;
339
340          return False;
341       end Is_Present;
342
343    --  Start of processing for Add_To_Path
344
345    begin
346       if Is_Present (Buffer (1 .. Buffer_Last), Dir) then
347
348          --  Dir is already in the path, nothing to do
349
350          return;
351       end if;
352
353       Min_Len := Buffer_Last + Dir'Length;
354
355       if Buffer_Last > 0 then
356
357          --  Add 1 for the Path_Separator character
358
359          Min_Len := Min_Len + 1;
360       end if;
361
362       --  If Ada_Path_Buffer is too small, increase it
363
364       Len := Buffer'Last;
365
366       if Len < Min_Len then
367          loop
368             Len := Len * 2;
369             exit when Len >= Min_Len;
370          end loop;
371
372          New_Buffer := new String (1 .. Len);
373          New_Buffer (1 .. Buffer_Last) := Buffer (1 .. Buffer_Last);
374          Free (Buffer);
375          Buffer := New_Buffer;
376       end if;
377
378       if Buffer_Last > 0 then
379          Buffer_Last := Buffer_Last + 1;
380          Buffer (Buffer_Last) := Path_Separator;
381       end if;
382
383       Buffer (Buffer_Last + 1 .. Buffer_Last + Dir'Length) := Dir;
384       Buffer_Last := Buffer_Last + Dir'Length;
385    end Add_To_Path;
386
387    ------------------------
388    -- Add_To_Source_Path --
389    ------------------------
390
391    procedure Add_To_Source_Path
392      (Source_Dirs  : String_List_Id;
393       In_Tree      : Project_Tree_Ref;
394       Source_Paths : in out Source_Path_Table.Instance)
395    is
396       Current    : String_List_Id := Source_Dirs;
397       Source_Dir : String_Element;
398       Add_It     : Boolean;
399
400    begin
401       --  Add each source directory
402
403       while Current /= Nil_String loop
404          Source_Dir := In_Tree.String_Elements.Table (Current);
405          Add_It := True;
406
407          --  Check if the source directory is already in the table
408
409          for Index in Source_Path_Table.First ..
410                       Source_Path_Table.Last (Source_Paths)
411          loop
412             --  If it is already, no need to add it
413
414             if Source_Paths.Table (Index) = Source_Dir.Value then
415                Add_It := False;
416                exit;
417             end if;
418          end loop;
419
420          if Add_It then
421             Source_Path_Table.Append (Source_Paths, Source_Dir.Value);
422          end if;
423
424          --  Next source directory
425
426          Current := Source_Dir.Next;
427       end loop;
428    end Add_To_Source_Path;
429
430    --------------------------------
431    -- Create_Config_Pragmas_File --
432    --------------------------------
433
434    procedure Create_Config_Pragmas_File
435      (For_Project : Project_Id;
436       In_Tree     : Project_Tree_Ref)
437    is
438       type Naming_Id is new Nat;
439       package Naming_Table is new GNAT.Dynamic_Tables
440         (Table_Component_Type => Lang_Naming_Data,
441          Table_Index_Type     => Naming_Id,
442          Table_Low_Bound      => 1,
443          Table_Initial        => 5,
444          Table_Increment      => 100);
445       Default_Naming : constant Naming_Id := Naming_Table.First;
446       Namings        : Naming_Table.Instance;
447       --  Table storing the naming data for gnatmake/gprmake
448
449       Buffer      : String_Access := new String (1 .. Buffer_Initial);
450       Buffer_Last : Natural := 0;
451
452       File_Name : Path_Name_Type  := No_Path;
453       File      : File_Descriptor := Invalid_FD;
454
455       Current_Naming  : Naming_Id;
456       Iter            : Source_Iterator;
457       Source          : Source_Id;
458
459       procedure Check (Project : Project_Id; State : in out Integer);
460       --  Recursive procedure that put in the config pragmas file any non
461       --  standard naming schemes, if it is not already in the file, then call
462       --  itself for any imported project.
463
464       procedure Put (Source : Source_Id);
465       --  Put an SFN pragma in the temporary file
466
467       procedure Put (S : String);
468       procedure Put_Line (S : String);
469       --  Output procedures, analogous to normal Text_IO procs of same name.
470       --  The text is put in Buffer, then it will be writen into a temporary
471       --  file with procedure Write_Temp_File below.
472
473       procedure Write_Temp_File;
474       --  Create a temporary file and put the content of the buffer in it
475
476       -----------
477       -- Check --
478       -----------
479
480       procedure Check (Project : Project_Id; State : in out Integer) is
481          pragma Unreferenced (State);
482          Lang   : constant Language_Ptr :=
483                     Get_Language_From_Name (Project, "ada");
484          Naming : Lang_Naming_Data;
485
486       begin
487          if Current_Verbosity = High then
488             Write_Str ("Checking project file """);
489             Write_Str (Namet.Get_Name_String (Project.Name));
490             Write_Str (""".");
491             Write_Eol;
492          end if;
493
494          if Lang = null then
495             if Current_Verbosity = High then
496                Write_Line ("   Languages does not contain Ada, nothing to do");
497             end if;
498
499             return;
500          end if;
501
502          Naming := Lang.Config.Naming_Data;
503
504          --  Is the naming scheme of this project one that we know?
505
506          Current_Naming := Default_Naming;
507          while Current_Naming <= Naming_Table.Last (Namings)
508            and then Namings.Table (Current_Naming).Dot_Replacement =
509                                                     Naming.Dot_Replacement
510            and then Namings.Table (Current_Naming).Casing =
511                                                     Naming.Casing
512            and then Namings.Table (Current_Naming).Separate_Suffix =
513                                                     Naming.Separate_Suffix
514          loop
515             Current_Naming := Current_Naming + 1;
516          end loop;
517
518          --  If we don't know it, add it
519
520          if Current_Naming > Naming_Table.Last (Namings) then
521             Naming_Table.Increment_Last (Namings);
522             Namings.Table (Naming_Table.Last (Namings)) := Naming;
523
524             --  Put the SFN pragmas for the naming scheme
525
526             --  Spec
527
528             Put_Line
529               ("pragma Source_File_Name_Project");
530             Put_Line
531               ("  (Spec_File_Name  => ""*" &
532                Get_Name_String (Naming.Spec_Suffix) & """,");
533             Put_Line
534               ("   Casing          => " &
535                Image (Naming.Casing) & ",");
536             Put_Line
537               ("   Dot_Replacement => """ &
538                Get_Name_String (Naming.Dot_Replacement) & """);");
539
540             --  and body
541
542             Put_Line
543               ("pragma Source_File_Name_Project");
544             Put_Line
545               ("  (Body_File_Name  => ""*" &
546                Get_Name_String (Naming.Body_Suffix) & """,");
547             Put_Line
548               ("   Casing          => " &
549                Image (Naming.Casing) & ",");
550             Put_Line
551               ("   Dot_Replacement => """ &
552                Get_Name_String (Naming.Dot_Replacement) &
553                """);");
554
555             --  and maybe separate
556
557             if Naming.Body_Suffix /= Naming.Separate_Suffix then
558                Put_Line ("pragma Source_File_Name_Project");
559                Put_Line
560                  ("  (Subunit_File_Name  => ""*" &
561                   Get_Name_String (Naming.Separate_Suffix) & """,");
562                Put_Line
563                  ("   Casing          => " &
564                   Image (Naming.Casing) & ",");
565                Put_Line
566                  ("   Dot_Replacement => """ &
567                   Get_Name_String (Naming.Dot_Replacement) &
568                   """);");
569             end if;
570          end if;
571       end Check;
572
573       ---------
574       -- Put --
575       ---------
576
577       procedure Put (Source : Source_Id) is
578       begin
579          --  Put the pragma SFN for the unit kind (spec or body)
580
581          Put ("pragma Source_File_Name_Project (");
582          Put (Namet.Get_Name_String (Source.Unit.Name));
583
584          if Source.Kind = Spec then
585             Put (", Spec_File_Name => """);
586          else
587             Put (", Body_File_Name => """);
588          end if;
589
590          Put (Namet.Get_Name_String (Source.File));
591          Put ("""");
592
593          if Source.Index /= 0 then
594             Put (", Index =>");
595             Put (Source.Index'Img);
596          end if;
597
598          Put_Line (");");
599       end Put;
600
601       procedure Put (S : String) is
602       begin
603          Add_To_Buffer (S, Buffer, Buffer_Last);
604
605          if Current_Verbosity = High then
606             Write_Str (S);
607          end if;
608       end Put;
609
610       --------------
611       -- Put_Line --
612       --------------
613
614       procedure Put_Line (S : String) is
615       begin
616          --  Add an ASCII.LF to the string. As this config file is supposed to
617          --  be used only by the compiler, we don't care about the characters
618          --  for the end of line. In fact we could have put a space, but
619          --  it is more convenient to be able to read gnat.adc during
620          --  development, for which the ASCII.LF is fine.
621
622          Put (S);
623          Put (S => (1 => ASCII.LF));
624       end Put_Line;
625
626       ---------------------
627       -- Write_Temp_File --
628       ---------------------
629
630       procedure Write_Temp_File is
631          Status : Boolean := False;
632          Last   : Natural;
633
634       begin
635          Tempdir.Create_Temp_File (File, File_Name);
636
637          if File /= Invalid_FD then
638             Last := Write (File, Buffer (1)'Address, Buffer_Last);
639
640             if Last = Buffer_Last then
641                Close (File, Status);
642             end if;
643          end if;
644
645          if not Status then
646             Prj.Com.Fail ("unable to create temporary file");
647          end if;
648       end Write_Temp_File;
649
650       procedure Check_Imported_Projects is
651         new For_Every_Project_Imported (Integer, Check);
652
653       Dummy : Integer := 0;
654
655    --  Start of processing for Create_Config_Pragmas_File
656
657    begin
658       if not For_Project.Config_Checked then
659          Naming_Table.Init (Namings);
660
661          --  Check the naming schemes
662
663          Check_Imported_Projects (For_Project, Dummy, Imported_First => False);
664
665          --  Visit all the files and process those that need an SFN pragma
666
667          Iter := For_Each_Source (In_Tree, For_Project);
668          while Element (Iter) /= No_Source loop
669             Source := Element (Iter);
670
671             if Source.Index >= 1
672               and then not Source.Locally_Removed
673               and then Source.Unit /= null
674             then
675                Put (Source);
676             end if;
677
678             Next (Iter);
679          end loop;
680
681          --  If there are no non standard naming scheme, issue the GNAT
682          --  standard naming scheme. This will tell the compiler that
683          --  a project file is used and will forbid any pragma SFN.
684
685          if Buffer_Last = 0 then
686
687             Put_Line ("pragma Source_File_Name_Project");
688             Put_Line ("   (Spec_File_Name  => ""*.ads"",");
689             Put_Line ("    Dot_Replacement => ""-"",");
690             Put_Line ("    Casing          => lowercase);");
691
692             Put_Line ("pragma Source_File_Name_Project");
693             Put_Line ("   (Body_File_Name  => ""*.adb"",");
694             Put_Line ("    Dot_Replacement => ""-"",");
695             Put_Line ("    Casing          => lowercase);");
696          end if;
697
698          --  Close the temporary file
699
700          Write_Temp_File;
701
702          if Opt.Verbose_Mode then
703             Write_Str ("Created configuration file """);
704             Write_Str (Get_Name_String (File_Name));
705             Write_Line ("""");
706          end if;
707
708          For_Project.Config_File_Name := File_Name;
709          For_Project.Config_File_Temp := True;
710          For_Project.Config_Checked   := True;
711       end if;
712
713       Free (Buffer);
714    end Create_Config_Pragmas_File;
715
716    --------------------
717    -- Create_Mapping --
718    --------------------
719
720    procedure Create_Mapping (In_Tree : Project_Tree_Ref) is
721       Data : Source_Id;
722       Iter : Source_Iterator;
723
724    begin
725       Fmap.Reset_Tables;
726
727       Iter := For_Each_Source (In_Tree);
728       loop
729          Data := Element (Iter);
730          exit when Data = No_Source;
731
732          if Data.Unit /= No_Unit_Index then
733             if Data.Locally_Removed then
734                Fmap.Add_Forbidden_File_Name (Data.File);
735             else
736                Fmap.Add_To_File_Map
737                  (Unit_Name => Unit_Name_Type (Data.Unit.Name),
738                   File_Name => Data.File,
739                   Path_Name => File_Name_Type (Data.Path.Name));
740             end if;
741          end if;
742
743          Next (Iter);
744       end loop;
745    end Create_Mapping;
746
747    -------------------------
748    -- Create_Mapping_File --
749    -------------------------
750
751    procedure Create_Mapping_File
752      (Project  : Project_Id;
753       Language : Name_Id;
754       In_Tree  : Project_Tree_Ref;
755       Name     : out Path_Name_Type)
756    is
757       File   : File_Descriptor := Invalid_FD;
758
759       Buffer : String_Access := new String (1 .. Buffer_Initial);
760       Buffer_Last : Natural := 0;
761
762       procedure Put_Name_Buffer;
763       --  Put the line contained in the Name_Buffer in the global buffer
764
765       procedure Process (Project : Project_Id; State : in out Integer);
766       --  Generate the mapping file for Project (not recursively)
767
768       ---------------------
769       -- Put_Name_Buffer --
770       ---------------------
771
772       procedure Put_Name_Buffer is
773       begin
774          Name_Len := Name_Len + 1;
775          Name_Buffer (Name_Len) := ASCII.LF;
776
777          if Current_Verbosity = High then
778             Write_Str ("Mapping file: " & Name_Buffer (1 .. Name_Len));
779          end if;
780
781          Add_To_Buffer (Name_Buffer (1 .. Name_Len), Buffer, Buffer_Last);
782       end Put_Name_Buffer;
783
784       -------------
785       -- Process --
786       -------------
787
788       procedure Process (Project : Project_Id; State : in out Integer) is
789          pragma Unreferenced (State);
790          Source : Source_Id;
791          Suffix : File_Name_Type;
792          Iter   : Source_Iterator;
793
794       begin
795          Iter := For_Each_Source (In_Tree, Project, Language => Language);
796
797          loop
798             Source := Prj.Element (Iter);
799             exit when Source = No_Source;
800
801             if Source.Replaced_By = No_Source
802               and then Source.Path.Name /= No_Path
803               and then
804                 (Source.Language.Config.Kind = File_Based
805                   or else Source.Unit /= No_Unit_Index)
806             then
807                if Source.Unit /= No_Unit_Index then
808                   Get_Name_String (Source.Unit.Name);
809
810                   if Source.Language.Config.Kind = Unit_Based then
811
812                      --  ??? Mapping_Spec_Suffix could be set in the case of
813                      --  gnatmake as well
814
815                      Add_Char_To_Name_Buffer ('%');
816
817                      if Source.Kind = Spec then
818                         Add_Char_To_Name_Buffer ('s');
819                      else
820                         Add_Char_To_Name_Buffer ('b');
821                      end if;
822
823                   else
824                      case Source.Kind is
825                         when Spec =>
826                            Suffix :=
827                              Source.Language.Config.Mapping_Spec_Suffix;
828                         when Impl | Sep =>
829                            Suffix :=
830                              Source.Language.Config.Mapping_Body_Suffix;
831                      end case;
832
833                      if Suffix /= No_File then
834                         Add_Str_To_Name_Buffer
835                           (Get_Name_String (Suffix));
836                      end if;
837                   end if;
838
839                   Put_Name_Buffer;
840                end if;
841
842                Get_Name_String (Source.File);
843                Put_Name_Buffer;
844
845                if Source.Locally_Removed then
846                   Name_Len := 1;
847                   Name_Buffer (1) := '/';
848                else
849                   Get_Name_String (Source.Path.Name);
850                end if;
851
852                Put_Name_Buffer;
853             end if;
854
855             Next (Iter);
856          end loop;
857       end Process;
858
859       procedure For_Every_Imported_Project is new
860         For_Every_Project_Imported (State => Integer, Action => Process);
861
862       Dummy : Integer := 0;
863
864    --  Start of processing for Create_Mapping_File
865
866    begin
867       For_Every_Imported_Project (Project, Dummy);
868
869       declare
870          Last   : Natural;
871          Status : Boolean := False;
872
873       begin
874          Create_Temp_File (In_Tree, File, Name, "mapping");
875
876          if File /= Invalid_FD then
877             Last := Write (File, Buffer (1)'Address, Buffer_Last);
878
879             if Last = Buffer_Last then
880                GNAT.OS_Lib.Close (File, Status);
881             end if;
882          end if;
883
884          if not Status then
885             Prj.Com.Fail ("could not write mapping file");
886          end if;
887       end;
888
889       Free (Buffer);
890    end Create_Mapping_File;
891
892    ----------------------
893    -- Create_Temp_File --
894    ----------------------
895
896    procedure Create_Temp_File
897      (In_Tree   : Project_Tree_Ref;
898       Path_FD   : out File_Descriptor;
899       Path_Name : out Path_Name_Type;
900       File_Use  : String)
901    is
902    begin
903       Tempdir.Create_Temp_File (Path_FD, Path_Name);
904
905       if Path_Name /= No_Path then
906          if Current_Verbosity = High then
907             Write_Line ("Create temp file (" & File_Use & ") "
908                         & Get_Name_String (Path_Name));
909          end if;
910
911          Record_Temp_File (In_Tree, Path_Name);
912
913       else
914          Prj.Com.Fail
915            ("unable to create temporary " & File_Use & " file");
916       end if;
917    end Create_Temp_File;
918
919    --------------------------
920    -- Create_New_Path_File --
921    --------------------------
922
923    procedure Create_New_Path_File
924      (In_Tree   : Project_Tree_Ref;
925       Path_FD   : out File_Descriptor;
926       Path_Name : out Path_Name_Type)
927    is
928    begin
929       Create_Temp_File (In_Tree, Path_FD, Path_Name, "path file");
930    end Create_New_Path_File;
931
932    ------------------------------------
933    -- File_Name_Of_Library_Unit_Body --
934    ------------------------------------
935
936    function File_Name_Of_Library_Unit_Body
937      (Name              : String;
938       Project           : Project_Id;
939       In_Tree           : Project_Tree_Ref;
940       Main_Project_Only : Boolean := True;
941       Full_Path         : Boolean := False) return String
942    is
943       The_Project   : Project_Id := Project;
944       Original_Name : String := Name;
945
946       Lang   : constant Language_Ptr :=
947         Get_Language_From_Name (Project, "ada");
948
949       Unit              : Unit_Index;
950       The_Original_Name : Name_Id;
951       The_Spec_Name     : Name_Id;
952       The_Body_Name     : Name_Id;
953
954    begin
955       --  ??? Same block in Project_Of
956       Canonical_Case_File_Name (Original_Name);
957       Name_Len := Original_Name'Length;
958       Name_Buffer (1 .. Name_Len) := Original_Name;
959       The_Original_Name := Name_Find;
960
961       if Lang /= null then
962          declare
963             Naming : constant Lang_Naming_Data := Lang.Config.Naming_Data;
964             Extended_Spec_Name : String :=
965                                    Name & Namet.Get_Name_String
966                                             (Naming.Spec_Suffix);
967             Extended_Body_Name : String :=
968                                    Name & Namet.Get_Name_String
969                                             (Naming.Body_Suffix);
970
971          begin
972             Canonical_Case_File_Name (Extended_Spec_Name);
973             Name_Len := Extended_Spec_Name'Length;
974             Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
975             The_Spec_Name := Name_Find;
976
977             Canonical_Case_File_Name (Extended_Body_Name);
978             Name_Len := Extended_Body_Name'Length;
979             Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
980             The_Body_Name := Name_Find;
981          end;
982
983       else
984          Name_Len := Name'Length;
985          Name_Buffer (1 .. Name_Len) := Name;
986          Canonical_Case_File_Name (Name_Buffer);
987          The_Spec_Name := Name_Find;
988          The_Body_Name := The_Spec_Name;
989       end if;
990
991       if Current_Verbosity = High then
992          Write_Str  ("Looking for file name of """);
993          Write_Str  (Name);
994          Write_Char ('"');
995          Write_Eol;
996          Write_Str  ("   Extended Spec Name = """);
997          Write_Str  (Get_Name_String (The_Spec_Name));
998          Write_Char ('"');
999          Write_Eol;
1000          Write_Str  ("   Extended Body Name = """);
1001          Write_Str  (Get_Name_String (The_Body_Name));
1002          Write_Char ('"');
1003          Write_Eol;
1004       end if;
1005
1006       --  For extending project, search in the extended project if the source
1007       --  is not found. For non extending projects, this loop will be run only
1008       --  once.
1009
1010       loop
1011          --  Loop through units
1012
1013          Unit := Units_Htable.Get_First (In_Tree.Units_HT);
1014          while Unit /= null loop
1015             --  Check for body
1016
1017             if not Main_Project_Only
1018               or else
1019                 (Unit.File_Names (Impl) /= null
1020                  and then Unit.File_Names (Impl).Project = The_Project)
1021             then
1022                declare
1023                   Current_Name : File_Name_Type;
1024                begin
1025                   --  Case of a body present
1026
1027                   if Unit.File_Names (Impl) /= null then
1028                      Current_Name := Unit.File_Names (Impl).File;
1029
1030                      if Current_Verbosity = High then
1031                         Write_Str  ("   Comparing with """);
1032                         Write_Str  (Get_Name_String (Current_Name));
1033                         Write_Char ('"');
1034                         Write_Eol;
1035                      end if;
1036
1037                      --  If it has the name of the original name, return the
1038                      --  original name.
1039
1040                      if Unit.Name = The_Original_Name
1041                        or else
1042                          Current_Name = File_Name_Type (The_Original_Name)
1043                      then
1044                         if Current_Verbosity = High then
1045                            Write_Line ("   OK");
1046                         end if;
1047
1048                         if Full_Path then
1049                            return Get_Name_String
1050                              (Unit.File_Names (Impl).Path.Name);
1051
1052                         else
1053                            return Get_Name_String (Current_Name);
1054                         end if;
1055
1056                         --  If it has the name of the extended body name,
1057                         --  return the extended body name
1058
1059                      elsif Current_Name = File_Name_Type (The_Body_Name) then
1060                         if Current_Verbosity = High then
1061                            Write_Line ("   OK");
1062                         end if;
1063
1064                         if Full_Path then
1065                            return Get_Name_String
1066                              (Unit.File_Names (Impl).Path.Name);
1067
1068                         else
1069                            return Get_Name_String (The_Body_Name);
1070                         end if;
1071
1072                      else
1073                         if Current_Verbosity = High then
1074                            Write_Line ("   not good");
1075                         end if;
1076                      end if;
1077                   end if;
1078                end;
1079             end if;
1080
1081             --  Check for spec
1082
1083             if not Main_Project_Only
1084               or else
1085                 (Unit.File_Names (Spec) /= null
1086                  and then Unit.File_Names (Spec).Project =
1087                    The_Project)
1088             then
1089                declare
1090                   Current_Name : File_Name_Type;
1091
1092                begin
1093                   --  Case of spec present
1094
1095                   if Unit.File_Names (Spec) /= null then
1096                      Current_Name := Unit.File_Names (Spec).File;
1097                      if Current_Verbosity = High then
1098                         Write_Str  ("   Comparing with """);
1099                         Write_Str  (Get_Name_String (Current_Name));
1100                         Write_Char ('"');
1101                         Write_Eol;
1102                      end if;
1103
1104                      --  If name same as original name, return original name
1105
1106                      if Unit.Name = The_Original_Name
1107                        or else
1108                          Current_Name = File_Name_Type (The_Original_Name)
1109                      then
1110                         if Current_Verbosity = High then
1111                            Write_Line ("   OK");
1112                         end if;
1113
1114                         if Full_Path then
1115                            return Get_Name_String
1116                              (Unit.File_Names (Spec).Path.Name);
1117                         else
1118                            return Get_Name_String (Current_Name);
1119                         end if;
1120
1121                         --  If it has the same name as the extended spec name,
1122                         --  return the extended spec name.
1123
1124                      elsif Current_Name = File_Name_Type (The_Spec_Name) then
1125                         if Current_Verbosity = High then
1126                            Write_Line ("   OK");
1127                         end if;
1128
1129                         if Full_Path then
1130                            return Get_Name_String
1131                              (Unit.File_Names (Spec).Path.Name);
1132                         else
1133                            return Get_Name_String (The_Spec_Name);
1134                         end if;
1135
1136                      else
1137                         if Current_Verbosity = High then
1138                            Write_Line ("   not good");
1139                         end if;
1140                      end if;
1141                   end if;
1142                end;
1143             end if;
1144
1145             Unit := Units_Htable.Get_Next (In_Tree.Units_HT);
1146          end loop;
1147
1148          --  If we are not in an extending project, give up
1149
1150          exit when not Main_Project_Only
1151            or else The_Project.Extends = No_Project;
1152
1153          --  Otherwise, look in the project we are extending
1154
1155          The_Project := The_Project.Extends;
1156       end loop;
1157
1158       --  We don't know this file name, return an empty string
1159
1160       return "";
1161    end File_Name_Of_Library_Unit_Body;
1162
1163    -------------------------
1164    -- For_All_Object_Dirs --
1165    -------------------------
1166
1167    procedure For_All_Object_Dirs (Project : Project_Id) is
1168       procedure For_Project (Prj : Project_Id; Dummy : in out Integer);
1169       --  Get all object directories of Prj
1170
1171       -----------------
1172       -- For_Project --
1173       -----------------
1174
1175       procedure For_Project (Prj : Project_Id; Dummy : in out Integer) is
1176          pragma Unreferenced (Dummy);
1177       begin
1178          --  ??? Set_Ada_Paths has a different behavior for library project
1179          --  files, should we have the same ?
1180
1181          if Prj.Object_Directory /= No_Path_Information then
1182             Get_Name_String (Prj.Object_Directory.Display_Name);
1183             Action (Name_Buffer (1 .. Name_Len));
1184          end if;
1185       end For_Project;
1186
1187       procedure Get_Object_Dirs is
1188         new For_Every_Project_Imported (Integer, For_Project);
1189       Dummy : Integer := 1;
1190
1191    --  Start of processing for For_All_Object_Dirs
1192
1193    begin
1194       Get_Object_Dirs (Project, Dummy);
1195    end For_All_Object_Dirs;
1196
1197    -------------------------
1198    -- For_All_Source_Dirs --
1199    -------------------------
1200
1201    procedure For_All_Source_Dirs
1202      (Project : Project_Id;
1203       In_Tree : Project_Tree_Ref)
1204    is
1205       procedure For_Project (Prj : Project_Id; Dummy : in out Integer);
1206       --  Get all object directories of Prj
1207
1208       -----------------
1209       -- For_Project --
1210       -----------------
1211
1212       procedure For_Project (Prj : Project_Id; Dummy : in out Integer) is
1213          pragma Unreferenced (Dummy);
1214          Current    : String_List_Id := Prj.Source_Dirs;
1215          The_String : String_Element;
1216
1217       begin
1218          --  If there are Ada sources, call action with the name of every
1219          --  source directory.
1220
1221          if Has_Ada_Sources (Project) then
1222             while Current /= Nil_String loop
1223                The_String := In_Tree.String_Elements.Table (Current);
1224                Action (Get_Name_String (The_String.Display_Value));
1225                Current := The_String.Next;
1226             end loop;
1227          end if;
1228       end For_Project;
1229
1230       procedure Get_Source_Dirs is
1231         new For_Every_Project_Imported (Integer, For_Project);
1232       Dummy : Integer := 1;
1233
1234    --  Start of processing for For_All_Source_Dirs
1235
1236    begin
1237       Get_Source_Dirs (Project, Dummy);
1238    end For_All_Source_Dirs;
1239
1240    -------------------
1241    -- Get_Reference --
1242    -------------------
1243
1244    procedure Get_Reference
1245      (Source_File_Name : String;
1246       In_Tree          : Project_Tree_Ref;
1247       Project          : out Project_Id;
1248       Path             : out Path_Name_Type)
1249    is
1250    begin
1251       --  Body below could use some comments ???
1252
1253       if Current_Verbosity > Default then
1254          Write_Str ("Getting Reference_Of (""");
1255          Write_Str (Source_File_Name);
1256          Write_Str (""") ... ");
1257       end if;
1258
1259       declare
1260          Original_Name : String := Source_File_Name;
1261          Unit          : Unit_Index;
1262
1263       begin
1264          Canonical_Case_File_Name (Original_Name);
1265          Unit := Units_Htable.Get_First (In_Tree.Units_HT);
1266
1267          while Unit /= null loop
1268             if Unit.File_Names (Spec) /= null
1269               and then Unit.File_Names (Spec).File /= No_File
1270               and then
1271                 (Namet.Get_Name_String
1272                      (Unit.File_Names (Spec).File) = Original_Name
1273                  or else (Unit.File_Names (Spec).Path /=
1274                             No_Path_Information
1275                           and then
1276                             Namet.Get_Name_String
1277                               (Unit.File_Names (Spec).Path.Name) =
1278                             Original_Name))
1279             then
1280                Project := Ultimate_Extension_Of
1281                           (Project => Unit.File_Names (Spec).Project);
1282                Path := Unit.File_Names (Spec).Path.Display_Name;
1283
1284                if Current_Verbosity > Default then
1285                   Write_Str ("Done: Spec.");
1286                   Write_Eol;
1287                end if;
1288
1289                return;
1290
1291             elsif Unit.File_Names (Impl) /= null
1292               and then Unit.File_Names (Impl).File /= No_File
1293               and then
1294                 (Namet.Get_Name_String
1295                    (Unit.File_Names (Impl).File) = Original_Name
1296                  or else (Unit.File_Names (Impl).Path /=
1297                             No_Path_Information
1298                           and then Namet.Get_Name_String
1299                             (Unit.File_Names (Impl).Path.Name) =
1300                             Original_Name))
1301             then
1302                Project := Ultimate_Extension_Of
1303                             (Project => Unit.File_Names (Impl).Project);
1304                Path := Unit.File_Names (Impl).Path.Display_Name;
1305
1306                if Current_Verbosity > Default then
1307                   Write_Str ("Done: Body.");
1308                   Write_Eol;
1309                end if;
1310
1311                return;
1312             end if;
1313
1314             Unit := Units_Htable.Get_Next (In_Tree.Units_HT);
1315          end loop;
1316       end;
1317
1318       Project := No_Project;
1319       Path    := No_Path;
1320
1321       if Current_Verbosity > Default then
1322          Write_Str ("Cannot be found.");
1323          Write_Eol;
1324       end if;
1325    end Get_Reference;
1326
1327    ----------------
1328    -- Initialize --
1329    ----------------
1330
1331    procedure Initialize (In_Tree : Project_Tree_Ref) is
1332    begin
1333       In_Tree.Private_Part.Current_Source_Path_File := No_Path;
1334       In_Tree.Private_Part.Current_Object_Path_File := No_Path;
1335    end Initialize;
1336
1337    -------------------
1338    -- Print_Sources --
1339    -------------------
1340
1341    --  Could use some comments in this body ???
1342
1343    procedure Print_Sources (In_Tree : Project_Tree_Ref) is
1344       Unit : Unit_Index;
1345
1346    begin
1347       Write_Line ("List of Sources:");
1348
1349       Unit := Units_Htable.Get_First (In_Tree.Units_HT);
1350
1351       while Unit /= No_Unit_Index loop
1352          Write_Str  ("   ");
1353          Write_Line (Namet.Get_Name_String (Unit.Name));
1354
1355          if Unit.File_Names (Spec).File /= No_File then
1356             if Unit.File_Names (Spec).Project = No_Project then
1357                Write_Line ("   No project");
1358
1359             else
1360                Write_Str  ("   Project: ");
1361                Get_Name_String
1362                  (Unit.File_Names (Spec).Project.Path.Name);
1363                Write_Line (Name_Buffer (1 .. Name_Len));
1364             end if;
1365
1366             Write_Str  ("      spec: ");
1367             Write_Line
1368               (Namet.Get_Name_String
1369                (Unit.File_Names (Spec).File));
1370          end if;
1371
1372          if Unit.File_Names (Impl).File /= No_File then
1373             if Unit.File_Names (Impl).Project = No_Project then
1374                Write_Line ("   No project");
1375
1376             else
1377                Write_Str  ("   Project: ");
1378                Get_Name_String
1379                  (Unit.File_Names (Impl).Project.Path.Name);
1380                Write_Line (Name_Buffer (1 .. Name_Len));
1381             end if;
1382
1383             Write_Str  ("      body: ");
1384             Write_Line
1385               (Namet.Get_Name_String (Unit.File_Names (Impl).File));
1386          end if;
1387
1388          Unit := Units_Htable.Get_Next (In_Tree.Units_HT);
1389       end loop;
1390
1391       Write_Line ("end of List of Sources.");
1392    end Print_Sources;
1393
1394    ----------------
1395    -- Project_Of --
1396    ----------------
1397
1398    function Project_Of
1399      (Name         : String;
1400       Main_Project : Project_Id;
1401       In_Tree      : Project_Tree_Ref) return Project_Id
1402    is
1403       Result : Project_Id := No_Project;
1404
1405       Original_Name : String := Name;
1406
1407       Lang : constant Language_Ptr :=
1408                Get_Language_From_Name (Main_Project, "ada");
1409
1410       Unit : Unit_Index;
1411
1412       Current_Name      : File_Name_Type;
1413       The_Original_Name : File_Name_Type;
1414       The_Spec_Name     : File_Name_Type;
1415       The_Body_Name     : File_Name_Type;
1416
1417    begin
1418       --  ??? Same block in File_Name_Of_Library_Unit_Body
1419       Canonical_Case_File_Name (Original_Name);
1420       Name_Len := Original_Name'Length;
1421       Name_Buffer (1 .. Name_Len) := Original_Name;
1422       The_Original_Name := Name_Find;
1423
1424       if Lang /= null then
1425          declare
1426             Naming : Lang_Naming_Data renames Lang.Config.Naming_Data;
1427             Extended_Spec_Name : String :=
1428                                    Name & Namet.Get_Name_String
1429                                             (Naming.Spec_Suffix);
1430             Extended_Body_Name : String :=
1431                                    Name & Namet.Get_Name_String
1432                                             (Naming.Body_Suffix);
1433
1434          begin
1435             Canonical_Case_File_Name (Extended_Spec_Name);
1436             Name_Len := Extended_Spec_Name'Length;
1437             Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
1438             The_Spec_Name := Name_Find;
1439
1440             Canonical_Case_File_Name (Extended_Body_Name);
1441             Name_Len := Extended_Body_Name'Length;
1442             Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
1443             The_Body_Name := Name_Find;
1444          end;
1445
1446       else
1447          The_Spec_Name := The_Original_Name;
1448          The_Body_Name := The_Original_Name;
1449       end if;
1450
1451       Unit := Units_Htable.Get_First (In_Tree.Units_HT);
1452       while Unit /= null loop
1453
1454          --  Case of a body present
1455
1456          if Unit.File_Names (Impl) /= null then
1457             Current_Name := Unit.File_Names (Impl).File;
1458
1459             --  If it has the name of the original name or the body name,
1460             --  we have found the project.
1461
1462             if Unit.Name = Name_Id (The_Original_Name)
1463               or else Current_Name = The_Original_Name
1464               or else Current_Name = The_Body_Name
1465             then
1466                Result := Unit.File_Names (Impl).Project;
1467                exit;
1468             end if;
1469          end if;
1470
1471          --  Check for spec
1472
1473          if Unit.File_Names (Spec) /= null then
1474             Current_Name := Unit.File_Names (Spec).File;
1475
1476             --  If name same as the original name, or the spec name, we have
1477             --  found the project.
1478
1479             if Unit.Name = Name_Id (The_Original_Name)
1480               or else Current_Name = The_Original_Name
1481               or else Current_Name = The_Spec_Name
1482             then
1483                Result := Unit.File_Names (Spec).Project;
1484                exit;
1485             end if;
1486          end if;
1487
1488          Unit := Units_Htable.Get_Next (In_Tree.Units_HT);
1489       end loop;
1490
1491       --  Get the ultimate extending project
1492
1493       if Result /= No_Project then
1494          while Result.Extended_By /= No_Project loop
1495             Result := Result.Extended_By;
1496          end loop;
1497       end if;
1498
1499       return Result;
1500    end Project_Of;
1501
1502    -------------------
1503    -- Set_Ada_Paths --
1504    -------------------
1505
1506    procedure Set_Ada_Paths
1507      (Project             : Project_Id;
1508       In_Tree             : Project_Tree_Ref;
1509       Including_Libraries : Boolean)
1510
1511    is
1512       Source_Paths : Source_Path_Table.Instance;
1513       Object_Paths : Object_Path_Table.Instance;
1514       --  List of source or object dirs. Only computed the first time this
1515       --  procedure is called (since Source_FD is then reused)
1516
1517       Source_FD : File_Descriptor := Invalid_FD;
1518       Object_FD : File_Descriptor := Invalid_FD;
1519       --  The temporary files to store the paths. These are only created the
1520       --  first time this procedure is called, and reused from then on.
1521
1522       Process_Source_Dirs : Boolean := False;
1523       Process_Object_Dirs : Boolean := False;
1524
1525       Status : Boolean;
1526       --  For calls to Close
1527
1528       Last        : Natural;
1529       Buffer      : String_Access := new String (1 .. Buffer_Initial);
1530       Buffer_Last : Natural := 0;
1531
1532       procedure Recursive_Add (Project : Project_Id; Dummy : in out Boolean);
1533       --  Recursive procedure to add the source/object paths of extended/
1534       --  imported projects.
1535
1536       -------------------
1537       -- Recursive_Add --
1538       -------------------
1539
1540       procedure Recursive_Add (Project : Project_Id; Dummy : in out Boolean) is
1541          pragma Unreferenced (Dummy);
1542
1543          Path : Path_Name_Type;
1544
1545       begin
1546          --  ??? This is almost the equivalent of For_All_Source_Dirs
1547
1548          if Process_Source_Dirs then
1549
1550             --  Add to path all source directories of this project if there are
1551             --  Ada sources.
1552
1553             if Has_Ada_Sources (Project) then
1554                Add_To_Source_Path (Project.Source_Dirs, In_Tree, Source_Paths);
1555             end if;
1556          end if;
1557
1558          if Process_Object_Dirs then
1559             Path := Get_Object_Directory
1560               (Project,
1561                Including_Libraries => Including_Libraries,
1562                Only_If_Ada         => True);
1563
1564             if Path /= No_Path then
1565                Add_To_Object_Path (Path, Object_Paths);
1566             end if;
1567          end if;
1568       end Recursive_Add;
1569
1570       procedure For_All_Projects is
1571         new For_Every_Project_Imported (Boolean, Recursive_Add);
1572
1573       Dummy : Boolean := False;
1574
1575    --  Start of processing for Set_Ada_Paths
1576
1577    begin
1578       --  If it is the first time we call this procedure for this project,
1579       --  compute the source path and/or the object path.
1580
1581       if Project.Include_Path_File = No_Path then
1582          Source_Path_Table.Init (Source_Paths);
1583          Process_Source_Dirs := True;
1584          Create_New_Path_File
1585            (In_Tree, Source_FD, Project.Include_Path_File);
1586       end if;
1587
1588       --  For the object path, we make a distinction depending on
1589       --  Including_Libraries.
1590
1591       if Including_Libraries then
1592          if Project.Objects_Path_File_With_Libs = No_Path then
1593             Object_Path_Table.Init (Object_Paths);
1594             Process_Object_Dirs := True;
1595             Create_New_Path_File
1596               (In_Tree, Object_FD, Project.Objects_Path_File_With_Libs);
1597          end if;
1598
1599       else
1600          if Project.Objects_Path_File_Without_Libs = No_Path then
1601             Object_Path_Table.Init (Object_Paths);
1602             Process_Object_Dirs := True;
1603             Create_New_Path_File
1604               (In_Tree, Object_FD, Project.Objects_Path_File_Without_Libs);
1605          end if;
1606       end if;
1607
1608       --  If there is something to do, set Seen to False for all projects,
1609       --  then call the recursive procedure Add for Project.
1610
1611       if Process_Source_Dirs or Process_Object_Dirs then
1612          For_All_Projects (Project, Dummy);
1613       end if;
1614
1615       --  Write and close any file that has been created. Source_FD is not set
1616       --  when this subprogram is called a second time or more, since we reuse
1617       --  the previous version of the file.
1618
1619       if Source_FD /= Invalid_FD then
1620          Buffer_Last := 0;
1621
1622          for Index in Source_Path_Table.First ..
1623                       Source_Path_Table.Last (Source_Paths)
1624          loop
1625             Get_Name_String (Source_Paths.Table (Index));
1626             Name_Len := Name_Len + 1;
1627             Name_Buffer (Name_Len) := ASCII.LF;
1628             Add_To_Buffer (Name_Buffer (1 .. Name_Len), Buffer, Buffer_Last);
1629          end loop;
1630
1631          Last := Write (Source_FD, Buffer (1)'Address, Buffer_Last);
1632
1633          if Last = Buffer_Last then
1634             Close (Source_FD, Status);
1635
1636          else
1637             Status := False;
1638          end if;
1639
1640          if not Status then
1641             Prj.Com.Fail ("could not write temporary file");
1642          end if;
1643       end if;
1644
1645       if Object_FD /= Invalid_FD then
1646          Buffer_Last := 0;
1647
1648          for Index in Object_Path_Table.First ..
1649                       Object_Path_Table.Last (Object_Paths)
1650          loop
1651             Get_Name_String (Object_Paths.Table (Index));
1652             Name_Len := Name_Len + 1;
1653             Name_Buffer (Name_Len) := ASCII.LF;
1654             Add_To_Buffer (Name_Buffer (1 .. Name_Len), Buffer, Buffer_Last);
1655          end loop;
1656
1657          Last := Write (Object_FD, Buffer (1)'Address, Buffer_Last);
1658
1659          if Last = Buffer_Last then
1660             Close (Object_FD, Status);
1661          else
1662             Status := False;
1663          end if;
1664
1665          if not Status then
1666             Prj.Com.Fail ("could not write temporary file");
1667          end if;
1668       end if;
1669
1670       --  Set the env vars, if they need to be changed, and set the
1671       --  corresponding flags.
1672
1673       if In_Tree.Private_Part.Current_Source_Path_File /=
1674            Project.Include_Path_File
1675       then
1676          In_Tree.Private_Part.Current_Source_Path_File :=
1677            Project.Include_Path_File;
1678          Set_Path_File_Var
1679            (Project_Include_Path_File,
1680             Get_Name_String (In_Tree.Private_Part.Current_Source_Path_File));
1681       end if;
1682
1683       if Including_Libraries then
1684          if In_Tree.Private_Part.Current_Object_Path_File /=
1685             Project.Objects_Path_File_With_Libs
1686          then
1687             In_Tree.Private_Part.Current_Object_Path_File :=
1688               Project.Objects_Path_File_With_Libs;
1689             Set_Path_File_Var
1690               (Project_Objects_Path_File,
1691                Get_Name_String
1692                  (In_Tree.Private_Part.Current_Object_Path_File));
1693          end if;
1694
1695       else
1696          if In_Tree.Private_Part.Current_Object_Path_File /=
1697             Project.Objects_Path_File_Without_Libs
1698          then
1699             In_Tree.Private_Part.Current_Object_Path_File :=
1700               Project.Objects_Path_File_Without_Libs;
1701             Set_Path_File_Var
1702               (Project_Objects_Path_File,
1703                Get_Name_String
1704                  (In_Tree.Private_Part.Current_Object_Path_File));
1705          end if;
1706       end if;
1707
1708       Free (Buffer);
1709    end Set_Ada_Paths;
1710
1711    -----------------------
1712    -- Set_Path_File_Var --
1713    -----------------------
1714
1715    procedure Set_Path_File_Var (Name : String; Value : String) is
1716       Host_Spec : String_Access := To_Host_File_Spec (Value);
1717    begin
1718       if Host_Spec = null then
1719          Prj.Com.Fail
1720            ("could not convert file name """ & Value & """ to host spec");
1721       else
1722          Setenv (Name, Host_Spec.all);
1723          Free (Host_Spec);
1724       end if;
1725    end Set_Path_File_Var;
1726
1727    ---------------------------
1728    -- Ultimate_Extension_Of --
1729    ---------------------------
1730
1731    function Ultimate_Extension_Of
1732      (Project : Project_Id) return Project_Id
1733    is
1734       Result : Project_Id;
1735
1736    begin
1737       Result := Project;
1738       while Result.Extended_By /= No_Project loop
1739          Result := Result.Extended_By;
1740       end loop;
1741
1742       return Result;
1743    end Ultimate_Extension_Of;
1744
1745 end Prj.Env;