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 2, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING. If not, write --
19 -- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
20 -- Boston, MA 02110-1301, USA. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
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 Current_Source_Path_File : Path_Name_Type := No_Path;
38 -- Current value of project source path file env var.
39 -- Used to avoid setting the env var to the same value.
41 Current_Object_Path_File : Path_Name_Type := No_Path;
42 -- Current value of project object path file env var.
43 -- Used to avoid setting the env var to the same value.
45 Ada_Path_Buffer : String_Access := new String (1 .. 1024);
46 -- A buffer where values for ADA_INCLUDE_PATH
47 -- and ADA_OBJECTS_PATH are stored.
49 Ada_Path_Length : Natural := 0;
50 -- Index of the last valid character in Ada_Path_Buffer
52 Ada_Prj_Include_File_Set : Boolean := False;
53 Ada_Prj_Objects_File_Set : Boolean := False;
54 -- These flags are set to True when the corresponding environment variables
55 -- are set and are used to give these environment variables an empty string
56 -- value at the end of the program. This has no practical effect on most
57 -- platforms, except on VMS where the logical names are deassigned, thus
58 -- avoiding the pollution of the environment of the caller.
60 Default_Naming : constant Naming_Id := Naming_Table.First;
62 Fill_Mapping_File : Boolean := True;
64 type Project_Flags is array (Project_Id range <>) of Boolean;
65 -- A Boolean array type used in Create_Mapping_File to select the projects
66 -- in the closure of a specific project.
68 -----------------------
69 -- Local Subprograms --
70 -----------------------
72 function Body_Path_Name_Of
74 In_Tree : Project_Tree_Ref) return String;
75 -- Returns the path name of the body of a unit.
76 -- Compute it first, if necessary.
78 function Spec_Path_Name_Of
80 In_Tree : Project_Tree_Ref) return String;
81 -- Returns the path name of the spec of a unit.
82 -- Compute it first, if necessary.
85 (Source_Dirs : String_List_Id;
86 In_Tree : Project_Tree_Ref);
87 -- Add to Ada_Path_Buffer all the source directories in string list
88 -- Source_Dirs, if any. Increment Ada_Path_Length.
90 procedure Add_To_Path (Dir : String);
91 -- If Dir is not already in the global variable Ada_Path_Buffer, add it.
92 -- Increment Ada_Path_Length.
93 -- If Ada_Path_Length /= 0, prepend a Path_Separator character to
96 procedure Add_To_Source_Path
97 (Source_Dirs : String_List_Id; In_Tree : Project_Tree_Ref);
98 -- Add to Ada_Path_B all the source directories in string list
99 -- Source_Dirs, if any. Increment Ada_Path_Length.
101 procedure Add_To_Object_Path
102 (Object_Dir : Path_Name_Type;
103 In_Tree : Project_Tree_Ref);
104 -- Add Object_Dir to object path table. Make sure it is not duplicate
105 -- and it is the last one in the current table.
107 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean;
108 -- Return True if there is at least one ALI file in the directory Dir
110 procedure Set_Path_File_Var (Name : String; Value : String);
111 -- Call Setenv, after calling To_Host_File_Spec
113 function Ultimate_Extension_Of
114 (Project : Project_Id;
115 In_Tree : Project_Tree_Ref) return Project_Id;
116 -- Return a project that is either Project or an extended ancestor of
117 -- Project that itself is not extended.
119 ----------------------
120 -- Ada_Include_Path --
121 ----------------------
123 function Ada_Include_Path
124 (Project : Project_Id;
125 In_Tree : Project_Tree_Ref) return String_Access is
127 procedure Add (Project : Project_Id);
128 -- Add all the source directories of a project to the path only if
129 -- this project has not been visited. Calls itself recursively for
130 -- projects being extended, and imported projects. Adds the project
131 -- to the list Seen if this is the call to Add for this project.
137 procedure Add (Project : Project_Id) is
139 -- If Seen is empty, then the project cannot have been visited
141 if not In_Tree.Projects.Table (Project).Seen then
142 In_Tree.Projects.Table (Project).Seen := True;
145 Data : constant Project_Data :=
146 In_Tree.Projects.Table (Project);
147 List : Project_List := Data.Imported_Projects;
150 -- Add to path all source directories of this project
152 Add_To_Path (Data.Source_Dirs, In_Tree);
154 -- Call Add to the project being extended, if any
156 if Data.Extends /= No_Project then
160 -- Call Add for each imported project, if any
162 while List /= Empty_Project_List loop
164 (In_Tree.Project_Lists.Table (List).Project);
165 List := In_Tree.Project_Lists.Table (List).Next;
171 -- Start of processing for Ada_Include_Path
174 -- If it is the first time we call this function for
175 -- this project, compute the source path
178 In_Tree.Projects.Table (Project).Ada_Include_Path = null
180 Ada_Path_Length := 0;
182 for Index in Project_Table.First ..
183 Project_Table.Last (In_Tree.Projects)
185 In_Tree.Projects.Table (Index).Seen := False;
189 In_Tree.Projects.Table (Project).Ada_Include_Path :=
190 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
193 return In_Tree.Projects.Table (Project).Ada_Include_Path;
194 end Ada_Include_Path;
196 ----------------------
197 -- Ada_Include_Path --
198 ----------------------
200 function Ada_Include_Path
201 (Project : Project_Id;
202 In_Tree : Project_Tree_Ref;
203 Recursive : Boolean) return String
207 return Ada_Include_Path (Project, In_Tree).all;
209 Ada_Path_Length := 0;
211 (In_Tree.Projects.Table (Project).Source_Dirs, In_Tree);
212 return Ada_Path_Buffer (1 .. Ada_Path_Length);
214 end Ada_Include_Path;
216 ----------------------
217 -- Ada_Objects_Path --
218 ----------------------
220 function Ada_Objects_Path
221 (Project : Project_Id;
222 In_Tree : Project_Tree_Ref;
223 Including_Libraries : Boolean := True) return String_Access
225 procedure Add (Project : Project_Id);
226 -- Add all the object directories of a project to the path only if
227 -- this project has not been visited. Calls itself recursively for
228 -- projects being extended, and imported projects. Adds the project
229 -- to the list Seen if this is the first call to Add for this project.
235 procedure Add (Project : Project_Id) is
237 -- If this project has not been seen yet
239 if not In_Tree.Projects.Table (Project).Seen then
240 In_Tree.Projects.Table (Project).Seen := True;
243 Data : constant Project_Data :=
244 In_Tree.Projects.Table (Project);
245 List : Project_List := Data.Imported_Projects;
248 -- Add to path the object directory of this project
249 -- except if we don't include library project and
250 -- this is a library project.
252 if (Data.Library and then Including_Libraries)
254 (Data.Object_Directory /= No_Path
256 (not Including_Libraries or else not Data.Library))
258 -- For a library project, add the library directory,
259 -- if there is no object directory or if it contains ALI
260 -- files; otherwise add the object directory.
263 if Data.Object_Directory = No_Path
265 Contains_ALI_Files (Data.Library_ALI_Dir)
267 Add_To_Path (Get_Name_String (Data.Library_ALI_Dir));
269 Add_To_Path (Get_Name_String (Data.Object_Directory));
273 -- For a non library project, add the object directory
275 Add_To_Path (Get_Name_String (Data.Object_Directory));
279 -- Call Add to the project being extended, if any
281 if Data.Extends /= No_Project then
285 -- Call Add for each imported project, if any
287 while List /= Empty_Project_List loop
289 (In_Tree.Project_Lists.Table (List).Project);
290 List := In_Tree.Project_Lists.Table (List).Next;
297 -- Start of processing for Ada_Objects_Path
300 -- If it is the first time we call this function for
301 -- this project, compute the objects path
304 In_Tree.Projects.Table (Project).Ada_Objects_Path = null
306 Ada_Path_Length := 0;
308 for Index in Project_Table.First ..
309 Project_Table.Last (In_Tree.Projects)
311 In_Tree.Projects.Table (Index).Seen := False;
315 In_Tree.Projects.Table (Project).Ada_Objects_Path :=
316 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
319 return In_Tree.Projects.Table (Project).Ada_Objects_Path;
320 end Ada_Objects_Path;
322 ------------------------
323 -- Add_To_Object_Path --
324 ------------------------
326 procedure Add_To_Object_Path
327 (Object_Dir : Path_Name_Type; In_Tree : Project_Tree_Ref)
330 -- Check if the directory is already in the table
332 for Index in Object_Path_Table.First ..
333 Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)
336 -- If it is, remove it, and add it as the last one
338 if In_Tree.Private_Part.Object_Paths.Table (Index) = Object_Dir then
339 for Index2 in Index + 1 ..
340 Object_Path_Table.Last
341 (In_Tree.Private_Part.Object_Paths)
343 In_Tree.Private_Part.Object_Paths.Table (Index2 - 1) :=
344 In_Tree.Private_Part.Object_Paths.Table (Index2);
347 In_Tree.Private_Part.Object_Paths.Table
348 (Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)) :=
354 -- The directory is not already in the table, add it
356 Object_Path_Table.Increment_Last (In_Tree.Private_Part.Object_Paths);
357 In_Tree.Private_Part.Object_Paths.Table
358 (Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)) :=
360 end Add_To_Object_Path;
366 procedure Add_To_Path
367 (Source_Dirs : String_List_Id;
368 In_Tree : Project_Tree_Ref)
370 Current : String_List_Id := Source_Dirs;
371 Source_Dir : String_Element;
373 while Current /= Nil_String loop
374 Source_Dir := In_Tree.String_Elements.Table (Current);
375 Add_To_Path (Get_Name_String (Source_Dir.Display_Value));
376 Current := Source_Dir.Next;
380 procedure Add_To_Path (Dir : String) is
382 New_Buffer : String_Access;
385 function Is_Present (Path : String; Dir : String) return Boolean;
386 -- Return True if Dir is part of Path
392 function Is_Present (Path : String; Dir : String) return Boolean is
393 Last : constant Integer := Path'Last - Dir'Length + 1;
396 for J in Path'First .. Last loop
398 -- Note: the order of the conditions below is important, since
399 -- it ensures a minimal number of string comparisons.
402 or else Path (J - 1) = Path_Separator)
404 (J + Dir'Length > Path'Last
405 or else Path (J + Dir'Length) = Path_Separator)
406 and then Dir = Path (J .. J + Dir'Length - 1)
415 -- Start of processing for Add_To_Path
418 if Is_Present (Ada_Path_Buffer (1 .. Ada_Path_Length), Dir) then
420 -- Dir is already in the path, nothing to do
425 Min_Len := Ada_Path_Length + Dir'Length;
427 if Ada_Path_Length > 0 then
429 -- Add 1 for the Path_Separator character
431 Min_Len := Min_Len + 1;
434 -- If Ada_Path_Buffer is too small, increase it
436 Len := Ada_Path_Buffer'Last;
438 if Len < Min_Len then
441 exit when Len >= Min_Len;
444 New_Buffer := new String (1 .. Len);
445 New_Buffer (1 .. Ada_Path_Length) :=
446 Ada_Path_Buffer (1 .. Ada_Path_Length);
447 Free (Ada_Path_Buffer);
448 Ada_Path_Buffer := New_Buffer;
451 if Ada_Path_Length > 0 then
452 Ada_Path_Length := Ada_Path_Length + 1;
453 Ada_Path_Buffer (Ada_Path_Length) := Path_Separator;
457 (Ada_Path_Length + 1 .. Ada_Path_Length + Dir'Length) := Dir;
458 Ada_Path_Length := Ada_Path_Length + Dir'Length;
461 ------------------------
462 -- Add_To_Source_Path --
463 ------------------------
465 procedure Add_To_Source_Path
466 (Source_Dirs : String_List_Id; In_Tree : Project_Tree_Ref)
468 Current : String_List_Id := Source_Dirs;
469 Source_Dir : String_Element;
473 -- Add each source directory
475 while Current /= Nil_String loop
476 Source_Dir := In_Tree.String_Elements.Table (Current);
479 -- Check if the source directory is already in the table
481 for Index in Source_Path_Table.First ..
482 Source_Path_Table.Last
483 (In_Tree.Private_Part.Source_Paths)
485 -- If it is already, no need to add it
487 if In_Tree.Private_Part.Source_Paths.Table (Index) =
496 Source_Path_Table.Increment_Last
497 (In_Tree.Private_Part.Source_Paths);
498 In_Tree.Private_Part.Source_Paths.Table
499 (Source_Path_Table.Last (In_Tree.Private_Part.Source_Paths)) :=
503 -- Next source directory
505 Current := Source_Dir.Next;
507 end Add_To_Source_Path;
509 -----------------------
510 -- Body_Path_Name_Of --
511 -----------------------
513 function Body_Path_Name_Of
515 In_Tree : Project_Tree_Ref) return String
517 Data : Unit_Data := In_Tree.Units.Table (Unit);
520 -- If we don't know the path name of the body of this unit,
521 -- we compute it, and we store it.
523 if Data.File_Names (Body_Part).Path = No_Path then
525 Current_Source : String_List_Id :=
526 In_Tree.Projects.Table
527 (Data.File_Names (Body_Part).Project).Ada_Sources;
528 Path : GNAT.OS_Lib.String_Access;
531 -- By default, put the file name
533 Data.File_Names (Body_Part).Path :=
534 Path_Name_Type (Data.File_Names (Body_Part).Name);
536 -- For each source directory
538 while Current_Source /= Nil_String loop
541 (Namet.Get_Name_String
542 (Data.File_Names (Body_Part).Name),
543 Namet.Get_Name_String
544 (In_Tree.String_Elements.Table
545 (Current_Source).Value));
547 -- If the file is in this directory, then we store the path,
551 Name_Len := Path'Length;
552 Name_Buffer (1 .. Name_Len) := Path.all;
553 Data.File_Names (Body_Part).Path := Name_Enter;
558 In_Tree.String_Elements.Table
559 (Current_Source).Next;
563 In_Tree.Units.Table (Unit) := Data;
567 -- Returned the stored value
569 return Namet.Get_Name_String (Data.File_Names (Body_Part).Path);
570 end Body_Path_Name_Of;
572 ------------------------
573 -- Contains_ALI_Files --
574 ------------------------
576 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean is
577 Dir_Name : constant String := Get_Name_String (Dir);
579 Name : String (1 .. 1_000);
581 Result : Boolean := False;
584 Open (Direct, Dir_Name);
586 -- For each file in the directory, check if it is an ALI file
589 Read (Direct, Name, Last);
591 Canonical_Case_File_Name (Name (1 .. Last));
592 Result := Last >= 5 and then Name (Last - 3 .. Last) = ".ali";
600 -- If there is any problem, close the directory if open and return
601 -- True; the library directory will be added to the path.
604 if Is_Open (Direct) then
609 end Contains_ALI_Files;
611 --------------------------------
612 -- Create_Config_Pragmas_File --
613 --------------------------------
615 procedure Create_Config_Pragmas_File
616 (For_Project : Project_Id;
617 Main_Project : Project_Id;
618 In_Tree : Project_Tree_Ref;
619 Include_Config_Files : Boolean := True)
621 pragma Unreferenced (Main_Project);
622 pragma Unreferenced (Include_Config_Files);
624 File_Name : Path_Name_Type := No_Path;
625 File : File_Descriptor := Invalid_FD;
627 Current_Unit : Unit_Index := Unit_Table.First;
629 First_Project : Project_List := Empty_Project_List;
631 Current_Project : Project_List;
632 Current_Naming : Naming_Id;
637 procedure Check (Project : Project_Id);
638 -- Recursive procedure that put in the config pragmas file any non
639 -- standard naming schemes, if it is not already in the file, then call
640 -- itself for any imported project.
642 procedure Check_Temp_File;
643 -- Check that a temporary file has been opened.
644 -- If not, create one, and put its name in the project data,
645 -- with the indication that it is a temporary file.
648 (Unit_Name : Name_Id;
649 File_Name : File_Name_Type;
650 Unit_Kind : Spec_Or_Body;
652 -- Put an SFN pragma in the temporary file
654 procedure Put (File : File_Descriptor; S : String);
655 procedure Put_Line (File : File_Descriptor; S : String);
656 -- Output procedures, analogous to normal Text_IO procs of same name
662 procedure Check (Project : Project_Id) is
663 Data : constant Project_Data :=
664 In_Tree.Projects.Table (Project);
667 if Current_Verbosity = High then
668 Write_Str ("Checking project file """);
669 Write_Str (Namet.Get_Name_String (Data.Name));
674 -- Is this project in the list of the visited project?
676 Current_Project := First_Project;
677 while Current_Project /= Empty_Project_List
678 and then In_Tree.Project_Lists.Table
679 (Current_Project).Project /= Project
682 In_Tree.Project_Lists.Table (Current_Project).Next;
685 -- If it is not, put it in the list, and visit it
687 if Current_Project = Empty_Project_List then
688 Project_List_Table.Increment_Last
689 (In_Tree.Project_Lists);
690 In_Tree.Project_Lists.Table
691 (Project_List_Table.Last (In_Tree.Project_Lists)) :=
692 (Project => Project, Next => First_Project);
694 Project_List_Table.Last (In_Tree.Project_Lists);
696 -- Is the naming scheme of this project one that we know?
698 Current_Naming := Default_Naming;
699 while Current_Naming <=
700 Naming_Table.Last (In_Tree.Private_Part.Namings)
701 and then not Same_Naming_Scheme
702 (Left => In_Tree.Private_Part.Namings.Table (Current_Naming),
703 Right => Data.Naming) loop
704 Current_Naming := Current_Naming + 1;
707 -- If we don't know it, add it
710 Naming_Table.Last (In_Tree.Private_Part.Namings)
712 Naming_Table.Increment_Last (In_Tree.Private_Part.Namings);
713 In_Tree.Private_Part.Namings.Table
714 (Naming_Table.Last (In_Tree.Private_Part.Namings)) :=
717 -- We need a temporary file to be created
721 -- Put the SFN pragmas for the naming scheme
726 (File, "pragma Source_File_Name_Project");
728 (File, " (Spec_File_Name => ""*" &
729 Spec_Suffix_Of (In_Tree, "ada", Data.Naming) &
732 (File, " Casing => " &
733 Image (Data.Naming.Casing) & ",");
735 (File, " Dot_Replacement => """ &
736 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
742 (File, "pragma Source_File_Name_Project");
744 (File, " (Body_File_Name => ""*" &
745 Body_Suffix_Of (In_Tree, "ada", Data.Naming) &
748 (File, " Casing => " &
749 Image (Data.Naming.Casing) & ",");
751 (File, " Dot_Replacement => """ &
752 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
755 -- and maybe separate
757 if Body_Suffix_Of (In_Tree, "ada", Data.Naming) /=
758 Get_Name_String (Data.Naming.Separate_Suffix)
761 (File, "pragma Source_File_Name_Project");
763 (File, " (Subunit_File_Name => ""*" &
764 Namet.Get_Name_String (Data.Naming.Separate_Suffix) &
767 (File, " Casing => " &
768 Image (Data.Naming.Casing) &
771 (File, " Dot_Replacement => """ &
772 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
777 if Data.Extends /= No_Project then
778 Check (Data.Extends);
782 Current : Project_List := Data.Imported_Projects;
785 while Current /= Empty_Project_List loop
787 (In_Tree.Project_Lists.Table
789 Current := In_Tree.Project_Lists.Table
796 ---------------------
797 -- Check_Temp_File --
798 ---------------------
800 procedure Check_Temp_File is
802 if File = Invalid_FD then
803 Tempdir.Create_Temp_File (File, Name => File_Name);
805 if File = Invalid_FD then
807 ("unable to create temporary configuration pragmas file");
810 Record_Temp_File (File_Name);
812 if Opt.Verbose_Mode then
813 Write_Str ("Creating temp file """);
814 Write_Str (Get_Name_String (File_Name));
826 (Unit_Name : Name_Id;
827 File_Name : File_Name_Type;
828 Unit_Kind : Spec_Or_Body;
832 -- A temporary file needs to be open
836 -- Put the pragma SFN for the unit kind (spec or body)
838 Put (File, "pragma Source_File_Name_Project (");
839 Put (File, Namet.Get_Name_String (Unit_Name));
841 if Unit_Kind = Specification then
842 Put (File, ", Spec_File_Name => """);
844 Put (File, ", Body_File_Name => """);
847 Put (File, Namet.Get_Name_String (File_Name));
851 Put (File, ", Index =>");
852 Put (File, Index'Img);
855 Put_Line (File, ");");
858 procedure Put (File : File_Descriptor; S : String) is
862 Last := Write (File, S (S'First)'Address, S'Length);
864 if Last /= S'Length then
865 Prj.Com.Fail ("Disk full");
868 if Current_Verbosity = High then
877 procedure Put_Line (File : File_Descriptor; S : String) is
878 S0 : String (1 .. S'Length + 1);
882 -- Add an ASCII.LF to the string. As this config file is supposed to
883 -- be used only by the compiler, we don't care about the characters
884 -- for the end of line. In fact we could have put a space, but
885 -- it is more convenient to be able to read gnat.adc during
886 -- development, for which the ASCII.LF is fine.
888 S0 (1 .. S'Length) := S;
889 S0 (S0'Last) := ASCII.LF;
890 Last := Write (File, S0'Address, S0'Length);
892 if Last /= S'Length + 1 then
893 Prj.Com.Fail ("Disk full");
896 if Current_Verbosity = High then
901 -- Start of processing for Create_Config_Pragmas_File
905 In_Tree.Projects.Table (For_Project).Config_Checked
908 -- Remove any memory of processed naming schemes, if any
910 Naming_Table.Set_Last (In_Tree.Private_Part.Namings, Default_Naming);
912 -- Check the naming schemes
916 -- Visit all the units and process those that need an SFN pragma
919 Current_Unit <= Unit_Table.Last (In_Tree.Units)
922 Unit : constant Unit_Data :=
923 In_Tree.Units.Table (Current_Unit);
926 if Unit.File_Names (Specification).Needs_Pragma then
928 Unit.File_Names (Specification).Name,
930 Unit.File_Names (Specification).Index);
933 if Unit.File_Names (Body_Part).Needs_Pragma then
935 Unit.File_Names (Body_Part).Name,
937 Unit.File_Names (Body_Part).Index);
940 Current_Unit := Current_Unit + 1;
944 -- If there are no non standard naming scheme, issue the GNAT
945 -- standard naming scheme. This will tell the compiler that
946 -- a project file is used and will forbid any pragma SFN.
948 if File = Invalid_FD then
951 Put_Line (File, "pragma Source_File_Name_Project");
952 Put_Line (File, " (Spec_File_Name => ""*.ads"",");
953 Put_Line (File, " Dot_Replacement => ""-"",");
954 Put_Line (File, " Casing => lowercase);");
956 Put_Line (File, "pragma Source_File_Name_Project");
957 Put_Line (File, " (Body_File_Name => ""*.adb"",");
958 Put_Line (File, " Dot_Replacement => ""-"",");
959 Put_Line (File, " Casing => lowercase);");
962 -- Close the temporary file
964 GNAT.OS_Lib.Close (File, Status);
967 Prj.Com.Fail ("disk full");
970 if Opt.Verbose_Mode then
971 Write_Str ("Closing configuration file """);
972 Write_Str (Get_Name_String (File_Name));
976 In_Tree.Projects.Table (For_Project).Config_File_Name :=
978 In_Tree.Projects.Table (For_Project).Config_File_Temp :=
981 In_Tree.Projects.Table (For_Project).Config_Checked :=
984 end Create_Config_Pragmas_File;
986 -------------------------
987 -- Create_Mapping_File --
988 -------------------------
990 procedure Create_Mapping_File
991 (Project : Project_Id;
992 In_Tree : Project_Tree_Ref;
993 Name : out Path_Name_Type)
995 File : File_Descriptor := Invalid_FD;
996 The_Unit_Data : Unit_Data;
997 Data : File_Name_Data;
1000 -- For call to Close
1002 Present : Project_Flags
1003 (No_Project .. Project_Table.Last (In_Tree.Projects)) :=
1005 -- For each project in the closure of Project, the corresponding flag
1006 -- will be set to True;
1008 procedure Put_Name_Buffer;
1009 -- Put the line contained in the Name_Buffer in the mapping file
1011 procedure Put_Data (Spec : Boolean);
1012 -- Put the mapping of the spec or body contained in Data in the file
1015 procedure Recursive_Flag (Prj : Project_Id);
1016 -- Set the flags corresponding to Prj, the projects it imports
1017 -- (directly or indirectly) or extends to True. Call itself recursively.
1023 procedure Put_Name_Buffer is
1027 Name_Len := Name_Len + 1;
1028 Name_Buffer (Name_Len) := ASCII.LF;
1029 Last := Write (File, Name_Buffer (1)'Address, Name_Len);
1031 if Last /= Name_Len then
1032 Prj.Com.Fail ("Disk full");
1034 end Put_Name_Buffer;
1040 procedure Put_Data (Spec : Boolean) is
1042 -- Line with the unit name
1044 Get_Name_String (The_Unit_Data.Name);
1045 Name_Len := Name_Len + 1;
1046 Name_Buffer (Name_Len) := '%';
1047 Name_Len := Name_Len + 1;
1050 Name_Buffer (Name_Len) := 's';
1052 Name_Buffer (Name_Len) := 'b';
1057 -- Line with the file name
1059 Get_Name_String (Data.Name);
1062 -- Line with the path name
1064 Get_Name_String (Data.Path);
1069 --------------------
1070 -- Recursive_Flag --
1071 --------------------
1073 procedure Recursive_Flag (Prj : Project_Id) is
1074 Imported : Project_List;
1078 -- Nothing to do for non existent project or project that has
1079 -- already been flagged.
1081 if Prj = No_Project or else Present (Prj) then
1085 -- Flag the current project
1087 Present (Prj) := True;
1089 In_Tree.Projects.Table (Prj).Imported_Projects;
1091 -- Call itself for each project directly imported
1093 while Imported /= Empty_Project_List loop
1095 In_Tree.Project_Lists.Table (Imported).Project;
1097 In_Tree.Project_Lists.Table (Imported).Next;
1098 Recursive_Flag (Proj);
1101 -- Call itself for an eventual project being extended
1103 Recursive_Flag (In_Tree.Projects.Table (Prj).Extends);
1106 -- Start of processing for Create_Mapping_File
1109 -- Flag the necessary projects
1111 Recursive_Flag (Project);
1113 -- Create the temporary file
1115 Tempdir.Create_Temp_File (File, Name => Name);
1117 if File = Invalid_FD then
1118 Prj.Com.Fail ("unable to create temporary mapping file");
1121 Record_Temp_File (Name);
1123 if Opt.Verbose_Mode then
1124 Write_Str ("Creating temp mapping file """);
1125 Write_Str (Get_Name_String (Name));
1130 if Fill_Mapping_File then
1132 -- For all units in table Units
1134 for Unit in 1 .. Unit_Table.Last (In_Tree.Units) loop
1135 The_Unit_Data := In_Tree.Units.Table (Unit);
1137 -- If the unit has a valid name
1139 if The_Unit_Data.Name /= No_Name then
1140 Data := The_Unit_Data.File_Names (Specification);
1142 -- If there is a spec, put it mapping in the file if it is
1143 -- from a project in the closure of Project.
1145 if Data.Name /= No_File and then Present (Data.Project) then
1146 Put_Data (Spec => True);
1149 Data := The_Unit_Data.File_Names (Body_Part);
1151 -- If there is a body (or subunit) put its mapping in the file
1152 -- if it is from a project in the closure of Project.
1154 if Data.Name /= No_File and then Present (Data.Project) then
1155 Put_Data (Spec => False);
1162 GNAT.OS_Lib.Close (File, Status);
1165 Prj.Com.Fail ("disk full");
1167 end Create_Mapping_File;
1169 procedure Create_Mapping_File
1170 (Project : Project_Id;
1172 Runtime : Project_Id;
1173 In_Tree : Project_Tree_Ref;
1174 Name : out Path_Name_Type)
1176 File : File_Descriptor := Invalid_FD;
1179 -- For call to Close
1181 Present : Project_Flags
1182 (No_Project .. Project_Table.Last (In_Tree.Projects)) :=
1184 -- For each project in the closure of Project, the corresponding flag
1185 -- will be set to True.
1188 Src_Data : Source_Data;
1189 Suffix : File_Name_Type;
1191 procedure Put_Name_Buffer;
1192 -- Put the line contained in the Name_Buffer in the mapping file
1194 procedure Recursive_Flag (Prj : Project_Id);
1195 -- Set the flags corresponding to Prj, the projects it imports
1196 -- (directly or indirectly) or extends to True. Call itself recursively.
1202 procedure Put_Name_Buffer is
1206 Name_Len := Name_Len + 1;
1207 Name_Buffer (Name_Len) := ASCII.LF;
1208 Last := Write (File, Name_Buffer (1)'Address, Name_Len);
1210 if Last /= Name_Len then
1211 Prj.Com.Fail ("Disk full");
1213 end Put_Name_Buffer;
1215 --------------------
1216 -- Recursive_Flag --
1217 --------------------
1219 procedure Recursive_Flag (Prj : Project_Id) is
1220 Imported : Project_List;
1224 -- Nothing to do for non existent or runtime project or project
1225 -- that has already been flagged.
1227 if Prj = No_Project or else Prj = Runtime or else Present (Prj) then
1231 -- Flag the current project
1233 Present (Prj) := True;
1235 In_Tree.Projects.Table (Prj).Imported_Projects;
1237 -- Call itself for each project directly imported
1239 while Imported /= Empty_Project_List loop
1241 In_Tree.Project_Lists.Table (Imported).Project;
1243 In_Tree.Project_Lists.Table (Imported).Next;
1244 Recursive_Flag (Proj);
1247 -- Call itself for an eventual project being extended
1249 Recursive_Flag (In_Tree.Projects.Table (Prj).Extends);
1252 -- Start of processing for Create_Mapping_File
1255 -- Flag the necessary projects
1257 Recursive_Flag (Project);
1259 -- Create the temporary file
1261 Tempdir.Create_Temp_File (File, Name => Name);
1263 if File = Invalid_FD then
1264 Prj.Com.Fail ("unable to create temporary mapping file");
1267 Record_Temp_File (Name);
1269 if Opt.Verbose_Mode then
1270 Write_Str ("Creating temp mapping file """);
1271 Write_Str (Get_Name_String (Name));
1276 -- For all source of the Language of all projects in the closure
1278 for Proj in Present'Range loop
1279 if Present (Proj) then
1280 Source := In_Tree.Projects.Table (Proj).First_Source;
1282 while Source /= No_Source loop
1283 Src_Data := In_Tree.Sources.Table (Source);
1285 if Src_Data.Language_Name = Language and then
1286 (not Src_Data.Locally_Removed) and then
1287 Src_Data.Replaced_By = No_Source
1289 if Src_Data.Unit /= No_Name then
1290 Get_Name_String (Src_Data.Unit);
1292 if Src_Data.Kind = Spec then
1293 Suffix := In_Tree.Languages_Data.Table
1294 (Src_Data.Language).Config.Mapping_Spec_Suffix;
1297 Suffix := In_Tree.Languages_Data.Table
1298 (Src_Data.Language).Config.Mapping_Body_Suffix;
1301 if Suffix /= No_File then
1302 Add_Str_To_Name_Buffer (Get_Name_String (Suffix));
1308 Get_Name_String (Src_Data.File);
1311 Get_Name_String (Src_Data.Path);
1315 Source := Src_Data.Next_In_Project;
1320 GNAT.OS_Lib.Close (File, Status);
1323 Prj.Com.Fail ("disk full");
1325 end Create_Mapping_File;
1327 --------------------------
1328 -- Create_New_Path_File --
1329 --------------------------
1331 procedure Create_New_Path_File
1332 (In_Tree : Project_Tree_Ref;
1333 Path_FD : out File_Descriptor;
1334 Path_Name : out Path_Name_Type)
1337 Tempdir.Create_Temp_File (Path_FD, Path_Name);
1339 if Path_Name /= No_Path then
1340 Record_Temp_File (Path_Name);
1342 -- Record the name, so that the temp path file will be deleted at the
1343 -- end of the program.
1345 Path_File_Table.Increment_Last (In_Tree.Private_Part.Path_Files);
1346 In_Tree.Private_Part.Path_Files.Table
1347 (Path_File_Table.Last (In_Tree.Private_Part.Path_Files)) :=
1350 end Create_New_Path_File;
1352 ---------------------------
1353 -- Delete_All_Path_Files --
1354 ---------------------------
1356 procedure Delete_All_Path_Files (In_Tree : Project_Tree_Ref) is
1357 Disregard : Boolean := True;
1360 for Index in Path_File_Table.First ..
1361 Path_File_Table.Last (In_Tree.Private_Part.Path_Files)
1363 if In_Tree.Private_Part.Path_Files.Table (Index) /= No_Path then
1366 (In_Tree.Private_Part.Path_Files.Table (Index)),
1371 -- If any of the environment variables ADA_PRJ_INCLUDE_FILE or
1372 -- ADA_PRJ_OBJECTS_FILE has been set, then reset their value to
1373 -- the empty string. On VMS, this has the effect of deassigning
1374 -- the logical names.
1376 if Ada_Prj_Include_File_Set then
1377 Setenv (Project_Include_Path_File, "");
1378 Ada_Prj_Include_File_Set := False;
1381 if Ada_Prj_Objects_File_Set then
1382 Setenv (Project_Objects_Path_File, "");
1383 Ada_Prj_Objects_File_Set := False;
1385 end Delete_All_Path_Files;
1387 ------------------------------------
1388 -- File_Name_Of_Library_Unit_Body --
1389 ------------------------------------
1391 function File_Name_Of_Library_Unit_Body
1393 Project : Project_Id;
1394 In_Tree : Project_Tree_Ref;
1395 Main_Project_Only : Boolean := True;
1396 Full_Path : Boolean := False) return String
1398 The_Project : Project_Id := Project;
1399 Data : Project_Data :=
1400 In_Tree.Projects.Table (Project);
1401 Original_Name : String := Name;
1403 Extended_Spec_Name : String :=
1405 Spec_Suffix_Of (In_Tree, "ada", Data.Naming);
1406 Extended_Body_Name : String :=
1408 Body_Suffix_Of (In_Tree, "ada", Data.Naming);
1412 The_Original_Name : Name_Id;
1413 The_Spec_Name : Name_Id;
1414 The_Body_Name : Name_Id;
1417 Canonical_Case_File_Name (Original_Name);
1418 Name_Len := Original_Name'Length;
1419 Name_Buffer (1 .. Name_Len) := Original_Name;
1420 The_Original_Name := Name_Find;
1422 Canonical_Case_File_Name (Extended_Spec_Name);
1423 Name_Len := Extended_Spec_Name'Length;
1424 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
1425 The_Spec_Name := Name_Find;
1427 Canonical_Case_File_Name (Extended_Body_Name);
1428 Name_Len := Extended_Body_Name'Length;
1429 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
1430 The_Body_Name := Name_Find;
1432 if Current_Verbosity = High then
1433 Write_Str ("Looking for file name of """);
1437 Write_Str (" Extended Spec Name = """);
1438 Write_Str (Extended_Spec_Name);
1441 Write_Str (" Extended Body Name = """);
1442 Write_Str (Extended_Body_Name);
1447 -- For extending project, search in the extended project if the source
1448 -- is not found. For non extending projects, this loop will be run only
1452 -- Loop through units
1453 -- Should have comment explaining reverse ???
1455 for Current in reverse Unit_Table.First ..
1456 Unit_Table.Last (In_Tree.Units)
1458 Unit := In_Tree.Units.Table (Current);
1462 if not Main_Project_Only
1463 or else Unit.File_Names (Body_Part).Project = The_Project
1466 Current_Name : constant File_Name_Type :=
1467 Unit.File_Names (Body_Part).Name;
1470 -- Case of a body present
1472 if Current_Name /= No_File then
1473 if Current_Verbosity = High then
1474 Write_Str (" Comparing with """);
1475 Write_Str (Get_Name_String (Current_Name));
1480 -- If it has the name of the original name, return the
1483 if Unit.Name = The_Original_Name
1485 Current_Name = File_Name_Type (The_Original_Name)
1487 if Current_Verbosity = High then
1492 return Get_Name_String
1493 (Unit.File_Names (Body_Part).Path);
1496 return Get_Name_String (Current_Name);
1499 -- If it has the name of the extended body name,
1500 -- return the extended body name
1502 elsif Current_Name = File_Name_Type (The_Body_Name) then
1503 if Current_Verbosity = High then
1508 return Get_Name_String
1509 (Unit.File_Names (Body_Part).Path);
1512 return Extended_Body_Name;
1516 if Current_Verbosity = High then
1517 Write_Line (" not good");
1526 if not Main_Project_Only
1527 or else Unit.File_Names (Specification).Project = The_Project
1530 Current_Name : constant File_Name_Type :=
1531 Unit.File_Names (Specification).Name;
1534 -- Case of spec present
1536 if Current_Name /= No_File then
1537 if Current_Verbosity = High then
1538 Write_Str (" Comparing with """);
1539 Write_Str (Get_Name_String (Current_Name));
1544 -- If name same as original name, return original name
1546 if Unit.Name = The_Original_Name
1548 Current_Name = File_Name_Type (The_Original_Name)
1550 if Current_Verbosity = High then
1555 return Get_Name_String
1556 (Unit.File_Names (Specification).Path);
1558 return Get_Name_String (Current_Name);
1561 -- If it has the same name as the extended spec name,
1562 -- return the extended spec name.
1564 elsif Current_Name = File_Name_Type (The_Spec_Name) then
1565 if Current_Verbosity = High then
1570 return Get_Name_String
1571 (Unit.File_Names (Specification).Path);
1573 return Extended_Spec_Name;
1577 if Current_Verbosity = High then
1578 Write_Line (" not good");
1586 -- If we are not in an extending project, give up
1588 exit when (not Main_Project_Only) or else Data.Extends = No_Project;
1590 -- Otherwise, look in the project we are extending
1592 The_Project := Data.Extends;
1593 Data := In_Tree.Projects.Table (The_Project);
1596 -- We don't know this file name, return an empty string
1599 end File_Name_Of_Library_Unit_Body;
1601 -------------------------
1602 -- For_All_Object_Dirs --
1603 -------------------------
1605 procedure For_All_Object_Dirs
1606 (Project : Project_Id;
1607 In_Tree : Project_Tree_Ref)
1609 Seen : Project_List := Empty_Project_List;
1611 procedure Add (Project : Project_Id);
1612 -- Process a project. Remember the processes visited to avoid processing
1613 -- a project twice. Recursively process an eventual extended project,
1614 -- and all imported projects.
1620 procedure Add (Project : Project_Id) is
1621 Data : constant Project_Data :=
1622 In_Tree.Projects.Table (Project);
1623 List : Project_List := Data.Imported_Projects;
1626 -- If the list of visited project is empty, then
1627 -- for sure we never visited this project.
1629 if Seen = Empty_Project_List then
1630 Project_List_Table.Increment_Last (In_Tree.Project_Lists);
1631 Seen := Project_List_Table.Last (In_Tree.Project_Lists);
1632 In_Tree.Project_Lists.Table (Seen) :=
1633 (Project => Project, Next => Empty_Project_List);
1636 -- Check if the project is in the list
1639 Current : Project_List := Seen;
1643 -- If it is, then there is nothing else to do
1645 if In_Tree.Project_Lists.Table
1646 (Current).Project = Project
1652 In_Tree.Project_Lists.Table (Current).Next =
1655 In_Tree.Project_Lists.Table (Current).Next;
1658 -- This project has never been visited, add it
1661 Project_List_Table.Increment_Last
1662 (In_Tree.Project_Lists);
1663 In_Tree.Project_Lists.Table (Current).Next :=
1664 Project_List_Table.Last (In_Tree.Project_Lists);
1665 In_Tree.Project_Lists.Table
1666 (Project_List_Table.Last
1667 (In_Tree.Project_Lists)) :=
1668 (Project => Project, Next => Empty_Project_List);
1672 -- If there is an object directory, call Action with its name
1674 if Data.Object_Directory /= No_Path then
1675 Get_Name_String (Data.Display_Object_Dir);
1676 Action (Name_Buffer (1 .. Name_Len));
1679 -- If we are extending a project, visit it
1681 if Data.Extends /= No_Project then
1685 -- And visit all imported projects
1687 while List /= Empty_Project_List loop
1688 Add (In_Tree.Project_Lists.Table (List).Project);
1689 List := In_Tree.Project_Lists.Table (List).Next;
1693 -- Start of processing for For_All_Object_Dirs
1696 -- Visit this project, and its imported projects, recursively
1699 end For_All_Object_Dirs;
1701 -------------------------
1702 -- For_All_Source_Dirs --
1703 -------------------------
1705 procedure For_All_Source_Dirs
1706 (Project : Project_Id;
1707 In_Tree : Project_Tree_Ref)
1709 Seen : Project_List := Empty_Project_List;
1711 procedure Add (Project : Project_Id);
1712 -- Process a project. Remember the processes visited to avoid processing
1713 -- a project twice. Recursively process an eventual extended project,
1714 -- and all imported projects.
1720 procedure Add (Project : Project_Id) is
1721 Data : constant Project_Data :=
1722 In_Tree.Projects.Table (Project);
1723 List : Project_List := Data.Imported_Projects;
1726 -- If the list of visited project is empty, then for sure we never
1727 -- visited this project.
1729 if Seen = Empty_Project_List then
1730 Project_List_Table.Increment_Last
1731 (In_Tree.Project_Lists);
1732 Seen := Project_List_Table.Last
1733 (In_Tree.Project_Lists);
1734 In_Tree.Project_Lists.Table (Seen) :=
1735 (Project => Project, Next => Empty_Project_List);
1738 -- Check if the project is in the list
1741 Current : Project_List := Seen;
1745 -- If it is, then there is nothing else to do
1747 if In_Tree.Project_Lists.Table
1748 (Current).Project = Project
1754 In_Tree.Project_Lists.Table (Current).Next =
1757 In_Tree.Project_Lists.Table (Current).Next;
1760 -- This project has never been visited, add it to the list
1762 Project_List_Table.Increment_Last
1763 (In_Tree.Project_Lists);
1764 In_Tree.Project_Lists.Table (Current).Next :=
1765 Project_List_Table.Last (In_Tree.Project_Lists);
1766 In_Tree.Project_Lists.Table
1767 (Project_List_Table.Last
1768 (In_Tree.Project_Lists)) :=
1769 (Project => Project, Next => Empty_Project_List);
1774 Current : String_List_Id := Data.Source_Dirs;
1775 The_String : String_Element;
1778 -- If there are Ada sources, call action with the name of every
1779 -- source directory.
1782 In_Tree.Projects.Table (Project).Ada_Sources /= Nil_String
1784 while Current /= Nil_String loop
1786 In_Tree.String_Elements.Table (Current);
1787 Action (Get_Name_String (The_String.Display_Value));
1788 Current := The_String.Next;
1793 -- If we are extending a project, visit it
1795 if Data.Extends /= No_Project then
1799 -- And visit all imported projects
1801 while List /= Empty_Project_List loop
1802 Add (In_Tree.Project_Lists.Table (List).Project);
1803 List := In_Tree.Project_Lists.Table (List).Next;
1807 -- Start of processing for For_All_Source_Dirs
1810 -- Visit this project, and its imported projects recursively
1813 end For_All_Source_Dirs;
1819 procedure Get_Reference
1820 (Source_File_Name : String;
1821 In_Tree : Project_Tree_Ref;
1822 Project : out Project_Id;
1823 Path : out Path_Name_Type)
1826 -- Body below could use some comments ???
1828 if Current_Verbosity > Default then
1829 Write_Str ("Getting Reference_Of (""");
1830 Write_Str (Source_File_Name);
1831 Write_Str (""") ... ");
1835 Original_Name : String := Source_File_Name;
1839 Canonical_Case_File_Name (Original_Name);
1841 for Id in Unit_Table.First ..
1842 Unit_Table.Last (In_Tree.Units)
1844 Unit := In_Tree.Units.Table (Id);
1846 if (Unit.File_Names (Specification).Name /= No_File
1848 Namet.Get_Name_String
1849 (Unit.File_Names (Specification).Name) = Original_Name)
1850 or else (Unit.File_Names (Specification).Path /= No_Path
1852 Namet.Get_Name_String
1853 (Unit.File_Names (Specification).Path) =
1856 Project := Ultimate_Extension_Of
1857 (Project => Unit.File_Names (Specification).Project,
1858 In_Tree => In_Tree);
1859 Path := Unit.File_Names (Specification).Display_Path;
1861 if Current_Verbosity > Default then
1862 Write_Str ("Done: Specification.");
1868 elsif (Unit.File_Names (Body_Part).Name /= No_File
1870 Namet.Get_Name_String
1871 (Unit.File_Names (Body_Part).Name) = Original_Name)
1872 or else (Unit.File_Names (Body_Part).Path /= No_Path
1873 and then Namet.Get_Name_String
1874 (Unit.File_Names (Body_Part).Path) =
1877 Project := Ultimate_Extension_Of
1878 (Project => Unit.File_Names (Body_Part).Project,
1879 In_Tree => In_Tree);
1880 Path := Unit.File_Names (Body_Part).Display_Path;
1882 if Current_Verbosity > Default then
1883 Write_Str ("Done: Body.");
1892 Project := No_Project;
1895 if Current_Verbosity > Default then
1896 Write_Str ("Cannot be found.");
1905 procedure Initialize is
1907 Fill_Mapping_File := True;
1910 ------------------------------------
1911 -- Path_Name_Of_Library_Unit_Body --
1912 ------------------------------------
1914 -- Could use some comments in the body here ???
1916 function Path_Name_Of_Library_Unit_Body
1918 Project : Project_Id;
1919 In_Tree : Project_Tree_Ref) return String
1921 Data : constant Project_Data :=
1922 In_Tree.Projects.Table (Project);
1923 Original_Name : String := Name;
1925 Extended_Spec_Name : String :=
1927 Spec_Suffix_Of (In_Tree, "ada", Data.Naming);
1928 Extended_Body_Name : String :=
1930 Body_Suffix_Of (In_Tree, "ada", Data.Naming);
1932 First : Unit_Index := Unit_Table.First;
1933 Current : Unit_Index;
1937 Canonical_Case_File_Name (Original_Name);
1938 Canonical_Case_File_Name (Extended_Spec_Name);
1939 Canonical_Case_File_Name (Extended_Body_Name);
1941 if Current_Verbosity = High then
1942 Write_Str ("Looking for path name of """);
1946 Write_Str (" Extended Spec Name = """);
1947 Write_Str (Extended_Spec_Name);
1950 Write_Str (" Extended Body Name = """);
1951 Write_Str (Extended_Body_Name);
1956 while First <= Unit_Table.Last (In_Tree.Units)
1957 and then In_Tree.Units.Table
1958 (First).File_Names (Body_Part).Project /= Project
1964 while Current <= Unit_Table.Last (In_Tree.Units) loop
1965 Unit := In_Tree.Units.Table (Current);
1967 if Unit.File_Names (Body_Part).Project = Project
1968 and then Unit.File_Names (Body_Part).Name /= No_File
1971 Current_Name : constant String :=
1972 Namet.Get_Name_String (Unit.File_Names (Body_Part).Name);
1974 if Current_Verbosity = High then
1975 Write_Str (" Comparing with """);
1976 Write_Str (Current_Name);
1981 if Current_Name = Original_Name then
1982 if Current_Verbosity = High then
1986 return Body_Path_Name_Of (Current, In_Tree);
1988 elsif Current_Name = Extended_Body_Name then
1989 if Current_Verbosity = High then
1993 return Body_Path_Name_Of (Current, In_Tree);
1996 if Current_Verbosity = High then
1997 Write_Line (" not good");
2002 elsif Unit.File_Names (Specification).Name /= No_File then
2004 Current_Name : constant String :=
2005 Namet.Get_Name_String
2006 (Unit.File_Names (Specification).Name);
2009 if Current_Verbosity = High then
2010 Write_Str (" Comparing with """);
2011 Write_Str (Current_Name);
2016 if Current_Name = Original_Name then
2017 if Current_Verbosity = High then
2021 return Spec_Path_Name_Of (Current, In_Tree);
2023 elsif Current_Name = Extended_Spec_Name then
2024 if Current_Verbosity = High then
2028 return Spec_Path_Name_Of (Current, In_Tree);
2031 if Current_Verbosity = High then
2032 Write_Line (" not good");
2037 Current := Current + 1;
2041 end Path_Name_Of_Library_Unit_Body;
2047 -- Could use some comments in this body ???
2049 procedure Print_Sources (In_Tree : Project_Tree_Ref) is
2053 Write_Line ("List of Sources:");
2055 for Id in Unit_Table.First ..
2056 Unit_Table.Last (In_Tree.Units)
2058 Unit := In_Tree.Units.Table (Id);
2060 Write_Line (Namet.Get_Name_String (Unit.Name));
2062 if Unit.File_Names (Specification).Name /= No_File then
2063 if Unit.File_Names (Specification).Project = No_Project then
2064 Write_Line (" No project");
2067 Write_Str (" Project: ");
2069 (In_Tree.Projects.Table
2070 (Unit.File_Names (Specification).Project).Path_Name);
2071 Write_Line (Name_Buffer (1 .. Name_Len));
2074 Write_Str (" spec: ");
2076 (Namet.Get_Name_String
2077 (Unit.File_Names (Specification).Name));
2080 if Unit.File_Names (Body_Part).Name /= No_File then
2081 if Unit.File_Names (Body_Part).Project = No_Project then
2082 Write_Line (" No project");
2085 Write_Str (" Project: ");
2087 (In_Tree.Projects.Table
2088 (Unit.File_Names (Body_Part).Project).Path_Name);
2089 Write_Line (Name_Buffer (1 .. Name_Len));
2092 Write_Str (" body: ");
2094 (Namet.Get_Name_String
2095 (Unit.File_Names (Body_Part).Name));
2099 Write_Line ("end of List of Sources.");
2108 Main_Project : Project_Id;
2109 In_Tree : Project_Tree_Ref) return Project_Id
2111 Result : Project_Id := No_Project;
2113 Original_Name : String := Name;
2115 Data : constant Project_Data :=
2116 In_Tree.Projects.Table (Main_Project);
2118 Extended_Spec_Name : String :=
2120 Spec_Suffix_Of (In_Tree, "ada", Data.Naming);
2121 Extended_Body_Name : String :=
2123 Body_Suffix_Of (In_Tree, "ada", Data.Naming);
2127 Current_Name : File_Name_Type;
2128 The_Original_Name : File_Name_Type;
2129 The_Spec_Name : File_Name_Type;
2130 The_Body_Name : File_Name_Type;
2133 Canonical_Case_File_Name (Original_Name);
2134 Name_Len := Original_Name'Length;
2135 Name_Buffer (1 .. Name_Len) := Original_Name;
2136 The_Original_Name := Name_Find;
2138 Canonical_Case_File_Name (Extended_Spec_Name);
2139 Name_Len := Extended_Spec_Name'Length;
2140 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
2141 The_Spec_Name := Name_Find;
2143 Canonical_Case_File_Name (Extended_Body_Name);
2144 Name_Len := Extended_Body_Name'Length;
2145 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
2146 The_Body_Name := Name_Find;
2148 for Current in reverse Unit_Table.First ..
2149 Unit_Table.Last (In_Tree.Units)
2151 Unit := In_Tree.Units.Table (Current);
2155 Current_Name := Unit.File_Names (Body_Part).Name;
2157 -- Case of a body present
2159 if Current_Name /= No_File then
2161 -- If it has the name of the original name or the body name,
2162 -- we have found the project.
2164 if Unit.Name = Name_Id (The_Original_Name)
2165 or else Current_Name = The_Original_Name
2166 or else Current_Name = The_Body_Name
2168 Result := Unit.File_Names (Body_Part).Project;
2175 Current_Name := Unit.File_Names (Specification).Name;
2177 if Current_Name /= No_File then
2179 -- If name same as the original name, or the spec name, we have
2180 -- found the project.
2182 if Unit.Name = Name_Id (The_Original_Name)
2183 or else Current_Name = The_Original_Name
2184 or else Current_Name = The_Spec_Name
2186 Result := Unit.File_Names (Specification).Project;
2192 -- Get the ultimate extending project
2194 if Result /= No_Project then
2195 while In_Tree.Projects.Table (Result).Extended_By /=
2198 Result := In_Tree.Projects.Table (Result).Extended_By;
2209 procedure Set_Ada_Paths
2210 (Project : Project_Id;
2211 In_Tree : Project_Tree_Ref;
2212 Including_Libraries : Boolean)
2214 Source_FD : File_Descriptor := Invalid_FD;
2215 Object_FD : File_Descriptor := Invalid_FD;
2217 Process_Source_Dirs : Boolean := False;
2218 Process_Object_Dirs : Boolean := False;
2221 -- For calls to Close
2225 procedure Add (Proj : Project_Id);
2226 -- Add all the source/object directories of a project to the path only
2227 -- if this project has not been visited. Calls an internal procedure
2228 -- recursively for projects being extended, and imported projects.
2234 procedure Add (Proj : Project_Id) is
2236 procedure Recursive_Add (Project : Project_Id);
2237 -- Recursive procedure to add the source/object paths of extended/
2238 -- imported projects.
2244 procedure Recursive_Add (Project : Project_Id) is
2246 -- If Seen is False, then the project has not yet been visited
2248 if not In_Tree.Projects.Table (Project).Seen then
2249 In_Tree.Projects.Table (Project).Seen := True;
2252 Data : constant Project_Data :=
2253 In_Tree.Projects.Table (Project);
2254 List : Project_List := Data.Imported_Projects;
2257 if Process_Source_Dirs then
2259 -- Add to path all source directories of this project if
2260 -- there are Ada sources.
2262 if In_Tree.Projects.Table (Project).Ada_Sources /=
2265 Add_To_Source_Path (Data.Source_Dirs, In_Tree);
2269 if Process_Object_Dirs then
2271 -- Add to path the object directory of this project
2272 -- except if we don't include library project and this
2273 -- is a library project.
2275 if (Data.Library and then Including_Libraries)
2277 (Data.Object_Directory /= No_Path
2279 (not Including_Libraries or else not Data.Library))
2281 -- For a library project, add the library ALI
2282 -- directory if there is no object directory or
2283 -- if the library ALI directory contains ALI files;
2284 -- otherwise add the object directory.
2286 if Data.Library then
2287 if Data.Object_Directory = No_Path
2288 or else Contains_ALI_Files (Data.Library_ALI_Dir)
2291 (Data.Library_ALI_Dir, In_Tree);
2294 (Data.Object_Directory, In_Tree);
2297 -- For a non-library project, add the object
2298 -- directory, if it is not a virtual project, and if
2299 -- there are Ada sources or if the project is an
2300 -- extending project. if There Are No Ada sources,
2301 -- adding the object directory could disrupt the order
2302 -- of the object dirs in the path.
2304 elsif not Data.Virtual
2305 and then There_Are_Ada_Sources (In_Tree, Project)
2308 (Data.Object_Directory, In_Tree);
2313 -- Call Add to the project being extended, if any
2315 if Data.Extends /= No_Project then
2316 Recursive_Add (Data.Extends);
2319 -- Call Add for each imported project, if any
2321 while List /= Empty_Project_List loop
2323 (In_Tree.Project_Lists.Table
2326 In_Tree.Project_Lists.Table (List).Next;
2333 Source_Path_Table.Set_Last (In_Tree.Private_Part.Source_Paths, 0);
2334 Object_Path_Table.Set_Last (In_Tree.Private_Part.Object_Paths, 0);
2336 for Index in Project_Table.First ..
2337 Project_Table.Last (In_Tree.Projects)
2339 In_Tree.Projects.Table (Index).Seen := False;
2342 Recursive_Add (Proj);
2345 -- Start of processing for Set_Ada_Paths
2348 -- If it is the first time we call this procedure for
2349 -- this project, compute the source path and/or the object path.
2351 if In_Tree.Projects.Table (Project).Include_Path_File = No_Path then
2352 Process_Source_Dirs := True;
2353 Create_New_Path_File
2354 (In_Tree, Source_FD,
2355 In_Tree.Projects.Table (Project).Include_Path_File);
2358 -- For the object path, we make a distinction depending on
2359 -- Including_Libraries.
2361 if Including_Libraries then
2362 if In_Tree.Projects.Table
2363 (Project).Objects_Path_File_With_Libs = No_Path
2365 Process_Object_Dirs := True;
2366 Create_New_Path_File
2367 (In_Tree, Object_FD, In_Tree.Projects.Table (Project).
2368 Objects_Path_File_With_Libs);
2372 if In_Tree.Projects.Table
2373 (Project).Objects_Path_File_Without_Libs = No_Path
2375 Process_Object_Dirs := True;
2376 Create_New_Path_File
2377 (In_Tree, Object_FD, In_Tree.Projects.Table (Project).
2378 Objects_Path_File_Without_Libs);
2382 -- If there is something to do, set Seen to False for all projects,
2383 -- then call the recursive procedure Add for Project.
2385 if Process_Source_Dirs or Process_Object_Dirs then
2389 -- Write and close any file that has been created
2391 if Source_FD /= Invalid_FD then
2392 for Index in Source_Path_Table.First ..
2393 Source_Path_Table.Last
2394 (In_Tree.Private_Part.Source_Paths)
2396 Get_Name_String (In_Tree.Private_Part.Source_Paths.Table (Index));
2397 Name_Len := Name_Len + 1;
2398 Name_Buffer (Name_Len) := ASCII.LF;
2399 Len := Write (Source_FD, Name_Buffer (1)'Address, Name_Len);
2401 if Len /= Name_Len then
2402 Prj.Com.Fail ("disk full");
2406 Close (Source_FD, Status);
2409 Prj.Com.Fail ("disk full");
2413 if Object_FD /= Invalid_FD then
2414 for Index in Object_Path_Table.First ..
2415 Object_Path_Table.Last
2416 (In_Tree.Private_Part.Object_Paths)
2418 Get_Name_String (In_Tree.Private_Part.Object_Paths.Table (Index));
2419 Name_Len := Name_Len + 1;
2420 Name_Buffer (Name_Len) := ASCII.LF;
2421 Len := Write (Object_FD, Name_Buffer (1)'Address, Name_Len);
2423 if Len /= Name_Len then
2424 Prj.Com.Fail ("disk full");
2428 Close (Object_FD, Status);
2431 Prj.Com.Fail ("disk full");
2435 -- Set the env vars, if they need to be changed, and set the
2436 -- corresponding flags.
2438 if Current_Source_Path_File /=
2439 In_Tree.Projects.Table (Project).Include_Path_File
2441 Current_Source_Path_File :=
2442 In_Tree.Projects.Table (Project).Include_Path_File;
2444 (Project_Include_Path_File,
2445 Get_Name_String (Current_Source_Path_File));
2446 Ada_Prj_Include_File_Set := True;
2449 if Including_Libraries then
2450 if Current_Object_Path_File
2451 /= In_Tree.Projects.Table
2452 (Project).Objects_Path_File_With_Libs
2454 Current_Object_Path_File :=
2455 In_Tree.Projects.Table
2456 (Project).Objects_Path_File_With_Libs;
2458 (Project_Objects_Path_File,
2459 Get_Name_String (Current_Object_Path_File));
2460 Ada_Prj_Objects_File_Set := True;
2464 if Current_Object_Path_File /=
2465 In_Tree.Projects.Table
2466 (Project).Objects_Path_File_Without_Libs
2468 Current_Object_Path_File :=
2469 In_Tree.Projects.Table
2470 (Project).Objects_Path_File_Without_Libs;
2472 (Project_Objects_Path_File,
2473 Get_Name_String (Current_Object_Path_File));
2474 Ada_Prj_Objects_File_Set := True;
2479 ---------------------------------------------
2480 -- Set_Mapping_File_Initial_State_To_Empty --
2481 ---------------------------------------------
2483 procedure Set_Mapping_File_Initial_State_To_Empty is
2485 Fill_Mapping_File := False;
2486 end Set_Mapping_File_Initial_State_To_Empty;
2488 -----------------------
2489 -- Set_Path_File_Var --
2490 -----------------------
2492 procedure Set_Path_File_Var (Name : String; Value : String) is
2493 Host_Spec : String_Access := To_Host_File_Spec (Value);
2496 if Host_Spec = null then
2498 ("could not convert file name """, Value, """ to host spec");
2500 Setenv (Name, Host_Spec.all);
2503 end Set_Path_File_Var;
2505 -----------------------
2506 -- Spec_Path_Name_Of --
2507 -----------------------
2509 function Spec_Path_Name_Of
2510 (Unit : Unit_Index; In_Tree : Project_Tree_Ref) return String
2512 Data : Unit_Data := In_Tree.Units.Table (Unit);
2515 if Data.File_Names (Specification).Path = No_Path then
2517 Current_Source : String_List_Id :=
2518 In_Tree.Projects.Table
2519 (Data.File_Names (Specification).Project).Ada_Sources;
2520 Path : GNAT.OS_Lib.String_Access;
2523 Data.File_Names (Specification).Path :=
2524 Path_Name_Type (Data.File_Names (Specification).Name);
2526 while Current_Source /= Nil_String loop
2527 Path := Locate_Regular_File
2528 (Namet.Get_Name_String
2529 (Data.File_Names (Specification).Name),
2530 Namet.Get_Name_String
2531 (In_Tree.String_Elements.Table
2532 (Current_Source).Value));
2534 if Path /= null then
2535 Name_Len := Path'Length;
2536 Name_Buffer (1 .. Name_Len) := Path.all;
2537 Data.File_Names (Specification).Path := Name_Enter;
2541 In_Tree.String_Elements.Table
2542 (Current_Source).Next;
2546 In_Tree.Units.Table (Unit) := Data;
2550 return Namet.Get_Name_String (Data.File_Names (Specification).Path);
2551 end Spec_Path_Name_Of;
2553 ---------------------------
2554 -- Ultimate_Extension_Of --
2555 ---------------------------
2557 function Ultimate_Extension_Of
2558 (Project : Project_Id;
2559 In_Tree : Project_Tree_Ref) return Project_Id
2561 Result : Project_Id := Project;
2564 while In_Tree.Projects.Table (Result).Extended_By /=
2567 Result := In_Tree.Projects.Table (Result).Extended_By;
2571 end Ultimate_Extension_Of;