1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2009, Free Software Foundation, Inc. --
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. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
28 with Osint; use Osint;
29 with Output; use Output;
30 with Prj.Com; use Prj.Com;
33 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
35 package body Prj.Env is
37 Default_Naming : constant Naming_Id := Naming_Table.First;
39 package Project_Boolean_Htable is new Simple_HTable
40 (Header_Num => Header_Num,
46 -- A table that associates a project to a boolean. This is used to detect
47 -- whether a project was already processed for instance.
49 -----------------------
50 -- Local Subprograms --
51 -----------------------
54 (Source_Dirs : String_List_Id;
55 In_Tree : Project_Tree_Ref);
56 -- Add to Ada_Path_Buffer all the source directories in string list
57 -- Source_Dirs, if any. Increment Ada_Path_Length.
59 procedure Add_To_Path (Dir : String; In_Tree : Project_Tree_Ref);
60 -- If Dir is not already in the global variable Ada_Path_Buffer, add it.
61 -- Increment Ada_Path_Length.
62 -- If Ada_Path_Length /= 0, prepend a Path_Separator character to
65 procedure Add_To_Source_Path
66 (Source_Dirs : String_List_Id; In_Tree : Project_Tree_Ref);
67 -- Add to Ada_Path_B all the source directories in string list
68 -- Source_Dirs, if any. Increment Ada_Path_Length.
70 procedure Add_To_Object_Path
71 (Object_Dir : Path_Name_Type;
72 In_Tree : Project_Tree_Ref);
73 -- Add Object_Dir to object path table. Make sure it is not duplicate
74 -- and it is the last one in the current table.
76 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean;
77 -- Return True if there is at least one ALI file in the directory Dir
79 procedure Set_Path_File_Var (Name : String; Value : String);
80 -- Call Setenv, after calling To_Host_File_Spec
82 function Ultimate_Extension_Of
83 (Project : Project_Id;
84 In_Tree : Project_Tree_Ref) return Project_Id;
85 -- Return a project that is either Project or an extended ancestor of
86 -- Project that itself is not extended.
88 ----------------------
89 -- Ada_Include_Path --
90 ----------------------
92 function Ada_Include_Path
93 (Project : Project_Id;
94 In_Tree : Project_Tree_Ref) return String_Access is
96 procedure Add (Project : Project_Id);
97 -- Add all the source directories of a project to the path only if
98 -- this project has not been visited. Calls itself recursively for
99 -- projects being extended, and imported projects. Adds the project
100 -- to the list Seen if this is the call to Add for this project.
106 procedure Add (Project : Project_Id) is
108 -- If Seen is empty, then the project cannot have been visited
110 if not In_Tree.Projects.Table (Project).Seen then
111 In_Tree.Projects.Table (Project).Seen := True;
114 Data : constant Project_Data :=
115 In_Tree.Projects.Table (Project);
116 List : Project_List := Data.Imported_Projects;
119 -- Add to path all source directories of this project
121 Add_To_Path (Data.Source_Dirs, In_Tree);
123 -- Call Add to the project being extended, if any
125 if Data.Extends /= No_Project then
129 -- Call Add for each imported project, if any
131 while List /= Empty_Project_List loop
133 (In_Tree.Project_Lists.Table (List).Project);
134 List := In_Tree.Project_Lists.Table (List).Next;
140 -- Start of processing for Ada_Include_Path
143 -- If it is the first time we call this function for
144 -- this project, compute the source path
147 In_Tree.Projects.Table (Project).Ada_Include_Path = null
149 In_Tree.Private_Part.Ada_Path_Length := 0;
151 for Index in Project_Table.First ..
152 Project_Table.Last (In_Tree.Projects)
154 In_Tree.Projects.Table (Index).Seen := False;
158 In_Tree.Projects.Table (Project).Ada_Include_Path :=
160 (In_Tree.Private_Part.Ada_Path_Buffer
161 (1 .. In_Tree.Private_Part.Ada_Path_Length));
164 return In_Tree.Projects.Table (Project).Ada_Include_Path;
165 end Ada_Include_Path;
167 ----------------------
168 -- Ada_Include_Path --
169 ----------------------
171 function Ada_Include_Path
172 (Project : Project_Id;
173 In_Tree : Project_Tree_Ref;
174 Recursive : Boolean) return String
178 return Ada_Include_Path (Project, In_Tree).all;
180 In_Tree.Private_Part.Ada_Path_Length := 0;
182 (In_Tree.Projects.Table (Project).Source_Dirs, In_Tree);
184 In_Tree.Private_Part.Ada_Path_Buffer
185 (1 .. In_Tree.Private_Part.Ada_Path_Length);
187 end Ada_Include_Path;
189 ----------------------
190 -- Ada_Objects_Path --
191 ----------------------
193 function Ada_Objects_Path
194 (Project : Project_Id;
195 In_Tree : Project_Tree_Ref;
196 Including_Libraries : Boolean := True) return String_Access
198 procedure Add (Project : Project_Id);
199 -- Add all the object directories of a project to the path only if
200 -- this project has not been visited. Calls itself recursively for
201 -- projects being extended, and imported projects. Adds the project
202 -- to the list Seen if this is the first call to Add for this project.
208 procedure Add (Project : Project_Id) is
210 -- If this project has not been seen yet
212 if not In_Tree.Projects.Table (Project).Seen then
213 In_Tree.Projects.Table (Project).Seen := True;
216 Data : constant Project_Data :=
217 In_Tree.Projects.Table (Project);
218 List : Project_List := Data.Imported_Projects;
221 -- Add to path the object directory of this project
222 -- except if we don't include library project and
223 -- this is a library project.
225 if (Data.Library and then Including_Libraries)
227 (Data.Object_Directory /= No_Path_Information
229 (not Including_Libraries or else not Data.Library))
231 -- For a library project, add the library directory,
232 -- if there is no object directory or if it contains ALI
233 -- files; otherwise add the object directory.
236 if Data.Object_Directory = No_Path_Information
238 Contains_ALI_Files (Data.Library_ALI_Dir.Name)
241 (Get_Name_String (Data.Library_ALI_Dir.Name),
245 (Get_Name_String (Data.Object_Directory.Name),
250 -- For a non library project, add the object directory
253 (Get_Name_String (Data.Object_Directory.Name),
258 -- Call Add to the project being extended, if any
260 if Data.Extends /= No_Project then
264 -- Call Add for each imported project, if any
266 while List /= Empty_Project_List loop
268 (In_Tree.Project_Lists.Table (List).Project);
269 List := In_Tree.Project_Lists.Table (List).Next;
276 -- Start of processing for Ada_Objects_Path
279 -- If it is the first time we call this function for
280 -- this project, compute the objects path
283 In_Tree.Projects.Table (Project).Ada_Objects_Path = null
285 In_Tree.Private_Part.Ada_Path_Length := 0;
287 for Index in Project_Table.First ..
288 Project_Table.Last (In_Tree.Projects)
290 In_Tree.Projects.Table (Index).Seen := False;
294 In_Tree.Projects.Table (Project).Ada_Objects_Path :=
296 (In_Tree.Private_Part.Ada_Path_Buffer
297 (1 .. In_Tree.Private_Part.Ada_Path_Length));
300 return In_Tree.Projects.Table (Project).Ada_Objects_Path;
301 end Ada_Objects_Path;
303 ------------------------
304 -- Add_To_Object_Path --
305 ------------------------
307 procedure Add_To_Object_Path
308 (Object_Dir : Path_Name_Type; In_Tree : Project_Tree_Ref)
311 -- Check if the directory is already in the table
313 for Index in Object_Path_Table.First ..
314 Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)
317 -- If it is, remove it, and add it as the last one
319 if In_Tree.Private_Part.Object_Paths.Table (Index) = Object_Dir then
320 for Index2 in Index + 1 ..
321 Object_Path_Table.Last
322 (In_Tree.Private_Part.Object_Paths)
324 In_Tree.Private_Part.Object_Paths.Table (Index2 - 1) :=
325 In_Tree.Private_Part.Object_Paths.Table (Index2);
328 In_Tree.Private_Part.Object_Paths.Table
329 (Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)) :=
335 -- The directory is not already in the table, add it
337 Object_Path_Table.Increment_Last (In_Tree.Private_Part.Object_Paths);
338 In_Tree.Private_Part.Object_Paths.Table
339 (Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)) :=
341 end Add_To_Object_Path;
347 procedure Add_To_Path
348 (Source_Dirs : String_List_Id;
349 In_Tree : Project_Tree_Ref)
351 Current : String_List_Id := Source_Dirs;
352 Source_Dir : String_Element;
354 while Current /= Nil_String loop
355 Source_Dir := In_Tree.String_Elements.Table (Current);
356 Add_To_Path (Get_Name_String (Source_Dir.Display_Value), In_Tree);
357 Current := Source_Dir.Next;
361 procedure Add_To_Path (Dir : String; In_Tree : Project_Tree_Ref) is
363 New_Buffer : String_Access;
366 function Is_Present (Path : String; Dir : String) return Boolean;
367 -- Return True if Dir is part of Path
373 function Is_Present (Path : String; Dir : String) return Boolean is
374 Last : constant Integer := Path'Last - Dir'Length + 1;
377 for J in Path'First .. Last loop
379 -- Note: the order of the conditions below is important, since
380 -- it ensures a minimal number of string comparisons.
383 or else Path (J - 1) = Path_Separator)
385 (J + Dir'Length > Path'Last
386 or else Path (J + Dir'Length) = Path_Separator)
387 and then Dir = Path (J .. J + Dir'Length - 1)
396 -- Start of processing for Add_To_Path
399 if Is_Present (In_Tree.Private_Part.Ada_Path_Buffer
400 (1 .. In_Tree.Private_Part.Ada_Path_Length),
404 -- Dir is already in the path, nothing to do
409 Min_Len := In_Tree.Private_Part.Ada_Path_Length + Dir'Length;
411 if In_Tree.Private_Part.Ada_Path_Length > 0 then
413 -- Add 1 for the Path_Separator character
415 Min_Len := Min_Len + 1;
418 -- If Ada_Path_Buffer is too small, increase it
420 Len := In_Tree.Private_Part.Ada_Path_Buffer'Last;
422 if Len < Min_Len then
425 exit when Len >= Min_Len;
428 New_Buffer := new String (1 .. Len);
429 New_Buffer (1 .. In_Tree.Private_Part.Ada_Path_Length) :=
430 In_Tree.Private_Part.Ada_Path_Buffer
431 (1 .. In_Tree.Private_Part.Ada_Path_Length);
432 Free (In_Tree.Private_Part.Ada_Path_Buffer);
433 In_Tree.Private_Part.Ada_Path_Buffer := New_Buffer;
436 if In_Tree.Private_Part.Ada_Path_Length > 0 then
437 In_Tree.Private_Part.Ada_Path_Length :=
438 In_Tree.Private_Part.Ada_Path_Length + 1;
439 In_Tree.Private_Part.Ada_Path_Buffer
440 (In_Tree.Private_Part.Ada_Path_Length) := Path_Separator;
443 In_Tree.Private_Part.Ada_Path_Buffer
444 (In_Tree.Private_Part.Ada_Path_Length + 1 ..
445 In_Tree.Private_Part.Ada_Path_Length + Dir'Length) := Dir;
446 In_Tree.Private_Part.Ada_Path_Length :=
447 In_Tree.Private_Part.Ada_Path_Length + Dir'Length;
450 ------------------------
451 -- Add_To_Source_Path --
452 ------------------------
454 procedure Add_To_Source_Path
455 (Source_Dirs : String_List_Id; In_Tree : Project_Tree_Ref)
457 Current : String_List_Id := Source_Dirs;
458 Source_Dir : String_Element;
462 -- Add each source directory
464 while Current /= Nil_String loop
465 Source_Dir := In_Tree.String_Elements.Table (Current);
468 -- Check if the source directory is already in the table
470 for Index in Source_Path_Table.First ..
471 Source_Path_Table.Last
472 (In_Tree.Private_Part.Source_Paths)
474 -- If it is already, no need to add it
476 if In_Tree.Private_Part.Source_Paths.Table (Index) =
485 Source_Path_Table.Increment_Last
486 (In_Tree.Private_Part.Source_Paths);
487 In_Tree.Private_Part.Source_Paths.Table
488 (Source_Path_Table.Last (In_Tree.Private_Part.Source_Paths)) :=
492 -- Next source directory
494 Current := Source_Dir.Next;
496 end Add_To_Source_Path;
498 ------------------------
499 -- Contains_ALI_Files --
500 ------------------------
502 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean is
503 Dir_Name : constant String := Get_Name_String (Dir);
505 Name : String (1 .. 1_000);
507 Result : Boolean := False;
510 Open (Direct, Dir_Name);
512 -- For each file in the directory, check if it is an ALI file
515 Read (Direct, Name, Last);
517 Canonical_Case_File_Name (Name (1 .. Last));
518 Result := Last >= 5 and then Name (Last - 3 .. Last) = ".ali";
526 -- If there is any problem, close the directory if open and return
527 -- True; the library directory will be added to the path.
530 if Is_Open (Direct) then
535 end Contains_ALI_Files;
537 --------------------------------
538 -- Create_Config_Pragmas_File --
539 --------------------------------
541 procedure Create_Config_Pragmas_File
542 (For_Project : Project_Id;
543 Main_Project : Project_Id;
544 In_Tree : Project_Tree_Ref;
545 Include_Config_Files : Boolean := True)
547 pragma Unreferenced (Main_Project);
548 pragma Unreferenced (Include_Config_Files);
550 File_Name : Path_Name_Type := No_Path;
551 File : File_Descriptor := Invalid_FD;
553 Current_Unit : Unit_Index := Unit_Table.First;
555 First_Project : Project_List := Empty_Project_List;
557 Current_Project : Project_List;
558 Current_Naming : Naming_Id;
563 procedure Check (Project : Project_Id);
564 -- Recursive procedure that put in the config pragmas file any non
565 -- standard naming schemes, if it is not already in the file, then call
566 -- itself for any imported project.
568 procedure Check_Temp_File;
569 -- Check that a temporary file has been opened.
570 -- If not, create one, and put its name in the project data,
571 -- with the indication that it is a temporary file.
574 (Unit_Name : Name_Id;
575 File_Name : File_Name_Type;
576 Unit_Kind : Spec_Or_Body;
578 -- Put an SFN pragma in the temporary file
580 procedure Put (File : File_Descriptor; S : String);
581 procedure Put_Line (File : File_Descriptor; S : String);
582 -- Output procedures, analogous to normal Text_IO procs of same name
588 procedure Check (Project : Project_Id) is
589 Data : constant Project_Data :=
590 In_Tree.Projects.Table (Project);
593 if Current_Verbosity = High then
594 Write_Str ("Checking project file """);
595 Write_Str (Namet.Get_Name_String (Data.Name));
600 -- Is this project in the list of the visited project?
602 Current_Project := First_Project;
603 while Current_Project /= Empty_Project_List
604 and then In_Tree.Project_Lists.Table
605 (Current_Project).Project /= Project
608 In_Tree.Project_Lists.Table (Current_Project).Next;
611 -- If it is not, put it in the list, and visit it
613 if Current_Project = Empty_Project_List then
614 Project_List_Table.Increment_Last
615 (In_Tree.Project_Lists);
616 In_Tree.Project_Lists.Table
617 (Project_List_Table.Last (In_Tree.Project_Lists)) :=
618 (Project => Project, Next => First_Project);
620 Project_List_Table.Last (In_Tree.Project_Lists);
622 -- Is the naming scheme of this project one that we know?
624 Current_Naming := Default_Naming;
625 while Current_Naming <=
626 Naming_Table.Last (In_Tree.Private_Part.Namings)
627 and then not Same_Naming_Scheme
628 (Left => In_Tree.Private_Part.Namings.Table (Current_Naming),
629 Right => Data.Naming) loop
630 Current_Naming := Current_Naming + 1;
633 -- If we don't know it, add it
636 Naming_Table.Last (In_Tree.Private_Part.Namings)
638 Naming_Table.Increment_Last (In_Tree.Private_Part.Namings);
639 In_Tree.Private_Part.Namings.Table
640 (Naming_Table.Last (In_Tree.Private_Part.Namings)) :=
643 -- We need a temporary file to be created
647 -- Put the SFN pragmas for the naming scheme
652 (File, "pragma Source_File_Name_Project");
654 (File, " (Spec_File_Name => ""*" &
655 Spec_Suffix_Of (In_Tree, "ada", Data.Naming) &
658 (File, " Casing => " &
659 Image (Data.Naming.Casing) & ",");
661 (File, " Dot_Replacement => """ &
662 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
668 (File, "pragma Source_File_Name_Project");
670 (File, " (Body_File_Name => ""*" &
671 Body_Suffix_Of (In_Tree, "ada", Data.Naming) &
674 (File, " Casing => " &
675 Image (Data.Naming.Casing) & ",");
677 (File, " Dot_Replacement => """ &
678 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
681 -- and maybe separate
683 if Body_Suffix_Of (In_Tree, "ada", Data.Naming) /=
684 Get_Name_String (Data.Naming.Separate_Suffix)
687 (File, "pragma Source_File_Name_Project");
689 (File, " (Subunit_File_Name => ""*" &
690 Namet.Get_Name_String (Data.Naming.Separate_Suffix) &
693 (File, " Casing => " &
694 Image (Data.Naming.Casing) &
697 (File, " Dot_Replacement => """ &
698 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
703 if Data.Extends /= No_Project then
704 Check (Data.Extends);
708 Current : Project_List := Data.Imported_Projects;
711 while Current /= Empty_Project_List loop
713 (In_Tree.Project_Lists.Table
715 Current := In_Tree.Project_Lists.Table
722 ---------------------
723 -- Check_Temp_File --
724 ---------------------
726 procedure Check_Temp_File is
728 if File = Invalid_FD then
729 Tempdir.Create_Temp_File (File, Name => File_Name);
731 if File = Invalid_FD then
733 ("unable to create temporary configuration pragmas file");
736 Record_Temp_File (File_Name);
738 if Opt.Verbose_Mode then
739 Write_Str ("Creating temp file """);
740 Write_Str (Get_Name_String (File_Name));
752 (Unit_Name : Name_Id;
753 File_Name : File_Name_Type;
754 Unit_Kind : Spec_Or_Body;
758 -- A temporary file needs to be open
762 -- Put the pragma SFN for the unit kind (spec or body)
764 Put (File, "pragma Source_File_Name_Project (");
765 Put (File, Namet.Get_Name_String (Unit_Name));
767 if Unit_Kind = Specification then
768 Put (File, ", Spec_File_Name => """);
770 Put (File, ", Body_File_Name => """);
773 Put (File, Namet.Get_Name_String (File_Name));
777 Put (File, ", Index =>");
778 Put (File, Index'Img);
781 Put_Line (File, ");");
784 procedure Put (File : File_Descriptor; S : String) is
788 Last := Write (File, S (S'First)'Address, S'Length);
790 if Last /= S'Length then
791 Prj.Com.Fail ("Disk full");
794 if Current_Verbosity = High then
803 procedure Put_Line (File : File_Descriptor; S : String) is
804 S0 : String (1 .. S'Length + 1);
808 -- Add an ASCII.LF to the string. As this config file is supposed to
809 -- be used only by the compiler, we don't care about the characters
810 -- for the end of line. In fact we could have put a space, but
811 -- it is more convenient to be able to read gnat.adc during
812 -- development, for which the ASCII.LF is fine.
814 S0 (1 .. S'Length) := S;
815 S0 (S0'Last) := ASCII.LF;
816 Last := Write (File, S0'Address, S0'Length);
818 if Last /= S'Length + 1 then
819 Prj.Com.Fail ("Disk full");
822 if Current_Verbosity = High then
827 -- Start of processing for Create_Config_Pragmas_File
831 In_Tree.Projects.Table (For_Project).Config_Checked
834 -- Remove any memory of processed naming schemes, if any
836 Naming_Table.Set_Last (In_Tree.Private_Part.Namings, Default_Naming);
838 -- Check the naming schemes
842 -- Visit all the units and process those that need an SFN pragma
845 Current_Unit <= Unit_Table.Last (In_Tree.Units)
848 Unit : constant Unit_Data :=
849 In_Tree.Units.Table (Current_Unit);
852 if Unit.File_Names (Specification).Needs_Pragma then
854 Unit.File_Names (Specification).Name,
856 Unit.File_Names (Specification).Index);
859 if Unit.File_Names (Body_Part).Needs_Pragma then
861 Unit.File_Names (Body_Part).Name,
863 Unit.File_Names (Body_Part).Index);
866 Current_Unit := Current_Unit + 1;
870 -- If there are no non standard naming scheme, issue the GNAT
871 -- standard naming scheme. This will tell the compiler that
872 -- a project file is used and will forbid any pragma SFN.
874 if File = Invalid_FD then
877 Put_Line (File, "pragma Source_File_Name_Project");
878 Put_Line (File, " (Spec_File_Name => ""*.ads"",");
879 Put_Line (File, " Dot_Replacement => ""-"",");
880 Put_Line (File, " Casing => lowercase);");
882 Put_Line (File, "pragma Source_File_Name_Project");
883 Put_Line (File, " (Body_File_Name => ""*.adb"",");
884 Put_Line (File, " Dot_Replacement => ""-"",");
885 Put_Line (File, " Casing => lowercase);");
888 -- Close the temporary file
890 GNAT.OS_Lib.Close (File, Status);
893 Prj.Com.Fail ("disk full");
896 if Opt.Verbose_Mode then
897 Write_Str ("Closing configuration file """);
898 Write_Str (Get_Name_String (File_Name));
902 In_Tree.Projects.Table (For_Project).Config_File_Name :=
904 In_Tree.Projects.Table (For_Project).Config_File_Temp :=
907 In_Tree.Projects.Table (For_Project).Config_Checked :=
910 end Create_Config_Pragmas_File;
916 procedure Create_Mapping (In_Tree : Project_Tree_Ref) is
917 The_Unit_Data : Unit_Data;
918 Data : File_Name_Data;
923 for Unit in 1 .. Unit_Table.Last (In_Tree.Units) loop
924 The_Unit_Data := In_Tree.Units.Table (Unit);
926 -- Process only if the unit has a valid name
928 if The_Unit_Data.Name /= No_Name then
929 Data := The_Unit_Data.File_Names (Specification);
931 -- If there is a spec, put it in the mapping
933 if Data.Name /= No_File then
934 if Data.Path.Name = Slash then
935 Fmap.Add_Forbidden_File_Name (Data.Name);
938 (Unit_Name => Unit_Name_Type (The_Unit_Data.Name),
939 File_Name => Data.Name,
940 Path_Name => File_Name_Type (Data.Path.Name));
944 Data := The_Unit_Data.File_Names (Body_Part);
946 -- If there is a body (or subunit) put it in the mapping
948 if Data.Name /= No_File then
949 if Data.Path.Name = Slash then
950 Fmap.Add_Forbidden_File_Name (Data.Name);
953 (Unit_Name => Unit_Name_Type (The_Unit_Data.Name),
954 File_Name => Data.Name,
955 Path_Name => File_Name_Type (Data.Path.Name));
962 -------------------------
963 -- Create_Mapping_File --
964 -------------------------
966 procedure Create_Mapping_File
967 (Project : Project_Id;
968 Language : Name_Id := No_Name;
969 In_Tree : Project_Tree_Ref;
970 Name : out Path_Name_Type)
972 File : File_Descriptor := Invalid_FD;
975 Present : array (No_Project .. Project_Table.Last (In_Tree.Projects))
976 of Boolean := (others => False);
977 -- For each project in the closure of Project, the corresponding flag
978 -- will be set to True.
981 Suffix : File_Name_Type;
982 The_Unit_Data : Unit_Data;
983 Data : File_Name_Data;
984 Iter : Source_Iterator;
986 procedure Put_Name_Buffer;
987 -- Put the line contained in the Name_Buffer in the mapping file
989 procedure Put_Data (Spec : Boolean);
990 -- Put the mapping of the spec or body contained in Data in the file
993 procedure Recursive_Flag (Prj : Project_Id);
994 -- Set the flags corresponding to Prj, the projects it imports
995 -- (directly or indirectly) or extends to True. Call itself recursively.
1001 procedure Put_Name_Buffer is
1005 Name_Len := Name_Len + 1;
1006 Name_Buffer (Name_Len) := ASCII.LF;
1007 Last := Write (File, Name_Buffer (1)'Address, Name_Len);
1009 if Last /= Name_Len then
1010 Prj.Com.Fail ("Disk full, cannot write mapping file");
1012 end Put_Name_Buffer;
1018 procedure Put_Data (Spec : Boolean) is
1020 -- Line with the unit name
1022 Get_Name_String (The_Unit_Data.Name);
1023 Name_Len := Name_Len + 1;
1024 Name_Buffer (Name_Len) := '%';
1025 Name_Len := Name_Len + 1;
1028 Name_Buffer (Name_Len) := 's';
1030 Name_Buffer (Name_Len) := 'b';
1035 -- Line with the file name
1037 Get_Name_String (Data.Name);
1040 -- Line with the path name
1042 Get_Name_String (Data.Path.Name);
1046 --------------------
1047 -- Recursive_Flag --
1048 --------------------
1050 procedure Recursive_Flag (Prj : Project_Id) is
1051 Imported : Project_List;
1055 -- Nothing to do for non existent project or project that has already
1058 if Prj /= No_Project and then not Present (Prj) then
1059 Present (Prj) := True;
1061 Imported := In_Tree.Projects.Table (Prj).Imported_Projects;
1062 while Imported /= Empty_Project_List loop
1063 Proj := In_Tree.Project_Lists.Table (Imported).Project;
1064 Imported := In_Tree.Project_Lists.Table (Imported).Next;
1065 Recursive_Flag (Proj);
1068 Recursive_Flag (In_Tree.Projects.Table (Prj).Extends);
1072 -- Start of processing for Create_Mapping_File
1075 -- Flag the necessary projects
1077 Recursive_Flag (Project);
1079 -- Create the temporary file
1081 Tempdir.Create_Temp_File (File, Name => Name);
1083 if File = Invalid_FD then
1084 Prj.Com.Fail ("unable to create temporary mapping file");
1087 Record_Temp_File (Name);
1089 if Opt.Verbose_Mode then
1090 Write_Str ("Creating temp mapping file """);
1091 Write_Str (Get_Name_String (Name));
1096 if Language = No_Name then
1097 if In_Tree.Private_Part.Fill_Mapping_File then
1098 for Unit in 1 .. Unit_Table.Last (In_Tree.Units) loop
1099 The_Unit_Data := In_Tree.Units.Table (Unit);
1101 -- Case of unit has a valid name
1103 if The_Unit_Data.Name /= No_Name then
1104 Data := The_Unit_Data.File_Names (Specification);
1106 -- If there is a spec, put it mapping in the file if it is
1107 -- from a project in the closure of Project.
1109 if Data.Name /= No_File and then Present (Data.Project) then
1110 Put_Data (Spec => True);
1113 Data := The_Unit_Data.File_Names (Body_Part);
1115 -- If there is a body (or subunit) put its mapping in the
1116 -- file if it is from a project in the closure of Project.
1118 if Data.Name /= No_File and then Present (Data.Project) then
1119 Put_Data (Spec => False);
1125 -- If language is defined
1127 -- For all source of the Language of all projects in the closure
1129 for Proj in Present'Range loop
1130 if Present (Proj) then
1132 Iter := For_Each_Source (In_Tree, Proj);
1134 Source := Prj.Element (Iter);
1135 exit when Source = No_Source;
1137 if Source.Language.Name = Language
1138 and then not Source.Locally_Removed
1139 and then Source.Replaced_By = No_Source
1140 and then Source.Path.Name /= No_Path
1142 if Source.Unit /= No_Name then
1143 Get_Name_String (Source.Unit);
1145 if Source.Kind = Spec then
1147 Source.Language.Config.Mapping_Spec_Suffix;
1150 Source.Language.Config.Mapping_Body_Suffix;
1153 if Suffix /= No_File then
1154 Add_Str_To_Name_Buffer (Get_Name_String (Suffix));
1160 Get_Name_String (Source.File);
1163 Get_Name_String (Source.Path.Name);
1173 GNAT.OS_Lib.Close (File, Status);
1177 -- We were able to create the temporary file, so there is no problem
1178 -- of protection. However, we are not able to close it, so there must
1179 -- be a capacity problem that we express using "disk full".
1181 Prj.Com.Fail ("disk full, could not write mapping file");
1183 end Create_Mapping_File;
1185 --------------------------
1186 -- Create_New_Path_File --
1187 --------------------------
1189 procedure Create_New_Path_File
1190 (In_Tree : Project_Tree_Ref;
1191 Path_FD : out File_Descriptor;
1192 Path_Name : out Path_Name_Type)
1195 Tempdir.Create_Temp_File (Path_FD, Path_Name);
1197 if Path_Name /= No_Path then
1198 Record_Temp_File (Path_Name);
1200 -- Record the name, so that the temp path file will be deleted at the
1201 -- end of the program.
1203 Path_File_Table.Increment_Last (In_Tree.Private_Part.Path_Files);
1204 In_Tree.Private_Part.Path_Files.Table
1205 (Path_File_Table.Last (In_Tree.Private_Part.Path_Files)) :=
1208 end Create_New_Path_File;
1210 ---------------------------
1211 -- Delete_All_Path_Files --
1212 ---------------------------
1214 procedure Delete_All_Path_Files (In_Tree : Project_Tree_Ref) is
1215 Disregard : Boolean := True;
1216 pragma Warnings (Off, Disregard);
1219 for Index in Path_File_Table.First ..
1220 Path_File_Table.Last (In_Tree.Private_Part.Path_Files)
1222 if In_Tree.Private_Part.Path_Files.Table (Index) /= No_Path then
1225 (In_Tree.Private_Part.Path_Files.Table (Index)),
1230 -- If any of the environment variables ADA_PRJ_INCLUDE_FILE or
1231 -- ADA_PRJ_OBJECTS_FILE has been set, then reset their value to
1232 -- the empty string. On VMS, this has the effect of deassigning
1233 -- the logical names.
1235 if In_Tree.Private_Part.Ada_Prj_Include_File_Set then
1236 Setenv (Project_Include_Path_File, "");
1237 In_Tree.Private_Part.Ada_Prj_Include_File_Set := False;
1240 if In_Tree.Private_Part.Ada_Prj_Objects_File_Set then
1241 Setenv (Project_Objects_Path_File, "");
1242 In_Tree.Private_Part.Ada_Prj_Objects_File_Set := False;
1244 end Delete_All_Path_Files;
1246 ------------------------------------
1247 -- File_Name_Of_Library_Unit_Body --
1248 ------------------------------------
1250 function File_Name_Of_Library_Unit_Body
1252 Project : Project_Id;
1253 In_Tree : Project_Tree_Ref;
1254 Main_Project_Only : Boolean := True;
1255 Full_Path : Boolean := False) return String
1257 The_Project : Project_Id := Project;
1258 Data : Project_Data :=
1259 In_Tree.Projects.Table (Project);
1260 Original_Name : String := Name;
1262 Extended_Spec_Name : String :=
1264 Spec_Suffix_Of (In_Tree, "ada", Data.Naming);
1265 Extended_Body_Name : String :=
1267 Body_Suffix_Of (In_Tree, "ada", Data.Naming);
1271 The_Original_Name : Name_Id;
1272 The_Spec_Name : Name_Id;
1273 The_Body_Name : Name_Id;
1276 Canonical_Case_File_Name (Original_Name);
1277 Name_Len := Original_Name'Length;
1278 Name_Buffer (1 .. Name_Len) := Original_Name;
1279 The_Original_Name := Name_Find;
1281 Canonical_Case_File_Name (Extended_Spec_Name);
1282 Name_Len := Extended_Spec_Name'Length;
1283 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
1284 The_Spec_Name := Name_Find;
1286 Canonical_Case_File_Name (Extended_Body_Name);
1287 Name_Len := Extended_Body_Name'Length;
1288 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
1289 The_Body_Name := Name_Find;
1291 if Current_Verbosity = High then
1292 Write_Str ("Looking for file name of """);
1296 Write_Str (" Extended Spec Name = """);
1297 Write_Str (Extended_Spec_Name);
1300 Write_Str (" Extended Body Name = """);
1301 Write_Str (Extended_Body_Name);
1306 -- For extending project, search in the extended project if the source
1307 -- is not found. For non extending projects, this loop will be run only
1311 -- Loop through units
1312 -- Should have comment explaining reverse ???
1314 for Current in reverse Unit_Table.First ..
1315 Unit_Table.Last (In_Tree.Units)
1317 Unit := In_Tree.Units.Table (Current);
1321 if not Main_Project_Only
1322 or else Unit.File_Names (Body_Part).Project = The_Project
1325 Current_Name : constant File_Name_Type :=
1326 Unit.File_Names (Body_Part).Name;
1329 -- Case of a body present
1331 if Current_Name /= No_File then
1332 if Current_Verbosity = High then
1333 Write_Str (" Comparing with """);
1334 Write_Str (Get_Name_String (Current_Name));
1339 -- If it has the name of the original name, return the
1342 if Unit.Name = The_Original_Name
1344 Current_Name = File_Name_Type (The_Original_Name)
1346 if Current_Verbosity = High then
1351 return Get_Name_String
1352 (Unit.File_Names (Body_Part).Path.Name);
1355 return Get_Name_String (Current_Name);
1358 -- If it has the name of the extended body name,
1359 -- return the extended body name
1361 elsif Current_Name = File_Name_Type (The_Body_Name) then
1362 if Current_Verbosity = High then
1367 return Get_Name_String
1368 (Unit.File_Names (Body_Part).Path.Name);
1371 return Extended_Body_Name;
1375 if Current_Verbosity = High then
1376 Write_Line (" not good");
1385 if not Main_Project_Only
1386 or else Unit.File_Names (Specification).Project = The_Project
1389 Current_Name : constant File_Name_Type :=
1390 Unit.File_Names (Specification).Name;
1393 -- Case of spec present
1395 if Current_Name /= No_File then
1396 if Current_Verbosity = High then
1397 Write_Str (" Comparing with """);
1398 Write_Str (Get_Name_String (Current_Name));
1403 -- If name same as original name, return original name
1405 if Unit.Name = The_Original_Name
1407 Current_Name = File_Name_Type (The_Original_Name)
1409 if Current_Verbosity = High then
1414 return Get_Name_String
1415 (Unit.File_Names (Specification).Path.Name);
1417 return Get_Name_String (Current_Name);
1420 -- If it has the same name as the extended spec name,
1421 -- return the extended spec name.
1423 elsif Current_Name = File_Name_Type (The_Spec_Name) then
1424 if Current_Verbosity = High then
1429 return Get_Name_String
1430 (Unit.File_Names (Specification).Path.Name);
1432 return Extended_Spec_Name;
1436 if Current_Verbosity = High then
1437 Write_Line (" not good");
1445 -- If we are not in an extending project, give up
1447 exit when (not Main_Project_Only) or else Data.Extends = No_Project;
1449 -- Otherwise, look in the project we are extending
1451 The_Project := Data.Extends;
1452 Data := In_Tree.Projects.Table (The_Project);
1455 -- We don't know this file name, return an empty string
1458 end File_Name_Of_Library_Unit_Body;
1460 -------------------------------
1461 -- For_All_Imported_Projects --
1462 -------------------------------
1464 procedure For_All_Imported_Projects
1465 (Project : Project_Id;
1466 In_Tree : Project_Tree_Ref)
1468 use Project_Boolean_Htable;
1469 Seen : Project_Boolean_Htable.Instance := Project_Boolean_Htable.Nil;
1471 procedure Recurse (Prj : Project_Id);
1472 -- Process Prj recursively
1478 procedure Recurse (Prj : Project_Id) is
1479 Data : Project_Data renames In_Tree.Projects.Table (Prj);
1480 List : Project_List := Data.Imported_Projects;
1483 if not Get (Seen, Prj) then
1484 Set (Seen, Prj, True);
1488 -- If we are extending a project, visit it
1490 if Data.Extends /= No_Project then
1491 Recurse (Data.Extends);
1494 -- And visit all imported projects
1496 while List /= Empty_Project_List loop
1497 Recurse (In_Tree.Project_Lists.Table (List).Project);
1498 List := In_Tree.Project_Lists.Table (List).Next;
1503 -- Start of processing for For_All_Imported_Projects
1508 end For_All_Imported_Projects;
1510 -------------------------
1511 -- For_All_Object_Dirs --
1512 -------------------------
1514 procedure For_All_Object_Dirs
1515 (Project : Project_Id;
1516 In_Tree : Project_Tree_Ref)
1518 procedure For_Project (Prj : Project_Id);
1519 -- Get all object directories of Prj
1525 procedure For_Project (Prj : Project_Id) is
1526 Data : Project_Data renames In_Tree.Projects.Table (Prj);
1528 if Data.Object_Directory /= No_Path_Information then
1529 Get_Name_String (Data.Object_Directory.Display_Name);
1530 Action (Name_Buffer (1 .. Name_Len));
1534 procedure Get_Object_Dirs is new For_All_Imported_Projects (For_Project);
1536 -- Start of processing for For_All_Object_Dirs
1539 Get_Object_Dirs (Project, In_Tree);
1540 end For_All_Object_Dirs;
1542 -------------------------
1543 -- For_All_Source_Dirs --
1544 -------------------------
1546 procedure For_All_Source_Dirs
1547 (Project : Project_Id;
1548 In_Tree : Project_Tree_Ref)
1550 procedure For_Project (Prj : Project_Id);
1551 -- Get all object directories of Prj
1557 procedure For_Project (Prj : Project_Id) is
1558 Data : Project_Data renames In_Tree.Projects.Table (Prj);
1559 Current : String_List_Id := Data.Source_Dirs;
1560 The_String : String_Element;
1563 -- If there are Ada sources, call action with the name of every
1564 -- source directory.
1566 if Has_Ada_Sources (In_Tree.Projects.Table (Project)) then
1567 while Current /= Nil_String loop
1568 The_String := In_Tree.String_Elements.Table (Current);
1569 Action (Get_Name_String (The_String.Display_Value));
1570 Current := The_String.Next;
1575 procedure Get_Source_Dirs is new For_All_Imported_Projects (For_Project);
1577 -- Start of processing for For_All_Source_Dirs
1580 Get_Source_Dirs (Project, In_Tree);
1581 end For_All_Source_Dirs;
1587 procedure Get_Reference
1588 (Source_File_Name : String;
1589 In_Tree : Project_Tree_Ref;
1590 Project : out Project_Id;
1591 Path : out Path_Name_Type)
1594 -- Body below could use some comments ???
1596 if Current_Verbosity > Default then
1597 Write_Str ("Getting Reference_Of (""");
1598 Write_Str (Source_File_Name);
1599 Write_Str (""") ... ");
1603 Original_Name : String := Source_File_Name;
1607 Canonical_Case_File_Name (Original_Name);
1609 for Id in Unit_Table.First ..
1610 Unit_Table.Last (In_Tree.Units)
1612 Unit := In_Tree.Units.Table (Id);
1614 if (Unit.File_Names (Specification).Name /= No_File
1616 Namet.Get_Name_String
1617 (Unit.File_Names (Specification).Name) = Original_Name)
1618 or else (Unit.File_Names (Specification).Path /=
1621 Namet.Get_Name_String
1622 (Unit.File_Names (Specification).Path.Name) =
1625 Project := Ultimate_Extension_Of
1626 (Project => Unit.File_Names (Specification).Project,
1627 In_Tree => In_Tree);
1628 Path := Unit.File_Names (Specification).Path.Display_Name;
1630 if Current_Verbosity > Default then
1631 Write_Str ("Done: Specification.");
1637 elsif (Unit.File_Names (Body_Part).Name /= No_File
1639 Namet.Get_Name_String
1640 (Unit.File_Names (Body_Part).Name) = Original_Name)
1641 or else (Unit.File_Names (Body_Part).Path /= No_Path_Information
1642 and then Namet.Get_Name_String
1643 (Unit.File_Names (Body_Part).Path.Name) =
1646 Project := Ultimate_Extension_Of
1647 (Project => Unit.File_Names (Body_Part).Project,
1648 In_Tree => In_Tree);
1649 Path := Unit.File_Names (Body_Part).Path.Display_Name;
1651 if Current_Verbosity > Default then
1652 Write_Str ("Done: Body.");
1661 Project := No_Project;
1664 if Current_Verbosity > Default then
1665 Write_Str ("Cannot be found.");
1674 procedure Initialize (In_Tree : Project_Tree_Ref) is
1676 In_Tree.Private_Part.Fill_Mapping_File := True;
1677 In_Tree.Private_Part.Current_Source_Path_File := No_Path;
1678 In_Tree.Private_Part.Current_Object_Path_File := No_Path;
1685 -- Could use some comments in this body ???
1687 procedure Print_Sources (In_Tree : Project_Tree_Ref) is
1691 Write_Line ("List of Sources:");
1693 for Id in Unit_Table.First ..
1694 Unit_Table.Last (In_Tree.Units)
1696 Unit := In_Tree.Units.Table (Id);
1698 Write_Line (Namet.Get_Name_String (Unit.Name));
1700 if Unit.File_Names (Specification).Name /= No_File then
1701 if Unit.File_Names (Specification).Project = No_Project then
1702 Write_Line (" No project");
1705 Write_Str (" Project: ");
1707 (In_Tree.Projects.Table
1708 (Unit.File_Names (Specification).Project).Path.Name);
1709 Write_Line (Name_Buffer (1 .. Name_Len));
1712 Write_Str (" spec: ");
1714 (Namet.Get_Name_String
1715 (Unit.File_Names (Specification).Name));
1718 if Unit.File_Names (Body_Part).Name /= No_File then
1719 if Unit.File_Names (Body_Part).Project = No_Project then
1720 Write_Line (" No project");
1723 Write_Str (" Project: ");
1725 (In_Tree.Projects.Table
1726 (Unit.File_Names (Body_Part).Project).Path.Name);
1727 Write_Line (Name_Buffer (1 .. Name_Len));
1730 Write_Str (" body: ");
1732 (Namet.Get_Name_String
1733 (Unit.File_Names (Body_Part).Name));
1737 Write_Line ("end of List of Sources.");
1746 Main_Project : Project_Id;
1747 In_Tree : Project_Tree_Ref) return Project_Id
1749 Result : Project_Id := No_Project;
1751 Original_Name : String := Name;
1753 Data : constant Project_Data :=
1754 In_Tree.Projects.Table (Main_Project);
1756 Extended_Spec_Name : String :=
1758 Spec_Suffix_Of (In_Tree, "ada", Data.Naming);
1759 Extended_Body_Name : String :=
1761 Body_Suffix_Of (In_Tree, "ada", Data.Naming);
1765 Current_Name : File_Name_Type;
1766 The_Original_Name : File_Name_Type;
1767 The_Spec_Name : File_Name_Type;
1768 The_Body_Name : File_Name_Type;
1771 Canonical_Case_File_Name (Original_Name);
1772 Name_Len := Original_Name'Length;
1773 Name_Buffer (1 .. Name_Len) := Original_Name;
1774 The_Original_Name := Name_Find;
1776 Canonical_Case_File_Name (Extended_Spec_Name);
1777 Name_Len := Extended_Spec_Name'Length;
1778 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
1779 The_Spec_Name := Name_Find;
1781 Canonical_Case_File_Name (Extended_Body_Name);
1782 Name_Len := Extended_Body_Name'Length;
1783 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
1784 The_Body_Name := Name_Find;
1786 for Current in reverse Unit_Table.First ..
1787 Unit_Table.Last (In_Tree.Units)
1789 Unit := In_Tree.Units.Table (Current);
1793 Current_Name := Unit.File_Names (Body_Part).Name;
1795 -- Case of a body present
1797 if Current_Name /= No_File then
1799 -- If it has the name of the original name or the body name,
1800 -- we have found the project.
1802 if Unit.Name = Name_Id (The_Original_Name)
1803 or else Current_Name = The_Original_Name
1804 or else Current_Name = The_Body_Name
1806 Result := Unit.File_Names (Body_Part).Project;
1813 Current_Name := Unit.File_Names (Specification).Name;
1815 if Current_Name /= No_File then
1817 -- If name same as the original name, or the spec name, we have
1818 -- found the project.
1820 if Unit.Name = Name_Id (The_Original_Name)
1821 or else Current_Name = The_Original_Name
1822 or else Current_Name = The_Spec_Name
1824 Result := Unit.File_Names (Specification).Project;
1830 -- Get the ultimate extending project
1832 if Result /= No_Project then
1833 while In_Tree.Projects.Table (Result).Extended_By /=
1836 Result := In_Tree.Projects.Table (Result).Extended_By;
1847 procedure Set_Ada_Paths
1848 (Project : Project_Id;
1849 In_Tree : Project_Tree_Ref;
1850 Including_Libraries : Boolean)
1852 Source_FD : File_Descriptor := Invalid_FD;
1853 Object_FD : File_Descriptor := Invalid_FD;
1855 Process_Source_Dirs : Boolean := False;
1856 Process_Object_Dirs : Boolean := False;
1859 -- For calls to Close
1863 procedure Add (Proj : Project_Id);
1864 -- Add all the source/object directories of a project to the path only
1865 -- if this project has not been visited. Calls an internal procedure
1866 -- recursively for projects being extended, and imported projects.
1872 procedure Add (Proj : Project_Id) is
1874 procedure Recursive_Add (Project : Project_Id);
1875 -- Recursive procedure to add the source/object paths of extended/
1876 -- imported projects.
1882 procedure Recursive_Add (Project : Project_Id) is
1884 -- If Seen is False, then the project has not yet been visited
1886 if not In_Tree.Projects.Table (Project).Seen then
1887 In_Tree.Projects.Table (Project).Seen := True;
1890 Data : constant Project_Data :=
1891 In_Tree.Projects.Table (Project);
1892 List : Project_List := Data.Imported_Projects;
1895 if Process_Source_Dirs then
1897 -- Add to path all source directories of this project if
1898 -- there are Ada sources.
1900 if In_Tree.Projects.Table (Project).Ada_Sources /=
1903 Add_To_Source_Path (Data.Source_Dirs, In_Tree);
1907 if Process_Object_Dirs then
1909 -- Add to path the object directory of this project
1910 -- except if we don't include library project and this
1911 -- is a library project.
1913 if (Data.Library and Including_Libraries)
1915 (Data.Object_Directory /= No_Path_Information
1917 (not Including_Libraries or else not Data.Library))
1919 -- For a library project, add the library ALI
1920 -- directory if there is no object directory or
1921 -- if the library ALI directory contains ALI files;
1922 -- otherwise add the object directory.
1924 if Data.Library then
1925 if Data.Object_Directory = No_Path_Information
1926 or else Contains_ALI_Files
1927 (Data.Library_ALI_Dir.Name)
1930 (Data.Library_ALI_Dir.Name, In_Tree);
1933 (Data.Object_Directory.Name, In_Tree);
1936 -- For a non-library project, add object directory if
1937 -- it is not a virtual project, and if there are Ada
1938 -- sources in the project or one of the projects it
1939 -- extends. If there are no Ada sources, adding the
1940 -- object directory could disrupt the order of the
1941 -- object dirs in the path.
1943 elsif not Data.Virtual then
1945 Add_Object_Dir : Boolean := False;
1946 Prj : Project_Id := Project;
1949 while not Add_Object_Dir
1950 and then Prj /= No_Project
1952 if In_Tree.Projects.Table
1953 (Prj).Ada_Sources /= Nil_String
1955 Add_Object_Dir := True;
1959 In_Tree.Projects.Table (Prj).Extends;
1963 if Add_Object_Dir then
1965 (Data.Object_Directory.Name, In_Tree);
1972 -- Call Add to the project being extended, if any
1974 if Data.Extends /= No_Project then
1975 Recursive_Add (Data.Extends);
1978 -- Call Add for each imported project, if any
1980 while List /= Empty_Project_List loop
1982 (In_Tree.Project_Lists.Table
1985 In_Tree.Project_Lists.Table (List).Next;
1992 Source_Path_Table.Set_Last (In_Tree.Private_Part.Source_Paths, 0);
1993 Object_Path_Table.Set_Last (In_Tree.Private_Part.Object_Paths, 0);
1995 for Index in Project_Table.First ..
1996 Project_Table.Last (In_Tree.Projects)
1998 In_Tree.Projects.Table (Index).Seen := False;
2001 Recursive_Add (Proj);
2004 -- Start of processing for Set_Ada_Paths
2007 -- If it is the first time we call this procedure for
2008 -- this project, compute the source path and/or the object path.
2010 if In_Tree.Projects.Table (Project).Include_Path_File = No_Path then
2011 Process_Source_Dirs := True;
2012 Create_New_Path_File
2013 (In_Tree, Source_FD,
2014 In_Tree.Projects.Table (Project).Include_Path_File);
2017 -- For the object path, we make a distinction depending on
2018 -- Including_Libraries.
2020 if Including_Libraries then
2021 if In_Tree.Projects.Table
2022 (Project).Objects_Path_File_With_Libs = No_Path
2024 Process_Object_Dirs := True;
2025 Create_New_Path_File
2026 (In_Tree, Object_FD, In_Tree.Projects.Table (Project).
2027 Objects_Path_File_With_Libs);
2031 if In_Tree.Projects.Table
2032 (Project).Objects_Path_File_Without_Libs = No_Path
2034 Process_Object_Dirs := True;
2035 Create_New_Path_File
2036 (In_Tree, Object_FD, In_Tree.Projects.Table (Project).
2037 Objects_Path_File_Without_Libs);
2041 -- If there is something to do, set Seen to False for all projects,
2042 -- then call the recursive procedure Add for Project.
2044 if Process_Source_Dirs or Process_Object_Dirs then
2048 -- Write and close any file that has been created
2050 if Source_FD /= Invalid_FD then
2051 for Index in Source_Path_Table.First ..
2052 Source_Path_Table.Last
2053 (In_Tree.Private_Part.Source_Paths)
2055 Get_Name_String (In_Tree.Private_Part.Source_Paths.Table (Index));
2056 Name_Len := Name_Len + 1;
2057 Name_Buffer (Name_Len) := ASCII.LF;
2058 Len := Write (Source_FD, Name_Buffer (1)'Address, Name_Len);
2060 if Len /= Name_Len then
2061 Prj.Com.Fail ("disk full");
2065 Close (Source_FD, Status);
2068 Prj.Com.Fail ("disk full");
2072 if Object_FD /= Invalid_FD then
2073 for Index in Object_Path_Table.First ..
2074 Object_Path_Table.Last
2075 (In_Tree.Private_Part.Object_Paths)
2077 Get_Name_String (In_Tree.Private_Part.Object_Paths.Table (Index));
2078 Name_Len := Name_Len + 1;
2079 Name_Buffer (Name_Len) := ASCII.LF;
2080 Len := Write (Object_FD, Name_Buffer (1)'Address, Name_Len);
2082 if Len /= Name_Len then
2083 Prj.Com.Fail ("disk full");
2087 Close (Object_FD, Status);
2090 Prj.Com.Fail ("disk full");
2094 -- Set the env vars, if they need to be changed, and set the
2095 -- corresponding flags.
2097 if In_Tree.Private_Part.Current_Source_Path_File /=
2098 In_Tree.Projects.Table (Project).Include_Path_File
2100 In_Tree.Private_Part.Current_Source_Path_File :=
2101 In_Tree.Projects.Table (Project).Include_Path_File;
2103 (Project_Include_Path_File,
2104 Get_Name_String (In_Tree.Private_Part.Current_Source_Path_File));
2105 In_Tree.Private_Part.Ada_Prj_Include_File_Set := True;
2108 if Including_Libraries then
2109 if In_Tree.Private_Part.Current_Object_Path_File /=
2110 In_Tree.Projects.Table (Project).Objects_Path_File_With_Libs
2112 In_Tree.Private_Part.Current_Object_Path_File :=
2113 In_Tree.Projects.Table
2114 (Project).Objects_Path_File_With_Libs;
2116 (Project_Objects_Path_File,
2118 (In_Tree.Private_Part.Current_Object_Path_File));
2119 In_Tree.Private_Part.Ada_Prj_Objects_File_Set := True;
2123 if In_Tree.Private_Part.Current_Object_Path_File /=
2124 In_Tree.Projects.Table (Project).Objects_Path_File_Without_Libs
2126 In_Tree.Private_Part.Current_Object_Path_File :=
2127 In_Tree.Projects.Table
2128 (Project).Objects_Path_File_Without_Libs;
2130 (Project_Objects_Path_File,
2132 (In_Tree.Private_Part.Current_Object_Path_File));
2133 In_Tree.Private_Part.Ada_Prj_Objects_File_Set := True;
2138 ---------------------------------------------
2139 -- Set_Mapping_File_Initial_State_To_Empty --
2140 ---------------------------------------------
2142 procedure Set_Mapping_File_Initial_State_To_Empty
2143 (In_Tree : Project_Tree_Ref)
2146 In_Tree.Private_Part.Fill_Mapping_File := False;
2147 end Set_Mapping_File_Initial_State_To_Empty;
2149 -----------------------
2150 -- Set_Path_File_Var --
2151 -----------------------
2153 procedure Set_Path_File_Var (Name : String; Value : String) is
2154 Host_Spec : String_Access := To_Host_File_Spec (Value);
2156 if Host_Spec = null then
2158 ("could not convert file name """ & Value & """ to host spec");
2160 Setenv (Name, Host_Spec.all);
2163 end Set_Path_File_Var;
2165 ---------------------------
2166 -- Ultimate_Extension_Of --
2167 ---------------------------
2169 function Ultimate_Extension_Of
2170 (Project : Project_Id;
2171 In_Tree : Project_Tree_Ref) return Project_Id
2173 Result : Project_Id := Project;
2176 while In_Tree.Projects.Table (Result).Extended_By /= No_Project loop
2177 Result := In_Tree.Projects.Table (Result).Extended_By;
2181 end Ultimate_Extension_Of;