1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2007, 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 ------------------------------------------------------------------------------
27 with Osint; use Osint;
28 with Output; use Output;
29 with Prj.Com; use Prj.Com;
32 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
34 package body Prj.Env is
36 Current_Source_Path_File : Path_Name_Type := No_Path;
37 -- Current value of project source path file env var.
38 -- Used to avoid setting the env var to the same value.
40 Current_Object_Path_File : Path_Name_Type := No_Path;
41 -- Current value of project object path file env var.
42 -- Used to avoid setting the env var to the same value.
44 Ada_Path_Buffer : String_Access := new String (1 .. 1024);
45 -- A buffer where values for ADA_INCLUDE_PATH
46 -- and ADA_OBJECTS_PATH are stored.
48 Ada_Path_Length : Natural := 0;
49 -- Index of the last valid character in Ada_Path_Buffer
51 Ada_Prj_Include_File_Set : Boolean := False;
52 Ada_Prj_Objects_File_Set : Boolean := False;
53 -- These flags are set to True when the corresponding environment variables
54 -- are set and are used to give these environment variables an empty string
55 -- value at the end of the program. This has no practical effect on most
56 -- platforms, except on VMS where the logical names are deassigned, thus
57 -- avoiding the pollution of the environment of the caller.
59 Default_Naming : constant Naming_Id := Naming_Table.First;
61 Fill_Mapping_File : Boolean := True;
63 type Project_Flags is array (Project_Id range <>) of Boolean;
64 -- A Boolean array type used in Create_Mapping_File to select the projects
65 -- in the closure of a specific project.
67 -----------------------
68 -- Local Subprograms --
69 -----------------------
71 function Body_Path_Name_Of
73 In_Tree : Project_Tree_Ref) return String;
74 -- Returns the path name of the body of a unit.
75 -- Compute it first, if necessary.
77 function Spec_Path_Name_Of
79 In_Tree : Project_Tree_Ref) return String;
80 -- Returns the path name of the spec of a unit.
81 -- Compute it first, if necessary.
84 (Source_Dirs : String_List_Id;
85 In_Tree : Project_Tree_Ref);
86 -- Add to Ada_Path_Buffer all the source directories in string list
87 -- Source_Dirs, if any. Increment Ada_Path_Length.
89 procedure Add_To_Path (Dir : String);
90 -- If Dir is not already in the global variable Ada_Path_Buffer, add it.
91 -- Increment Ada_Path_Length.
92 -- If Ada_Path_Length /= 0, prepend a Path_Separator character to
95 procedure Add_To_Source_Path
96 (Source_Dirs : String_List_Id; In_Tree : Project_Tree_Ref);
97 -- Add to Ada_Path_B all the source directories in string list
98 -- Source_Dirs, if any. Increment Ada_Path_Length.
100 procedure Add_To_Object_Path
101 (Object_Dir : Path_Name_Type;
102 In_Tree : Project_Tree_Ref);
103 -- Add Object_Dir to object path table. Make sure it is not duplicate
104 -- and it is the last one in the current table.
106 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean;
107 -- Return True if there is at least one ALI file in the directory Dir
109 procedure Set_Path_File_Var (Name : String; Value : String);
110 -- Call Setenv, after calling To_Host_File_Spec
112 function Ultimate_Extension_Of
113 (Project : Project_Id;
114 In_Tree : Project_Tree_Ref) return Project_Id;
115 -- Return a project that is either Project or an extended ancestor of
116 -- Project that itself is not extended.
118 ----------------------
119 -- Ada_Include_Path --
120 ----------------------
122 function Ada_Include_Path
123 (Project : Project_Id;
124 In_Tree : Project_Tree_Ref) return String_Access is
126 procedure Add (Project : Project_Id);
127 -- Add all the source directories of a project to the path only if
128 -- this project has not been visited. Calls itself recursively for
129 -- projects being extended, and imported projects. Adds the project
130 -- to the list Seen if this is the call to Add for this project.
136 procedure Add (Project : Project_Id) is
138 -- If Seen is empty, then the project cannot have been visited
140 if not In_Tree.Projects.Table (Project).Seen then
141 In_Tree.Projects.Table (Project).Seen := True;
144 Data : constant Project_Data :=
145 In_Tree.Projects.Table (Project);
146 List : Project_List := Data.Imported_Projects;
149 -- Add to path all source directories of this project
151 Add_To_Path (Data.Source_Dirs, In_Tree);
153 -- Call Add to the project being extended, if any
155 if Data.Extends /= No_Project then
159 -- Call Add for each imported project, if any
161 while List /= Empty_Project_List loop
163 (In_Tree.Project_Lists.Table (List).Project);
164 List := In_Tree.Project_Lists.Table (List).Next;
170 -- Start of processing for Ada_Include_Path
173 -- If it is the first time we call this function for
174 -- this project, compute the source path
177 In_Tree.Projects.Table (Project).Ada_Include_Path = null
179 Ada_Path_Length := 0;
181 for Index in Project_Table.First ..
182 Project_Table.Last (In_Tree.Projects)
184 In_Tree.Projects.Table (Index).Seen := False;
188 In_Tree.Projects.Table (Project).Ada_Include_Path :=
189 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
192 return In_Tree.Projects.Table (Project).Ada_Include_Path;
193 end Ada_Include_Path;
195 ----------------------
196 -- Ada_Include_Path --
197 ----------------------
199 function Ada_Include_Path
200 (Project : Project_Id;
201 In_Tree : Project_Tree_Ref;
202 Recursive : Boolean) return String
206 return Ada_Include_Path (Project, In_Tree).all;
208 Ada_Path_Length := 0;
210 (In_Tree.Projects.Table (Project).Source_Dirs, In_Tree);
211 return Ada_Path_Buffer (1 .. Ada_Path_Length);
213 end Ada_Include_Path;
215 ----------------------
216 -- Ada_Objects_Path --
217 ----------------------
219 function Ada_Objects_Path
220 (Project : Project_Id;
221 In_Tree : Project_Tree_Ref;
222 Including_Libraries : Boolean := True) return String_Access
224 procedure Add (Project : Project_Id);
225 -- Add all the object directories of a project to the path only if
226 -- this project has not been visited. Calls itself recursively for
227 -- projects being extended, and imported projects. Adds the project
228 -- to the list Seen if this is the first call to Add for this project.
234 procedure Add (Project : Project_Id) is
236 -- If this project has not been seen yet
238 if not In_Tree.Projects.Table (Project).Seen then
239 In_Tree.Projects.Table (Project).Seen := True;
242 Data : constant Project_Data :=
243 In_Tree.Projects.Table (Project);
244 List : Project_List := Data.Imported_Projects;
247 -- Add to path the object directory of this project
248 -- except if we don't include library project and
249 -- this is a library project.
251 if (Data.Library and then Including_Libraries)
253 (Data.Object_Directory /= No_Path
255 (not Including_Libraries or else not Data.Library))
257 -- For a library project, add the library directory,
258 -- if there is no object directory or if it contains ALI
259 -- files; otherwise add the object directory.
262 if Data.Object_Directory = No_Path
264 Contains_ALI_Files (Data.Library_ALI_Dir)
266 Add_To_Path (Get_Name_String (Data.Library_ALI_Dir));
268 Add_To_Path (Get_Name_String (Data.Object_Directory));
272 -- For a non library project, add the object directory
274 Add_To_Path (Get_Name_String (Data.Object_Directory));
278 -- Call Add to the project being extended, if any
280 if Data.Extends /= No_Project then
284 -- Call Add for each imported project, if any
286 while List /= Empty_Project_List loop
288 (In_Tree.Project_Lists.Table (List).Project);
289 List := In_Tree.Project_Lists.Table (List).Next;
296 -- Start of processing for Ada_Objects_Path
299 -- If it is the first time we call this function for
300 -- this project, compute the objects path
303 In_Tree.Projects.Table (Project).Ada_Objects_Path = null
305 Ada_Path_Length := 0;
307 for Index in Project_Table.First ..
308 Project_Table.Last (In_Tree.Projects)
310 In_Tree.Projects.Table (Index).Seen := False;
314 In_Tree.Projects.Table (Project).Ada_Objects_Path :=
315 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
318 return In_Tree.Projects.Table (Project).Ada_Objects_Path;
319 end Ada_Objects_Path;
321 ------------------------
322 -- Add_To_Object_Path --
323 ------------------------
325 procedure Add_To_Object_Path
326 (Object_Dir : Path_Name_Type; In_Tree : Project_Tree_Ref)
329 -- Check if the directory is already in the table
331 for Index in Object_Path_Table.First ..
332 Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)
335 -- If it is, remove it, and add it as the last one
337 if In_Tree.Private_Part.Object_Paths.Table (Index) = Object_Dir then
338 for Index2 in Index + 1 ..
339 Object_Path_Table.Last
340 (In_Tree.Private_Part.Object_Paths)
342 In_Tree.Private_Part.Object_Paths.Table (Index2 - 1) :=
343 In_Tree.Private_Part.Object_Paths.Table (Index2);
346 In_Tree.Private_Part.Object_Paths.Table
347 (Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)) :=
353 -- The directory is not already in the table, add it
355 Object_Path_Table.Increment_Last (In_Tree.Private_Part.Object_Paths);
356 In_Tree.Private_Part.Object_Paths.Table
357 (Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)) :=
359 end Add_To_Object_Path;
365 procedure Add_To_Path
366 (Source_Dirs : String_List_Id;
367 In_Tree : Project_Tree_Ref)
369 Current : String_List_Id := Source_Dirs;
370 Source_Dir : String_Element;
372 while Current /= Nil_String loop
373 Source_Dir := In_Tree.String_Elements.Table (Current);
374 Add_To_Path (Get_Name_String (Source_Dir.Display_Value));
375 Current := Source_Dir.Next;
379 procedure Add_To_Path (Dir : String) is
381 New_Buffer : String_Access;
384 function Is_Present (Path : String; Dir : String) return Boolean;
385 -- Return True if Dir is part of Path
391 function Is_Present (Path : String; Dir : String) return Boolean is
392 Last : constant Integer := Path'Last - Dir'Length + 1;
395 for J in Path'First .. Last loop
397 -- Note: the order of the conditions below is important, since
398 -- it ensures a minimal number of string comparisons.
401 or else Path (J - 1) = Path_Separator)
403 (J + Dir'Length > Path'Last
404 or else Path (J + Dir'Length) = Path_Separator)
405 and then Dir = Path (J .. J + Dir'Length - 1)
414 -- Start of processing for Add_To_Path
417 if Is_Present (Ada_Path_Buffer (1 .. Ada_Path_Length), Dir) then
419 -- Dir is already in the path, nothing to do
424 Min_Len := Ada_Path_Length + Dir'Length;
426 if Ada_Path_Length > 0 then
428 -- Add 1 for the Path_Separator character
430 Min_Len := Min_Len + 1;
433 -- If Ada_Path_Buffer is too small, increase it
435 Len := Ada_Path_Buffer'Last;
437 if Len < Min_Len then
440 exit when Len >= Min_Len;
443 New_Buffer := new String (1 .. Len);
444 New_Buffer (1 .. Ada_Path_Length) :=
445 Ada_Path_Buffer (1 .. Ada_Path_Length);
446 Free (Ada_Path_Buffer);
447 Ada_Path_Buffer := New_Buffer;
450 if Ada_Path_Length > 0 then
451 Ada_Path_Length := Ada_Path_Length + 1;
452 Ada_Path_Buffer (Ada_Path_Length) := Path_Separator;
456 (Ada_Path_Length + 1 .. Ada_Path_Length + Dir'Length) := Dir;
457 Ada_Path_Length := Ada_Path_Length + Dir'Length;
460 ------------------------
461 -- Add_To_Source_Path --
462 ------------------------
464 procedure Add_To_Source_Path
465 (Source_Dirs : String_List_Id; In_Tree : Project_Tree_Ref)
467 Current : String_List_Id := Source_Dirs;
468 Source_Dir : String_Element;
472 -- Add each source directory
474 while Current /= Nil_String loop
475 Source_Dir := In_Tree.String_Elements.Table (Current);
478 -- Check if the source directory is already in the table
480 for Index in Source_Path_Table.First ..
481 Source_Path_Table.Last
482 (In_Tree.Private_Part.Source_Paths)
484 -- If it is already, no need to add it
486 if In_Tree.Private_Part.Source_Paths.Table (Index) =
495 Source_Path_Table.Increment_Last
496 (In_Tree.Private_Part.Source_Paths);
497 In_Tree.Private_Part.Source_Paths.Table
498 (Source_Path_Table.Last (In_Tree.Private_Part.Source_Paths)) :=
502 -- Next source directory
504 Current := Source_Dir.Next;
506 end Add_To_Source_Path;
508 -----------------------
509 -- Body_Path_Name_Of --
510 -----------------------
512 function Body_Path_Name_Of
514 In_Tree : Project_Tree_Ref) return String
516 Data : Unit_Data := In_Tree.Units.Table (Unit);
519 -- If we don't know the path name of the body of this unit,
520 -- we compute it, and we store it.
522 if Data.File_Names (Body_Part).Path = No_Path then
524 Current_Source : String_List_Id :=
525 In_Tree.Projects.Table
526 (Data.File_Names (Body_Part).Project).Ada_Sources;
527 Path : GNAT.OS_Lib.String_Access;
530 -- By default, put the file name
532 Data.File_Names (Body_Part).Path :=
533 Path_Name_Type (Data.File_Names (Body_Part).Name);
535 -- For each source directory
537 while Current_Source /= Nil_String loop
540 (Namet.Get_Name_String
541 (Data.File_Names (Body_Part).Name),
542 Namet.Get_Name_String
543 (In_Tree.String_Elements.Table
544 (Current_Source).Value));
546 -- If the file is in this directory, then we store the path,
550 Name_Len := Path'Length;
551 Name_Buffer (1 .. Name_Len) := Path.all;
552 Data.File_Names (Body_Part).Path := Name_Enter;
557 In_Tree.String_Elements.Table
558 (Current_Source).Next;
562 In_Tree.Units.Table (Unit) := Data;
566 -- Returned the stored value
568 return Namet.Get_Name_String (Data.File_Names (Body_Part).Path);
569 end Body_Path_Name_Of;
571 ------------------------
572 -- Contains_ALI_Files --
573 ------------------------
575 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean is
576 Dir_Name : constant String := Get_Name_String (Dir);
578 Name : String (1 .. 1_000);
580 Result : Boolean := False;
583 Open (Direct, Dir_Name);
585 -- For each file in the directory, check if it is an ALI file
588 Read (Direct, Name, Last);
590 Canonical_Case_File_Name (Name (1 .. Last));
591 Result := Last >= 5 and then Name (Last - 3 .. Last) = ".ali";
599 -- If there is any problem, close the directory if open and return
600 -- True; the library directory will be added to the path.
603 if Is_Open (Direct) then
608 end Contains_ALI_Files;
610 --------------------------------
611 -- Create_Config_Pragmas_File --
612 --------------------------------
614 procedure Create_Config_Pragmas_File
615 (For_Project : Project_Id;
616 Main_Project : Project_Id;
617 In_Tree : Project_Tree_Ref;
618 Include_Config_Files : Boolean := True)
620 pragma Unreferenced (Main_Project);
621 pragma Unreferenced (Include_Config_Files);
623 File_Name : Path_Name_Type := No_Path;
624 File : File_Descriptor := Invalid_FD;
626 Current_Unit : Unit_Index := Unit_Table.First;
628 First_Project : Project_List := Empty_Project_List;
630 Current_Project : Project_List;
631 Current_Naming : Naming_Id;
636 procedure Check (Project : Project_Id);
637 -- Recursive procedure that put in the config pragmas file any non
638 -- standard naming schemes, if it is not already in the file, then call
639 -- itself for any imported project.
641 procedure Check_Temp_File;
642 -- Check that a temporary file has been opened.
643 -- If not, create one, and put its name in the project data,
644 -- with the indication that it is a temporary file.
647 (Unit_Name : Name_Id;
648 File_Name : File_Name_Type;
649 Unit_Kind : Spec_Or_Body;
651 -- Put an SFN pragma in the temporary file
653 procedure Put (File : File_Descriptor; S : String);
654 procedure Put_Line (File : File_Descriptor; S : String);
655 -- Output procedures, analogous to normal Text_IO procs of same name
661 procedure Check (Project : Project_Id) is
662 Data : constant Project_Data :=
663 In_Tree.Projects.Table (Project);
666 if Current_Verbosity = High then
667 Write_Str ("Checking project file """);
668 Write_Str (Namet.Get_Name_String (Data.Name));
673 -- Is this project in the list of the visited project?
675 Current_Project := First_Project;
676 while Current_Project /= Empty_Project_List
677 and then In_Tree.Project_Lists.Table
678 (Current_Project).Project /= Project
681 In_Tree.Project_Lists.Table (Current_Project).Next;
684 -- If it is not, put it in the list, and visit it
686 if Current_Project = Empty_Project_List then
687 Project_List_Table.Increment_Last
688 (In_Tree.Project_Lists);
689 In_Tree.Project_Lists.Table
690 (Project_List_Table.Last (In_Tree.Project_Lists)) :=
691 (Project => Project, Next => First_Project);
693 Project_List_Table.Last (In_Tree.Project_Lists);
695 -- Is the naming scheme of this project one that we know?
697 Current_Naming := Default_Naming;
698 while Current_Naming <=
699 Naming_Table.Last (In_Tree.Private_Part.Namings)
700 and then not Same_Naming_Scheme
701 (Left => In_Tree.Private_Part.Namings.Table (Current_Naming),
702 Right => Data.Naming) loop
703 Current_Naming := Current_Naming + 1;
706 -- If we don't know it, add it
709 Naming_Table.Last (In_Tree.Private_Part.Namings)
711 Naming_Table.Increment_Last (In_Tree.Private_Part.Namings);
712 In_Tree.Private_Part.Namings.Table
713 (Naming_Table.Last (In_Tree.Private_Part.Namings)) :=
716 -- We need a temporary file to be created
720 -- Put the SFN pragmas for the naming scheme
725 (File, "pragma Source_File_Name_Project");
727 (File, " (Spec_File_Name => ""*" &
728 Spec_Suffix_Of (In_Tree, "ada", Data.Naming) &
731 (File, " Casing => " &
732 Image (Data.Naming.Casing) & ",");
734 (File, " Dot_Replacement => """ &
735 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
741 (File, "pragma Source_File_Name_Project");
743 (File, " (Body_File_Name => ""*" &
744 Body_Suffix_Of (In_Tree, "ada", Data.Naming) &
747 (File, " Casing => " &
748 Image (Data.Naming.Casing) & ",");
750 (File, " Dot_Replacement => """ &
751 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
754 -- and maybe separate
756 if Body_Suffix_Of (In_Tree, "ada", Data.Naming) /=
757 Get_Name_String (Data.Naming.Separate_Suffix)
760 (File, "pragma Source_File_Name_Project");
762 (File, " (Subunit_File_Name => ""*" &
763 Namet.Get_Name_String (Data.Naming.Separate_Suffix) &
766 (File, " Casing => " &
767 Image (Data.Naming.Casing) &
770 (File, " Dot_Replacement => """ &
771 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
776 if Data.Extends /= No_Project then
777 Check (Data.Extends);
781 Current : Project_List := Data.Imported_Projects;
784 while Current /= Empty_Project_List loop
786 (In_Tree.Project_Lists.Table
788 Current := In_Tree.Project_Lists.Table
795 ---------------------
796 -- Check_Temp_File --
797 ---------------------
799 procedure Check_Temp_File is
801 if File = Invalid_FD then
802 Tempdir.Create_Temp_File (File, Name => File_Name);
804 if File = Invalid_FD then
806 ("unable to create temporary configuration pragmas file");
809 Record_Temp_File (File_Name);
811 if Opt.Verbose_Mode then
812 Write_Str ("Creating temp file """);
813 Write_Str (Get_Name_String (File_Name));
825 (Unit_Name : Name_Id;
826 File_Name : File_Name_Type;
827 Unit_Kind : Spec_Or_Body;
831 -- A temporary file needs to be open
835 -- Put the pragma SFN for the unit kind (spec or body)
837 Put (File, "pragma Source_File_Name_Project (");
838 Put (File, Namet.Get_Name_String (Unit_Name));
840 if Unit_Kind = Specification then
841 Put (File, ", Spec_File_Name => """);
843 Put (File, ", Body_File_Name => """);
846 Put (File, Namet.Get_Name_String (File_Name));
850 Put (File, ", Index =>");
851 Put (File, Index'Img);
854 Put_Line (File, ");");
857 procedure Put (File : File_Descriptor; S : String) is
861 Last := Write (File, S (S'First)'Address, S'Length);
863 if Last /= S'Length then
864 Prj.Com.Fail ("Disk full");
867 if Current_Verbosity = High then
876 procedure Put_Line (File : File_Descriptor; S : String) is
877 S0 : String (1 .. S'Length + 1);
881 -- Add an ASCII.LF to the string. As this config file is supposed to
882 -- be used only by the compiler, we don't care about the characters
883 -- for the end of line. In fact we could have put a space, but
884 -- it is more convenient to be able to read gnat.adc during
885 -- development, for which the ASCII.LF is fine.
887 S0 (1 .. S'Length) := S;
888 S0 (S0'Last) := ASCII.LF;
889 Last := Write (File, S0'Address, S0'Length);
891 if Last /= S'Length + 1 then
892 Prj.Com.Fail ("Disk full");
895 if Current_Verbosity = High then
900 -- Start of processing for Create_Config_Pragmas_File
904 In_Tree.Projects.Table (For_Project).Config_Checked
907 -- Remove any memory of processed naming schemes, if any
909 Naming_Table.Set_Last (In_Tree.Private_Part.Namings, Default_Naming);
911 -- Check the naming schemes
915 -- Visit all the units and process those that need an SFN pragma
918 Current_Unit <= Unit_Table.Last (In_Tree.Units)
921 Unit : constant Unit_Data :=
922 In_Tree.Units.Table (Current_Unit);
925 if Unit.File_Names (Specification).Needs_Pragma then
927 Unit.File_Names (Specification).Name,
929 Unit.File_Names (Specification).Index);
932 if Unit.File_Names (Body_Part).Needs_Pragma then
934 Unit.File_Names (Body_Part).Name,
936 Unit.File_Names (Body_Part).Index);
939 Current_Unit := Current_Unit + 1;
943 -- If there are no non standard naming scheme, issue the GNAT
944 -- standard naming scheme. This will tell the compiler that
945 -- a project file is used and will forbid any pragma SFN.
947 if File = Invalid_FD then
950 Put_Line (File, "pragma Source_File_Name_Project");
951 Put_Line (File, " (Spec_File_Name => ""*.ads"",");
952 Put_Line (File, " Dot_Replacement => ""-"",");
953 Put_Line (File, " Casing => lowercase);");
955 Put_Line (File, "pragma Source_File_Name_Project");
956 Put_Line (File, " (Body_File_Name => ""*.adb"",");
957 Put_Line (File, " Dot_Replacement => ""-"",");
958 Put_Line (File, " Casing => lowercase);");
961 -- Close the temporary file
963 GNAT.OS_Lib.Close (File, Status);
966 Prj.Com.Fail ("disk full");
969 if Opt.Verbose_Mode then
970 Write_Str ("Closing configuration file """);
971 Write_Str (Get_Name_String (File_Name));
975 In_Tree.Projects.Table (For_Project).Config_File_Name :=
977 In_Tree.Projects.Table (For_Project).Config_File_Temp :=
980 In_Tree.Projects.Table (For_Project).Config_Checked :=
983 end Create_Config_Pragmas_File;
985 -------------------------
986 -- Create_Mapping_File --
987 -------------------------
989 procedure Create_Mapping_File
990 (Project : Project_Id;
991 In_Tree : Project_Tree_Ref;
992 Name : out Path_Name_Type)
994 File : File_Descriptor := Invalid_FD;
995 The_Unit_Data : Unit_Data;
996 Data : File_Name_Data;
1001 Present : Project_Flags
1002 (No_Project .. Project_Table.Last (In_Tree.Projects)) :=
1004 -- For each project in the closure of Project, the corresponding flag
1005 -- will be set to True;
1007 procedure Put_Name_Buffer;
1008 -- Put the line contained in the Name_Buffer in the mapping file
1010 procedure Put_Data (Spec : Boolean);
1011 -- Put the mapping of the spec or body contained in Data in the file
1014 procedure Recursive_Flag (Prj : Project_Id);
1015 -- Set the flags corresponding to Prj, the projects it imports
1016 -- (directly or indirectly) or extends to True. Call itself recursively.
1022 procedure Put_Name_Buffer is
1026 Name_Len := Name_Len + 1;
1027 Name_Buffer (Name_Len) := ASCII.LF;
1028 Last := Write (File, Name_Buffer (1)'Address, Name_Len);
1030 if Last /= Name_Len then
1031 Prj.Com.Fail ("Disk full");
1033 end Put_Name_Buffer;
1039 procedure Put_Data (Spec : Boolean) is
1041 -- Line with the unit name
1043 Get_Name_String (The_Unit_Data.Name);
1044 Name_Len := Name_Len + 1;
1045 Name_Buffer (Name_Len) := '%';
1046 Name_Len := Name_Len + 1;
1049 Name_Buffer (Name_Len) := 's';
1051 Name_Buffer (Name_Len) := 'b';
1056 -- Line with the file name
1058 Get_Name_String (Data.Name);
1061 -- Line with the path name
1063 Get_Name_String (Data.Path);
1068 --------------------
1069 -- Recursive_Flag --
1070 --------------------
1072 procedure Recursive_Flag (Prj : Project_Id) is
1073 Imported : Project_List;
1077 -- Nothing to do for non existent project or project that has
1078 -- already been flagged.
1080 if Prj = No_Project or else Present (Prj) then
1084 -- Flag the current project
1086 Present (Prj) := True;
1088 In_Tree.Projects.Table (Prj).Imported_Projects;
1090 -- Call itself for each project directly imported
1092 while Imported /= Empty_Project_List loop
1094 In_Tree.Project_Lists.Table (Imported).Project;
1096 In_Tree.Project_Lists.Table (Imported).Next;
1097 Recursive_Flag (Proj);
1100 -- Call itself for an eventual project being extended
1102 Recursive_Flag (In_Tree.Projects.Table (Prj).Extends);
1105 -- Start of processing for Create_Mapping_File
1108 -- Flag the necessary projects
1110 Recursive_Flag (Project);
1112 -- Create the temporary file
1114 Tempdir.Create_Temp_File (File, Name => Name);
1116 if File = Invalid_FD then
1117 Prj.Com.Fail ("unable to create temporary mapping file");
1120 Record_Temp_File (Name);
1122 if Opt.Verbose_Mode then
1123 Write_Str ("Creating temp mapping file """);
1124 Write_Str (Get_Name_String (Name));
1129 if Fill_Mapping_File then
1131 -- For all units in table Units
1133 for Unit in 1 .. Unit_Table.Last (In_Tree.Units) loop
1134 The_Unit_Data := In_Tree.Units.Table (Unit);
1136 -- If the unit has a valid name
1138 if The_Unit_Data.Name /= No_Name then
1139 Data := The_Unit_Data.File_Names (Specification);
1141 -- If there is a spec, put it mapping in the file if it is
1142 -- from a project in the closure of Project.
1144 if Data.Name /= No_File and then Present (Data.Project) then
1145 Put_Data (Spec => True);
1148 Data := The_Unit_Data.File_Names (Body_Part);
1150 -- If there is a body (or subunit) put its mapping in the file
1151 -- if it is from a project in the closure of Project.
1153 if Data.Name /= No_File and then Present (Data.Project) then
1154 Put_Data (Spec => False);
1161 GNAT.OS_Lib.Close (File, Status);
1164 Prj.Com.Fail ("disk full");
1166 end Create_Mapping_File;
1168 procedure Create_Mapping_File
1169 (Project : Project_Id;
1171 In_Tree : Project_Tree_Ref;
1172 Name : out Path_Name_Type)
1174 File : File_Descriptor := Invalid_FD;
1177 -- For call to Close
1179 Present : Project_Flags
1180 (No_Project .. Project_Table.Last (In_Tree.Projects)) :=
1182 -- For each project in the closure of Project, the corresponding flag
1183 -- will be set to True.
1186 Src_Data : Source_Data;
1187 Suffix : File_Name_Type;
1189 procedure Put_Name_Buffer;
1190 -- Put the line contained in the Name_Buffer in the mapping file
1192 procedure Recursive_Flag (Prj : Project_Id);
1193 -- Set the flags corresponding to Prj, the projects it imports
1194 -- (directly or indirectly) or extends to True. Call itself recursively.
1200 procedure Put_Name_Buffer is
1204 Name_Len := Name_Len + 1;
1205 Name_Buffer (Name_Len) := ASCII.LF;
1206 Last := Write (File, Name_Buffer (1)'Address, Name_Len);
1208 if Last /= Name_Len then
1209 Prj.Com.Fail ("Disk full");
1211 end Put_Name_Buffer;
1213 --------------------
1214 -- Recursive_Flag --
1215 --------------------
1217 procedure Recursive_Flag (Prj : Project_Id) is
1218 Imported : Project_List;
1222 -- Nothing to do for non existent project or project that has already
1225 if Prj = No_Project or else Present (Prj) then
1229 -- Flag the current project
1231 Present (Prj) := True;
1233 In_Tree.Projects.Table (Prj).Imported_Projects;
1235 -- Call itself for each project directly imported
1237 while Imported /= Empty_Project_List loop
1239 In_Tree.Project_Lists.Table (Imported).Project;
1241 In_Tree.Project_Lists.Table (Imported).Next;
1242 Recursive_Flag (Proj);
1245 -- Call itself for an eventual project being extended
1247 Recursive_Flag (In_Tree.Projects.Table (Prj).Extends);
1250 -- Start of processing for Create_Mapping_File
1253 -- Flag the necessary projects
1255 Recursive_Flag (Project);
1257 -- Create the temporary file
1259 Tempdir.Create_Temp_File (File, Name => Name);
1261 if File = Invalid_FD then
1262 Prj.Com.Fail ("unable to create temporary mapping file");
1265 Record_Temp_File (Name);
1267 if Opt.Verbose_Mode then
1268 Write_Str ("Creating temp mapping file """);
1269 Write_Str (Get_Name_String (Name));
1274 -- For all source of the Language of all projects in the closure
1276 for Proj in Present'Range loop
1277 if Present (Proj) then
1278 Source := In_Tree.Projects.Table (Proj).First_Source;
1280 while Source /= No_Source loop
1281 Src_Data := In_Tree.Sources.Table (Source);
1283 if Src_Data.Language_Name = Language and then
1284 (not Src_Data.Locally_Removed) and then
1285 Src_Data.Replaced_By = No_Source
1287 if Src_Data.Unit /= No_Name then
1288 Get_Name_String (Src_Data.Unit);
1290 if Src_Data.Kind = Spec then
1291 Suffix := In_Tree.Languages_Data.Table
1292 (Src_Data.Language).Config.Mapping_Spec_Suffix;
1295 Suffix := In_Tree.Languages_Data.Table
1296 (Src_Data.Language).Config.Mapping_Body_Suffix;
1299 if Suffix /= No_File then
1300 Add_Str_To_Name_Buffer (Get_Name_String (Suffix));
1306 Get_Name_String (Src_Data.File);
1309 Get_Name_String (Src_Data.Path);
1313 Source := Src_Data.Next_In_Project;
1318 GNAT.OS_Lib.Close (File, Status);
1321 Prj.Com.Fail ("disk full");
1323 end Create_Mapping_File;
1325 --------------------------
1326 -- Create_New_Path_File --
1327 --------------------------
1329 procedure Create_New_Path_File
1330 (In_Tree : Project_Tree_Ref;
1331 Path_FD : out File_Descriptor;
1332 Path_Name : out Path_Name_Type)
1335 Tempdir.Create_Temp_File (Path_FD, Path_Name);
1337 if Path_Name /= No_Path then
1338 Record_Temp_File (Path_Name);
1340 -- Record the name, so that the temp path file will be deleted at the
1341 -- end of the program.
1343 Path_File_Table.Increment_Last (In_Tree.Private_Part.Path_Files);
1344 In_Tree.Private_Part.Path_Files.Table
1345 (Path_File_Table.Last (In_Tree.Private_Part.Path_Files)) :=
1348 end Create_New_Path_File;
1350 ---------------------------
1351 -- Delete_All_Path_Files --
1352 ---------------------------
1354 procedure Delete_All_Path_Files (In_Tree : Project_Tree_Ref) is
1355 Disregard : Boolean := True;
1358 for Index in Path_File_Table.First ..
1359 Path_File_Table.Last (In_Tree.Private_Part.Path_Files)
1361 if In_Tree.Private_Part.Path_Files.Table (Index) /= No_Path then
1364 (In_Tree.Private_Part.Path_Files.Table (Index)),
1369 -- If any of the environment variables ADA_PRJ_INCLUDE_FILE or
1370 -- ADA_PRJ_OBJECTS_FILE has been set, then reset their value to
1371 -- the empty string. On VMS, this has the effect of deassigning
1372 -- the logical names.
1374 if Ada_Prj_Include_File_Set then
1375 Setenv (Project_Include_Path_File, "");
1376 Ada_Prj_Include_File_Set := False;
1379 if Ada_Prj_Objects_File_Set then
1380 Setenv (Project_Objects_Path_File, "");
1381 Ada_Prj_Objects_File_Set := False;
1383 end Delete_All_Path_Files;
1385 ------------------------------------
1386 -- File_Name_Of_Library_Unit_Body --
1387 ------------------------------------
1389 function File_Name_Of_Library_Unit_Body
1391 Project : Project_Id;
1392 In_Tree : Project_Tree_Ref;
1393 Main_Project_Only : Boolean := True;
1394 Full_Path : Boolean := False) return String
1396 The_Project : Project_Id := Project;
1397 Data : Project_Data :=
1398 In_Tree.Projects.Table (Project);
1399 Original_Name : String := Name;
1401 Extended_Spec_Name : String :=
1403 Spec_Suffix_Of (In_Tree, "ada", Data.Naming);
1404 Extended_Body_Name : String :=
1406 Body_Suffix_Of (In_Tree, "ada", Data.Naming);
1410 The_Original_Name : Name_Id;
1411 The_Spec_Name : Name_Id;
1412 The_Body_Name : Name_Id;
1415 Canonical_Case_File_Name (Original_Name);
1416 Name_Len := Original_Name'Length;
1417 Name_Buffer (1 .. Name_Len) := Original_Name;
1418 The_Original_Name := Name_Find;
1420 Canonical_Case_File_Name (Extended_Spec_Name);
1421 Name_Len := Extended_Spec_Name'Length;
1422 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
1423 The_Spec_Name := Name_Find;
1425 Canonical_Case_File_Name (Extended_Body_Name);
1426 Name_Len := Extended_Body_Name'Length;
1427 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
1428 The_Body_Name := Name_Find;
1430 if Current_Verbosity = High then
1431 Write_Str ("Looking for file name of """);
1435 Write_Str (" Extended Spec Name = """);
1436 Write_Str (Extended_Spec_Name);
1439 Write_Str (" Extended Body Name = """);
1440 Write_Str (Extended_Body_Name);
1445 -- For extending project, search in the extended project if the source
1446 -- is not found. For non extending projects, this loop will be run only
1450 -- Loop through units
1451 -- Should have comment explaining reverse ???
1453 for Current in reverse Unit_Table.First ..
1454 Unit_Table.Last (In_Tree.Units)
1456 Unit := In_Tree.Units.Table (Current);
1460 if not Main_Project_Only
1461 or else Unit.File_Names (Body_Part).Project = The_Project
1464 Current_Name : constant File_Name_Type :=
1465 Unit.File_Names (Body_Part).Name;
1468 -- Case of a body present
1470 if Current_Name /= No_File then
1471 if Current_Verbosity = High then
1472 Write_Str (" Comparing with """);
1473 Write_Str (Get_Name_String (Current_Name));
1478 -- If it has the name of the original name, return the
1481 if Unit.Name = The_Original_Name
1483 Current_Name = File_Name_Type (The_Original_Name)
1485 if Current_Verbosity = High then
1490 return Get_Name_String
1491 (Unit.File_Names (Body_Part).Path);
1494 return Get_Name_String (Current_Name);
1497 -- If it has the name of the extended body name,
1498 -- return the extended body name
1500 elsif Current_Name = File_Name_Type (The_Body_Name) then
1501 if Current_Verbosity = High then
1506 return Get_Name_String
1507 (Unit.File_Names (Body_Part).Path);
1510 return Extended_Body_Name;
1514 if Current_Verbosity = High then
1515 Write_Line (" not good");
1524 if not Main_Project_Only
1525 or else Unit.File_Names (Specification).Project = The_Project
1528 Current_Name : constant File_Name_Type :=
1529 Unit.File_Names (Specification).Name;
1532 -- Case of spec present
1534 if Current_Name /= No_File then
1535 if Current_Verbosity = High then
1536 Write_Str (" Comparing with """);
1537 Write_Str (Get_Name_String (Current_Name));
1542 -- If name same as original name, return original name
1544 if Unit.Name = The_Original_Name
1546 Current_Name = File_Name_Type (The_Original_Name)
1548 if Current_Verbosity = High then
1553 return Get_Name_String
1554 (Unit.File_Names (Specification).Path);
1556 return Get_Name_String (Current_Name);
1559 -- If it has the same name as the extended spec name,
1560 -- return the extended spec name.
1562 elsif Current_Name = File_Name_Type (The_Spec_Name) then
1563 if Current_Verbosity = High then
1568 return Get_Name_String
1569 (Unit.File_Names (Specification).Path);
1571 return Extended_Spec_Name;
1575 if Current_Verbosity = High then
1576 Write_Line (" not good");
1584 -- If we are not in an extending project, give up
1586 exit when (not Main_Project_Only) or else Data.Extends = No_Project;
1588 -- Otherwise, look in the project we are extending
1590 The_Project := Data.Extends;
1591 Data := In_Tree.Projects.Table (The_Project);
1594 -- We don't know this file name, return an empty string
1597 end File_Name_Of_Library_Unit_Body;
1599 -------------------------
1600 -- For_All_Object_Dirs --
1601 -------------------------
1603 procedure For_All_Object_Dirs
1604 (Project : Project_Id;
1605 In_Tree : Project_Tree_Ref)
1607 Seen : Project_List := Empty_Project_List;
1609 procedure Add (Project : Project_Id);
1610 -- Process a project. Remember the processes visited to avoid processing
1611 -- a project twice. Recursively process an eventual extended project,
1612 -- and all imported projects.
1618 procedure Add (Project : Project_Id) is
1619 Data : constant Project_Data :=
1620 In_Tree.Projects.Table (Project);
1621 List : Project_List := Data.Imported_Projects;
1624 -- If the list of visited project is empty, then
1625 -- for sure we never visited this project.
1627 if Seen = Empty_Project_List then
1628 Project_List_Table.Increment_Last (In_Tree.Project_Lists);
1629 Seen := Project_List_Table.Last (In_Tree.Project_Lists);
1630 In_Tree.Project_Lists.Table (Seen) :=
1631 (Project => Project, Next => Empty_Project_List);
1634 -- Check if the project is in the list
1637 Current : Project_List := Seen;
1641 -- If it is, then there is nothing else to do
1643 if In_Tree.Project_Lists.Table
1644 (Current).Project = Project
1650 In_Tree.Project_Lists.Table (Current).Next =
1653 In_Tree.Project_Lists.Table (Current).Next;
1656 -- This project has never been visited, add it
1659 Project_List_Table.Increment_Last
1660 (In_Tree.Project_Lists);
1661 In_Tree.Project_Lists.Table (Current).Next :=
1662 Project_List_Table.Last (In_Tree.Project_Lists);
1663 In_Tree.Project_Lists.Table
1664 (Project_List_Table.Last
1665 (In_Tree.Project_Lists)) :=
1666 (Project => Project, Next => Empty_Project_List);
1670 -- If there is an object directory, call Action with its name
1672 if Data.Object_Directory /= No_Path then
1673 Get_Name_String (Data.Display_Object_Dir);
1674 Action (Name_Buffer (1 .. Name_Len));
1677 -- If we are extending a project, visit it
1679 if Data.Extends /= No_Project then
1683 -- And visit all imported projects
1685 while List /= Empty_Project_List loop
1686 Add (In_Tree.Project_Lists.Table (List).Project);
1687 List := In_Tree.Project_Lists.Table (List).Next;
1691 -- Start of processing for For_All_Object_Dirs
1694 -- Visit this project, and its imported projects, recursively
1697 end For_All_Object_Dirs;
1699 -------------------------
1700 -- For_All_Source_Dirs --
1701 -------------------------
1703 procedure For_All_Source_Dirs
1704 (Project : Project_Id;
1705 In_Tree : Project_Tree_Ref)
1707 Seen : Project_List := Empty_Project_List;
1709 procedure Add (Project : Project_Id);
1710 -- Process a project. Remember the processes visited to avoid processing
1711 -- a project twice. Recursively process an eventual extended project,
1712 -- and all imported projects.
1718 procedure Add (Project : Project_Id) is
1719 Data : constant Project_Data :=
1720 In_Tree.Projects.Table (Project);
1721 List : Project_List := Data.Imported_Projects;
1724 -- If the list of visited project is empty, then for sure we never
1725 -- visited this project.
1727 if Seen = Empty_Project_List then
1728 Project_List_Table.Increment_Last
1729 (In_Tree.Project_Lists);
1730 Seen := Project_List_Table.Last
1731 (In_Tree.Project_Lists);
1732 In_Tree.Project_Lists.Table (Seen) :=
1733 (Project => Project, Next => Empty_Project_List);
1736 -- Check if the project is in the list
1739 Current : Project_List := Seen;
1743 -- If it is, then there is nothing else to do
1745 if In_Tree.Project_Lists.Table
1746 (Current).Project = Project
1752 In_Tree.Project_Lists.Table (Current).Next =
1755 In_Tree.Project_Lists.Table (Current).Next;
1758 -- This project has never been visited, add it to the list
1760 Project_List_Table.Increment_Last
1761 (In_Tree.Project_Lists);
1762 In_Tree.Project_Lists.Table (Current).Next :=
1763 Project_List_Table.Last (In_Tree.Project_Lists);
1764 In_Tree.Project_Lists.Table
1765 (Project_List_Table.Last
1766 (In_Tree.Project_Lists)) :=
1767 (Project => Project, Next => Empty_Project_List);
1772 Current : String_List_Id := Data.Source_Dirs;
1773 The_String : String_Element;
1776 -- If there are Ada sources, call action with the name of every
1777 -- source directory.
1780 In_Tree.Projects.Table (Project).Ada_Sources /= Nil_String
1782 while Current /= Nil_String loop
1784 In_Tree.String_Elements.Table (Current);
1785 Action (Get_Name_String (The_String.Display_Value));
1786 Current := The_String.Next;
1791 -- If we are extending a project, visit it
1793 if Data.Extends /= No_Project then
1797 -- And visit all imported projects
1799 while List /= Empty_Project_List loop
1800 Add (In_Tree.Project_Lists.Table (List).Project);
1801 List := In_Tree.Project_Lists.Table (List).Next;
1805 -- Start of processing for For_All_Source_Dirs
1808 -- Visit this project, and its imported projects recursively
1811 end For_All_Source_Dirs;
1817 procedure Get_Reference
1818 (Source_File_Name : String;
1819 In_Tree : Project_Tree_Ref;
1820 Project : out Project_Id;
1821 Path : out Path_Name_Type)
1824 -- Body below could use some comments ???
1826 if Current_Verbosity > Default then
1827 Write_Str ("Getting Reference_Of (""");
1828 Write_Str (Source_File_Name);
1829 Write_Str (""") ... ");
1833 Original_Name : String := Source_File_Name;
1837 Canonical_Case_File_Name (Original_Name);
1839 for Id in Unit_Table.First ..
1840 Unit_Table.Last (In_Tree.Units)
1842 Unit := In_Tree.Units.Table (Id);
1844 if (Unit.File_Names (Specification).Name /= No_File
1846 Namet.Get_Name_String
1847 (Unit.File_Names (Specification).Name) = Original_Name)
1848 or else (Unit.File_Names (Specification).Path /= No_Path
1850 Namet.Get_Name_String
1851 (Unit.File_Names (Specification).Path) =
1854 Project := Ultimate_Extension_Of
1855 (Project => Unit.File_Names (Specification).Project,
1856 In_Tree => In_Tree);
1857 Path := Unit.File_Names (Specification).Display_Path;
1859 if Current_Verbosity > Default then
1860 Write_Str ("Done: Specification.");
1866 elsif (Unit.File_Names (Body_Part).Name /= No_File
1868 Namet.Get_Name_String
1869 (Unit.File_Names (Body_Part).Name) = Original_Name)
1870 or else (Unit.File_Names (Body_Part).Path /= No_Path
1871 and then Namet.Get_Name_String
1872 (Unit.File_Names (Body_Part).Path) =
1875 Project := Ultimate_Extension_Of
1876 (Project => Unit.File_Names (Body_Part).Project,
1877 In_Tree => In_Tree);
1878 Path := Unit.File_Names (Body_Part).Display_Path;
1880 if Current_Verbosity > Default then
1881 Write_Str ("Done: Body.");
1890 Project := No_Project;
1893 if Current_Verbosity > Default then
1894 Write_Str ("Cannot be found.");
1903 procedure Initialize is
1905 Fill_Mapping_File := True;
1908 ------------------------------------
1909 -- Path_Name_Of_Library_Unit_Body --
1910 ------------------------------------
1912 -- Could use some comments in the body here ???
1914 function Path_Name_Of_Library_Unit_Body
1916 Project : Project_Id;
1917 In_Tree : Project_Tree_Ref) return String
1919 Data : constant Project_Data :=
1920 In_Tree.Projects.Table (Project);
1921 Original_Name : String := Name;
1923 Extended_Spec_Name : String :=
1925 Spec_Suffix_Of (In_Tree, "ada", Data.Naming);
1926 Extended_Body_Name : String :=
1928 Body_Suffix_Of (In_Tree, "ada", Data.Naming);
1930 First : Unit_Index := Unit_Table.First;
1931 Current : Unit_Index;
1935 Canonical_Case_File_Name (Original_Name);
1936 Canonical_Case_File_Name (Extended_Spec_Name);
1937 Canonical_Case_File_Name (Extended_Body_Name);
1939 if Current_Verbosity = High then
1940 Write_Str ("Looking for path name of """);
1944 Write_Str (" Extended Spec Name = """);
1945 Write_Str (Extended_Spec_Name);
1948 Write_Str (" Extended Body Name = """);
1949 Write_Str (Extended_Body_Name);
1954 while First <= Unit_Table.Last (In_Tree.Units)
1955 and then In_Tree.Units.Table
1956 (First).File_Names (Body_Part).Project /= Project
1962 while Current <= Unit_Table.Last (In_Tree.Units) loop
1963 Unit := In_Tree.Units.Table (Current);
1965 if Unit.File_Names (Body_Part).Project = Project
1966 and then Unit.File_Names (Body_Part).Name /= No_File
1969 Current_Name : constant String :=
1970 Namet.Get_Name_String (Unit.File_Names (Body_Part).Name);
1972 if Current_Verbosity = High then
1973 Write_Str (" Comparing with """);
1974 Write_Str (Current_Name);
1979 if Current_Name = Original_Name then
1980 if Current_Verbosity = High then
1984 return Body_Path_Name_Of (Current, In_Tree);
1986 elsif Current_Name = Extended_Body_Name then
1987 if Current_Verbosity = High then
1991 return Body_Path_Name_Of (Current, In_Tree);
1994 if Current_Verbosity = High then
1995 Write_Line (" not good");
2000 elsif Unit.File_Names (Specification).Name /= No_File then
2002 Current_Name : constant String :=
2003 Namet.Get_Name_String
2004 (Unit.File_Names (Specification).Name);
2007 if Current_Verbosity = High then
2008 Write_Str (" Comparing with """);
2009 Write_Str (Current_Name);
2014 if Current_Name = Original_Name then
2015 if Current_Verbosity = High then
2019 return Spec_Path_Name_Of (Current, In_Tree);
2021 elsif Current_Name = Extended_Spec_Name then
2022 if Current_Verbosity = High then
2026 return Spec_Path_Name_Of (Current, In_Tree);
2029 if Current_Verbosity = High then
2030 Write_Line (" not good");
2035 Current := Current + 1;
2039 end Path_Name_Of_Library_Unit_Body;
2045 -- Could use some comments in this body ???
2047 procedure Print_Sources (In_Tree : Project_Tree_Ref) is
2051 Write_Line ("List of Sources:");
2053 for Id in Unit_Table.First ..
2054 Unit_Table.Last (In_Tree.Units)
2056 Unit := In_Tree.Units.Table (Id);
2058 Write_Line (Namet.Get_Name_String (Unit.Name));
2060 if Unit.File_Names (Specification).Name /= No_File then
2061 if Unit.File_Names (Specification).Project = No_Project then
2062 Write_Line (" No project");
2065 Write_Str (" Project: ");
2067 (In_Tree.Projects.Table
2068 (Unit.File_Names (Specification).Project).Path_Name);
2069 Write_Line (Name_Buffer (1 .. Name_Len));
2072 Write_Str (" spec: ");
2074 (Namet.Get_Name_String
2075 (Unit.File_Names (Specification).Name));
2078 if Unit.File_Names (Body_Part).Name /= No_File then
2079 if Unit.File_Names (Body_Part).Project = No_Project then
2080 Write_Line (" No project");
2083 Write_Str (" Project: ");
2085 (In_Tree.Projects.Table
2086 (Unit.File_Names (Body_Part).Project).Path_Name);
2087 Write_Line (Name_Buffer (1 .. Name_Len));
2090 Write_Str (" body: ");
2092 (Namet.Get_Name_String
2093 (Unit.File_Names (Body_Part).Name));
2097 Write_Line ("end of List of Sources.");
2106 Main_Project : Project_Id;
2107 In_Tree : Project_Tree_Ref) return Project_Id
2109 Result : Project_Id := No_Project;
2111 Original_Name : String := Name;
2113 Data : constant Project_Data :=
2114 In_Tree.Projects.Table (Main_Project);
2116 Extended_Spec_Name : String :=
2118 Spec_Suffix_Of (In_Tree, "ada", Data.Naming);
2119 Extended_Body_Name : String :=
2121 Body_Suffix_Of (In_Tree, "ada", Data.Naming);
2125 Current_Name : File_Name_Type;
2126 The_Original_Name : File_Name_Type;
2127 The_Spec_Name : File_Name_Type;
2128 The_Body_Name : File_Name_Type;
2131 Canonical_Case_File_Name (Original_Name);
2132 Name_Len := Original_Name'Length;
2133 Name_Buffer (1 .. Name_Len) := Original_Name;
2134 The_Original_Name := Name_Find;
2136 Canonical_Case_File_Name (Extended_Spec_Name);
2137 Name_Len := Extended_Spec_Name'Length;
2138 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
2139 The_Spec_Name := Name_Find;
2141 Canonical_Case_File_Name (Extended_Body_Name);
2142 Name_Len := Extended_Body_Name'Length;
2143 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
2144 The_Body_Name := Name_Find;
2146 for Current in reverse Unit_Table.First ..
2147 Unit_Table.Last (In_Tree.Units)
2149 Unit := In_Tree.Units.Table (Current);
2153 Current_Name := Unit.File_Names (Body_Part).Name;
2155 -- Case of a body present
2157 if Current_Name /= No_File then
2159 -- If it has the name of the original name or the body name,
2160 -- we have found the project.
2162 if Unit.Name = Name_Id (The_Original_Name)
2163 or else Current_Name = The_Original_Name
2164 or else Current_Name = The_Body_Name
2166 Result := Unit.File_Names (Body_Part).Project;
2173 Current_Name := Unit.File_Names (Specification).Name;
2175 if Current_Name /= No_File then
2177 -- If name same as the original name, or the spec name, we have
2178 -- found the project.
2180 if Unit.Name = Name_Id (The_Original_Name)
2181 or else Current_Name = The_Original_Name
2182 or else Current_Name = The_Spec_Name
2184 Result := Unit.File_Names (Specification).Project;
2190 -- Get the ultimate extending project
2192 if Result /= No_Project then
2193 while In_Tree.Projects.Table (Result).Extended_By /=
2196 Result := In_Tree.Projects.Table (Result).Extended_By;
2207 procedure Set_Ada_Paths
2208 (Project : Project_Id;
2209 In_Tree : Project_Tree_Ref;
2210 Including_Libraries : Boolean)
2212 Source_FD : File_Descriptor := Invalid_FD;
2213 Object_FD : File_Descriptor := Invalid_FD;
2215 Process_Source_Dirs : Boolean := False;
2216 Process_Object_Dirs : Boolean := False;
2219 -- For calls to Close
2223 procedure Add (Proj : Project_Id);
2224 -- Add all the source/object directories of a project to the path only
2225 -- if this project has not been visited. Calls an internal procedure
2226 -- recursively for projects being extended, and imported projects.
2232 procedure Add (Proj : Project_Id) is
2234 procedure Recursive_Add (Project : Project_Id);
2235 -- Recursive procedure to add the source/object paths of extended/
2236 -- imported projects.
2242 procedure Recursive_Add (Project : Project_Id) is
2244 -- If Seen is False, then the project has not yet been visited
2246 if not In_Tree.Projects.Table (Project).Seen then
2247 In_Tree.Projects.Table (Project).Seen := True;
2250 Data : constant Project_Data :=
2251 In_Tree.Projects.Table (Project);
2252 List : Project_List := Data.Imported_Projects;
2255 if Process_Source_Dirs then
2257 -- Add to path all source directories of this project if
2258 -- there are Ada sources.
2260 if In_Tree.Projects.Table (Project).Ada_Sources /=
2263 Add_To_Source_Path (Data.Source_Dirs, In_Tree);
2267 if Process_Object_Dirs then
2269 -- Add to path the object directory of this project
2270 -- except if we don't include library project and this
2271 -- is a library project.
2273 if (Data.Library and then Including_Libraries)
2275 (Data.Object_Directory /= No_Path
2277 (not Including_Libraries or else not Data.Library))
2279 -- For a library project, add the library ALI
2280 -- directory if there is no object directory or
2281 -- if the library ALI directory contains ALI files;
2282 -- otherwise add the object directory.
2284 if Data.Library then
2285 if Data.Object_Directory = No_Path
2286 or else Contains_ALI_Files (Data.Library_ALI_Dir)
2289 (Data.Library_ALI_Dir, In_Tree);
2292 (Data.Object_Directory, In_Tree);
2295 -- For a non-library project, add the object
2296 -- directory, if it is not a virtual project, and if
2297 -- there are Ada sources or if the project is an
2298 -- extending project. if There Are No Ada sources,
2299 -- adding the object directory could disrupt the order
2300 -- of the object dirs in the path.
2302 elsif not Data.Virtual
2303 and then There_Are_Ada_Sources (In_Tree, Project)
2306 (Data.Object_Directory, In_Tree);
2311 -- Call Add to the project being extended, if any
2313 if Data.Extends /= No_Project then
2314 Recursive_Add (Data.Extends);
2317 -- Call Add for each imported project, if any
2319 while List /= Empty_Project_List loop
2321 (In_Tree.Project_Lists.Table
2324 In_Tree.Project_Lists.Table (List).Next;
2331 Source_Path_Table.Set_Last (In_Tree.Private_Part.Source_Paths, 0);
2332 Object_Path_Table.Set_Last (In_Tree.Private_Part.Object_Paths, 0);
2334 for Index in Project_Table.First ..
2335 Project_Table.Last (In_Tree.Projects)
2337 In_Tree.Projects.Table (Index).Seen := False;
2340 Recursive_Add (Proj);
2343 -- Start of processing for Set_Ada_Paths
2346 -- If it is the first time we call this procedure for
2347 -- this project, compute the source path and/or the object path.
2349 if In_Tree.Projects.Table (Project).Include_Path_File = No_Path then
2350 Process_Source_Dirs := True;
2351 Create_New_Path_File
2352 (In_Tree, Source_FD,
2353 In_Tree.Projects.Table (Project).Include_Path_File);
2356 -- For the object path, we make a distinction depending on
2357 -- Including_Libraries.
2359 if Including_Libraries then
2360 if In_Tree.Projects.Table
2361 (Project).Objects_Path_File_With_Libs = No_Path
2363 Process_Object_Dirs := True;
2364 Create_New_Path_File
2365 (In_Tree, Object_FD, In_Tree.Projects.Table (Project).
2366 Objects_Path_File_With_Libs);
2370 if In_Tree.Projects.Table
2371 (Project).Objects_Path_File_Without_Libs = No_Path
2373 Process_Object_Dirs := True;
2374 Create_New_Path_File
2375 (In_Tree, Object_FD, In_Tree.Projects.Table (Project).
2376 Objects_Path_File_Without_Libs);
2380 -- If there is something to do, set Seen to False for all projects,
2381 -- then call the recursive procedure Add for Project.
2383 if Process_Source_Dirs or Process_Object_Dirs then
2387 -- Write and close any file that has been created
2389 if Source_FD /= Invalid_FD then
2390 for Index in Source_Path_Table.First ..
2391 Source_Path_Table.Last
2392 (In_Tree.Private_Part.Source_Paths)
2394 Get_Name_String (In_Tree.Private_Part.Source_Paths.Table (Index));
2395 Name_Len := Name_Len + 1;
2396 Name_Buffer (Name_Len) := ASCII.LF;
2397 Len := Write (Source_FD, Name_Buffer (1)'Address, Name_Len);
2399 if Len /= Name_Len then
2400 Prj.Com.Fail ("disk full");
2404 Close (Source_FD, Status);
2407 Prj.Com.Fail ("disk full");
2411 if Object_FD /= Invalid_FD then
2412 for Index in Object_Path_Table.First ..
2413 Object_Path_Table.Last
2414 (In_Tree.Private_Part.Object_Paths)
2416 Get_Name_String (In_Tree.Private_Part.Object_Paths.Table (Index));
2417 Name_Len := Name_Len + 1;
2418 Name_Buffer (Name_Len) := ASCII.LF;
2419 Len := Write (Object_FD, Name_Buffer (1)'Address, Name_Len);
2421 if Len /= Name_Len then
2422 Prj.Com.Fail ("disk full");
2426 Close (Object_FD, Status);
2429 Prj.Com.Fail ("disk full");
2433 -- Set the env vars, if they need to be changed, and set the
2434 -- corresponding flags.
2436 if Current_Source_Path_File /=
2437 In_Tree.Projects.Table (Project).Include_Path_File
2439 Current_Source_Path_File :=
2440 In_Tree.Projects.Table (Project).Include_Path_File;
2442 (Project_Include_Path_File,
2443 Get_Name_String (Current_Source_Path_File));
2444 Ada_Prj_Include_File_Set := True;
2447 if Including_Libraries then
2448 if Current_Object_Path_File
2449 /= In_Tree.Projects.Table
2450 (Project).Objects_Path_File_With_Libs
2452 Current_Object_Path_File :=
2453 In_Tree.Projects.Table
2454 (Project).Objects_Path_File_With_Libs;
2456 (Project_Objects_Path_File,
2457 Get_Name_String (Current_Object_Path_File));
2458 Ada_Prj_Objects_File_Set := True;
2462 if Current_Object_Path_File /=
2463 In_Tree.Projects.Table
2464 (Project).Objects_Path_File_Without_Libs
2466 Current_Object_Path_File :=
2467 In_Tree.Projects.Table
2468 (Project).Objects_Path_File_Without_Libs;
2470 (Project_Objects_Path_File,
2471 Get_Name_String (Current_Object_Path_File));
2472 Ada_Prj_Objects_File_Set := True;
2477 ---------------------------------------------
2478 -- Set_Mapping_File_Initial_State_To_Empty --
2479 ---------------------------------------------
2481 procedure Set_Mapping_File_Initial_State_To_Empty is
2483 Fill_Mapping_File := False;
2484 end Set_Mapping_File_Initial_State_To_Empty;
2486 -----------------------
2487 -- Set_Path_File_Var --
2488 -----------------------
2490 procedure Set_Path_File_Var (Name : String; Value : String) is
2491 Host_Spec : String_Access := To_Host_File_Spec (Value);
2494 if Host_Spec = null then
2496 ("could not convert file name """, Value, """ to host spec");
2498 Setenv (Name, Host_Spec.all);
2501 end Set_Path_File_Var;
2503 -----------------------
2504 -- Spec_Path_Name_Of --
2505 -----------------------
2507 function Spec_Path_Name_Of
2508 (Unit : Unit_Index; In_Tree : Project_Tree_Ref) return String
2510 Data : Unit_Data := In_Tree.Units.Table (Unit);
2513 if Data.File_Names (Specification).Path = No_Path then
2515 Current_Source : String_List_Id :=
2516 In_Tree.Projects.Table
2517 (Data.File_Names (Specification).Project).Ada_Sources;
2518 Path : GNAT.OS_Lib.String_Access;
2521 Data.File_Names (Specification).Path :=
2522 Path_Name_Type (Data.File_Names (Specification).Name);
2524 while Current_Source /= Nil_String loop
2525 Path := Locate_Regular_File
2526 (Namet.Get_Name_String
2527 (Data.File_Names (Specification).Name),
2528 Namet.Get_Name_String
2529 (In_Tree.String_Elements.Table
2530 (Current_Source).Value));
2532 if Path /= null then
2533 Name_Len := Path'Length;
2534 Name_Buffer (1 .. Name_Len) := Path.all;
2535 Data.File_Names (Specification).Path := Name_Enter;
2539 In_Tree.String_Elements.Table
2540 (Current_Source).Next;
2544 In_Tree.Units.Table (Unit) := Data;
2548 return Namet.Get_Name_String (Data.File_Names (Specification).Path);
2549 end Spec_Path_Name_Of;
2551 ---------------------------
2552 -- Ultimate_Extension_Of --
2553 ---------------------------
2555 function Ultimate_Extension_Of
2556 (Project : Project_Id;
2557 In_Tree : Project_Tree_Ref) return Project_Id
2559 Result : Project_Id := Project;
2562 while In_Tree.Projects.Table (Result).Extended_By /=
2565 Result := In_Tree.Projects.Table (Result).Extended_By;
2569 end Ultimate_Extension_Of;