1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2005 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 ------------------------------------------------------------------------------
27 with Namet; use Namet;
29 with Osint; use Osint;
30 with Output; use Output;
31 with Prj.Com; use Prj.Com;
34 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
36 package body Prj.Env is
38 Current_Source_Path_File : Name_Id := No_Name;
39 -- Current value of project source path file env var.
40 -- Used to avoid setting the env var to the same value.
42 Current_Object_Path_File : Name_Id := No_Name;
43 -- Current value of project object path file env var.
44 -- Used to avoid setting the env var to the same value.
46 Ada_Path_Buffer : String_Access := new String (1 .. 1024);
47 -- A buffer where values for ADA_INCLUDE_PATH
48 -- and ADA_OBJECTS_PATH are stored.
50 Ada_Path_Length : Natural := 0;
51 -- Index of the last valid character in Ada_Path_Buffer.
53 Ada_Prj_Include_File_Set : Boolean := False;
54 Ada_Prj_Objects_File_Set : Boolean := False;
55 -- These flags are set to True when the corresponding environment variables
56 -- are set and are used to give these environment variables an empty string
57 -- value at the end of the program. This has no practical effect on most
58 -- platforms, except on VMS where the logical names are deassigned, thus
59 -- avoiding the pollution of the environment of the caller.
61 Default_Naming : constant Naming_Id := Naming_Table.First;
63 Fill_Mapping_File : Boolean := True;
65 type Project_Flags is array (Project_Id range <>) of Boolean;
66 -- A Boolean array type used in Create_Mapping_File to select the projects
67 -- in the closure of a specific project.
69 -----------------------
70 -- Local Subprograms --
71 -----------------------
73 function Body_Path_Name_Of
75 In_Tree : Project_Tree_Ref) return String;
76 -- Returns the path name of the body of a unit.
77 -- Compute it first, if necessary.
79 function Spec_Path_Name_Of
81 In_Tree : Project_Tree_Ref) return String;
82 -- Returns the path name of the spec of a unit.
83 -- Compute it first, if necessary.
86 (Source_Dirs : String_List_Id;
87 In_Tree : Project_Tree_Ref);
88 -- Add to Ada_Path_Buffer all the source directories in string list
89 -- Source_Dirs, if any. Increment Ada_Path_Length.
91 procedure Add_To_Path (Dir : String);
92 -- If Dir is not already in the global variable Ada_Path_Buffer, add it.
93 -- Increment Ada_Path_Length.
94 -- If Ada_Path_Length /= 0, prepend a Path_Separator character to
97 procedure Add_To_Source_Path
98 (Source_Dirs : String_List_Id; In_Tree : Project_Tree_Ref);
99 -- Add to Ada_Path_B all the source directories in string list
100 -- Source_Dirs, if any. Increment Ada_Path_Length.
102 procedure Add_To_Object_Path
103 (Object_Dir : Name_Id;
104 In_Tree : Project_Tree_Ref);
105 -- Add Object_Dir to object path table. Make sure it is not duplicate
106 -- and it is the last one in the current table.
108 function Contains_ALI_Files (Dir : Name_Id) return Boolean;
109 -- Return True if there is at least one ALI file in the directory Dir
111 procedure Create_New_Path_File
112 (In_Tree : Project_Tree_Ref;
113 Path_FD : out File_Descriptor;
114 Path_Name : out Name_Id);
115 -- Create a new temporary path file. Get the file name in Path_Name.
116 -- The name is normally obtained by increasing the number in
117 -- Temp_Path_File_Name by 1.
119 procedure Set_Path_File_Var (Name : String; Value : String);
120 -- Call Setenv, after calling To_Host_File_Spec
122 function Ultimate_Extension_Of
123 (Project : in Project_Id; In_Tree : Project_Tree_Ref) return Project_Id;
124 -- Return a project that is either Project or an extended ancestor of
125 -- Project that itself is not extended.
127 ----------------------
128 -- Ada_Include_Path --
129 ----------------------
131 function Ada_Include_Path
132 (Project : Project_Id;
133 In_Tree : Project_Tree_Ref) return String_Access is
135 procedure Add (Project : Project_Id);
136 -- Add all the source directories of a project to the path only if
137 -- this project has not been visited. Calls itself recursively for
138 -- projects being extended, and imported projects. Adds the project
139 -- to the list Seen if this is the call to Add for this project.
145 procedure Add (Project : Project_Id) is
147 -- If Seen is empty, then the project cannot have been visited
149 if not In_Tree.Projects.Table (Project).Seen then
150 In_Tree.Projects.Table (Project).Seen := True;
153 Data : constant Project_Data :=
154 In_Tree.Projects.Table (Project);
155 List : Project_List := Data.Imported_Projects;
158 -- Add to path all source directories of this project
160 Add_To_Path (Data.Source_Dirs, In_Tree);
162 -- Call Add to the project being extended, if any
164 if Data.Extends /= No_Project then
168 -- Call Add for each imported project, if any
170 while List /= Empty_Project_List loop
172 (In_Tree.Project_Lists.Table (List).Project);
173 List := In_Tree.Project_Lists.Table (List).Next;
179 -- Start of processing for Ada_Include_Path
182 -- If it is the first time we call this function for
183 -- this project, compute the source path
186 In_Tree.Projects.Table (Project).Ada_Include_Path = null
188 Ada_Path_Length := 0;
190 for Index in Project_Table.First ..
191 Project_Table.Last (In_Tree.Projects)
193 In_Tree.Projects.Table (Index).Seen := False;
197 In_Tree.Projects.Table (Project).Ada_Include_Path :=
198 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
201 return In_Tree.Projects.Table (Project).Ada_Include_Path;
202 end Ada_Include_Path;
204 ----------------------
205 -- Ada_Include_Path --
206 ----------------------
208 function Ada_Include_Path
209 (Project : Project_Id;
210 In_Tree : Project_Tree_Ref;
211 Recursive : Boolean) return String
215 return Ada_Include_Path (Project, In_Tree).all;
217 Ada_Path_Length := 0;
219 (In_Tree.Projects.Table (Project).Source_Dirs, In_Tree);
220 return Ada_Path_Buffer (1 .. Ada_Path_Length);
222 end Ada_Include_Path;
224 ----------------------
225 -- Ada_Objects_Path --
226 ----------------------
228 function Ada_Objects_Path
229 (Project : Project_Id;
230 In_Tree : Project_Tree_Ref;
231 Including_Libraries : Boolean := True) return String_Access
233 procedure Add (Project : Project_Id);
234 -- Add all the object directories of a project to the path only if
235 -- this project has not been visited. Calls itself recursively for
236 -- projects being extended, and imported projects. Adds the project
237 -- to the list Seen if this is the first call to Add for this project.
243 procedure Add (Project : Project_Id) is
245 -- If this project has not been seen yet
247 if not In_Tree.Projects.Table (Project).Seen then
248 In_Tree.Projects.Table (Project).Seen := True;
251 Data : constant Project_Data :=
252 In_Tree.Projects.Table (Project);
253 List : Project_List := Data.Imported_Projects;
256 -- Add to path the object directory of this project
257 -- except if we don't include library project and
258 -- this is a library project.
260 if (Data.Library and then Including_Libraries)
262 (Data.Object_Directory /= No_Name
264 (not Including_Libraries or else not Data.Library))
266 -- For a library project, add the library directory,
267 -- if there is no object directory or if it contains ALI
268 -- files; otherwise add the object directory.
271 if Data.Object_Directory = No_Name
273 Contains_ALI_Files (Data.Library_Dir)
275 Add_To_Path (Get_Name_String (Data.Library_Dir));
277 Add_To_Path (Get_Name_String (Data.Object_Directory));
281 -- For a non library project, add the object directory
283 Add_To_Path (Get_Name_String (Data.Object_Directory));
287 -- Call Add to the project being extended, if any
289 if Data.Extends /= No_Project then
293 -- Call Add for each imported project, if any
295 while List /= Empty_Project_List loop
297 (In_Tree.Project_Lists.Table (List).Project);
298 List := In_Tree.Project_Lists.Table (List).Next;
305 -- Start of processing for Ada_Objects_Path
308 -- If it is the first time we call this function for
309 -- this project, compute the objects path
312 In_Tree.Projects.Table (Project).Ada_Objects_Path = null
314 Ada_Path_Length := 0;
316 for Index in Project_Table.First ..
317 Project_Table.Last (In_Tree.Projects)
319 In_Tree.Projects.Table (Index).Seen := False;
323 In_Tree.Projects.Table (Project).Ada_Objects_Path :=
324 new String'(Ada_Path_Buffer (1 .. Ada_Path_Length));
327 return In_Tree.Projects.Table (Project).Ada_Objects_Path;
328 end Ada_Objects_Path;
330 ------------------------
331 -- Add_To_Object_Path --
332 ------------------------
334 procedure Add_To_Object_Path
335 (Object_Dir : Name_Id; In_Tree : Project_Tree_Ref)
338 -- Check if the directory is already in the table
340 for Index in Object_Path_Table.First ..
341 Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)
344 -- If it is, remove it, and add it as the last one
346 if In_Tree.Private_Part.Object_Paths.Table (Index) = Object_Dir then
347 for Index2 in Index + 1 ..
348 Object_Path_Table.Last
349 (In_Tree.Private_Part.Object_Paths)
351 In_Tree.Private_Part.Object_Paths.Table (Index2 - 1) :=
352 In_Tree.Private_Part.Object_Paths.Table (Index2);
355 In_Tree.Private_Part.Object_Paths.Table
356 (Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)) :=
362 -- The directory is not already in the table, add it
364 Object_Path_Table.Increment_Last (In_Tree.Private_Part.Object_Paths);
365 In_Tree.Private_Part.Object_Paths.Table
366 (Object_Path_Table.Last (In_Tree.Private_Part.Object_Paths)) :=
368 end Add_To_Object_Path;
374 procedure Add_To_Path
375 (Source_Dirs : String_List_Id;
376 In_Tree : Project_Tree_Ref)
378 Current : String_List_Id := Source_Dirs;
379 Source_Dir : String_Element;
381 while Current /= Nil_String loop
382 Source_Dir := In_Tree.String_Elements.Table (Current);
383 Add_To_Path (Get_Name_String (Source_Dir.Display_Value));
384 Current := Source_Dir.Next;
388 procedure Add_To_Path (Dir : String) is
390 New_Buffer : String_Access;
393 function Is_Present (Path : String; Dir : String) return Boolean;
394 -- Return True if Dir is part of Path
400 function Is_Present (Path : String; Dir : String) return Boolean is
401 Last : constant Integer := Path'Last - Dir'Length + 1;
404 for J in Path'First .. Last loop
406 -- Note: the order of the conditions below is important, since
407 -- it ensures a minimal number of string comparisons.
410 or else Path (J - 1) = Path_Separator)
412 (J + Dir'Length > Path'Last
413 or else Path (J + Dir'Length) = Path_Separator)
414 and then Dir = Path (J .. J + Dir'Length - 1)
423 -- Start of processing for Add_To_Path
426 if Is_Present (Ada_Path_Buffer (1 .. Ada_Path_Length), Dir) then
428 -- Dir is already in the path, nothing to do
433 Min_Len := Ada_Path_Length + Dir'Length;
435 if Ada_Path_Length > 0 then
437 -- Add 1 for the Path_Separator character
439 Min_Len := Min_Len + 1;
442 -- If Ada_Path_Buffer is too small, increase it
444 Len := Ada_Path_Buffer'Last;
446 if Len < Min_Len then
449 exit when Len >= Min_Len;
452 New_Buffer := new String (1 .. Len);
453 New_Buffer (1 .. Ada_Path_Length) :=
454 Ada_Path_Buffer (1 .. Ada_Path_Length);
455 Free (Ada_Path_Buffer);
456 Ada_Path_Buffer := New_Buffer;
459 if Ada_Path_Length > 0 then
460 Ada_Path_Length := Ada_Path_Length + 1;
461 Ada_Path_Buffer (Ada_Path_Length) := Path_Separator;
465 (Ada_Path_Length + 1 .. Ada_Path_Length + Dir'Length) := Dir;
466 Ada_Path_Length := Ada_Path_Length + Dir'Length;
469 ------------------------
470 -- Add_To_Source_Path --
471 ------------------------
473 procedure Add_To_Source_Path
474 (Source_Dirs : String_List_Id; In_Tree : Project_Tree_Ref)
476 Current : String_List_Id := Source_Dirs;
477 Source_Dir : String_Element;
481 -- Add each source directory
483 while Current /= Nil_String loop
484 Source_Dir := In_Tree.String_Elements.Table (Current);
487 -- Check if the source directory is already in the table
489 for Index in Source_Path_Table.First ..
490 Source_Path_Table.Last
491 (In_Tree.Private_Part.Source_Paths)
493 -- If it is already, no need to add it
495 if In_Tree.Private_Part.Source_Paths.Table (Index) =
504 Source_Path_Table.Increment_Last
505 (In_Tree.Private_Part.Source_Paths);
506 In_Tree.Private_Part.Source_Paths.Table
507 (Source_Path_Table.Last (In_Tree.Private_Part.Source_Paths)) :=
511 -- Next source directory
513 Current := Source_Dir.Next;
515 end Add_To_Source_Path;
517 -----------------------
518 -- Body_Path_Name_Of --
519 -----------------------
521 function Body_Path_Name_Of
522 (Unit : Unit_Id; In_Tree : Project_Tree_Ref) return String
524 Data : Unit_Data := In_Tree.Units.Table (Unit);
527 -- If we don't know the path name of the body of this unit,
528 -- we compute it, and we store it.
530 if Data.File_Names (Body_Part).Path = No_Name then
532 Current_Source : String_List_Id :=
533 In_Tree.Projects.Table
534 (Data.File_Names (Body_Part).Project).Sources;
535 Path : GNAT.OS_Lib.String_Access;
538 -- By default, put the file name
540 Data.File_Names (Body_Part).Path :=
541 Data.File_Names (Body_Part).Name;
543 -- For each source directory
545 while Current_Source /= Nil_String loop
548 (Namet.Get_Name_String
549 (Data.File_Names (Body_Part).Name),
550 Namet.Get_Name_String
551 (In_Tree.String_Elements.Table
552 (Current_Source).Value));
554 -- If the file is in this directory, then we store the path,
558 Name_Len := Path'Length;
559 Name_Buffer (1 .. Name_Len) := Path.all;
560 Data.File_Names (Body_Part).Path := Name_Enter;
565 In_Tree.String_Elements.Table
566 (Current_Source).Next;
570 In_Tree.Units.Table (Unit) := Data;
574 -- Returned the stored value
576 return Namet.Get_Name_String (Data.File_Names (Body_Part).Path);
577 end Body_Path_Name_Of;
579 ------------------------
580 -- Contains_ALI_Files --
581 ------------------------
583 function Contains_ALI_Files (Dir : Name_Id) return Boolean is
584 Dir_Name : constant String := Get_Name_String (Dir);
586 Name : String (1 .. 1_000);
588 Result : Boolean := False;
591 Open (Direct, Dir_Name);
593 -- For each file in the directory, check if it is an ALI file
596 Read (Direct, Name, Last);
598 Canonical_Case_File_Name (Name (1 .. Last));
599 Result := Last >= 5 and then Name (Last - 3 .. Last) = ".ali";
607 -- If there is any problem, close the directory if open and return
608 -- True; the library directory will be added to the path.
611 if Is_Open (Direct) then
616 end Contains_ALI_Files;
618 --------------------------------
619 -- Create_Config_Pragmas_File --
620 --------------------------------
622 procedure Create_Config_Pragmas_File
623 (For_Project : Project_Id;
624 Main_Project : Project_Id;
625 In_Tree : Project_Tree_Ref;
626 Include_Config_Files : Boolean := True)
628 pragma Unreferenced (Main_Project);
629 pragma Unreferenced (Include_Config_Files);
631 File_Name : Name_Id := No_Name;
632 File : File_Descriptor := Invalid_FD;
634 Current_Unit : Unit_Id := Unit_Table.First;
636 First_Project : Project_List := Empty_Project_List;
638 Current_Project : Project_List;
639 Current_Naming : Naming_Id;
644 procedure Check (Project : Project_Id);
645 -- Recursive procedure that put in the config pragmas file any non
646 -- standard naming schemes, if it is not already in the file, then call
647 -- itself for any imported project.
649 procedure Check_Temp_File;
650 -- Check that a temporary file has been opened.
651 -- If not, create one, and put its name in the project data,
652 -- with the indication that it is a temporary file.
655 (Unit_Name : Name_Id;
657 Unit_Kind : Spec_Or_Body;
659 -- Put an SFN pragma in the temporary file
661 procedure Put (File : File_Descriptor; S : String);
662 procedure Put_Line (File : File_Descriptor; S : String);
663 -- Output procedures, analogous to normal Text_IO procs of same name
669 procedure Check (Project : Project_Id) is
670 Data : constant Project_Data :=
671 In_Tree.Projects.Table (Project);
674 if Current_Verbosity = High then
675 Write_Str ("Checking project file """);
676 Write_Str (Namet.Get_Name_String (Data.Name));
681 -- Is this project in the list of the visited project?
683 Current_Project := First_Project;
684 while Current_Project /= Empty_Project_List
685 and then In_Tree.Project_Lists.Table
686 (Current_Project).Project /= Project
689 In_Tree.Project_Lists.Table (Current_Project).Next;
692 -- If it is not, put it in the list, and visit it
694 if Current_Project = Empty_Project_List then
695 Project_List_Table.Increment_Last
696 (In_Tree.Project_Lists);
697 In_Tree.Project_Lists.Table
698 (Project_List_Table.Last (In_Tree.Project_Lists)) :=
699 (Project => Project, Next => First_Project);
701 Project_List_Table.Last (In_Tree.Project_Lists);
703 -- Is the naming scheme of this project one that we know?
705 Current_Naming := Default_Naming;
706 while Current_Naming <=
707 Naming_Table.Last (In_Tree.Private_Part.Namings)
708 and then not Same_Naming_Scheme
709 (Left => In_Tree.Private_Part.Namings.Table (Current_Naming),
710 Right => Data.Naming) loop
711 Current_Naming := Current_Naming + 1;
714 -- If we don't know it, add it
717 Naming_Table.Last (In_Tree.Private_Part.Namings)
719 Naming_Table.Increment_Last (In_Tree.Private_Part.Namings);
720 In_Tree.Private_Part.Namings.Table
721 (Naming_Table.Last (In_Tree.Private_Part.Namings)) :=
724 -- We need a temporary file to be created
728 -- Put the SFN pragmas for the naming scheme
733 (File, "pragma Source_File_Name_Project");
735 (File, " (Spec_File_Name => ""*" &
736 Namet.Get_Name_String (Data.Naming.Ada_Spec_Suffix) &
739 (File, " Casing => " &
740 Image (Data.Naming.Casing) & ",");
742 (File, " Dot_Replacement => """ &
743 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
749 (File, "pragma Source_File_Name_Project");
751 (File, " (Body_File_Name => ""*" &
752 Namet.Get_Name_String (Data.Naming.Ada_Body_Suffix) &
755 (File, " Casing => " &
756 Image (Data.Naming.Casing) & ",");
758 (File, " Dot_Replacement => """ &
759 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
762 -- and maybe separate
765 Data.Naming.Ada_Body_Suffix /= Data.Naming.Separate_Suffix
768 (File, "pragma Source_File_Name_Project");
770 (File, " (Subunit_File_Name => ""*" &
771 Namet.Get_Name_String (Data.Naming.Separate_Suffix) &
774 (File, " Casing => " &
775 Image (Data.Naming.Casing) &
778 (File, " Dot_Replacement => """ &
779 Namet.Get_Name_String (Data.Naming.Dot_Replacement) &
784 if Data.Extends /= No_Project then
785 Check (Data.Extends);
789 Current : Project_List := Data.Imported_Projects;
792 while Current /= Empty_Project_List loop
794 (In_Tree.Project_Lists.Table
796 Current := In_Tree.Project_Lists.Table
803 ---------------------
804 -- Check_Temp_File --
805 ---------------------
807 procedure Check_Temp_File is
809 if File = Invalid_FD then
810 Tempdir.Create_Temp_File (File, Name => File_Name);
812 if File = Invalid_FD then
814 ("unable to create temporary configuration pragmas file");
815 elsif Opt.Verbose_Mode then
816 Write_Str ("Creating temp file """);
817 Write_Str (Get_Name_String (File_Name));
828 (Unit_Name : Name_Id;
830 Unit_Kind : Spec_Or_Body;
834 -- A temporary file needs to be open
838 -- Put the pragma SFN for the unit kind (spec or body)
840 Put (File, "pragma Source_File_Name_Project (");
841 Put (File, Namet.Get_Name_String (Unit_Name));
843 if Unit_Kind = Specification then
844 Put (File, ", Spec_File_Name => """);
846 Put (File, ", Body_File_Name => """);
849 Put (File, Namet.Get_Name_String (File_Name));
853 Put (File, ", Index =>");
854 Put (File, Index'Img);
857 Put_Line (File, ");");
860 procedure Put (File : File_Descriptor; S : String) is
864 Last := Write (File, S (S'First)'Address, S'Length);
866 if Last /= S'Length then
867 Prj.Com.Fail ("Disk full");
870 if Current_Verbosity = High then
879 procedure Put_Line (File : File_Descriptor; S : String) is
880 S0 : String (1 .. S'Length + 1);
884 -- Add an ASCII.LF to the string. As this config file is supposed to
885 -- be used only by the compiler, we don't care about the characters
886 -- for the end of line. In fact we could have put a space, but
887 -- it is more convenient to be able to read gnat.adc during
888 -- development, for which the ASCII.LF is fine.
890 S0 (1 .. S'Length) := S;
891 S0 (S0'Last) := ASCII.LF;
892 Last := Write (File, S0'Address, S0'Length);
894 if Last /= S'Length + 1 then
895 Prj.Com.Fail ("Disk full");
898 if Current_Verbosity = High then
903 -- Start of processing for Create_Config_Pragmas_File
907 In_Tree.Projects.Table (For_Project).Config_Checked
910 -- Remove any memory of processed naming schemes, if any
912 Naming_Table.Set_Last (In_Tree.Private_Part.Namings, Default_Naming);
914 -- Check the naming schemes
918 -- Visit all the units and process those that need an SFN pragma
921 Current_Unit <= Unit_Table.Last (In_Tree.Units)
924 Unit : constant Unit_Data :=
925 In_Tree.Units.Table (Current_Unit);
928 if Unit.File_Names (Specification).Needs_Pragma then
930 Unit.File_Names (Specification).Name,
932 Unit.File_Names (Specification).Index);
935 if Unit.File_Names (Body_Part).Needs_Pragma then
937 Unit.File_Names (Body_Part).Name,
939 Unit.File_Names (Body_Part).Index);
942 Current_Unit := Current_Unit + 1;
946 -- If there are no non standard naming scheme, issue the GNAT
947 -- standard naming scheme. This will tell the compiler that
948 -- a project file is used and will forbid any pragma SFN.
950 if File = Invalid_FD then
953 Put_Line (File, "pragma Source_File_Name_Project");
954 Put_Line (File, " (Spec_File_Name => ""*.ads"",");
955 Put_Line (File, " Dot_Replacement => ""-"",");
956 Put_Line (File, " Casing => lowercase);");
958 Put_Line (File, "pragma Source_File_Name_Project");
959 Put_Line (File, " (Body_File_Name => ""*.adb"",");
960 Put_Line (File, " Dot_Replacement => ""-"",");
961 Put_Line (File, " Casing => lowercase);");
964 -- Close the temporary file
966 GNAT.OS_Lib.Close (File, Status);
969 Prj.Com.Fail ("disk full");
972 if Opt.Verbose_Mode then
973 Write_Str ("Closing configuration file """);
974 Write_Str (Get_Name_String (File_Name));
978 In_Tree.Projects.Table (For_Project).Config_File_Name :=
980 In_Tree.Projects.Table (For_Project).Config_File_Temp :=
983 In_Tree.Projects.Table (For_Project).Config_Checked :=
986 end Create_Config_Pragmas_File;
988 -------------------------
989 -- Create_Mapping_File --
990 -------------------------
992 procedure Create_Mapping_File
993 (Project : Project_Id;
994 In_Tree : Project_Tree_Ref;
997 File : File_Descriptor := Invalid_FD;
998 The_Unit_Data : Unit_Data;
999 Data : File_Name_Data;
1002 -- For call to Close
1004 Present : Project_Flags
1005 (No_Project .. Project_Table.Last (In_Tree.Projects)) :=
1007 -- For each project in the closure of Project, the corresponding flag
1008 -- will be set to True;
1010 procedure Put_Name_Buffer;
1011 -- Put the line contained in the Name_Buffer in the mapping file
1013 procedure Put_Data (Spec : Boolean);
1014 -- Put the mapping of the spec or body contained in Data in the file
1017 procedure Recursive_Flag (Prj : Project_Id);
1018 -- Set the flags corresponding to Prj, the projects it imports
1019 -- (directly or indirectly) or extends to True. Call itself recursively.
1025 procedure Put_Name_Buffer is
1029 Name_Len := Name_Len + 1;
1030 Name_Buffer (Name_Len) := ASCII.LF;
1031 Last := Write (File, Name_Buffer (1)'Address, Name_Len);
1033 if Last /= Name_Len then
1034 Prj.Com.Fail ("Disk full");
1036 end Put_Name_Buffer;
1042 procedure Put_Data (Spec : Boolean) is
1044 -- Line with the unit name
1046 Get_Name_String (The_Unit_Data.Name);
1047 Name_Len := Name_Len + 1;
1048 Name_Buffer (Name_Len) := '%';
1049 Name_Len := Name_Len + 1;
1052 Name_Buffer (Name_Len) := 's';
1054 Name_Buffer (Name_Len) := 'b';
1059 -- Line with the file name
1061 Get_Name_String (Data.Name);
1064 -- Line with the path name
1066 Get_Name_String (Data.Path);
1071 --------------------
1072 -- Recursive_Flag --
1073 --------------------
1075 procedure Recursive_Flag (Prj : Project_Id) is
1076 Imported : Project_List;
1080 -- Nothing to do for non existent project or project that has
1081 -- already been flagged.
1083 if Prj = No_Project or else Present (Prj) then
1087 -- Flag the current project
1089 Present (Prj) := True;
1091 In_Tree.Projects.Table (Prj).Imported_Projects;
1093 -- Call itself for each project directly imported
1095 while Imported /= Empty_Project_List loop
1097 In_Tree.Project_Lists.Table (Imported).Project;
1099 In_Tree.Project_Lists.Table (Imported).Next;
1100 Recursive_Flag (Proj);
1103 -- Call itself for an eventual project being extended
1105 Recursive_Flag (In_Tree.Projects.Table (Prj).Extends);
1108 -- Start of processing for Create_Mapping_File
1111 -- Flag the necessary projects
1113 Recursive_Flag (Project);
1115 -- Create the temporary file
1117 Tempdir.Create_Temp_File (File, Name => Name);
1119 if File = Invalid_FD then
1120 Prj.Com.Fail ("unable to create temporary mapping file");
1122 elsif Opt.Verbose_Mode then
1123 Write_Str ("Creating temp mapping file """);
1124 Write_Str (Get_Name_String (Name));
1128 if Fill_Mapping_File then
1130 -- For all units in table Units
1132 for Unit in 1 .. Unit_Table.Last (In_Tree.Units) loop
1133 The_Unit_Data := In_Tree.Units.Table (Unit);
1135 -- If the unit has a valid name
1137 if The_Unit_Data.Name /= No_Name then
1138 Data := The_Unit_Data.File_Names (Specification);
1140 -- If there is a spec, put it mapping in the file if it is
1141 -- from a project in the closure of Project.
1143 if Data.Name /= No_Name and then Present (Data.Project) then
1144 Put_Data (Spec => True);
1147 Data := The_Unit_Data.File_Names (Body_Part);
1149 -- If there is a body (or subunit) put its mapping in the file
1150 -- if it is from a project in the closure of Project.
1152 if Data.Name /= No_Name and then Present (Data.Project) then
1153 Put_Data (Spec => False);
1160 GNAT.OS_Lib.Close (File, Status);
1163 Prj.Com.Fail ("disk full");
1165 end Create_Mapping_File;
1167 --------------------------
1168 -- Create_New_Path_File --
1169 --------------------------
1171 procedure Create_New_Path_File
1172 (In_Tree : Project_Tree_Ref;
1173 Path_FD : out File_Descriptor;
1174 Path_Name : out Name_Id)
1177 Tempdir.Create_Temp_File (Path_FD, Path_Name);
1179 if Path_Name /= No_Name then
1181 -- Record the name, so that the temp path file will be deleted
1182 -- at the end of the program.
1184 Path_File_Table.Increment_Last (In_Tree.Private_Part.Path_Files);
1185 In_Tree.Private_Part.Path_Files.Table
1186 (Path_File_Table.Last (In_Tree.Private_Part.Path_Files)) :=
1189 end Create_New_Path_File;
1191 ---------------------------
1192 -- Delete_All_Path_Files --
1193 ---------------------------
1195 procedure Delete_All_Path_Files (In_Tree : Project_Tree_Ref) is
1196 Disregard : Boolean := True;
1199 for Index in Path_File_Table.First ..
1200 Path_File_Table.Last (In_Tree.Private_Part.Path_Files)
1202 if In_Tree.Private_Part.Path_Files.Table (Index) /= No_Name then
1205 (In_Tree.Private_Part.Path_Files.Table (Index)),
1210 -- If any of the environment variables ADA_PRJ_INCLUDE_FILE or
1211 -- ADA_PRJ_OBJECTS_FILE has been set, then reset their value to
1212 -- the empty string. On VMS, this has the effect of deassigning
1213 -- the logical names.
1215 if Ada_Prj_Include_File_Set then
1216 Setenv (Project_Include_Path_File, "");
1217 Ada_Prj_Include_File_Set := False;
1220 if Ada_Prj_Objects_File_Set then
1221 Setenv (Project_Objects_Path_File, "");
1222 Ada_Prj_Objects_File_Set := False;
1224 end Delete_All_Path_Files;
1226 ------------------------------------
1227 -- File_Name_Of_Library_Unit_Body --
1228 ------------------------------------
1230 function File_Name_Of_Library_Unit_Body
1232 Project : Project_Id;
1233 In_Tree : Project_Tree_Ref;
1234 Main_Project_Only : Boolean := True;
1235 Full_Path : Boolean := False) return String
1237 The_Project : Project_Id := Project;
1238 Data : Project_Data :=
1239 In_Tree.Projects.Table (Project);
1240 Original_Name : String := Name;
1242 Extended_Spec_Name : String :=
1243 Name & Namet.Get_Name_String
1244 (Data.Naming.Ada_Spec_Suffix);
1245 Extended_Body_Name : String :=
1246 Name & Namet.Get_Name_String
1247 (Data.Naming.Ada_Body_Suffix);
1251 The_Original_Name : Name_Id;
1252 The_Spec_Name : Name_Id;
1253 The_Body_Name : Name_Id;
1256 Canonical_Case_File_Name (Original_Name);
1257 Name_Len := Original_Name'Length;
1258 Name_Buffer (1 .. Name_Len) := Original_Name;
1259 The_Original_Name := Name_Find;
1261 Canonical_Case_File_Name (Extended_Spec_Name);
1262 Name_Len := Extended_Spec_Name'Length;
1263 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
1264 The_Spec_Name := Name_Find;
1266 Canonical_Case_File_Name (Extended_Body_Name);
1267 Name_Len := Extended_Body_Name'Length;
1268 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
1269 The_Body_Name := Name_Find;
1271 if Current_Verbosity = High then
1272 Write_Str ("Looking for file name of """);
1276 Write_Str (" Extended Spec Name = """);
1277 Write_Str (Extended_Spec_Name);
1280 Write_Str (" Extended Body Name = """);
1281 Write_Str (Extended_Body_Name);
1286 -- For extending project, search in the extended project
1287 -- if the source is not found. For non extending projects,
1288 -- this loop will be run only once.
1291 -- Loop through units
1292 -- Should have comment explaining reverse ???
1294 for Current in reverse Unit_Table.First ..
1295 Unit_Table.Last (In_Tree.Units)
1297 Unit := In_Tree.Units.Table (Current);
1301 if not Main_Project_Only
1302 or else Unit.File_Names (Body_Part).Project = The_Project
1305 Current_Name : constant Name_Id :=
1306 Unit.File_Names (Body_Part).Name;
1309 -- Case of a body present
1311 if Current_Name /= No_Name then
1312 if Current_Verbosity = High then
1313 Write_Str (" Comparing with """);
1314 Write_Str (Get_Name_String (Current_Name));
1319 -- If it has the name of the original name,
1320 -- return the original name
1322 if Unit.Name = The_Original_Name
1323 or else Current_Name = The_Original_Name
1325 if Current_Verbosity = High then
1330 return Get_Name_String
1331 (Unit.File_Names (Body_Part).Path);
1334 return Get_Name_String (Current_Name);
1337 -- If it has the name of the extended body name,
1338 -- return the extended body name
1340 elsif Current_Name = The_Body_Name then
1341 if Current_Verbosity = High then
1346 return Get_Name_String
1347 (Unit.File_Names (Body_Part).Path);
1350 return Extended_Body_Name;
1354 if Current_Verbosity = High then
1355 Write_Line (" not good");
1364 if not Main_Project_Only
1365 or else Unit.File_Names (Specification).Project = The_Project
1368 Current_Name : constant Name_Id :=
1369 Unit.File_Names (Specification).Name;
1372 -- Case of spec present
1374 if Current_Name /= No_Name then
1375 if Current_Verbosity = High then
1376 Write_Str (" Comparing with """);
1377 Write_Str (Get_Name_String (Current_Name));
1382 -- If name same as original name, return original name
1384 if Unit.Name = The_Original_Name
1385 or else Current_Name = The_Original_Name
1387 if Current_Verbosity = High then
1392 return Get_Name_String
1393 (Unit.File_Names (Specification).Path);
1395 return Get_Name_String (Current_Name);
1398 -- If it has the same name as the extended spec name,
1399 -- return the extended spec name.
1401 elsif Current_Name = The_Spec_Name then
1402 if Current_Verbosity = High then
1407 return Get_Name_String
1408 (Unit.File_Names (Specification).Path);
1410 return Extended_Spec_Name;
1414 if Current_Verbosity = High then
1415 Write_Line (" not good");
1423 -- If we are not in an extending project, give up
1425 exit when (not Main_Project_Only) or else Data.Extends = No_Project;
1427 -- Otherwise, look in the project we are extending
1429 The_Project := Data.Extends;
1430 Data := In_Tree.Projects.Table (The_Project);
1433 -- We don't know this file name, return an empty string
1436 end File_Name_Of_Library_Unit_Body;
1438 -------------------------
1439 -- For_All_Object_Dirs --
1440 -------------------------
1442 procedure For_All_Object_Dirs
1443 (Project : Project_Id;
1444 In_Tree : Project_Tree_Ref)
1446 Seen : Project_List := Empty_Project_List;
1448 procedure Add (Project : Project_Id);
1449 -- Process a project. Remember the processes visited to avoid
1450 -- processing a project twice. Recursively process an eventual
1451 -- extended project, and all imported projects.
1457 procedure Add (Project : Project_Id) is
1458 Data : constant Project_Data :=
1459 In_Tree.Projects.Table (Project);
1460 List : Project_List := Data.Imported_Projects;
1463 -- If the list of visited project is empty, then
1464 -- for sure we never visited this project.
1466 if Seen = Empty_Project_List then
1467 Project_List_Table.Increment_Last
1468 (In_Tree.Project_Lists);
1470 Project_List_Table.Last (In_Tree.Project_Lists);
1471 In_Tree.Project_Lists.Table (Seen) :=
1472 (Project => Project, Next => Empty_Project_List);
1475 -- Check if the project is in the list
1478 Current : Project_List := Seen;
1482 -- If it is, then there is nothing else to do
1484 if In_Tree.Project_Lists.Table
1485 (Current).Project = Project
1491 In_Tree.Project_Lists.Table (Current).Next =
1494 In_Tree.Project_Lists.Table (Current).Next;
1497 -- This project has never been visited, add it
1500 Project_List_Table.Increment_Last
1501 (In_Tree.Project_Lists);
1502 In_Tree.Project_Lists.Table (Current).Next :=
1503 Project_List_Table.Last (In_Tree.Project_Lists);
1504 In_Tree.Project_Lists.Table
1505 (Project_List_Table.Last
1506 (In_Tree.Project_Lists)) :=
1507 (Project => Project, Next => Empty_Project_List);
1511 -- If there is an object directory, call Action
1514 if Data.Object_Directory /= No_Name then
1515 Get_Name_String (Data.Object_Directory);
1516 Action (Name_Buffer (1 .. Name_Len));
1519 -- If we are extending a project, visit it
1521 if Data.Extends /= No_Project then
1525 -- And visit all imported projects
1527 while List /= Empty_Project_List loop
1528 Add (In_Tree.Project_Lists.Table (List).Project);
1529 List := In_Tree.Project_Lists.Table (List).Next;
1533 -- Start of processing for For_All_Object_Dirs
1536 -- Visit this project, and its imported projects,
1540 end For_All_Object_Dirs;
1542 -------------------------
1543 -- For_All_Source_Dirs --
1544 -------------------------
1546 procedure For_All_Source_Dirs
1547 (Project : Project_Id;
1548 In_Tree : Project_Tree_Ref)
1550 Seen : Project_List := Empty_Project_List;
1552 procedure Add (Project : Project_Id);
1553 -- Process a project. Remember the processes visited to avoid
1554 -- processing a project twice. Recursively process an eventual
1555 -- extended project, and all imported projects.
1561 procedure Add (Project : Project_Id) is
1562 Data : constant Project_Data :=
1563 In_Tree.Projects.Table (Project);
1564 List : Project_List := Data.Imported_Projects;
1567 -- If the list of visited project is empty, then
1568 -- for sure we never visited this project.
1570 if Seen = Empty_Project_List then
1571 Project_List_Table.Increment_Last
1572 (In_Tree.Project_Lists);
1573 Seen := Project_List_Table.Last
1574 (In_Tree.Project_Lists);
1575 In_Tree.Project_Lists.Table (Seen) :=
1576 (Project => Project, Next => Empty_Project_List);
1579 -- Check if the project is in the list
1582 Current : Project_List := Seen;
1586 -- If it is, then there is nothing else to do
1588 if In_Tree.Project_Lists.Table
1589 (Current).Project = Project
1595 In_Tree.Project_Lists.Table (Current).Next =
1598 In_Tree.Project_Lists.Table (Current).Next;
1601 -- This project has never been visited, add it
1604 Project_List_Table.Increment_Last
1605 (In_Tree.Project_Lists);
1606 In_Tree.Project_Lists.Table (Current).Next :=
1607 Project_List_Table.Last (In_Tree.Project_Lists);
1608 In_Tree.Project_Lists.Table
1609 (Project_List_Table.Last
1610 (In_Tree.Project_Lists)) :=
1611 (Project => Project, Next => Empty_Project_List);
1616 Current : String_List_Id := Data.Source_Dirs;
1617 The_String : String_Element;
1620 -- If there are Ada sources, call action with the name of every
1621 -- source directory.
1624 In_Tree.Projects.Table (Project).Ada_Sources_Present
1626 while Current /= Nil_String loop
1628 In_Tree.String_Elements.Table (Current);
1629 Action (Get_Name_String (The_String.Value));
1630 Current := The_String.Next;
1635 -- If we are extending a project, visit it
1637 if Data.Extends /= No_Project then
1641 -- And visit all imported projects
1643 while List /= Empty_Project_List loop
1644 Add (In_Tree.Project_Lists.Table (List).Project);
1645 List := In_Tree.Project_Lists.Table (List).Next;
1649 -- Start of processing for For_All_Source_Dirs
1652 -- Visit this project, and its imported projects recursively
1655 end For_All_Source_Dirs;
1661 procedure Get_Reference
1662 (Source_File_Name : String;
1663 In_Tree : Project_Tree_Ref;
1664 Project : out Project_Id;
1668 -- Body below could use some comments ???
1670 if Current_Verbosity > Default then
1671 Write_Str ("Getting Reference_Of (""");
1672 Write_Str (Source_File_Name);
1673 Write_Str (""") ... ");
1677 Original_Name : String := Source_File_Name;
1681 Canonical_Case_File_Name (Original_Name);
1683 for Id in Unit_Table.First ..
1684 Unit_Table.Last (In_Tree.Units)
1686 Unit := In_Tree.Units.Table (Id);
1688 if (Unit.File_Names (Specification).Name /= No_Name
1690 Namet.Get_Name_String
1691 (Unit.File_Names (Specification).Name) = Original_Name)
1692 or else (Unit.File_Names (Specification).Path /= No_Name
1694 Namet.Get_Name_String
1695 (Unit.File_Names (Specification).Path) =
1698 Project := Ultimate_Extension_Of
1699 (Project => Unit.File_Names (Specification).Project,
1700 In_Tree => In_Tree);
1701 Path := Unit.File_Names (Specification).Display_Path;
1703 if Current_Verbosity > Default then
1704 Write_Str ("Done: Specification.");
1710 elsif (Unit.File_Names (Body_Part).Name /= No_Name
1712 Namet.Get_Name_String
1713 (Unit.File_Names (Body_Part).Name) = Original_Name)
1714 or else (Unit.File_Names (Body_Part).Path /= No_Name
1715 and then Namet.Get_Name_String
1716 (Unit.File_Names (Body_Part).Path) =
1719 Project := Ultimate_Extension_Of
1720 (Project => Unit.File_Names (Body_Part).Project,
1721 In_Tree => In_Tree);
1722 Path := Unit.File_Names (Body_Part).Display_Path;
1724 if Current_Verbosity > Default then
1725 Write_Str ("Done: Body.");
1734 Project := No_Project;
1737 if Current_Verbosity > Default then
1738 Write_Str ("Cannot be found.");
1747 procedure Initialize is
1749 Fill_Mapping_File := True;
1752 ------------------------------------
1753 -- Path_Name_Of_Library_Unit_Body --
1754 ------------------------------------
1756 -- Could use some comments in the body here ???
1758 function Path_Name_Of_Library_Unit_Body
1760 Project : Project_Id;
1761 In_Tree : Project_Tree_Ref) return String
1763 Data : constant Project_Data :=
1764 In_Tree.Projects.Table (Project);
1765 Original_Name : String := Name;
1767 Extended_Spec_Name : String :=
1768 Name & Namet.Get_Name_String
1769 (Data.Naming.Ada_Spec_Suffix);
1770 Extended_Body_Name : String :=
1771 Name & Namet.Get_Name_String
1772 (Data.Naming.Ada_Body_Suffix);
1774 First : Unit_Id := Unit_Table.First;
1779 Canonical_Case_File_Name (Original_Name);
1780 Canonical_Case_File_Name (Extended_Spec_Name);
1781 Canonical_Case_File_Name (Extended_Body_Name);
1783 if Current_Verbosity = High then
1784 Write_Str ("Looking for path name of """);
1788 Write_Str (" Extended Spec Name = """);
1789 Write_Str (Extended_Spec_Name);
1792 Write_Str (" Extended Body Name = """);
1793 Write_Str (Extended_Body_Name);
1798 while First <= Unit_Table.Last (In_Tree.Units)
1799 and then In_Tree.Units.Table
1800 (First).File_Names (Body_Part).Project /= Project
1806 while Current <= Unit_Table.Last (In_Tree.Units) loop
1807 Unit := In_Tree.Units.Table (Current);
1809 if Unit.File_Names (Body_Part).Project = Project
1810 and then Unit.File_Names (Body_Part).Name /= No_Name
1813 Current_Name : constant String :=
1814 Namet.Get_Name_String (Unit.File_Names (Body_Part).Name);
1816 if Current_Verbosity = High then
1817 Write_Str (" Comparing with """);
1818 Write_Str (Current_Name);
1823 if Current_Name = Original_Name then
1824 if Current_Verbosity = High then
1828 return Body_Path_Name_Of (Current, In_Tree);
1830 elsif Current_Name = Extended_Body_Name then
1831 if Current_Verbosity = High then
1835 return Body_Path_Name_Of (Current, In_Tree);
1838 if Current_Verbosity = High then
1839 Write_Line (" not good");
1844 elsif Unit.File_Names (Specification).Name /= No_Name then
1846 Current_Name : constant String :=
1847 Namet.Get_Name_String
1848 (Unit.File_Names (Specification).Name);
1851 if Current_Verbosity = High then
1852 Write_Str (" Comparing with """);
1853 Write_Str (Current_Name);
1858 if Current_Name = Original_Name then
1859 if Current_Verbosity = High then
1863 return Spec_Path_Name_Of (Current, In_Tree);
1865 elsif Current_Name = Extended_Spec_Name then
1866 if Current_Verbosity = High then
1870 return Spec_Path_Name_Of (Current, In_Tree);
1873 if Current_Verbosity = High then
1874 Write_Line (" not good");
1879 Current := Current + 1;
1883 end Path_Name_Of_Library_Unit_Body;
1889 -- Could use some comments in this body ???
1891 procedure Print_Sources (In_Tree : Project_Tree_Ref) is
1895 Write_Line ("List of Sources:");
1897 for Id in Unit_Table.First ..
1898 Unit_Table.Last (In_Tree.Units)
1900 Unit := In_Tree.Units.Table (Id);
1902 Write_Line (Namet.Get_Name_String (Unit.Name));
1904 if Unit.File_Names (Specification).Name /= No_Name then
1905 if Unit.File_Names (Specification).Project = No_Project then
1906 Write_Line (" No project");
1909 Write_Str (" Project: ");
1911 (In_Tree.Projects.Table
1912 (Unit.File_Names (Specification).Project).Path_Name);
1913 Write_Line (Name_Buffer (1 .. Name_Len));
1916 Write_Str (" spec: ");
1918 (Namet.Get_Name_String
1919 (Unit.File_Names (Specification).Name));
1922 if Unit.File_Names (Body_Part).Name /= No_Name then
1923 if Unit.File_Names (Body_Part).Project = No_Project then
1924 Write_Line (" No project");
1927 Write_Str (" Project: ");
1929 (In_Tree.Projects.Table
1930 (Unit.File_Names (Body_Part).Project).Path_Name);
1931 Write_Line (Name_Buffer (1 .. Name_Len));
1934 Write_Str (" body: ");
1936 (Namet.Get_Name_String
1937 (Unit.File_Names (Body_Part).Name));
1941 Write_Line ("end of List of Sources.");
1950 Main_Project : Project_Id;
1951 In_Tree : Project_Tree_Ref) return Project_Id
1953 Result : Project_Id := No_Project;
1955 Original_Name : String := Name;
1957 Data : constant Project_Data :=
1958 In_Tree.Projects.Table (Main_Project);
1960 Extended_Spec_Name : String :=
1961 Name & Namet.Get_Name_String
1962 (Data.Naming.Ada_Spec_Suffix);
1963 Extended_Body_Name : String :=
1964 Name & Namet.Get_Name_String
1965 (Data.Naming.Ada_Body_Suffix);
1969 Current_Name : Name_Id;
1971 The_Original_Name : Name_Id;
1972 The_Spec_Name : Name_Id;
1973 The_Body_Name : Name_Id;
1976 Canonical_Case_File_Name (Original_Name);
1977 Name_Len := Original_Name'Length;
1978 Name_Buffer (1 .. Name_Len) := Original_Name;
1979 The_Original_Name := Name_Find;
1981 Canonical_Case_File_Name (Extended_Spec_Name);
1982 Name_Len := Extended_Spec_Name'Length;
1983 Name_Buffer (1 .. Name_Len) := Extended_Spec_Name;
1984 The_Spec_Name := Name_Find;
1986 Canonical_Case_File_Name (Extended_Body_Name);
1987 Name_Len := Extended_Body_Name'Length;
1988 Name_Buffer (1 .. Name_Len) := Extended_Body_Name;
1989 The_Body_Name := Name_Find;
1991 for Current in reverse Unit_Table.First ..
1992 Unit_Table.Last (In_Tree.Units)
1994 Unit := In_Tree.Units.Table (Current);
1998 Current_Name := Unit.File_Names (Body_Part).Name;
2000 -- Case of a body present
2002 if Current_Name /= No_Name then
2004 -- If it has the name of the original name or the body name,
2005 -- we have found the project.
2007 if Unit.Name = The_Original_Name
2008 or else Current_Name = The_Original_Name
2009 or else Current_Name = The_Body_Name
2011 Result := Unit.File_Names (Body_Part).Project;
2018 Current_Name := Unit.File_Names (Specification).Name;
2020 if Current_Name /= No_Name then
2022 -- If name same as the original name, or the spec name, we have
2023 -- found the project.
2025 if Unit.Name = The_Original_Name
2026 or else Current_Name = The_Original_Name
2027 or else Current_Name = The_Spec_Name
2029 Result := Unit.File_Names (Specification).Project;
2035 -- Get the ultimate extending project
2037 if Result /= No_Project then
2038 while In_Tree.Projects.Table (Result).Extended_By /=
2041 Result := In_Tree.Projects.Table (Result).Extended_By;
2052 procedure Set_Ada_Paths
2053 (Project : Project_Id;
2054 In_Tree : Project_Tree_Ref;
2055 Including_Libraries : Boolean)
2057 Source_FD : File_Descriptor := Invalid_FD;
2058 Object_FD : File_Descriptor := Invalid_FD;
2060 Process_Source_Dirs : Boolean := False;
2061 Process_Object_Dirs : Boolean := False;
2064 -- For calls to Close
2068 procedure Add (Proj : Project_Id);
2069 -- Add all the source/object directories of a project to the path only
2070 -- if this project has not been visited. Calls an internal procedure
2071 -- recursively for projects being extended, and imported projects.
2077 procedure Add (Proj : Project_Id) is
2079 procedure Recursive_Add (Project : Project_Id);
2080 -- Recursive procedure to add the source/object paths of extended/
2081 -- imported projects.
2087 procedure Recursive_Add (Project : Project_Id) is
2089 -- If Seen is False, then the project has not yet been visited
2091 if not In_Tree.Projects.Table (Project).Seen then
2092 In_Tree.Projects.Table (Project).Seen := True;
2095 Data : constant Project_Data :=
2096 In_Tree.Projects.Table (Project);
2097 List : Project_List := Data.Imported_Projects;
2100 if Process_Source_Dirs then
2102 -- Add to path all source directories of this project
2103 -- if there are Ada sources.
2105 if In_Tree.Projects.Table
2106 (Project).Ada_Sources_Present
2108 Add_To_Source_Path (Data.Source_Dirs, In_Tree);
2112 if Process_Object_Dirs then
2114 -- Add to path the object directory of this project
2115 -- except if we don't include library project and
2116 -- this is a library project.
2118 if (Data.Library and then Including_Libraries)
2120 (Data.Object_Directory /= No_Name
2122 (not Including_Libraries or else not Data.Library))
2124 -- For a library project, add the library directory
2125 -- if there is no object directory or if the library
2126 -- directory contains ALI files; otherwise add the
2127 -- object directory.
2129 if Data.Library then
2130 if Data.Object_Directory = No_Name
2131 or else Contains_ALI_Files (Data.Library_Dir)
2133 Add_To_Object_Path (Data.Library_Dir, In_Tree);
2136 (Data.Object_Directory, In_Tree);
2139 -- For a non-library project, add the object
2140 -- directory, if it is not a virtual project, and
2141 -- if there are Ada sources. If there are no Ada
2142 -- sources, adding the object directory could
2143 -- disrupt the order of the object dirs in the path.
2145 elsif not Data.Virtual
2146 and then In_Tree.Projects.Table
2147 (Project).Ada_Sources_Present
2150 (Data.Object_Directory, In_Tree);
2155 -- Call Add to the project being extended, if any
2157 if Data.Extends /= No_Project then
2158 Recursive_Add (Data.Extends);
2161 -- Call Add for each imported project, if any
2163 while List /= Empty_Project_List loop
2165 (In_Tree.Project_Lists.Table
2168 In_Tree.Project_Lists.Table (List).Next;
2175 Source_Path_Table.Set_Last (In_Tree.Private_Part.Source_Paths, 0);
2176 Object_Path_Table.Set_Last (In_Tree.Private_Part.Object_Paths, 0);
2178 for Index in Project_Table.First ..
2179 Project_Table.Last (In_Tree.Projects)
2181 In_Tree.Projects.Table (Index).Seen := False;
2184 Recursive_Add (Proj);
2187 -- Start of processing for Set_Ada_Paths
2190 -- If it is the first time we call this procedure for
2191 -- this project, compute the source path and/or the object path.
2193 if In_Tree.Projects.Table (Project).Include_Path_File =
2196 Process_Source_Dirs := True;
2197 Create_New_Path_File
2198 (In_Tree, Source_FD,
2199 In_Tree.Projects.Table (Project).Include_Path_File);
2202 -- For the object path, we make a distinction depending on
2203 -- Including_Libraries.
2205 if Including_Libraries then
2206 if In_Tree.Projects.Table
2207 (Project).Objects_Path_File_With_Libs = No_Name
2209 Process_Object_Dirs := True;
2210 Create_New_Path_File
2211 (In_Tree, Object_FD, In_Tree.Projects.Table (Project).
2212 Objects_Path_File_With_Libs);
2216 if In_Tree.Projects.Table
2217 (Project).Objects_Path_File_Without_Libs = No_Name
2219 Process_Object_Dirs := True;
2220 Create_New_Path_File
2221 (In_Tree, Object_FD, In_Tree.Projects.Table (Project).
2222 Objects_Path_File_Without_Libs);
2226 -- If there is something to do, set Seen to False for all projects,
2227 -- then call the recursive procedure Add for Project.
2229 if Process_Source_Dirs or Process_Object_Dirs then
2233 -- Write and close any file that has been created.
2235 if Source_FD /= Invalid_FD then
2236 for Index in Source_Path_Table.First ..
2237 Source_Path_Table.Last
2238 (In_Tree.Private_Part.Source_Paths)
2240 Get_Name_String (In_Tree.Private_Part.Source_Paths.Table (Index));
2241 Name_Len := Name_Len + 1;
2242 Name_Buffer (Name_Len) := ASCII.LF;
2243 Len := Write (Source_FD, Name_Buffer (1)'Address, Name_Len);
2245 if Len /= Name_Len then
2246 Prj.Com.Fail ("disk full");
2250 Close (Source_FD, Status);
2253 Prj.Com.Fail ("disk full");
2257 if Object_FD /= Invalid_FD then
2258 for Index in Object_Path_Table.First ..
2259 Object_Path_Table.Last
2260 (In_Tree.Private_Part.Object_Paths)
2262 Get_Name_String (In_Tree.Private_Part.Object_Paths.Table (Index));
2263 Name_Len := Name_Len + 1;
2264 Name_Buffer (Name_Len) := ASCII.LF;
2265 Len := Write (Object_FD, Name_Buffer (1)'Address, Name_Len);
2267 if Len /= Name_Len then
2268 Prj.Com.Fail ("disk full");
2272 Close (Object_FD, Status);
2275 Prj.Com.Fail ("disk full");
2279 -- Set the env vars, if they need to be changed, and set the
2280 -- corresponding flags.
2282 if Current_Source_Path_File /=
2283 In_Tree.Projects.Table (Project).Include_Path_File
2285 Current_Source_Path_File :=
2286 In_Tree.Projects.Table (Project).Include_Path_File;
2288 (Project_Include_Path_File,
2289 Get_Name_String (Current_Source_Path_File));
2290 Ada_Prj_Include_File_Set := True;
2293 if Including_Libraries then
2294 if Current_Object_Path_File
2295 /= In_Tree.Projects.Table
2296 (Project).Objects_Path_File_With_Libs
2298 Current_Object_Path_File :=
2299 In_Tree.Projects.Table
2300 (Project).Objects_Path_File_With_Libs;
2302 (Project_Objects_Path_File,
2303 Get_Name_String (Current_Object_Path_File));
2304 Ada_Prj_Objects_File_Set := True;
2308 if Current_Object_Path_File /=
2309 In_Tree.Projects.Table
2310 (Project).Objects_Path_File_Without_Libs
2312 Current_Object_Path_File :=
2313 In_Tree.Projects.Table
2314 (Project).Objects_Path_File_Without_Libs;
2316 (Project_Objects_Path_File,
2317 Get_Name_String (Current_Object_Path_File));
2318 Ada_Prj_Objects_File_Set := True;
2323 ---------------------------------------------
2324 -- Set_Mapping_File_Initial_State_To_Empty --
2325 ---------------------------------------------
2327 procedure Set_Mapping_File_Initial_State_To_Empty is
2329 Fill_Mapping_File := False;
2330 end Set_Mapping_File_Initial_State_To_Empty;
2332 -----------------------
2333 -- Set_Path_File_Var --
2334 -----------------------
2336 procedure Set_Path_File_Var (Name : String; Value : String) is
2337 Host_Spec : String_Access := To_Host_File_Spec (Value);
2340 if Host_Spec = null then
2342 ("could not convert file name """, Value, """ to host spec");
2344 Setenv (Name, Host_Spec.all);
2347 end Set_Path_File_Var;
2349 -----------------------
2350 -- Spec_Path_Name_Of --
2351 -----------------------
2353 function Spec_Path_Name_Of
2354 (Unit : Unit_Id; In_Tree : Project_Tree_Ref) return String
2356 Data : Unit_Data := In_Tree.Units.Table (Unit);
2359 if Data.File_Names (Specification).Path = No_Name then
2361 Current_Source : String_List_Id :=
2362 In_Tree.Projects.Table
2363 (Data.File_Names (Specification).Project).Sources;
2364 Path : GNAT.OS_Lib.String_Access;
2367 Data.File_Names (Specification).Path :=
2368 Data.File_Names (Specification).Name;
2370 while Current_Source /= Nil_String loop
2371 Path := Locate_Regular_File
2372 (Namet.Get_Name_String
2373 (Data.File_Names (Specification).Name),
2374 Namet.Get_Name_String
2375 (In_Tree.String_Elements.Table
2376 (Current_Source).Value));
2378 if Path /= null then
2379 Name_Len := Path'Length;
2380 Name_Buffer (1 .. Name_Len) := Path.all;
2381 Data.File_Names (Specification).Path := Name_Enter;
2385 In_Tree.String_Elements.Table
2386 (Current_Source).Next;
2390 In_Tree.Units.Table (Unit) := Data;
2394 return Namet.Get_Name_String (Data.File_Names (Specification).Path);
2395 end Spec_Path_Name_Of;
2397 ---------------------------
2398 -- Ultimate_Extension_Of --
2399 ---------------------------
2401 function Ultimate_Extension_Of
2402 (Project : Project_Id; In_Tree : Project_Tree_Ref) return Project_Id
2404 Result : Project_Id := Project;
2407 while In_Tree.Projects.Table (Result).Extended_By /=
2410 Result := In_Tree.Projects.Table (Result).Extended_By;
2414 end Ultimate_Extension_Of;