OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [ada/] [prj-env.adb] - Blame information for rev 16

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT COMPILER COMPONENTS                         --
4
--                                                                          --
5
--                              P R J . E N V                               --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 2001-2005, Free Software Foundation, Inc.         --
10
--                                                                          --
11
-- GNAT is free software;  you can  redistribute it  and/or modify it under --
12
-- terms of the  GNU General Public License as published  by the Free Soft- --
13
-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
14
-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17
-- for  more details.  You should have  received  a copy of the GNU General --
18
-- Public License  distributed with GNAT;  see file COPYING.  If not, write --
19
-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
20
-- Boston, MA 02110-1301, USA.                                              --
21
--                                                                          --
22
-- GNAT was originally developed  by the GNAT team at  New York University. --
23
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
24
--                                                                          --
25
------------------------------------------------------------------------------
26
 
27
with Namet;    use Namet;
28
with Opt;
29
with Osint;    use Osint;
30
with Output;   use Output;
31
with Prj.Com;  use Prj.Com;
32
with Tempdir;
33
 
34
with GNAT.Directory_Operations; use GNAT.Directory_Operations;
35
 
36
package body Prj.Env is
37
 
38
   Current_Source_Path_File : Name_Id := No_Name;
39
   --  Current value of project source path file env var.
40
   --  Used to avoid setting the env var to the same value.
41
 
42
   Current_Object_Path_File : Name_Id := No_Name;
43
   --  Current value of project object path file env var.
44
   --  Used to avoid setting the env var to the same value.
45
 
46
   Ada_Path_Buffer : String_Access := new String (1 .. 1024);
47
   --  A buffer where values for ADA_INCLUDE_PATH
48
   --  and ADA_OBJECTS_PATH are stored.
49
 
50
   Ada_Path_Length : Natural := 0;
51
   --  Index of the last valid character in Ada_Path_Buffer
52
 
53
   Ada_Prj_Include_File_Set : Boolean := False;
54
   Ada_Prj_Objects_File_Set : Boolean := False;
55
   --  These flags are set to True when the corresponding environment variables
56
   --  are set and are used to give these environment variables an empty string
57
   --  value at the end of the program. This has no practical effect on most
58
   --  platforms, except on VMS where the logical names are deassigned, thus
59
   --  avoiding the pollution of the environment of the caller.
60
 
61
   Default_Naming : constant Naming_Id := Naming_Table.First;
62
 
63
   Fill_Mapping_File : Boolean := True;
64
 
65
   type Project_Flags is array (Project_Id range <>) of Boolean;
66
   --  A Boolean array type used in Create_Mapping_File to select the projects
67
   --  in the closure of a specific project.
68
 
69
   -----------------------
70
   -- Local Subprograms --
71
   -----------------------
72
 
73
   function Body_Path_Name_Of
74
     (Unit    : Unit_Id;
75
      In_Tree : Project_Tree_Ref) return String;
76
   --  Returns the path name of the body of a unit.
77
   --  Compute it first, if necessary.
78
 
79
   function Spec_Path_Name_Of
80
     (Unit    : Unit_Id;
81
      In_Tree : Project_Tree_Ref) return String;
82
   --  Returns the path name of the spec of a unit.
83
   --  Compute it first, if necessary.
84
 
85
   procedure Add_To_Path
86
     (Source_Dirs : String_List_Id;
87
      In_Tree     : Project_Tree_Ref);
88
   --  Add to Ada_Path_Buffer all the source directories in string list
89
   --  Source_Dirs, if any. Increment Ada_Path_Length.
90
 
91
   procedure Add_To_Path (Dir : String);
92
   --  If Dir is not already in the global variable Ada_Path_Buffer, add it.
93
   --  Increment Ada_Path_Length.
94
   --  If Ada_Path_Length /= 0, prepend a Path_Separator character to
95
   --  Path.
96
 
97
   procedure Add_To_Source_Path
98
     (Source_Dirs : String_List_Id; In_Tree : Project_Tree_Ref);
99
   --  Add to Ada_Path_B all the source directories in string list
100
   --  Source_Dirs, if any. Increment Ada_Path_Length.
101
 
102
   procedure Add_To_Object_Path
103
     (Object_Dir : Name_Id;
104
      In_Tree    : Project_Tree_Ref);
105
   --  Add Object_Dir to object path table. Make sure it is not duplicate
106
   --  and it is the last one in the current table.
107
 
108
   function Contains_ALI_Files (Dir : Name_Id) return Boolean;
109
   --  Return True if there is at least one ALI file in the directory Dir
110
 
111
   procedure Create_New_Path_File
112
     (In_Tree   : Project_Tree_Ref;
113
      Path_FD   : out File_Descriptor;
114
      Path_Name : out Name_Id);
115
   --  Create a new temporary path file. Get the file name in Path_Name.
116
   --  The name is normally obtained by increasing the number in
117
   --  Temp_Path_File_Name by 1.
118
 
119
   procedure Set_Path_File_Var (Name : String; Value : String);
120
   --  Call Setenv, after calling To_Host_File_Spec
121
 
122
   function Ultimate_Extension_Of
123
     (Project : in Project_Id; In_Tree : Project_Tree_Ref) return Project_Id;
124
   --  Return a project that is either Project or an extended ancestor of
125
   --  Project that itself is not extended.
126
 
127
   ----------------------
128
   -- Ada_Include_Path --
129
   ----------------------
130
 
131
   function Ada_Include_Path
132
     (Project : Project_Id;
133
      In_Tree : Project_Tree_Ref) return String_Access is
134
 
135
      procedure Add (Project : Project_Id);
136
      --  Add all the source directories of a project to the path only if
137
      --  this project has not been visited. Calls itself recursively for
138
      --  projects being extended, and imported projects. Adds the project
139
      --  to the list Seen if this is the call to Add for this project.
140
 
141
      ---------
142
      -- Add --
143
      ---------
144
 
145
      procedure Add (Project : Project_Id) is
146
      begin
147
         --  If Seen is empty, then the project cannot have been visited
148
 
149
         if not In_Tree.Projects.Table (Project).Seen then
150
            In_Tree.Projects.Table (Project).Seen := True;
151
 
152
            declare
153
               Data : constant Project_Data :=
154
                        In_Tree.Projects.Table (Project);
155
               List : Project_List := Data.Imported_Projects;
156
 
157
            begin
158
               --  Add to path all source directories of this project
159
 
160
               Add_To_Path (Data.Source_Dirs, In_Tree);
161
 
162
               --  Call Add to the project being extended, if any
163
 
164
               if Data.Extends /= No_Project then
165
                  Add (Data.Extends);
166
               end if;
167
 
168
               --  Call Add for each imported project, if any
169
 
170
               while List /= Empty_Project_List loop
171
                  Add
172
                    (In_Tree.Project_Lists.Table (List).Project);
173
                  List := In_Tree.Project_Lists.Table (List).Next;
174
               end loop;
175
            end;
176
         end if;
177
      end Add;
178
 
179
   --  Start of processing for Ada_Include_Path
180
 
181
   begin
182
      --  If it is the first time we call this function for
183
      --  this project, compute the source path
184
 
185
      if
186
        In_Tree.Projects.Table (Project).Ada_Include_Path = null
187
      then
188
         Ada_Path_Length := 0;
189
 
190
         for Index in Project_Table.First ..
191
                      Project_Table.Last (In_Tree.Projects)
192
         loop
193
            In_Tree.Projects.Table (Index).Seen := False;
194
         end loop;
195
 
196
         Add (Project);
197
         In_Tree.Projects.Table (Project).Ada_Include_Path :=
198
           new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
199
      end if;
200
 
201
      return In_Tree.Projects.Table (Project).Ada_Include_Path;
202
   end Ada_Include_Path;
203
 
204
   ----------------------
205
   -- Ada_Include_Path --
206
   ----------------------
207
 
208
   function Ada_Include_Path
209
     (Project   : Project_Id;
210
      In_Tree   : Project_Tree_Ref;
211
      Recursive : Boolean) return String
212
   is
213
   begin
214
      if Recursive then
215
         return Ada_Include_Path (Project, In_Tree).all;
216
      else
217
         Ada_Path_Length := 0;
218
         Add_To_Path
219
           (In_Tree.Projects.Table (Project).Source_Dirs, In_Tree);
220
         return Ada_Path_Buffer (1 .. Ada_Path_Length);
221
      end if;
222
   end Ada_Include_Path;
223
 
224
   ----------------------
225
   -- Ada_Objects_Path --
226
   ----------------------
227
 
228
   function Ada_Objects_Path
229
     (Project             : Project_Id;
230
      In_Tree             : Project_Tree_Ref;
231
      Including_Libraries : Boolean := True) return String_Access
232
   is
233
      procedure Add (Project : Project_Id);
234
      --  Add all the object directories of a project to the path only if
235
      --  this project has not been visited. Calls itself recursively for
236
      --  projects being extended, and imported projects. Adds the project
237
      --  to the list Seen if this is the first call to Add for this project.
238
 
239
      ---------
240
      -- Add --
241
      ---------
242
 
243
      procedure Add (Project : Project_Id) is
244
      begin
245
         --  If this project has not been seen yet
246
 
247
         if not In_Tree.Projects.Table (Project).Seen then
248
            In_Tree.Projects.Table (Project).Seen := True;
249
 
250
            declare
251
               Data : constant Project_Data :=
252
                 In_Tree.Projects.Table (Project);
253
               List : Project_List := Data.Imported_Projects;
254
 
255
            begin
256
               --  Add to path the object directory of this project
257
               --  except if we don't include library project and
258
               --  this is a library project.
259
 
260
               if (Data.Library and then Including_Libraries)
261
                 or else
262
                 (Data.Object_Directory /= No_Name
263
                   and then
264
                   (not Including_Libraries or else not Data.Library))
265
               then
266
                  --  For a library project, add the library directory,
267
                  --  if there is no object directory or if it contains ALI
268
                  --  files; otherwise add the object directory.
269
 
270
                  if Data.Library then
271
                     if Data.Object_Directory = No_Name
272
                       or else
273
                         Contains_ALI_Files (Data.Library_ALI_Dir)
274
                     then
275
                        Add_To_Path (Get_Name_String (Data.Library_ALI_Dir));
276
                     else
277
                        Add_To_Path (Get_Name_String (Data.Object_Directory));
278
                     end if;
279
 
280
                  else
281
                     --  For a non library project, add the object directory
282
 
283
                     Add_To_Path (Get_Name_String (Data.Object_Directory));
284
                  end if;
285
               end if;
286
 
287
               --  Call Add to the project being extended, if any
288
 
289
               if Data.Extends /= No_Project then
290
                  Add (Data.Extends);
291
               end if;
292
 
293
               --  Call Add for each imported project, if any
294
 
295
               while List /= Empty_Project_List loop
296
                  Add
297
                    (In_Tree.Project_Lists.Table (List).Project);
298
                  List := In_Tree.Project_Lists.Table (List).Next;
299
               end loop;
300
            end;
301
 
302
         end if;
303
      end Add;
304
 
305
   --  Start of processing for Ada_Objects_Path
306
 
307
   begin
308
      --  If it is the first time we call this function for
309
      --  this project, compute the objects path
310
 
311
      if
312
        In_Tree.Projects.Table (Project).Ada_Objects_Path = null
313
      then
314
         Ada_Path_Length := 0;
315
 
316
         for Index in Project_Table.First ..
317
                      Project_Table.Last (In_Tree.Projects)
318
         loop
319
            In_Tree.Projects.Table (Index).Seen := False;
320
         end loop;
321
 
322
         Add (Project);
323
         In_Tree.Projects.Table (Project).Ada_Objects_Path :=
324
           new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
325
      end if;
326
 
327
      return In_Tree.Projects.Table (Project).Ada_Objects_Path;
328
   end Ada_Objects_Path;
329
 
330
   ------------------------
331
   -- Add_To_Object_Path --
332
   ------------------------
333
 
334
   procedure Add_To_Object_Path
335
     (Object_Dir : Name_Id; In_Tree : Project_Tree_Ref)
336
   is
337
   begin
338
      --  Check if the directory is already in the table
339
 
340
      for Index in Object_Path_Table.First ..
341
                   Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)
342
      loop
343
 
344
         --  If it is, remove it, and add it as the last one
345
 
346
         if In_Tree.Private_Part.Object_Paths.Table (Index) = Object_Dir then
347
            for Index2 in Index + 1 ..
348
                          Object_Path_Table.Last
349
                            (In_Tree.Private_Part.Object_Paths)
350
            loop
351
               In_Tree.Private_Part.Object_Paths.Table (Index2 - 1) :=
352
                 In_Tree.Private_Part.Object_Paths.Table (Index2);
353
            end loop;
354
 
355
            In_Tree.Private_Part.Object_Paths.Table
356
              (Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)) :=
357
                 Object_Dir;
358
            return;
359
         end if;
360
      end loop;
361
 
362
      --  The directory is not already in the table, add it
363
 
364
      Object_Path_Table.Increment_Last (In_Tree.Private_Part.Object_Paths);
365
      In_Tree.Private_Part.Object_Paths.Table
366
        (Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)) :=
367
           Object_Dir;
368
   end Add_To_Object_Path;
369
 
370
   -----------------
371
   -- Add_To_Path --
372
   -----------------
373
 
374
   procedure Add_To_Path
375
     (Source_Dirs : String_List_Id;
376
      In_Tree     : Project_Tree_Ref)
377
   is
378
      Current    : String_List_Id := Source_Dirs;
379
      Source_Dir : String_Element;
380
   begin
381
      while Current /= Nil_String loop
382
         Source_Dir := In_Tree.String_Elements.Table (Current);
383
         Add_To_Path (Get_Name_String (Source_Dir.Display_Value));
384
         Current := Source_Dir.Next;
385
      end loop;
386
   end Add_To_Path;
387
 
388
   procedure Add_To_Path (Dir : String) is
389
      Len        : Natural;
390
      New_Buffer : String_Access;
391
      Min_Len    : Natural;
392
 
393
      function Is_Present (Path : String; Dir : String) return Boolean;
394
      --  Return True if Dir is part of Path
395
 
396
      ----------------
397
      -- Is_Present --
398
      ----------------
399
 
400
      function Is_Present (Path : String; Dir : String) return Boolean is
401
         Last : constant Integer := Path'Last - Dir'Length + 1;
402
 
403
      begin
404
         for J in Path'First .. Last loop
405
 
406
            --  Note: the order of the conditions below is important, since
407
            --  it ensures a minimal number of string comparisons.
408
 
409
            if (J = Path'First
410
                or else Path (J - 1) = Path_Separator)
411
              and then
412
                (J + Dir'Length > Path'Last
413
                 or else Path (J + Dir'Length) = Path_Separator)
414
              and then Dir = Path (J .. J + Dir'Length - 1)
415
            then
416
               return True;
417
            end if;
418
         end loop;
419
 
420
         return False;
421
      end Is_Present;
422
 
423
   --  Start of processing for Add_To_Path
424
 
425
   begin
426
      if Is_Present (Ada_Path_Buffer (1 .. Ada_Path_Length), Dir) then
427
 
428
         --  Dir is already in the path, nothing to do
429
 
430
         return;
431
      end if;
432
 
433
      Min_Len := Ada_Path_Length + Dir'Length;
434
 
435
      if Ada_Path_Length > 0 then
436
 
437
         --  Add 1 for the Path_Separator character
438
 
439
         Min_Len := Min_Len + 1;
440
      end if;
441
 
442
      --  If Ada_Path_Buffer is too small, increase it
443
 
444
      Len := Ada_Path_Buffer'Last;
445
 
446
      if Len < Min_Len then
447
         loop
448
            Len := Len * 2;
449
            exit when Len >= Min_Len;
450
         end loop;
451
 
452
         New_Buffer := new String (1 .. Len);
453
         New_Buffer (1 .. Ada_Path_Length) :=
454
           Ada_Path_Buffer (1 .. Ada_Path_Length);
455
         Free (Ada_Path_Buffer);
456
         Ada_Path_Buffer := New_Buffer;
457
      end if;
458
 
459
      if Ada_Path_Length > 0 then
460
         Ada_Path_Length := Ada_Path_Length + 1;
461
         Ada_Path_Buffer (Ada_Path_Length) := Path_Separator;
462
      end if;
463
 
464
      Ada_Path_Buffer
465
        (Ada_Path_Length + 1 .. Ada_Path_Length + Dir'Length) := Dir;
466
      Ada_Path_Length := Ada_Path_Length + Dir'Length;
467
   end Add_To_Path;
468
 
469
   ------------------------
470
   -- Add_To_Source_Path --
471
   ------------------------
472
 
473
   procedure Add_To_Source_Path
474
     (Source_Dirs : String_List_Id; In_Tree : Project_Tree_Ref)
475
   is
476
      Current    : String_List_Id := Source_Dirs;
477
      Source_Dir : String_Element;
478
      Add_It     : Boolean;
479
 
480
   begin
481
      --  Add each source directory
482
 
483
      while Current /= Nil_String loop
484
         Source_Dir := In_Tree.String_Elements.Table (Current);
485
         Add_It := True;
486
 
487
         --  Check if the source directory is already in the table
488
 
489
         for Index in Source_Path_Table.First ..
490
                      Source_Path_Table.Last
491
                                          (In_Tree.Private_Part.Source_Paths)
492
         loop
493
            --  If it is already, no need to add it
494
 
495
            if In_Tree.Private_Part.Source_Paths.Table (Index) =
496
                        Source_Dir.Value
497
            then
498
               Add_It := False;
499
               exit;
500
            end if;
501
         end loop;
502
 
503
         if Add_It then
504
            Source_Path_Table.Increment_Last
505
              (In_Tree.Private_Part.Source_Paths);
506
            In_Tree.Private_Part.Source_Paths.Table
507
              (Source_Path_Table.Last (In_Tree.Private_Part.Source_Paths)) :=
508
              Source_Dir.Value;
509
         end if;
510
 
511
         --  Next source directory
512
 
513
         Current := Source_Dir.Next;
514
      end loop;
515
   end Add_To_Source_Path;
516
 
517
   -----------------------
518
   -- Body_Path_Name_Of --
519
   -----------------------
520
 
521
   function Body_Path_Name_Of
522
     (Unit : Unit_Id; In_Tree : Project_Tree_Ref) return String
523
   is
524
      Data : Unit_Data := In_Tree.Units.Table (Unit);
525
 
526
   begin
527
      --  If we don't know the path name of the body of this unit,
528
      --  we compute it, and we store it.
529
 
530
      if Data.File_Names (Body_Part).Path = No_Name then
531
         declare
532
            Current_Source : String_List_Id :=
533
              In_Tree.Projects.Table
534
                (Data.File_Names (Body_Part).Project).Sources;
535
            Path : GNAT.OS_Lib.String_Access;
536
 
537
         begin
538
            --  By default, put the file name
539
 
540
            Data.File_Names (Body_Part).Path :=
541
              Data.File_Names (Body_Part).Name;
542
 
543
            --  For each source directory
544
 
545
            while Current_Source /= Nil_String loop
546
               Path :=
547
                 Locate_Regular_File
548
                   (Namet.Get_Name_String
549
                      (Data.File_Names (Body_Part).Name),
550
                    Namet.Get_Name_String
551
                      (In_Tree.String_Elements.Table
552
                         (Current_Source).Value));
553
 
554
               --  If the file is in this directory, then we store the path,
555
               --  and we are done.
556
 
557
               if Path /= null then
558
                  Name_Len := Path'Length;
559
                  Name_Buffer (1 .. Name_Len) := Path.all;
560
                  Data.File_Names (Body_Part).Path := Name_Enter;
561
                  exit;
562
 
563
               else
564
                  Current_Source :=
565
                    In_Tree.String_Elements.Table
566
                      (Current_Source).Next;
567
               end if;
568
            end loop;
569
 
570
            In_Tree.Units.Table (Unit) := Data;
571
         end;
572
      end if;
573
 
574
      --  Returned the stored value
575
 
576
      return Namet.Get_Name_String (Data.File_Names (Body_Part).Path);
577
   end Body_Path_Name_Of;
578
 
579
   ------------------------
580
   -- Contains_ALI_Files --
581
   ------------------------
582
 
583
   function Contains_ALI_Files (Dir : Name_Id) return Boolean is
584
      Dir_Name : constant String := Get_Name_String (Dir);
585
      Direct : Dir_Type;
586
      Name   : String (1 .. 1_000);
587
      Last   : Natural;
588
      Result : Boolean := False;
589
 
590
   begin
591
      Open (Direct, Dir_Name);
592
 
593
      --  For each file in the directory, check if it is an ALI file
594
 
595
      loop
596
         Read (Direct, Name, Last);
597
         exit when Last = 0;
598
         Canonical_Case_File_Name (Name (1 .. Last));
599
         Result := Last >= 5 and then Name (Last - 3 .. Last) = ".ali";
600
         exit when Result;
601
      end loop;
602
 
603
      Close (Direct);
604
      return Result;
605
 
606
   exception
607
      --  If there is any problem, close the directory if open and return
608
      --  True; the library directory will be added to the path.
609
 
610
      when others =>
611
         if Is_Open (Direct) then
612
            Close (Direct);
613
         end if;
614
 
615
         return True;
616
   end Contains_ALI_Files;
617
 
618
   --------------------------------
619
   -- Create_Config_Pragmas_File --
620
   --------------------------------
621
 
622
   procedure Create_Config_Pragmas_File
623
     (For_Project          : Project_Id;
624
      Main_Project         : Project_Id;
625
      In_Tree              : Project_Tree_Ref;
626
      Include_Config_Files : Boolean := True)
627
   is
628
      pragma Unreferenced (Main_Project);
629
      pragma Unreferenced (Include_Config_Files);
630
 
631
      File_Name : Name_Id         := No_Name;
632
      File      : File_Descriptor := Invalid_FD;
633
 
634
      Current_Unit : Unit_Id := Unit_Table.First;
635
 
636
      First_Project : Project_List := Empty_Project_List;
637
 
638
      Current_Project : Project_List;
639
      Current_Naming  : Naming_Id;
640
 
641
      Status : Boolean;
642
      --  For call to Close
643
 
644
      procedure Check (Project : Project_Id);
645
      --  Recursive procedure that put in the config pragmas file any non
646
      --  standard naming schemes, if it is not already in the file, then call
647
      --  itself for any imported project.
648
 
649
      procedure Check_Temp_File;
650
      --  Check that a temporary file has been opened.
651
      --  If not, create one, and put its name in the project data,
652
      --  with the indication that it is a temporary file.
653
 
654
      procedure Put
655
        (Unit_Name : Name_Id;
656
         File_Name : Name_Id;
657
         Unit_Kind : Spec_Or_Body;
658
         Index     : Int);
659
      --  Put an SFN pragma in the temporary file
660
 
661
      procedure Put (File : File_Descriptor; S : String);
662
      procedure Put_Line (File : File_Descriptor; S : String);
663
      --  Output procedures, analogous to normal Text_IO procs of same name
664
 
665
      -----------
666
      -- Check --
667
      -----------
668
 
669
      procedure Check (Project : Project_Id) is
670
         Data : constant Project_Data :=
671
           In_Tree.Projects.Table (Project);
672
 
673
      begin
674
         if Current_Verbosity = High then
675
            Write_Str ("Checking project file """);
676
            Write_Str (Namet.Get_Name_String (Data.Name));
677
            Write_Str (""".");
678
            Write_Eol;
679
         end if;
680
 
681
         --  Is this project in the list of the visited project?
682
 
683
         Current_Project := First_Project;
684
         while Current_Project /= Empty_Project_List
685
           and then In_Tree.Project_Lists.Table
686
                      (Current_Project).Project /= Project
687
         loop
688
            Current_Project :=
689
              In_Tree.Project_Lists.Table (Current_Project).Next;
690
         end loop;
691
 
692
         --  If it is not, put it in the list, and visit it
693
 
694
         if Current_Project = Empty_Project_List then
695
            Project_List_Table.Increment_Last
696
              (In_Tree.Project_Lists);
697
            In_Tree.Project_Lists.Table
698
              (Project_List_Table.Last (In_Tree.Project_Lists)) :=
699
                 (Project => Project, Next => First_Project);
700
               First_Project :=
701
                 Project_List_Table.Last (In_Tree.Project_Lists);
702
 
703
            --  Is the naming scheme of this project one that we know?
704
 
705
            Current_Naming := Default_Naming;
706
            while Current_Naming <=
707
                    Naming_Table.Last (In_Tree.Private_Part.Namings)
708
              and then not Same_Naming_Scheme
709
              (Left => In_Tree.Private_Part.Namings.Table (Current_Naming),
710
               Right => Data.Naming) loop
711
               Current_Naming := Current_Naming + 1;
712
            end loop;
713
 
714
            --  If we don't know it, add it
715
 
716
            if Current_Naming >
717
                 Naming_Table.Last (In_Tree.Private_Part.Namings)
718
            then
719
               Naming_Table.Increment_Last (In_Tree.Private_Part.Namings);
720
               In_Tree.Private_Part.Namings.Table
721
                 (Naming_Table.Last (In_Tree.Private_Part.Namings)) :=
722
                    Data.Naming;
723
 
724
               --  We need a temporary file to be created
725
 
726
               Check_Temp_File;
727
 
728
               --  Put the SFN pragmas for the naming scheme
729
 
730
               --  Spec
731
 
732
               Put_Line
733
                 (File, "pragma Source_File_Name_Project");
734
               Put_Line
735
                 (File, "  (Spec_File_Name  => ""*" &
736
                  Namet.Get_Name_String (Data.Naming.Ada_Spec_Suffix) &
737
                  """,");
738
               Put_Line
739
                 (File, "   Casing          => " &
740
                  Image (Data.Naming.Casing) & ",");
741
               Put_Line
742
                 (File, "   Dot_Replacement => """ &
743
                 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
744
                  """);");
745
 
746
               --  and body
747
 
748
               Put_Line
749
                 (File, "pragma Source_File_Name_Project");
750
               Put_Line
751
                 (File, "  (Body_File_Name  => ""*" &
752
                  Namet.Get_Name_String (Data.Naming.Ada_Body_Suffix) &
753
                  """,");
754
               Put_Line
755
                 (File, "   Casing          => " &
756
                  Image (Data.Naming.Casing) & ",");
757
               Put_Line
758
                 (File, "   Dot_Replacement => """ &
759
                  Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
760
                  """);");
761
 
762
               --  and maybe separate
763
 
764
               if
765
                 Data.Naming.Ada_Body_Suffix /= Data.Naming.Separate_Suffix
766
               then
767
                  Put_Line
768
                    (File, "pragma Source_File_Name_Project");
769
                  Put_Line
770
                    (File, "  (Subunit_File_Name  => ""*" &
771
                     Namet.Get_Name_String (Data.Naming.Separate_Suffix) &
772
                     """,");
773
                  Put_Line
774
                    (File, "   Casing          => " &
775
                     Image (Data.Naming.Casing) &
776
                     ",");
777
                  Put_Line
778
                    (File, "   Dot_Replacement => """ &
779
                     Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
780
                     """);");
781
               end if;
782
            end if;
783
 
784
            if Data.Extends /= No_Project then
785
               Check (Data.Extends);
786
            end if;
787
 
788
            declare
789
               Current : Project_List := Data.Imported_Projects;
790
 
791
            begin
792
               while Current /= Empty_Project_List loop
793
                  Check
794
                    (In_Tree.Project_Lists.Table
795
                       (Current).Project);
796
                  Current := In_Tree.Project_Lists.Table
797
                               (Current).Next;
798
               end loop;
799
            end;
800
         end if;
801
      end Check;
802
 
803
      ---------------------
804
      -- Check_Temp_File --
805
      ---------------------
806
 
807
      procedure Check_Temp_File is
808
      begin
809
         if File = Invalid_FD then
810
            Tempdir.Create_Temp_File (File, Name => File_Name);
811
 
812
            if File = Invalid_FD then
813
               Prj.Com.Fail
814
                 ("unable to create temporary configuration pragmas file");
815
            elsif Opt.Verbose_Mode then
816
               Write_Str ("Creating temp file """);
817
               Write_Str (Get_Name_String (File_Name));
818
               Write_Line ("""");
819
            end if;
820
         end if;
821
      end Check_Temp_File;
822
 
823
      ---------
824
      -- Put --
825
      ---------
826
 
827
      procedure Put
828
        (Unit_Name : Name_Id;
829
         File_Name : Name_Id;
830
         Unit_Kind : Spec_Or_Body;
831
         Index     : Int)
832
      is
833
      begin
834
         --  A temporary file needs to be open
835
 
836
         Check_Temp_File;
837
 
838
         --  Put the pragma SFN for the unit kind (spec or body)
839
 
840
         Put (File, "pragma Source_File_Name_Project (");
841
         Put (File, Namet.Get_Name_String (Unit_Name));
842
 
843
         if Unit_Kind = Specification then
844
            Put (File, ", Spec_File_Name => """);
845
         else
846
            Put (File, ", Body_File_Name => """);
847
         end if;
848
 
849
         Put (File, Namet.Get_Name_String (File_Name));
850
         Put (File, """");
851
 
852
         if Index /= 0 then
853
            Put (File, ", Index =>");
854
            Put (File, Index'Img);
855
         end if;
856
 
857
         Put_Line (File, ");");
858
      end Put;
859
 
860
      procedure Put (File : File_Descriptor; S : String) is
861
         Last : Natural;
862
 
863
      begin
864
         Last := Write (File, S (S'First)'Address, S'Length);
865
 
866
         if Last /= S'Length then
867
            Prj.Com.Fail ("Disk full");
868
         end if;
869
 
870
         if Current_Verbosity = High then
871
            Write_Str (S);
872
         end if;
873
      end Put;
874
 
875
      --------------
876
      -- Put_Line --
877
      --------------
878
 
879
      procedure Put_Line (File : File_Descriptor; S : String) is
880
         S0   : String (1 .. S'Length + 1);
881
         Last : Natural;
882
 
883
      begin
884
         --  Add an ASCII.LF to the string. As this config file is supposed to
885
         --  be used only by the compiler, we don't care about the characters
886
         --  for the end of line. In fact we could have put a space, but
887
         --  it is more convenient to be able to read gnat.adc during
888
         --  development, for which the ASCII.LF is fine.
889
 
890
         S0 (1 .. S'Length) := S;
891
         S0 (S0'Last) := ASCII.LF;
892
         Last := Write (File, S0'Address, S0'Length);
893
 
894
         if Last /= S'Length + 1 then
895
            Prj.Com.Fail ("Disk full");
896
         end if;
897
 
898
         if Current_Verbosity = High then
899
            Write_Line (S);
900
         end if;
901
      end Put_Line;
902
 
903
   --  Start of processing for Create_Config_Pragmas_File
904
 
905
   begin
906
      if not
907
        In_Tree.Projects.Table (For_Project).Config_Checked
908
      then
909
 
910
         --  Remove any memory of processed naming schemes, if any
911
 
912
         Naming_Table.Set_Last (In_Tree.Private_Part.Namings, Default_Naming);
913
 
914
         --  Check the naming schemes
915
 
916
         Check (For_Project);
917
 
918
         --  Visit all the units and process those that need an SFN pragma
919
 
920
         while
921
           Current_Unit <= Unit_Table.Last (In_Tree.Units)
922
         loop
923
            declare
924
               Unit : constant Unit_Data :=
925
                 In_Tree.Units.Table (Current_Unit);
926
 
927
            begin
928
               if Unit.File_Names (Specification).Needs_Pragma then
929
                  Put (Unit.Name,
930
                       Unit.File_Names (Specification).Name,
931
                       Specification,
932
                       Unit.File_Names (Specification).Index);
933
               end if;
934
 
935
               if Unit.File_Names (Body_Part).Needs_Pragma then
936
                  Put (Unit.Name,
937
                       Unit.File_Names (Body_Part).Name,
938
                       Body_Part,
939
                       Unit.File_Names (Body_Part).Index);
940
               end if;
941
 
942
               Current_Unit := Current_Unit + 1;
943
            end;
944
         end loop;
945
 
946
         --  If there are no non standard naming scheme, issue the GNAT
947
         --  standard naming scheme. This will tell the compiler that
948
         --  a project file is used and will forbid any pragma SFN.
949
 
950
         if File = Invalid_FD then
951
            Check_Temp_File;
952
 
953
            Put_Line (File, "pragma Source_File_Name_Project");
954
            Put_Line (File, "   (Spec_File_Name  => ""*.ads"",");
955
            Put_Line (File, "    Dot_Replacement => ""-"",");
956
            Put_Line (File, "    Casing          => lowercase);");
957
 
958
            Put_Line (File, "pragma Source_File_Name_Project");
959
            Put_Line (File, "   (Body_File_Name  => ""*.adb"",");
960
            Put_Line (File, "    Dot_Replacement => ""-"",");
961
            Put_Line (File, "    Casing          => lowercase);");
962
         end if;
963
 
964
         --  Close the temporary file
965
 
966
         GNAT.OS_Lib.Close (File, Status);
967
 
968
         if not Status then
969
            Prj.Com.Fail ("disk full");
970
         end if;
971
 
972
         if Opt.Verbose_Mode then
973
            Write_Str ("Closing configuration file """);
974
            Write_Str (Get_Name_String (File_Name));
975
            Write_Line ("""");
976
         end if;
977
 
978
         In_Tree.Projects.Table (For_Project).Config_File_Name :=
979
           File_Name;
980
         In_Tree.Projects.Table (For_Project).Config_File_Temp :=
981
           True;
982
 
983
         In_Tree.Projects.Table (For_Project).Config_Checked :=
984
           True;
985
      end if;
986
   end Create_Config_Pragmas_File;
987
 
988
   -------------------------
989
   -- Create_Mapping_File --
990
   -------------------------
991
 
992
   procedure Create_Mapping_File
993
     (Project : Project_Id;
994
      In_Tree : Project_Tree_Ref;
995
      Name    : out Name_Id)
996
   is
997
      File          : File_Descriptor := Invalid_FD;
998
      The_Unit_Data : Unit_Data;
999
      Data          : File_Name_Data;
1000
 
1001
      Status : Boolean;
1002
      --  For call to Close
1003
 
1004
      Present       : Project_Flags
1005
        (No_Project .. Project_Table.Last (In_Tree.Projects)) :=
1006
        (others => False);
1007
      --  For each project in the closure of Project, the corresponding flag
1008
      --  will be set to True;
1009
 
1010
      procedure Put_Name_Buffer;
1011
      --  Put the line contained in the Name_Buffer in the mapping file
1012
 
1013
      procedure Put_Data (Spec : Boolean);
1014
      --  Put the mapping of the spec or body contained in Data in the file
1015
      --  (3 lines).
1016
 
1017
      procedure Recursive_Flag (Prj : Project_Id);
1018
      --  Set the flags corresponding to Prj, the projects it imports
1019
      --  (directly or indirectly) or extends to True. Call itself recursively.
1020
 
1021
      ---------
1022
      -- Put --
1023
      ---------
1024
 
1025
      procedure Put_Name_Buffer is
1026
         Last : Natural;
1027
 
1028
      begin
1029
         Name_Len := Name_Len + 1;
1030
         Name_Buffer (Name_Len) := ASCII.LF;
1031
         Last := Write (File, Name_Buffer (1)'Address, Name_Len);
1032
 
1033
         if Last /= Name_Len then
1034
            Prj.Com.Fail ("Disk full");
1035
         end if;
1036
      end Put_Name_Buffer;
1037
 
1038
      --------------
1039
      -- Put_Data --
1040
      --------------
1041
 
1042
      procedure Put_Data (Spec : Boolean) is
1043
      begin
1044
         --  Line with the unit name
1045
 
1046
         Get_Name_String (The_Unit_Data.Name);
1047
         Name_Len := Name_Len + 1;
1048
         Name_Buffer (Name_Len) := '%';
1049
         Name_Len := Name_Len + 1;
1050
 
1051
         if Spec then
1052
            Name_Buffer (Name_Len) := 's';
1053
         else
1054
            Name_Buffer (Name_Len) := 'b';
1055
         end if;
1056
 
1057
         Put_Name_Buffer;
1058
 
1059
         --  Line with the file name
1060
 
1061
         Get_Name_String (Data.Name);
1062
         Put_Name_Buffer;
1063
 
1064
         --  Line with the path name
1065
 
1066
         Get_Name_String (Data.Path);
1067
         Put_Name_Buffer;
1068
 
1069
      end Put_Data;
1070
 
1071
      --------------------
1072
      -- Recursive_Flag --
1073
      --------------------
1074
 
1075
      procedure Recursive_Flag (Prj : Project_Id) is
1076
         Imported : Project_List;
1077
         Proj     : Project_Id;
1078
 
1079
      begin
1080
         --  Nothing to do for non existent project or project that has
1081
         --  already been flagged.
1082
 
1083
         if Prj = No_Project or else Present (Prj) then
1084
            return;
1085
         end if;
1086
 
1087
         --  Flag the current project
1088
 
1089
         Present (Prj) := True;
1090
         Imported :=
1091
           In_Tree.Projects.Table (Prj).Imported_Projects;
1092
 
1093
         --  Call itself for each project directly imported
1094
 
1095
         while Imported /= Empty_Project_List loop
1096
            Proj :=
1097
              In_Tree.Project_Lists.Table (Imported).Project;
1098
            Imported :=
1099
              In_Tree.Project_Lists.Table (Imported).Next;
1100
            Recursive_Flag (Proj);
1101
         end loop;
1102
 
1103
         --  Call itself for an eventual project being extended
1104
 
1105
         Recursive_Flag (In_Tree.Projects.Table (Prj).Extends);
1106
      end Recursive_Flag;
1107
 
1108
   --  Start of processing for Create_Mapping_File
1109
 
1110
   begin
1111
      --  Flag the necessary projects
1112
 
1113
      Recursive_Flag (Project);
1114
 
1115
      --  Create the temporary file
1116
 
1117
      Tempdir.Create_Temp_File (File, Name => Name);
1118
 
1119
      if File = Invalid_FD then
1120
         Prj.Com.Fail ("unable to create temporary mapping file");
1121
 
1122
      elsif Opt.Verbose_Mode then
1123
         Write_Str ("Creating temp mapping file """);
1124
         Write_Str (Get_Name_String (Name));
1125
         Write_Line ("""");
1126
      end if;
1127
 
1128
      if Fill_Mapping_File then
1129
 
1130
         --  For all units in table Units
1131
 
1132
         for Unit in 1 .. Unit_Table.Last (In_Tree.Units) loop
1133
            The_Unit_Data := In_Tree.Units.Table (Unit);
1134
 
1135
            --  If the unit has a valid name
1136
 
1137
            if The_Unit_Data.Name /= No_Name then
1138
               Data := The_Unit_Data.File_Names (Specification);
1139
 
1140
               --  If there is a spec, put it mapping in the file if it is
1141
               --  from a project in the closure of Project.
1142
 
1143
               if Data.Name /= No_Name and then Present (Data.Project) then
1144
                  Put_Data (Spec => True);
1145
               end if;
1146
 
1147
               Data := The_Unit_Data.File_Names (Body_Part);
1148
 
1149
               --  If there is a body (or subunit) put its mapping in the file
1150
               --  if it is from a project in the closure of Project.
1151
 
1152
               if Data.Name /= No_Name and then Present (Data.Project) then
1153
                  Put_Data (Spec => False);
1154
               end if;
1155
 
1156
            end if;
1157
         end loop;
1158
      end if;
1159
 
1160
      GNAT.OS_Lib.Close (File, Status);
1161
 
1162
      if not Status then
1163
         Prj.Com.Fail ("disk full");
1164
      end if;
1165
   end Create_Mapping_File;
1166
 
1167
   --------------------------
1168
   -- Create_New_Path_File --
1169
   --------------------------
1170
 
1171
   procedure Create_New_Path_File
1172
     (In_Tree   : Project_Tree_Ref;
1173
      Path_FD   : out File_Descriptor;
1174
      Path_Name : out Name_Id)
1175
   is
1176
   begin
1177
      Tempdir.Create_Temp_File (Path_FD, Path_Name);
1178
 
1179
      if Path_Name /= No_Name then
1180
 
1181
         --  Record the name, so that the temp path file will be deleted
1182
         --  at the end of the program.
1183
 
1184
         Path_File_Table.Increment_Last (In_Tree.Private_Part.Path_Files);
1185
         In_Tree.Private_Part.Path_Files.Table
1186
           (Path_File_Table.Last (In_Tree.Private_Part.Path_Files)) :=
1187
              Path_Name;
1188
      end if;
1189
   end Create_New_Path_File;
1190
 
1191
   ---------------------------
1192
   -- Delete_All_Path_Files --
1193
   ---------------------------
1194
 
1195
   procedure Delete_All_Path_Files (In_Tree : Project_Tree_Ref) is
1196
      Disregard : Boolean := True;
1197
 
1198
   begin
1199
      for Index in Path_File_Table.First ..
1200
                   Path_File_Table.Last (In_Tree.Private_Part.Path_Files)
1201
      loop
1202
         if In_Tree.Private_Part.Path_Files.Table (Index) /= No_Name then
1203
            Delete_File
1204
              (Get_Name_String
1205
                 (In_Tree.Private_Part.Path_Files.Table (Index)),
1206
               Disregard);
1207
         end if;
1208
      end loop;
1209
 
1210
      --  If any of the environment variables ADA_PRJ_INCLUDE_FILE or
1211
      --  ADA_PRJ_OBJECTS_FILE has been set, then reset their value to
1212
      --  the empty string. On VMS, this has the effect of deassigning
1213
      --  the logical names.
1214
 
1215
      if Ada_Prj_Include_File_Set then
1216
         Setenv (Project_Include_Path_File, "");
1217
         Ada_Prj_Include_File_Set := False;
1218
      end if;
1219
 
1220
      if Ada_Prj_Objects_File_Set then
1221
         Setenv (Project_Objects_Path_File, "");
1222
         Ada_Prj_Objects_File_Set := False;
1223
      end if;
1224
   end Delete_All_Path_Files;
1225
 
1226
   ------------------------------------
1227
   -- File_Name_Of_Library_Unit_Body --
1228
   ------------------------------------
1229
 
1230
   function File_Name_Of_Library_Unit_Body
1231
     (Name              : String;
1232
      Project           : Project_Id;
1233
      In_Tree           : Project_Tree_Ref;
1234
      Main_Project_Only : Boolean := True;
1235
      Full_Path         : Boolean := False) return String
1236
   is
1237
      The_Project   : Project_Id := Project;
1238
      Data          : Project_Data :=
1239
                        In_Tree.Projects.Table (Project);
1240
      Original_Name : String := Name;
1241
 
1242
      Extended_Spec_Name : String :=
1243
                             Name & Namet.Get_Name_String
1244
                                      (Data.Naming.Ada_Spec_Suffix);
1245
      Extended_Body_Name : String :=
1246
                             Name & Namet.Get_Name_String
1247
                                      (Data.Naming.Ada_Body_Suffix);
1248
 
1249
      Unit : Unit_Data;
1250
 
1251
      The_Original_Name : Name_Id;
1252
      The_Spec_Name     : Name_Id;
1253
      The_Body_Name     : Name_Id;
1254
 
1255
   begin
1256
      Canonical_Case_File_Name (Original_Name);
1257
      Name_Len := Original_Name'Length;
1258
      Name_Buffer (1 .. Name_Len) := Original_Name;
1259
      The_Original_Name := Name_Find;
1260
 
1261
      Canonical_Case_File_Name (Extended_Spec_Name);
1262
      Name_Len := Extended_Spec_Name'Length;
1263
      Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
1264
      The_Spec_Name := Name_Find;
1265
 
1266
      Canonical_Case_File_Name (Extended_Body_Name);
1267
      Name_Len := Extended_Body_Name'Length;
1268
      Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
1269
      The_Body_Name := Name_Find;
1270
 
1271
      if Current_Verbosity = High then
1272
         Write_Str  ("Looking for file name of """);
1273
         Write_Str  (Name);
1274
         Write_Char ('"');
1275
         Write_Eol;
1276
         Write_Str  ("   Extended Spec Name = """);
1277
         Write_Str  (Extended_Spec_Name);
1278
         Write_Char ('"');
1279
         Write_Eol;
1280
         Write_Str  ("   Extended Body Name = """);
1281
         Write_Str  (Extended_Body_Name);
1282
         Write_Char ('"');
1283
         Write_Eol;
1284
      end if;
1285
 
1286
      --  For extending project, search in the extended project
1287
      --  if the source is not found. For non extending projects,
1288
      --  this loop will be run only once.
1289
 
1290
      loop
1291
         --  Loop through units
1292
         --  Should have comment explaining reverse ???
1293
 
1294
         for Current in reverse Unit_Table.First ..
1295
                                Unit_Table.Last (In_Tree.Units)
1296
         loop
1297
            Unit := In_Tree.Units.Table (Current);
1298
 
1299
            --  Check for body
1300
 
1301
            if not Main_Project_Only
1302
              or else Unit.File_Names (Body_Part).Project = The_Project
1303
            then
1304
               declare
1305
                  Current_Name : constant Name_Id :=
1306
                                   Unit.File_Names (Body_Part).Name;
1307
 
1308
               begin
1309
                  --  Case of a body present
1310
 
1311
                  if Current_Name /= No_Name then
1312
                     if Current_Verbosity = High then
1313
                        Write_Str  ("   Comparing with """);
1314
                        Write_Str  (Get_Name_String (Current_Name));
1315
                        Write_Char ('"');
1316
                        Write_Eol;
1317
                     end if;
1318
 
1319
                     --  If it has the name of the original name,
1320
                     --  return the original name
1321
 
1322
                     if Unit.Name = The_Original_Name
1323
                       or else Current_Name = The_Original_Name
1324
                     then
1325
                        if Current_Verbosity = High then
1326
                           Write_Line ("   OK");
1327
                        end if;
1328
 
1329
                        if Full_Path then
1330
                           return Get_Name_String
1331
                             (Unit.File_Names (Body_Part).Path);
1332
 
1333
                        else
1334
                           return Get_Name_String (Current_Name);
1335
                        end if;
1336
 
1337
                        --  If it has the name of the extended body name,
1338
                        --  return the extended body name
1339
 
1340
                     elsif Current_Name = The_Body_Name then
1341
                        if Current_Verbosity = High then
1342
                           Write_Line ("   OK");
1343
                        end if;
1344
 
1345
                        if Full_Path then
1346
                           return Get_Name_String
1347
                             (Unit.File_Names (Body_Part).Path);
1348
 
1349
                        else
1350
                           return Extended_Body_Name;
1351
                        end if;
1352
 
1353
                     else
1354
                        if Current_Verbosity = High then
1355
                           Write_Line ("   not good");
1356
                        end if;
1357
                     end if;
1358
                  end if;
1359
               end;
1360
            end if;
1361
 
1362
            --  Check for spec
1363
 
1364
            if not Main_Project_Only
1365
              or else Unit.File_Names (Specification).Project = The_Project
1366
            then
1367
               declare
1368
                  Current_Name : constant Name_Id :=
1369
                                   Unit.File_Names (Specification).Name;
1370
 
1371
               begin
1372
                  --  Case of spec present
1373
 
1374
                  if Current_Name /= No_Name then
1375
                     if Current_Verbosity = High then
1376
                        Write_Str  ("   Comparing with """);
1377
                        Write_Str  (Get_Name_String (Current_Name));
1378
                        Write_Char ('"');
1379
                        Write_Eol;
1380
                     end if;
1381
 
1382
                     --  If name same as original name, return original name
1383
 
1384
                     if Unit.Name = The_Original_Name
1385
                       or else Current_Name = The_Original_Name
1386
                     then
1387
                        if Current_Verbosity = High then
1388
                           Write_Line ("   OK");
1389
                        end if;
1390
 
1391
                        if Full_Path then
1392
                           return Get_Name_String
1393
                             (Unit.File_Names (Specification).Path);
1394
                        else
1395
                           return Get_Name_String (Current_Name);
1396
                        end if;
1397
 
1398
                        --  If it has the same name as the extended spec name,
1399
                        --  return the extended spec name.
1400
 
1401
                     elsif Current_Name = The_Spec_Name then
1402
                        if Current_Verbosity = High then
1403
                           Write_Line ("   OK");
1404
                        end if;
1405
 
1406
                        if Full_Path then
1407
                           return Get_Name_String
1408
                             (Unit.File_Names (Specification).Path);
1409
                        else
1410
                           return Extended_Spec_Name;
1411
                        end if;
1412
 
1413
                     else
1414
                        if Current_Verbosity = High then
1415
                           Write_Line ("   not good");
1416
                        end if;
1417
                     end if;
1418
                  end if;
1419
               end;
1420
            end if;
1421
         end loop;
1422
 
1423
         --  If we are not in an extending project, give up
1424
 
1425
         exit when (not Main_Project_Only) or else Data.Extends = No_Project;
1426
 
1427
         --  Otherwise, look in the project we are extending
1428
 
1429
         The_Project := Data.Extends;
1430
         Data := In_Tree.Projects.Table (The_Project);
1431
      end loop;
1432
 
1433
      --  We don't know this file name, return an empty string
1434
 
1435
      return "";
1436
   end File_Name_Of_Library_Unit_Body;
1437
 
1438
   -------------------------
1439
   -- For_All_Object_Dirs --
1440
   -------------------------
1441
 
1442
   procedure For_All_Object_Dirs
1443
     (Project : Project_Id;
1444
      In_Tree : Project_Tree_Ref)
1445
   is
1446
      Seen : Project_List := Empty_Project_List;
1447
 
1448
      procedure Add (Project : Project_Id);
1449
      --  Process a project. Remember the processes visited to avoid
1450
      --  processing a project twice. Recursively process an eventual
1451
      --  extended project, and all imported projects.
1452
 
1453
      ---------
1454
      -- Add --
1455
      ---------
1456
 
1457
      procedure Add (Project : Project_Id) is
1458
         Data : constant Project_Data :=
1459
                  In_Tree.Projects.Table (Project);
1460
         List : Project_List := Data.Imported_Projects;
1461
 
1462
      begin
1463
         --  If the list of visited project is empty, then
1464
         --  for sure we never visited this project.
1465
 
1466
         if Seen = Empty_Project_List then
1467
            Project_List_Table.Increment_Last
1468
              (In_Tree.Project_Lists);
1469
            Seen :=
1470
              Project_List_Table.Last (In_Tree.Project_Lists);
1471
            In_Tree.Project_Lists.Table (Seen) :=
1472
              (Project => Project, Next => Empty_Project_List);
1473
 
1474
         else
1475
            --  Check if the project is in the list
1476
 
1477
            declare
1478
               Current : Project_List := Seen;
1479
 
1480
            begin
1481
               loop
1482
                  --  If it is, then there is nothing else to do
1483
 
1484
                  if In_Tree.Project_Lists.Table
1485
                                           (Current).Project = Project
1486
                  then
1487
                     return;
1488
                  end if;
1489
 
1490
                  exit when
1491
                    In_Tree.Project_Lists.Table (Current).Next =
1492
                      Empty_Project_List;
1493
                  Current :=
1494
                    In_Tree.Project_Lists.Table (Current).Next;
1495
               end loop;
1496
 
1497
               --  This project has never been visited, add it
1498
               --  to the list.
1499
 
1500
               Project_List_Table.Increment_Last
1501
                 (In_Tree.Project_Lists);
1502
               In_Tree.Project_Lists.Table (Current).Next :=
1503
                 Project_List_Table.Last (In_Tree.Project_Lists);
1504
               In_Tree.Project_Lists.Table
1505
                 (Project_List_Table.Last
1506
                    (In_Tree.Project_Lists)) :=
1507
                 (Project => Project, Next => Empty_Project_List);
1508
            end;
1509
         end if;
1510
 
1511
         --  If there is an object directory, call Action
1512
         --  with its name
1513
 
1514
         if Data.Object_Directory /= No_Name then
1515
            Get_Name_String (Data.Object_Directory);
1516
            Action (Name_Buffer (1 .. Name_Len));
1517
         end if;
1518
 
1519
         --  If we are extending a project, visit it
1520
 
1521
         if Data.Extends /= No_Project then
1522
            Add (Data.Extends);
1523
         end if;
1524
 
1525
         --  And visit all imported projects
1526
 
1527
         while List /= Empty_Project_List loop
1528
            Add (In_Tree.Project_Lists.Table (List).Project);
1529
            List := In_Tree.Project_Lists.Table (List).Next;
1530
         end loop;
1531
      end Add;
1532
 
1533
   --  Start of processing for For_All_Object_Dirs
1534
 
1535
   begin
1536
      --  Visit this project, and its imported projects,
1537
      --  recursively
1538
 
1539
      Add (Project);
1540
   end For_All_Object_Dirs;
1541
 
1542
   -------------------------
1543
   -- For_All_Source_Dirs --
1544
   -------------------------
1545
 
1546
   procedure For_All_Source_Dirs
1547
     (Project : Project_Id;
1548
      In_Tree : Project_Tree_Ref)
1549
   is
1550
      Seen : Project_List := Empty_Project_List;
1551
 
1552
      procedure Add (Project : Project_Id);
1553
      --  Process a project. Remember the processes visited to avoid
1554
      --  processing a project twice. Recursively process an eventual
1555
      --  extended project, and all imported projects.
1556
 
1557
      ---------
1558
      -- Add --
1559
      ---------
1560
 
1561
      procedure Add (Project : Project_Id) is
1562
         Data : constant Project_Data :=
1563
                  In_Tree.Projects.Table (Project);
1564
         List : Project_List := Data.Imported_Projects;
1565
 
1566
      begin
1567
         --  If the list of visited project is empty, then
1568
         --  for sure we never visited this project.
1569
 
1570
         if Seen = Empty_Project_List then
1571
            Project_List_Table.Increment_Last
1572
              (In_Tree.Project_Lists);
1573
            Seen := Project_List_Table.Last
1574
                                         (In_Tree.Project_Lists);
1575
            In_Tree.Project_Lists.Table (Seen) :=
1576
              (Project => Project, Next => Empty_Project_List);
1577
 
1578
         else
1579
            --  Check if the project is in the list
1580
 
1581
            declare
1582
               Current : Project_List := Seen;
1583
 
1584
            begin
1585
               loop
1586
                  --  If it is, then there is nothing else to do
1587
 
1588
                  if In_Tree.Project_Lists.Table
1589
                                           (Current).Project = Project
1590
                  then
1591
                     return;
1592
                  end if;
1593
 
1594
                  exit when
1595
                    In_Tree.Project_Lists.Table (Current).Next =
1596
                      Empty_Project_List;
1597
                  Current :=
1598
                    In_Tree.Project_Lists.Table (Current).Next;
1599
               end loop;
1600
 
1601
               --  This project has never been visited, add it
1602
               --  to the list.
1603
 
1604
               Project_List_Table.Increment_Last
1605
                 (In_Tree.Project_Lists);
1606
               In_Tree.Project_Lists.Table (Current).Next :=
1607
                 Project_List_Table.Last (In_Tree.Project_Lists);
1608
               In_Tree.Project_Lists.Table
1609
                 (Project_List_Table.Last
1610
                    (In_Tree.Project_Lists)) :=
1611
                 (Project => Project, Next => Empty_Project_List);
1612
            end;
1613
         end if;
1614
 
1615
         declare
1616
            Current    : String_List_Id := Data.Source_Dirs;
1617
            The_String : String_Element;
1618
 
1619
         begin
1620
            --  If there are Ada sources, call action with the name of every
1621
            --  source directory.
1622
 
1623
            if
1624
              In_Tree.Projects.Table (Project).Ada_Sources_Present
1625
            then
1626
               while Current /= Nil_String loop
1627
                  The_String :=
1628
                    In_Tree.String_Elements.Table (Current);
1629
                  Action (Get_Name_String (The_String.Value));
1630
                  Current := The_String.Next;
1631
               end loop;
1632
            end if;
1633
         end;
1634
 
1635
         --  If we are extending a project, visit it
1636
 
1637
         if Data.Extends /= No_Project then
1638
            Add (Data.Extends);
1639
         end if;
1640
 
1641
         --  And visit all imported projects
1642
 
1643
         while List /= Empty_Project_List loop
1644
            Add (In_Tree.Project_Lists.Table (List).Project);
1645
            List := In_Tree.Project_Lists.Table (List).Next;
1646
         end loop;
1647
      end Add;
1648
 
1649
   --  Start of processing for For_All_Source_Dirs
1650
 
1651
   begin
1652
      --  Visit this project, and its imported projects recursively
1653
 
1654
      Add (Project);
1655
   end For_All_Source_Dirs;
1656
 
1657
   -------------------
1658
   -- Get_Reference --
1659
   -------------------
1660
 
1661
   procedure Get_Reference
1662
     (Source_File_Name : String;
1663
      In_Tree          : Project_Tree_Ref;
1664
      Project          : out Project_Id;
1665
      Path             : out Name_Id)
1666
   is
1667
   begin
1668
      --  Body below could use some comments ???
1669
 
1670
      if Current_Verbosity > Default then
1671
         Write_Str ("Getting Reference_Of (""");
1672
         Write_Str (Source_File_Name);
1673
         Write_Str (""") ... ");
1674
      end if;
1675
 
1676
      declare
1677
         Original_Name : String := Source_File_Name;
1678
         Unit          : Unit_Data;
1679
 
1680
      begin
1681
         Canonical_Case_File_Name (Original_Name);
1682
 
1683
         for Id in Unit_Table.First ..
1684
                   Unit_Table.Last (In_Tree.Units)
1685
         loop
1686
            Unit := In_Tree.Units.Table (Id);
1687
 
1688
            if (Unit.File_Names (Specification).Name /= No_Name
1689
                 and then
1690
                   Namet.Get_Name_String
1691
                     (Unit.File_Names (Specification).Name) = Original_Name)
1692
              or else (Unit.File_Names (Specification).Path /= No_Name
1693
                         and then
1694
                           Namet.Get_Name_String
1695
                           (Unit.File_Names (Specification).Path) =
1696
                                                              Original_Name)
1697
            then
1698
               Project := Ultimate_Extension_Of
1699
                           (Project => Unit.File_Names (Specification).Project,
1700
                            In_Tree => In_Tree);
1701
               Path := Unit.File_Names (Specification).Display_Path;
1702
 
1703
               if Current_Verbosity > Default then
1704
                  Write_Str ("Done: Specification.");
1705
                  Write_Eol;
1706
               end if;
1707
 
1708
               return;
1709
 
1710
            elsif (Unit.File_Names (Body_Part).Name /= No_Name
1711
                    and then
1712
                      Namet.Get_Name_String
1713
                        (Unit.File_Names (Body_Part).Name) = Original_Name)
1714
              or else (Unit.File_Names (Body_Part).Path /= No_Name
1715
                         and then Namet.Get_Name_String
1716
                                    (Unit.File_Names (Body_Part).Path) =
1717
                                                             Original_Name)
1718
            then
1719
               Project := Ultimate_Extension_Of
1720
                            (Project => Unit.File_Names (Body_Part).Project,
1721
                             In_Tree => In_Tree);
1722
               Path := Unit.File_Names (Body_Part).Display_Path;
1723
 
1724
               if Current_Verbosity > Default then
1725
                  Write_Str ("Done: Body.");
1726
                  Write_Eol;
1727
               end if;
1728
 
1729
               return;
1730
            end if;
1731
         end loop;
1732
      end;
1733
 
1734
      Project := No_Project;
1735
      Path    := No_Name;
1736
 
1737
      if Current_Verbosity > Default then
1738
         Write_Str ("Cannot be found.");
1739
         Write_Eol;
1740
      end if;
1741
   end Get_Reference;
1742
 
1743
   ----------------
1744
   -- Initialize --
1745
   ----------------
1746
 
1747
   procedure Initialize is
1748
   begin
1749
      Fill_Mapping_File := True;
1750
   end Initialize;
1751
 
1752
   ------------------------------------
1753
   -- Path_Name_Of_Library_Unit_Body --
1754
   ------------------------------------
1755
 
1756
   --  Could use some comments in the body here ???
1757
 
1758
   function Path_Name_Of_Library_Unit_Body
1759
     (Name    : String;
1760
      Project : Project_Id;
1761
      In_Tree : Project_Tree_Ref) return String
1762
   is
1763
      Data          : constant Project_Data :=
1764
                        In_Tree.Projects.Table (Project);
1765
      Original_Name : String := Name;
1766
 
1767
      Extended_Spec_Name : String :=
1768
                             Name & Namet.Get_Name_String
1769
                                     (Data.Naming.Ada_Spec_Suffix);
1770
      Extended_Body_Name : String :=
1771
                             Name & Namet.Get_Name_String
1772
                                     (Data.Naming.Ada_Body_Suffix);
1773
 
1774
      First   : Unit_Id := Unit_Table.First;
1775
      Current : Unit_Id;
1776
      Unit    : Unit_Data;
1777
 
1778
   begin
1779
      Canonical_Case_File_Name (Original_Name);
1780
      Canonical_Case_File_Name (Extended_Spec_Name);
1781
      Canonical_Case_File_Name (Extended_Body_Name);
1782
 
1783
      if Current_Verbosity = High then
1784
         Write_Str  ("Looking for path name of """);
1785
         Write_Str  (Name);
1786
         Write_Char ('"');
1787
         Write_Eol;
1788
         Write_Str  ("   Extended Spec Name = """);
1789
         Write_Str  (Extended_Spec_Name);
1790
         Write_Char ('"');
1791
         Write_Eol;
1792
         Write_Str  ("   Extended Body Name = """);
1793
         Write_Str  (Extended_Body_Name);
1794
         Write_Char ('"');
1795
         Write_Eol;
1796
      end if;
1797
 
1798
      while First <= Unit_Table.Last (In_Tree.Units)
1799
        and then In_Tree.Units.Table
1800
                   (First).File_Names (Body_Part).Project /= Project
1801
      loop
1802
         First := First + 1;
1803
      end loop;
1804
 
1805
      Current := First;
1806
      while Current <= Unit_Table.Last (In_Tree.Units) loop
1807
         Unit := In_Tree.Units.Table (Current);
1808
 
1809
         if Unit.File_Names (Body_Part).Project = Project
1810
           and then Unit.File_Names (Body_Part).Name /= No_Name
1811
         then
1812
            declare
1813
               Current_Name : constant String :=
1814
                 Namet.Get_Name_String (Unit.File_Names (Body_Part).Name);
1815
            begin
1816
               if Current_Verbosity = High then
1817
                  Write_Str  ("   Comparing with """);
1818
                  Write_Str  (Current_Name);
1819
                  Write_Char ('"');
1820
                  Write_Eol;
1821
               end if;
1822
 
1823
               if Current_Name = Original_Name then
1824
                  if Current_Verbosity = High then
1825
                     Write_Line ("   OK");
1826
                  end if;
1827
 
1828
                  return Body_Path_Name_Of (Current, In_Tree);
1829
 
1830
               elsif Current_Name = Extended_Body_Name then
1831
                  if Current_Verbosity = High then
1832
                     Write_Line ("   OK");
1833
                  end if;
1834
 
1835
                  return Body_Path_Name_Of (Current, In_Tree);
1836
 
1837
               else
1838
                  if Current_Verbosity = High then
1839
                     Write_Line ("   not good");
1840
                  end if;
1841
               end if;
1842
            end;
1843
 
1844
         elsif Unit.File_Names (Specification).Name /= No_Name then
1845
            declare
1846
               Current_Name : constant String :=
1847
                                Namet.Get_Name_String
1848
                                  (Unit.File_Names (Specification).Name);
1849
 
1850
            begin
1851
               if Current_Verbosity = High then
1852
                  Write_Str  ("   Comparing with """);
1853
                  Write_Str  (Current_Name);
1854
                  Write_Char ('"');
1855
                  Write_Eol;
1856
               end if;
1857
 
1858
               if Current_Name = Original_Name then
1859
                  if Current_Verbosity = High then
1860
                     Write_Line ("   OK");
1861
                  end if;
1862
 
1863
                  return Spec_Path_Name_Of (Current, In_Tree);
1864
 
1865
               elsif Current_Name = Extended_Spec_Name then
1866
                  if Current_Verbosity = High then
1867
                     Write_Line ("   OK");
1868
                  end if;
1869
 
1870
                  return Spec_Path_Name_Of (Current, In_Tree);
1871
 
1872
               else
1873
                  if Current_Verbosity = High then
1874
                     Write_Line ("   not good");
1875
                  end if;
1876
               end if;
1877
            end;
1878
         end if;
1879
         Current := Current + 1;
1880
      end loop;
1881
 
1882
      return "";
1883
   end Path_Name_Of_Library_Unit_Body;
1884
 
1885
   -------------------
1886
   -- Print_Sources --
1887
   -------------------
1888
 
1889
   --  Could use some comments in this body ???
1890
 
1891
   procedure Print_Sources (In_Tree : Project_Tree_Ref) is
1892
      Unit : Unit_Data;
1893
 
1894
   begin
1895
      Write_Line ("List of Sources:");
1896
 
1897
      for Id in Unit_Table.First ..
1898
                Unit_Table.Last (In_Tree.Units)
1899
      loop
1900
         Unit := In_Tree.Units.Table (Id);
1901
         Write_Str  ("   ");
1902
         Write_Line (Namet.Get_Name_String (Unit.Name));
1903
 
1904
         if Unit.File_Names (Specification).Name /= No_Name then
1905
            if Unit.File_Names (Specification).Project = No_Project then
1906
               Write_Line ("   No project");
1907
 
1908
            else
1909
               Write_Str  ("   Project: ");
1910
               Get_Name_String
1911
                 (In_Tree.Projects.Table
1912
                   (Unit.File_Names (Specification).Project).Path_Name);
1913
               Write_Line (Name_Buffer (1 .. Name_Len));
1914
            end if;
1915
 
1916
            Write_Str  ("      spec: ");
1917
            Write_Line
1918
              (Namet.Get_Name_String
1919
               (Unit.File_Names (Specification).Name));
1920
         end if;
1921
 
1922
         if Unit.File_Names (Body_Part).Name /= No_Name then
1923
            if Unit.File_Names (Body_Part).Project = No_Project then
1924
               Write_Line ("   No project");
1925
 
1926
            else
1927
               Write_Str  ("   Project: ");
1928
               Get_Name_String
1929
                 (In_Tree.Projects.Table
1930
                   (Unit.File_Names (Body_Part).Project).Path_Name);
1931
               Write_Line (Name_Buffer (1 .. Name_Len));
1932
            end if;
1933
 
1934
            Write_Str  ("      body: ");
1935
            Write_Line
1936
              (Namet.Get_Name_String
1937
               (Unit.File_Names (Body_Part).Name));
1938
         end if;
1939
      end loop;
1940
 
1941
      Write_Line ("end of List of Sources.");
1942
   end Print_Sources;
1943
 
1944
   ----------------
1945
   -- Project_Of --
1946
   ----------------
1947
 
1948
   function Project_Of
1949
     (Name         : String;
1950
      Main_Project : Project_Id;
1951
      In_Tree      : Project_Tree_Ref) return Project_Id
1952
   is
1953
      Result : Project_Id := No_Project;
1954
 
1955
      Original_Name : String := Name;
1956
 
1957
      Data   : constant Project_Data :=
1958
        In_Tree.Projects.Table (Main_Project);
1959
 
1960
      Extended_Spec_Name : String :=
1961
                             Name & Namet.Get_Name_String
1962
                                      (Data.Naming.Ada_Spec_Suffix);
1963
      Extended_Body_Name : String :=
1964
                             Name & Namet.Get_Name_String
1965
                                      (Data.Naming.Ada_Body_Suffix);
1966
 
1967
      Unit : Unit_Data;
1968
 
1969
      Current_Name : Name_Id;
1970
 
1971
      The_Original_Name : Name_Id;
1972
      The_Spec_Name     : Name_Id;
1973
      The_Body_Name     : Name_Id;
1974
 
1975
   begin
1976
      Canonical_Case_File_Name (Original_Name);
1977
      Name_Len := Original_Name'Length;
1978
      Name_Buffer (1 .. Name_Len) := Original_Name;
1979
      The_Original_Name := Name_Find;
1980
 
1981
      Canonical_Case_File_Name (Extended_Spec_Name);
1982
      Name_Len := Extended_Spec_Name'Length;
1983
      Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
1984
      The_Spec_Name := Name_Find;
1985
 
1986
      Canonical_Case_File_Name (Extended_Body_Name);
1987
      Name_Len := Extended_Body_Name'Length;
1988
      Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
1989
      The_Body_Name := Name_Find;
1990
 
1991
      for Current in reverse Unit_Table.First ..
1992
                             Unit_Table.Last (In_Tree.Units)
1993
      loop
1994
         Unit := In_Tree.Units.Table (Current);
1995
 
1996
         --  Check for body
1997
 
1998
         Current_Name := Unit.File_Names (Body_Part).Name;
1999
 
2000
         --  Case of a body present
2001
 
2002
         if Current_Name /= No_Name then
2003
 
2004
            --  If it has the name of the original name or the body name,
2005
            --  we have found the project.
2006
 
2007
            if Unit.Name = The_Original_Name
2008
              or else Current_Name = The_Original_Name
2009
              or else Current_Name = The_Body_Name
2010
            then
2011
               Result := Unit.File_Names (Body_Part).Project;
2012
               exit;
2013
            end if;
2014
         end if;
2015
 
2016
         --  Check for spec
2017
 
2018
         Current_Name := Unit.File_Names (Specification).Name;
2019
 
2020
         if Current_Name /= No_Name then
2021
 
2022
            --  If name same as the original name, or the spec name, we have
2023
            --  found the project.
2024
 
2025
            if Unit.Name = The_Original_Name
2026
              or else Current_Name = The_Original_Name
2027
              or else Current_Name = The_Spec_Name
2028
            then
2029
               Result := Unit.File_Names (Specification).Project;
2030
               exit;
2031
            end if;
2032
         end if;
2033
      end loop;
2034
 
2035
      --  Get the ultimate extending project
2036
 
2037
      if Result /= No_Project then
2038
         while In_Tree.Projects.Table (Result).Extended_By /=
2039
           No_Project
2040
         loop
2041
            Result := In_Tree.Projects.Table (Result).Extended_By;
2042
         end loop;
2043
      end if;
2044
 
2045
      return Result;
2046
   end Project_Of;
2047
 
2048
   -------------------
2049
   -- Set_Ada_Paths --
2050
   -------------------
2051
 
2052
   procedure Set_Ada_Paths
2053
     (Project             : Project_Id;
2054
      In_Tree             : Project_Tree_Ref;
2055
      Including_Libraries : Boolean)
2056
   is
2057
      Source_FD : File_Descriptor := Invalid_FD;
2058
      Object_FD : File_Descriptor := Invalid_FD;
2059
 
2060
      Process_Source_Dirs : Boolean := False;
2061
      Process_Object_Dirs : Boolean := False;
2062
 
2063
      Status : Boolean;
2064
      --  For calls to Close
2065
 
2066
      Len : Natural;
2067
 
2068
      procedure Add (Proj : Project_Id);
2069
      --  Add all the source/object directories of a project to the path only
2070
      --  if this project has not been visited. Calls an internal procedure
2071
      --  recursively for projects being extended, and imported projects.
2072
 
2073
      ---------
2074
      -- Add --
2075
      ---------
2076
 
2077
      procedure Add (Proj : Project_Id) is
2078
 
2079
         procedure Recursive_Add (Project : Project_Id);
2080
         --  Recursive procedure to add the source/object paths of extended/
2081
         --  imported projects.
2082
 
2083
         -------------------
2084
         -- Recursive_Add --
2085
         -------------------
2086
 
2087
         procedure Recursive_Add (Project : Project_Id) is
2088
         begin
2089
            --  If Seen is False, then the project has not yet been visited
2090
 
2091
            if not In_Tree.Projects.Table (Project).Seen then
2092
               In_Tree.Projects.Table (Project).Seen := True;
2093
 
2094
               declare
2095
                  Data : constant Project_Data :=
2096
                    In_Tree.Projects.Table (Project);
2097
                  List : Project_List := Data.Imported_Projects;
2098
 
2099
               begin
2100
                  if Process_Source_Dirs then
2101
 
2102
                     --  Add to path all source directories of this project
2103
                     --  if there are Ada sources.
2104
 
2105
                     if In_Tree.Projects.Table
2106
                          (Project).Ada_Sources_Present
2107
                     then
2108
                        Add_To_Source_Path (Data.Source_Dirs, In_Tree);
2109
                     end if;
2110
                  end if;
2111
 
2112
                  if Process_Object_Dirs then
2113
 
2114
                     --  Add to path the object directory of this project
2115
                     --  except if we don't include library project and
2116
                     --  this is a library project.
2117
 
2118
                     if (Data.Library and then Including_Libraries)
2119
                       or else
2120
                         (Data.Object_Directory /= No_Name
2121
                          and then
2122
                            (not Including_Libraries or else not Data.Library))
2123
                     then
2124
                        --  For a library project, add the library ALI
2125
                        --  directory if there is no object directory or
2126
                        --  if the library ALI directory contains ALI files;
2127
                        --  otherwise add the object directory.
2128
 
2129
                        if Data.Library then
2130
                           if Data.Object_Directory = No_Name
2131
                             or else Contains_ALI_Files (Data.Library_ALI_Dir)
2132
                           then
2133
                              Add_To_Object_Path
2134
                                (Data.Library_ALI_Dir, In_Tree);
2135
                           else
2136
                              Add_To_Object_Path
2137
                                (Data.Object_Directory, In_Tree);
2138
                           end if;
2139
 
2140
                        --  For a non-library project, add the object
2141
                        --  directory, if it is not a virtual project, and
2142
                        --  if there are Ada sources or if the project is an
2143
                        --  extending project. if There Are No Ada sources,
2144
                        --  adding the object directory could disrupt
2145
                        --  the order of the object dirs in the path.
2146
 
2147
                        elsif not Data.Virtual
2148
                          and then (In_Tree.Projects.Table
2149
                                      (Project).Ada_Sources_Present
2150
                                    or else
2151
                                      (Data.Extends /= No_Project
2152
                                       and then
2153
                                       Data.Object_Directory /= No_Name))
2154
                        then
2155
                           Add_To_Object_Path
2156
                             (Data.Object_Directory, In_Tree);
2157
                        end if;
2158
                     end if;
2159
                  end if;
2160
 
2161
                  --  Call Add to the project being extended, if any
2162
 
2163
                  if Data.Extends /= No_Project then
2164
                     Recursive_Add (Data.Extends);
2165
                  end if;
2166
 
2167
                  --  Call Add for each imported project, if any
2168
 
2169
                  while List /= Empty_Project_List loop
2170
                     Recursive_Add
2171
                       (In_Tree.Project_Lists.Table
2172
                          (List).Project);
2173
                     List :=
2174
                       In_Tree.Project_Lists.Table (List).Next;
2175
                  end loop;
2176
               end;
2177
            end if;
2178
         end Recursive_Add;
2179
 
2180
      begin
2181
         Source_Path_Table.Set_Last (In_Tree.Private_Part.Source_Paths, 0);
2182
         Object_Path_Table.Set_Last (In_Tree.Private_Part.Object_Paths, 0);
2183
 
2184
         for Index in Project_Table.First ..
2185
                      Project_Table.Last (In_Tree.Projects)
2186
         loop
2187
            In_Tree.Projects.Table (Index).Seen := False;
2188
         end loop;
2189
 
2190
         Recursive_Add (Proj);
2191
      end Add;
2192
 
2193
   --  Start of processing for Set_Ada_Paths
2194
 
2195
   begin
2196
      --  If it is the first time we call this procedure for
2197
      --  this project, compute the source path and/or the object path.
2198
 
2199
      if In_Tree.Projects.Table (Project).Include_Path_File =
2200
        No_Name
2201
      then
2202
         Process_Source_Dirs := True;
2203
         Create_New_Path_File
2204
           (In_Tree, Source_FD,
2205
            In_Tree.Projects.Table (Project).Include_Path_File);
2206
      end if;
2207
 
2208
      --  For the object path, we make a distinction depending on
2209
      --  Including_Libraries.
2210
 
2211
      if Including_Libraries then
2212
         if In_Tree.Projects.Table
2213
           (Project).Objects_Path_File_With_Libs = No_Name
2214
         then
2215
            Process_Object_Dirs := True;
2216
            Create_New_Path_File
2217
              (In_Tree, Object_FD, In_Tree.Projects.Table (Project).
2218
                                           Objects_Path_File_With_Libs);
2219
         end if;
2220
 
2221
      else
2222
         if In_Tree.Projects.Table
2223
              (Project).Objects_Path_File_Without_Libs = No_Name
2224
         then
2225
            Process_Object_Dirs := True;
2226
            Create_New_Path_File
2227
              (In_Tree, Object_FD, In_Tree.Projects.Table (Project).
2228
                                           Objects_Path_File_Without_Libs);
2229
         end if;
2230
      end if;
2231
 
2232
      --  If there is something to do, set Seen to False for all projects,
2233
      --  then call the recursive procedure Add for Project.
2234
 
2235
      if Process_Source_Dirs or Process_Object_Dirs then
2236
         Add (Project);
2237
      end if;
2238
 
2239
      --  Write and close any file that has been created
2240
 
2241
      if Source_FD /= Invalid_FD then
2242
         for Index in Source_Path_Table.First ..
2243
                      Source_Path_Table.Last
2244
                        (In_Tree.Private_Part.Source_Paths)
2245
         loop
2246
            Get_Name_String (In_Tree.Private_Part.Source_Paths.Table (Index));
2247
            Name_Len := Name_Len + 1;
2248
            Name_Buffer (Name_Len) := ASCII.LF;
2249
            Len := Write (Source_FD, Name_Buffer (1)'Address, Name_Len);
2250
 
2251
            if Len /= Name_Len then
2252
               Prj.Com.Fail ("disk full");
2253
            end if;
2254
         end loop;
2255
 
2256
         Close (Source_FD, Status);
2257
 
2258
         if not Status then
2259
            Prj.Com.Fail ("disk full");
2260
         end if;
2261
      end if;
2262
 
2263
      if Object_FD /= Invalid_FD then
2264
         for Index in Object_Path_Table.First ..
2265
                      Object_Path_Table.Last
2266
                        (In_Tree.Private_Part.Object_Paths)
2267
         loop
2268
            Get_Name_String (In_Tree.Private_Part.Object_Paths.Table (Index));
2269
            Name_Len := Name_Len + 1;
2270
            Name_Buffer (Name_Len) := ASCII.LF;
2271
            Len := Write (Object_FD, Name_Buffer (1)'Address, Name_Len);
2272
 
2273
            if Len /= Name_Len then
2274
               Prj.Com.Fail ("disk full");
2275
            end if;
2276
         end loop;
2277
 
2278
         Close (Object_FD, Status);
2279
 
2280
         if not Status then
2281
            Prj.Com.Fail ("disk full");
2282
         end if;
2283
      end if;
2284
 
2285
      --  Set the env vars, if they need to be changed, and set the
2286
      --  corresponding flags.
2287
 
2288
      if Current_Source_Path_File /=
2289
           In_Tree.Projects.Table (Project).Include_Path_File
2290
      then
2291
         Current_Source_Path_File :=
2292
           In_Tree.Projects.Table (Project).Include_Path_File;
2293
         Set_Path_File_Var
2294
           (Project_Include_Path_File,
2295
            Get_Name_String (Current_Source_Path_File));
2296
         Ada_Prj_Include_File_Set := True;
2297
      end if;
2298
 
2299
      if Including_Libraries then
2300
         if Current_Object_Path_File
2301
           /= In_Tree.Projects.Table
2302
                (Project).Objects_Path_File_With_Libs
2303
         then
2304
            Current_Object_Path_File :=
2305
              In_Tree.Projects.Table
2306
                (Project).Objects_Path_File_With_Libs;
2307
            Set_Path_File_Var
2308
              (Project_Objects_Path_File,
2309
               Get_Name_String (Current_Object_Path_File));
2310
            Ada_Prj_Objects_File_Set := True;
2311
         end if;
2312
 
2313
      else
2314
         if Current_Object_Path_File /=
2315
           In_Tree.Projects.Table
2316
             (Project).Objects_Path_File_Without_Libs
2317
         then
2318
            Current_Object_Path_File :=
2319
              In_Tree.Projects.Table
2320
                (Project).Objects_Path_File_Without_Libs;
2321
            Set_Path_File_Var
2322
              (Project_Objects_Path_File,
2323
               Get_Name_String (Current_Object_Path_File));
2324
            Ada_Prj_Objects_File_Set := True;
2325
         end if;
2326
      end if;
2327
   end Set_Ada_Paths;
2328
 
2329
   ---------------------------------------------
2330
   -- Set_Mapping_File_Initial_State_To_Empty --
2331
   ---------------------------------------------
2332
 
2333
   procedure Set_Mapping_File_Initial_State_To_Empty is
2334
   begin
2335
      Fill_Mapping_File := False;
2336
   end Set_Mapping_File_Initial_State_To_Empty;
2337
 
2338
   -----------------------
2339
   -- Set_Path_File_Var --
2340
   -----------------------
2341
 
2342
   procedure Set_Path_File_Var (Name : String; Value : String) is
2343
      Host_Spec : String_Access := To_Host_File_Spec (Value);
2344
 
2345
   begin
2346
      if Host_Spec = null then
2347
         Prj.Com.Fail
2348
           ("could not convert file name """, Value, """ to host spec");
2349
      else
2350
         Setenv (Name, Host_Spec.all);
2351
         Free (Host_Spec);
2352
      end if;
2353
   end Set_Path_File_Var;
2354
 
2355
   -----------------------
2356
   -- Spec_Path_Name_Of --
2357
   -----------------------
2358
 
2359
   function Spec_Path_Name_Of
2360
     (Unit : Unit_Id; In_Tree : Project_Tree_Ref) return String
2361
   is
2362
      Data : Unit_Data := In_Tree.Units.Table (Unit);
2363
 
2364
   begin
2365
      if Data.File_Names (Specification).Path = No_Name then
2366
         declare
2367
            Current_Source : String_List_Id :=
2368
              In_Tree.Projects.Table
2369
                (Data.File_Names (Specification).Project).Sources;
2370
            Path : GNAT.OS_Lib.String_Access;
2371
 
2372
         begin
2373
            Data.File_Names (Specification).Path :=
2374
              Data.File_Names (Specification).Name;
2375
 
2376
            while Current_Source /= Nil_String loop
2377
               Path := Locate_Regular_File
2378
                 (Namet.Get_Name_String
2379
                  (Data.File_Names (Specification).Name),
2380
                  Namet.Get_Name_String
2381
                    (In_Tree.String_Elements.Table
2382
                       (Current_Source).Value));
2383
 
2384
               if Path /= null then
2385
                  Name_Len := Path'Length;
2386
                  Name_Buffer (1 .. Name_Len) := Path.all;
2387
                  Data.File_Names (Specification).Path := Name_Enter;
2388
                  exit;
2389
               else
2390
                  Current_Source :=
2391
                    In_Tree.String_Elements.Table
2392
                      (Current_Source).Next;
2393
               end if;
2394
            end loop;
2395
 
2396
            In_Tree.Units.Table (Unit) := Data;
2397
         end;
2398
      end if;
2399
 
2400
      return Namet.Get_Name_String (Data.File_Names (Specification).Path);
2401
   end Spec_Path_Name_Of;
2402
 
2403
   ---------------------------
2404
   -- Ultimate_Extension_Of --
2405
   ---------------------------
2406
 
2407
   function Ultimate_Extension_Of
2408
     (Project : Project_Id; In_Tree : Project_Tree_Ref) return Project_Id
2409
   is
2410
      Result : Project_Id := Project;
2411
 
2412
   begin
2413
      while In_Tree.Projects.Table (Result).Extended_By /=
2414
        No_Project
2415
      loop
2416
         Result := In_Tree.Projects.Table (Result).Extended_By;
2417
      end loop;
2418
 
2419
      return Result;
2420
   end Ultimate_Extension_Of;
2421
 
2422
end Prj.Env;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.