1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2011, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
28 with Osint; use Osint;
29 with Output; use Output;
32 with Prj.Err; use Prj.Err;
33 with Snames; use Snames;
34 with Uintp; use Uintp;
36 with Ada.Characters.Handling; use Ada.Characters.Handling;
37 with Ada.Unchecked_Deallocation;
39 with GNAT.Case_Util; use GNAT.Case_Util;
40 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
45 Object_Suffix : constant String := Get_Target_Object_Suffix.all;
46 -- File suffix for object files
48 Initial_Buffer_Size : constant := 100;
49 -- Initial size for extensible buffer used in Add_To_Buffer
51 The_Empty_String : Name_Id := No_Name;
53 Debug_Level : Integer := 0;
54 -- Current indentation level for debug traces
56 type Cst_String_Access is access constant String;
58 All_Lower_Case_Image : aliased constant String := "lowercase";
59 All_Upper_Case_Image : aliased constant String := "UPPERCASE";
60 Mixed_Case_Image : aliased constant String := "MixedCase";
62 The_Casing_Images : constant array (Known_Casing) of Cst_String_Access :=
63 (All_Lower_Case => All_Lower_Case_Image'Access,
64 All_Upper_Case => All_Upper_Case_Image'Access,
65 Mixed_Case => Mixed_Case_Image'Access);
67 procedure Free (Project : in out Project_Id);
68 -- Free memory allocated for Project
70 procedure Free_List (Languages : in out Language_Ptr);
71 procedure Free_List (Source : in out Source_Id);
72 procedure Free_List (Languages : in out Language_List);
73 -- Free memory allocated for the list of languages or sources
75 procedure Reset_Units_In_Table (Table : in out Units_Htable.Instance);
76 -- Resets all Units to No_Unit_Index Unit.File_Names (Spec).Unit &
77 -- Unit.File_Names (Impl).Unit in the given table.
79 procedure Free_Units (Table : in out Units_Htable.Instance);
80 -- Free memory allocated for unit information in the project
82 procedure Language_Changed (Iter : in out Source_Iterator);
83 procedure Project_Changed (Iter : in out Source_Iterator);
84 -- Called when a new project or language was selected for this iterator
86 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean;
87 -- Return True if there is at least one ALI file in the directory Dir
93 procedure Add_To_Buffer
95 To : in out String_Access;
96 Last : in out Natural)
100 To := new String (1 .. Initial_Buffer_Size);
104 -- If Buffer is too small, double its size
106 while Last + S'Length > To'Last loop
108 New_Buffer : constant String_Access :=
109 new String (1 .. 2 * Last);
112 New_Buffer (1 .. Last) := To (1 .. Last);
118 To (Last + 1 .. Last + S'Length) := S;
119 Last := Last + S'Length;
122 ---------------------------------
123 -- Current_Object_Path_File_Of --
124 ---------------------------------
126 function Current_Object_Path_File_Of
127 (Shared : Shared_Project_Tree_Data_Access) return Path_Name_Type
130 return Shared.Private_Part.Current_Object_Path_File;
131 end Current_Object_Path_File_Of;
133 ---------------------------------
134 -- Current_Source_Path_File_Of --
135 ---------------------------------
137 function Current_Source_Path_File_Of
138 (Shared : Shared_Project_Tree_Data_Access)
139 return Path_Name_Type is
141 return Shared.Private_Part.Current_Source_Path_File;
142 end Current_Source_Path_File_Of;
144 ---------------------------
145 -- Delete_Temporary_File --
146 ---------------------------
148 procedure Delete_Temporary_File
149 (Shared : Shared_Project_Tree_Data_Access := null;
150 Path : Path_Name_Type)
153 pragma Warnings (Off, Dont_Care);
156 if not Debug.Debug_Flag_N then
157 if Current_Verbosity = High then
158 Write_Line ("Removing temp file: " & Get_Name_String (Path));
161 Delete_File (Get_Name_String (Path), Dont_Care);
163 if Shared /= null then
165 1 .. Temp_Files_Table.Last (Shared.Private_Part.Temp_Files)
167 if Shared.Private_Part.Temp_Files.Table (Index) = Path then
168 Shared.Private_Part.Temp_Files.Table (Index) := No_Path;
173 end Delete_Temporary_File;
175 ------------------------------
176 -- Delete_Temp_Config_Files --
177 ------------------------------
179 procedure Delete_Temp_Config_Files (Project_Tree : Project_Tree_Ref) is
181 pragma Warnings (Off, Success);
186 if not Debug.Debug_Flag_N then
187 if Project_Tree /= null then
188 Proj := Project_Tree.Projects;
189 while Proj /= null loop
190 if Proj.Project.Config_File_Temp then
191 Delete_Temporary_File
192 (Project_Tree.Shared, Proj.Project.Config_File_Name);
194 -- Make sure that we don't have a config file for this
195 -- project, in case there are several mains. In this case,
196 -- we will recreate another config file: we cannot reuse the
197 -- one that we just deleted!
199 Proj.Project.Config_Checked := False;
200 Proj.Project.Config_File_Name := No_Path;
201 Proj.Project.Config_File_Temp := False;
208 end Delete_Temp_Config_Files;
210 ---------------------------
211 -- Delete_All_Temp_Files --
212 ---------------------------
214 procedure Delete_All_Temp_Files
215 (Shared : Shared_Project_Tree_Data_Access)
218 pragma Warnings (Off, Dont_Care);
220 Path : Path_Name_Type;
223 if not Debug.Debug_Flag_N then
225 1 .. Temp_Files_Table.Last (Shared.Private_Part.Temp_Files)
227 Path := Shared.Private_Part.Temp_Files.Table (Index);
229 if Path /= No_Path then
230 if Current_Verbosity = High then
231 Write_Line ("Removing temp file: "
232 & Get_Name_String (Path));
235 Delete_File (Get_Name_String (Path), Dont_Care);
239 Temp_Files_Table.Free (Shared.Private_Part.Temp_Files);
240 Temp_Files_Table.Init (Shared.Private_Part.Temp_Files);
243 -- If any of the environment variables ADA_PRJ_INCLUDE_FILE or
244 -- ADA_PRJ_OBJECTS_FILE has been set, then reset their value to
245 -- the empty string. On VMS, this has the effect of deassigning
246 -- the logical names.
248 if Shared.Private_Part.Current_Source_Path_File /= No_Path then
249 Setenv (Project_Include_Path_File, "");
252 if Shared.Private_Part.Current_Object_Path_File /= No_Path then
253 Setenv (Project_Objects_Path_File, "");
255 end Delete_All_Temp_Files;
257 ---------------------
258 -- Dependency_Name --
259 ---------------------
261 function Dependency_Name
262 (Source_File_Name : File_Name_Type;
263 Dependency : Dependency_File_Kind) return File_Name_Type
271 return Extend_Name (Source_File_Name, Makefile_Dependency_Suffix);
274 return Extend_Name (Source_File_Name, ALI_Dependency_Suffix);
282 function Empty_File return File_Name_Type is
284 return File_Name_Type (The_Empty_String);
291 function Empty_Project
292 (Qualifier : Project_Qualifier) return Project_Data
295 Prj.Initialize (Tree => No_Project_Tree);
298 Data : Project_Data (Qualifier => Qualifier);
301 -- Only the fields for which no default value could be provided in
302 -- prj.ads are initialized below.
304 Data.Config := Default_Project_Config;
313 function Empty_String return Name_Id is
315 return The_Empty_String;
322 procedure Expect (The_Token : Token_Type; Token_Image : String) is
324 if Token /= The_Token then
326 -- ??? Should pass user flags here instead
328 Error_Msg (Gnatmake_Flags, Token_Image & " expected", Token_Ptr);
337 (File : File_Name_Type;
338 With_Suffix : String) return File_Name_Type
343 Get_Name_String (File);
344 Last := Name_Len + 1;
346 while Name_Len /= 0 and then Name_Buffer (Name_Len) /= '.' loop
347 Name_Len := Name_Len - 1;
350 if Name_Len <= 1 then
354 for J in With_Suffix'Range loop
355 Name_Buffer (Name_Len) := With_Suffix (J);
356 Name_Len := Name_Len + 1;
359 Name_Len := Name_Len - 1;
363 ---------------------
364 -- Project_Changed --
365 ---------------------
367 procedure Project_Changed (Iter : in out Source_Iterator) is
369 if Iter.Project /= null then
370 Iter.Language := Iter.Project.Project.Languages;
371 Language_Changed (Iter);
375 ----------------------
376 -- Language_Changed --
377 ----------------------
379 procedure Language_Changed (Iter : in out Source_Iterator) is
381 Iter.Current := No_Source;
383 if Iter.Language_Name /= No_Name then
384 while Iter.Language /= null
385 and then Iter.Language.Name /= Iter.Language_Name
387 Iter.Language := Iter.Language.Next;
391 -- If there is no matching language in this project, move to next
393 if Iter.Language = No_Language_Index then
394 if Iter.All_Projects then
395 Iter.Project := Iter.Project.Next;
396 Project_Changed (Iter);
398 Iter.Project := null;
402 Iter.Current := Iter.Language.First_Source;
404 if Iter.Current = No_Source then
405 Iter.Language := Iter.Language.Next;
406 Language_Changed (Iter);
409 end Language_Changed;
411 ---------------------
412 -- For_Each_Source --
413 ---------------------
415 function For_Each_Source
416 (In_Tree : Project_Tree_Ref;
417 Project : Project_Id := No_Project;
418 Language : Name_Id := No_Name) return Source_Iterator
420 Iter : Source_Iterator;
422 Iter := Source_Iterator'
424 Project => In_Tree.Projects,
425 All_Projects => Project = No_Project,
426 Language_Name => Language,
427 Language => No_Language_Index,
428 Current => No_Source);
430 if Project /= null then
431 while Iter.Project /= null
432 and then Iter.Project.Project /= Project
434 Iter.Project := Iter.Project.Next;
438 Project_Changed (Iter);
447 function Element (Iter : Source_Iterator) return Source_Id is
456 procedure Next (Iter : in out Source_Iterator) is
458 Iter.Current := Iter.Current.Next_In_Lang;
459 if Iter.Current = No_Source then
460 Iter.Language := Iter.Language.Next;
461 Language_Changed (Iter);
465 --------------------------------
466 -- For_Every_Project_Imported --
467 --------------------------------
469 procedure For_Every_Project_Imported
471 Tree : Project_Tree_Ref;
472 With_State : in out State;
473 Include_Aggregated : Boolean := True;
474 Imported_First : Boolean := False)
476 use Project_Boolean_Htable;
477 Seen : Project_Boolean_Htable.Instance := Project_Boolean_Htable.Nil;
479 procedure Recursive_Check
480 (Project : Project_Id;
481 Tree : Project_Tree_Ref);
482 -- Check if a project has already been seen. If not seen, mark it as
483 -- Seen, Call Action, and check all its imported projects.
485 ---------------------
486 -- Recursive_Check --
487 ---------------------
489 procedure Recursive_Check
490 (Project : Project_Id;
491 Tree : Project_Tree_Ref)
496 if not Get (Seen, Project) then
497 -- Even if a project is aggregated multiple times, we will only
500 Set (Seen, Project, True);
502 if not Imported_First then
503 Action (Project, Tree, With_State);
506 -- Visit all extended projects
508 if Project.Extends /= No_Project then
509 Recursive_Check (Project.Extends, Tree);
512 -- Visit all imported projects
514 List := Project.Imported_Projects;
515 while List /= null loop
516 Recursive_Check (List.Project, Tree);
520 -- Visit all aggregated projects
522 if Include_Aggregated
523 and then Project.Qualifier in Aggregate_Project
526 Agg : Aggregated_Project_List;
528 Agg := Project.Aggregated_Projects;
529 while Agg /= null loop
530 pragma Assert (Agg.Project /= No_Project);
531 Recursive_Check (Agg.Project, Agg.Tree);
537 if Imported_First then
538 Action (Project, Tree, With_State);
543 -- Start of processing for For_Every_Project_Imported
546 Recursive_Check (Project => By, Tree => Tree);
548 end For_Every_Project_Imported;
555 (In_Tree : Project_Tree_Ref;
556 Project : Project_Id;
557 In_Imported_Only : Boolean := False;
558 In_Extended_Only : Boolean := False;
559 Base_Name : File_Name_Type;
560 Index : Int := 0) return Source_Id
562 Result : Source_Id := No_Source;
564 procedure Look_For_Sources
566 Tree : Project_Tree_Ref;
567 Src : in out Source_Id);
568 -- Look for Base_Name in the sources of Proj
570 ----------------------
571 -- Look_For_Sources --
572 ----------------------
574 procedure Look_For_Sources
576 Tree : Project_Tree_Ref;
577 Src : in out Source_Id)
579 Iterator : Source_Iterator;
582 Iterator := For_Each_Source (In_Tree => Tree, Project => Proj);
583 while Element (Iterator) /= No_Source loop
584 if Element (Iterator).File = Base_Name
585 and then (Index = 0 or else Element (Iterator).Index = Index)
587 Src := Element (Iterator);
589 -- If the source has been excluded, continue looking. We will
590 -- get the excluded source only if there is no other source
591 -- with the same base name that is not locally removed.
593 if not Element (Iterator).Locally_Removed then
600 end Look_For_Sources;
602 procedure For_Imported_Projects is new For_Every_Project_Imported
603 (State => Source_Id, Action => Look_For_Sources);
607 -- Start of processing for Find_Source
610 if In_Extended_Only then
612 while Proj /= No_Project loop
613 Look_For_Sources (Proj, In_Tree, Result);
614 exit when Result /= No_Source;
616 Proj := Proj.Extends;
619 elsif In_Imported_Only then
620 Look_For_Sources (Project, In_Tree, Result);
622 if Result = No_Source then
623 For_Imported_Projects
626 Include_Aggregated => False,
627 With_State => Result);
631 Look_For_Sources (No_Project, In_Tree, Result);
641 function Hash is new GNAT.HTable.Hash (Header_Num => Header_Num);
642 -- Used in implementation of other functions Hash below
644 function Hash (Name : File_Name_Type) return Header_Num is
646 return Hash (Get_Name_String (Name));
649 function Hash (Name : Name_Id) return Header_Num is
651 return Hash (Get_Name_String (Name));
654 function Hash (Name : Path_Name_Type) return Header_Num is
656 return Hash (Get_Name_String (Name));
659 function Hash (Project : Project_Id) return Header_Num is
661 if Project = No_Project then
662 return Header_Num'First;
664 return Hash (Get_Name_String (Project.Name));
672 function Image (The_Casing : Casing_Type) return String is
674 return The_Casing_Images (The_Casing).all;
677 -----------------------------
678 -- Is_Standard_GNAT_Naming --
679 -----------------------------
681 function Is_Standard_GNAT_Naming
682 (Naming : Lang_Naming_Data) return Boolean
685 return Get_Name_String (Naming.Spec_Suffix) = ".ads"
686 and then Get_Name_String (Naming.Body_Suffix) = ".adb"
687 and then Get_Name_String (Naming.Dot_Replacement) = "-";
688 end Is_Standard_GNAT_Naming;
694 procedure Initialize (Tree : Project_Tree_Ref) is
696 if The_Empty_String = No_Name then
699 The_Empty_String := Name_Find;
703 -- Make sure that new reserved words after Ada 95 may be used as
706 Opt.Ada_Version := Opt.Ada_95;
708 Set_Name_Table_Byte (Name_Project, Token_Type'Pos (Tok_Project));
709 Set_Name_Table_Byte (Name_Extends, Token_Type'Pos (Tok_Extends));
710 Set_Name_Table_Byte (Name_External, Token_Type'Pos (Tok_External));
712 (Name_External_As_List, Token_Type'Pos (Tok_External_As_List));
715 if Tree /= No_Project_Tree then
724 function Is_Extending
725 (Extending : Project_Id;
726 Extended : Project_Id) return Boolean
732 while Proj /= No_Project loop
733 if Proj = Extended then
737 Proj := Proj.Extends;
748 (Source_File_Name : File_Name_Type;
749 Object_File_Suffix : Name_Id := No_Name) return File_Name_Type
752 if Object_File_Suffix = No_Name then
754 (Source_File_Name, Object_Suffix);
757 (Source_File_Name, Get_Name_String (Object_File_Suffix));
762 (Source_File_Name : File_Name_Type;
764 Index_Separator : Character;
765 Object_File_Suffix : Name_Id := No_Name) return File_Name_Type
767 Index_Img : constant String := Source_Index'Img;
771 Get_Name_String (Source_File_Name);
774 while Last > 1 and then Name_Buffer (Last) /= '.' loop
779 Name_Len := Last - 1;
782 Add_Char_To_Name_Buffer (Index_Separator);
783 Add_Str_To_Name_Buffer (Index_Img (2 .. Index_Img'Last));
785 if Object_File_Suffix = No_Name then
786 Add_Str_To_Name_Buffer (Object_Suffix);
788 Add_Str_To_Name_Buffer (Get_Name_String (Object_File_Suffix));
794 ----------------------
795 -- Record_Temp_File --
796 ----------------------
798 procedure Record_Temp_File
799 (Shared : Shared_Project_Tree_Data_Access;
800 Path : Path_Name_Type)
803 Temp_Files_Table.Append (Shared.Private_Part.Temp_Files, Path);
804 end Record_Temp_File;
810 procedure Free (List : in out Aggregated_Project_List) is
811 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
812 (Aggregated_Project, Aggregated_Project_List);
813 Tmp : Aggregated_Project_List;
815 while List /= null loop
820 Unchecked_Free (List);
825 ----------------------------
826 -- Add_Aggregated_Project --
827 ----------------------------
829 procedure Add_Aggregated_Project
830 (Project : Project_Id; Path : Path_Name_Type) is
832 Project.Aggregated_Projects := new Aggregated_Project'
834 Project => No_Project,
836 Next => Project.Aggregated_Projects);
837 end Add_Aggregated_Project;
843 procedure Free (Project : in out Project_Id) is
844 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
845 (Project_Data, Project_Id);
848 if Project /= null then
849 Free (Project.Ada_Include_Path);
850 Free (Project.Objects_Path);
851 Free (Project.Ada_Objects_Path);
852 Free_List (Project.Imported_Projects, Free_Project => False);
853 Free_List (Project.All_Imported_Projects, Free_Project => False);
854 Free_List (Project.Languages);
856 case Project.Qualifier is
857 when Aggregate | Aggregate_Library =>
858 Free (Project.Aggregated_Projects);
864 Unchecked_Free (Project);
872 procedure Free_List (Languages : in out Language_List) is
873 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
874 (Language_List_Element, Language_List);
877 while Languages /= null loop
878 Tmp := Languages.Next;
879 Unchecked_Free (Languages);
888 procedure Free_List (Source : in out Source_Id) is
889 procedure Unchecked_Free is new
890 Ada.Unchecked_Deallocation (Source_Data, Source_Id);
895 while Source /= No_Source loop
896 Tmp := Source.Next_In_Lang;
897 Free_List (Source.Alternate_Languages);
899 if Source.Unit /= null
900 and then Source.Kind in Spec_Or_Body
902 Source.Unit.File_Names (Source.Kind) := null;
905 Unchecked_Free (Source);
915 (List : in out Project_List;
916 Free_Project : Boolean)
918 procedure Unchecked_Free is new
919 Ada.Unchecked_Deallocation (Project_List_Element, Project_List);
924 while List /= null loop
931 Unchecked_Free (List);
940 procedure Free_List (Languages : in out Language_Ptr) is
941 procedure Unchecked_Free is new
942 Ada.Unchecked_Deallocation (Language_Data, Language_Ptr);
947 while Languages /= null loop
948 Tmp := Languages.Next;
949 Free_List (Languages.First_Source);
950 Unchecked_Free (Languages);
955 --------------------------
956 -- Reset_Units_In_Table --
957 --------------------------
959 procedure Reset_Units_In_Table (Table : in out Units_Htable.Instance) is
963 Unit := Units_Htable.Get_First (Table);
964 while Unit /= No_Unit_Index loop
965 if Unit.File_Names (Spec) /= null then
966 Unit.File_Names (Spec).Unit := No_Unit_Index;
969 if Unit.File_Names (Impl) /= null then
970 Unit.File_Names (Impl).Unit := No_Unit_Index;
973 Unit := Units_Htable.Get_Next (Table);
975 end Reset_Units_In_Table;
981 procedure Free_Units (Table : in out Units_Htable.Instance) is
982 procedure Unchecked_Free is new
983 Ada.Unchecked_Deallocation (Unit_Data, Unit_Index);
988 Unit := Units_Htable.Get_First (Table);
989 while Unit /= No_Unit_Index loop
991 -- We cannot reset Unit.File_Names (Impl or Spec).Unit here as
992 -- Source_Data buffer is freed by the following instruction
993 -- Free_List (Tree.Projects, Free_Project => True);
995 Unchecked_Free (Unit);
996 Unit := Units_Htable.Get_Next (Table);
999 Units_Htable.Reset (Table);
1006 procedure Free (Tree : in out Project_Tree_Ref) is
1007 procedure Unchecked_Free is new
1008 Ada.Unchecked_Deallocation
1009 (Project_Tree_Data, Project_Tree_Ref);
1011 procedure Unchecked_Free is new
1012 Ada.Unchecked_Deallocation
1013 (Project_Tree_Appdata'Class, Project_Tree_Appdata_Access);
1016 if Tree /= null then
1017 if Tree.Is_Root_Tree then
1018 Name_List_Table.Free (Tree.Shared.Name_Lists);
1019 Number_List_Table.Free (Tree.Shared.Number_Lists);
1020 String_Element_Table.Free (Tree.Shared.String_Elements);
1021 Variable_Element_Table.Free (Tree.Shared.Variable_Elements);
1022 Array_Element_Table.Free (Tree.Shared.Array_Elements);
1023 Array_Table.Free (Tree.Shared.Arrays);
1024 Package_Table.Free (Tree.Shared.Packages);
1025 Temp_Files_Table.Free (Tree.Shared.Private_Part.Temp_Files);
1028 if Tree.Appdata /= null then
1029 Free (Tree.Appdata.all);
1030 Unchecked_Free (Tree.Appdata);
1033 Source_Paths_Htable.Reset (Tree.Source_Paths_HT);
1034 Source_Files_Htable.Reset (Tree.Source_Files_HT);
1036 Reset_Units_In_Table (Tree.Units_HT);
1037 Free_List (Tree.Projects, Free_Project => True);
1038 Free_Units (Tree.Units_HT);
1040 Unchecked_Free (Tree);
1048 procedure Reset (Tree : Project_Tree_Ref) is
1052 if Tree.Is_Root_Tree then
1054 -- We cannot use 'Access here:
1055 -- "illegal attribute for discriminant-dependent component"
1056 -- However, we know this is valid since Shared and Shared_Data have
1057 -- the same lifetime and will always exist concurrently.
1059 Tree.Shared := Tree.Shared_Data'Unrestricted_Access;
1060 Name_List_Table.Init (Tree.Shared.Name_Lists);
1061 Number_List_Table.Init (Tree.Shared.Number_Lists);
1062 String_Element_Table.Init (Tree.Shared.String_Elements);
1063 Variable_Element_Table.Init (Tree.Shared.Variable_Elements);
1064 Array_Element_Table.Init (Tree.Shared.Array_Elements);
1065 Array_Table.Init (Tree.Shared.Arrays);
1066 Package_Table.Init (Tree.Shared.Packages);
1068 -- Private part table
1070 Temp_Files_Table.Init (Tree.Shared.Private_Part.Temp_Files);
1072 Tree.Shared.Private_Part.Current_Source_Path_File := No_Path;
1073 Tree.Shared.Private_Part.Current_Object_Path_File := No_Path;
1076 Source_Paths_Htable.Reset (Tree.Source_Paths_HT);
1077 Source_Files_Htable.Reset (Tree.Source_Files_HT);
1078 Replaced_Source_HTable.Reset (Tree.Replaced_Sources);
1080 Tree.Replaced_Source_Number := 0;
1082 Reset_Units_In_Table (Tree.Units_HT);
1083 Free_List (Tree.Projects, Free_Project => True);
1084 Free_Units (Tree.Units_HT);
1087 -------------------------------------
1088 -- Set_Current_Object_Path_File_Of --
1089 -------------------------------------
1091 procedure Set_Current_Object_Path_File_Of
1092 (Shared : Shared_Project_Tree_Data_Access;
1093 To : Path_Name_Type)
1096 Shared.Private_Part.Current_Object_Path_File := To;
1097 end Set_Current_Object_Path_File_Of;
1099 -------------------------------------
1100 -- Set_Current_Source_Path_File_Of --
1101 -------------------------------------
1103 procedure Set_Current_Source_Path_File_Of
1104 (Shared : Shared_Project_Tree_Data_Access;
1105 To : Path_Name_Type)
1108 Shared.Private_Part.Current_Source_Path_File := To;
1109 end Set_Current_Source_Path_File_Of;
1111 -----------------------
1112 -- Set_Path_File_Var --
1113 -----------------------
1115 procedure Set_Path_File_Var (Name : String; Value : String) is
1116 Host_Spec : String_Access := To_Host_File_Spec (Value);
1118 if Host_Spec = null then
1120 ("could not convert file name """ & Value & """ to host spec");
1122 Setenv (Name, Host_Spec.all);
1125 end Set_Path_File_Var;
1131 function Switches_Name
1132 (Source_File_Name : File_Name_Type) return File_Name_Type
1135 return Extend_Name (Source_File_Name, Switches_Dependency_Suffix);
1142 function Value (Image : String) return Casing_Type is
1144 for Casing in The_Casing_Images'Range loop
1145 if To_Lower (Image) = To_Lower (The_Casing_Images (Casing).all) then
1150 raise Constraint_Error;
1153 ---------------------
1154 -- Has_Ada_Sources --
1155 ---------------------
1157 function Has_Ada_Sources (Data : Project_Id) return Boolean is
1158 Lang : Language_Ptr;
1161 Lang := Data.Languages;
1162 while Lang /= No_Language_Index loop
1163 if Lang.Name = Name_Ada then
1164 return Lang.First_Source /= No_Source;
1170 end Has_Ada_Sources;
1172 ------------------------
1173 -- Contains_ALI_Files --
1174 ------------------------
1176 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean is
1177 Dir_Name : constant String := Get_Name_String (Dir);
1179 Name : String (1 .. 1_000);
1181 Result : Boolean := False;
1184 Open (Direct, Dir_Name);
1186 -- For each file in the directory, check if it is an ALI file
1189 Read (Direct, Name, Last);
1191 Canonical_Case_File_Name (Name (1 .. Last));
1192 Result := Last >= 5 and then Name (Last - 3 .. Last) = ".ali";
1200 -- If there is any problem, close the directory if open and return True.
1201 -- The library directory will be added to the path.
1204 if Is_Open (Direct) then
1209 end Contains_ALI_Files;
1211 --------------------------
1212 -- Get_Object_Directory --
1213 --------------------------
1215 function Get_Object_Directory
1216 (Project : Project_Id;
1217 Including_Libraries : Boolean;
1218 Only_If_Ada : Boolean := False) return Path_Name_Type
1221 if (Project.Library and then Including_Libraries)
1223 (Project.Object_Directory /= No_Path_Information
1224 and then (not Including_Libraries or else not Project.Library))
1226 -- For a library project, add the library ALI directory if there is
1227 -- no object directory or if the library ALI directory contains ALI
1228 -- files; otherwise add the object directory.
1230 if Project.Library then
1231 if Project.Object_Directory = No_Path_Information
1232 or else Contains_ALI_Files (Project.Library_ALI_Dir.Display_Name)
1234 return Project.Library_ALI_Dir.Display_Name;
1236 return Project.Object_Directory.Display_Name;
1239 -- For a non-library project, add object directory if it is not a
1240 -- virtual project, and if there are Ada sources in the project or
1241 -- one of the projects it extends. If there are no Ada sources,
1242 -- adding the object directory could disrupt the order of the
1243 -- object dirs in the path.
1245 elsif not Project.Virtual then
1247 Add_Object_Dir : Boolean;
1251 Add_Object_Dir := not Only_If_Ada;
1253 while not Add_Object_Dir and then Prj /= No_Project loop
1254 if Has_Ada_Sources (Prj) then
1255 Add_Object_Dir := True;
1261 if Add_Object_Dir then
1262 return Project.Object_Directory.Display_Name;
1269 end Get_Object_Directory;
1271 -----------------------------------
1272 -- Ultimate_Extending_Project_Of --
1273 -----------------------------------
1275 function Ultimate_Extending_Project_Of
1276 (Proj : Project_Id) return Project_Id
1282 while Prj /= null and then Prj.Extended_By /= No_Project loop
1283 Prj := Prj.Extended_By;
1287 end Ultimate_Extending_Project_Of;
1289 -----------------------------------
1290 -- Compute_All_Imported_Projects --
1291 -----------------------------------
1293 procedure Compute_All_Imported_Projects
1294 (Root_Project : Project_Id;
1295 Tree : Project_Tree_Ref)
1297 procedure Analyze_Tree
1298 (Local_Root : Project_Id;
1299 Local_Tree : Project_Tree_Ref);
1300 -- Process Project and all its aggregated project to analyze their own
1301 -- imported projects.
1307 procedure Analyze_Tree
1308 (Local_Root : Project_Id;
1309 Local_Tree : Project_Tree_Ref)
1311 pragma Unreferenced (Local_Root);
1313 Project : Project_Id;
1315 procedure Recursive_Add
1317 Tree : Project_Tree_Ref;
1318 Dummy : in out Boolean);
1319 -- Recursively add the projects imported by project Project, but not
1320 -- those that are extended.
1326 procedure Recursive_Add
1328 Tree : Project_Tree_Ref;
1329 Dummy : in out Boolean)
1331 pragma Unreferenced (Dummy, Tree);
1332 List : Project_List;
1336 -- A project is not importing itself
1338 Prj2 := Ultimate_Extending_Project_Of (Prj);
1340 if Project /= Prj2 then
1342 -- Check that the project is not already in the list. We know
1343 -- the one passed to Recursive_Add have never been visited
1344 -- before, but the one passed it are the extended projects.
1346 List := Project.All_Imported_Projects;
1347 while List /= null loop
1348 if List.Project = Prj2 then
1355 -- Add it to the list
1357 Project.All_Imported_Projects :=
1358 new Project_List_Element'
1360 Next => Project.All_Imported_Projects);
1364 procedure For_All_Projects is
1365 new For_Every_Project_Imported (Boolean, Recursive_Add);
1367 Dummy : Boolean := False;
1368 List : Project_List;
1371 List := Local_Tree.Projects;
1372 while List /= null loop
1373 Project := List.Project;
1375 (Project.All_Imported_Projects, Free_Project => False);
1377 (Project, Local_Tree, Dummy, Include_Aggregated => False);
1382 procedure For_Aggregates is
1383 new For_Project_And_Aggregated (Analyze_Tree);
1385 -- Start of processing for Compute_All_Imported_Projects
1388 For_Aggregates (Root_Project, Tree);
1389 end Compute_All_Imported_Projects;
1395 function Is_Compilable (Source : Source_Id) return Boolean is
1397 case Source.Compilable is
1399 if Source.Language.Config.Compiler_Driver /= No_File
1401 Length_Of_Name (Source.Language.Config.Compiler_Driver) /= 0
1402 and then not Source.Locally_Removed
1403 and then (Source.Language.Config.Kind /= File_Based
1404 or else Source.Kind /= Spec)
1406 -- Do not modify Source.Compilable before the source record
1407 -- has been initialized.
1409 if Source.Source_TS /= Empty_Time_Stamp then
1410 Source.Compilable := Yes;
1416 if Source.Source_TS /= Empty_Time_Stamp then
1417 Source.Compilable := No;
1431 ------------------------------
1432 -- Object_To_Global_Archive --
1433 ------------------------------
1435 function Object_To_Global_Archive (Source : Source_Id) return Boolean is
1437 return Source.Language.Config.Kind = File_Based
1438 and then Source.Kind = Impl
1439 and then Source.Language.Config.Objects_Linked
1440 and then Is_Compilable (Source)
1441 and then Source.Language.Config.Object_Generated;
1442 end Object_To_Global_Archive;
1444 ----------------------------
1445 -- Get_Language_From_Name --
1446 ----------------------------
1448 function Get_Language_From_Name
1449 (Project : Project_Id;
1450 Name : String) return Language_Ptr
1453 Result : Language_Ptr;
1456 Name_Len := Name'Length;
1457 Name_Buffer (1 .. Name_Len) := Name;
1458 To_Lower (Name_Buffer (1 .. Name_Len));
1461 Result := Project.Languages;
1462 while Result /= No_Language_Index loop
1463 if Result.Name = N then
1467 Result := Result.Next;
1470 return No_Language_Index;
1471 end Get_Language_From_Name;
1477 function Other_Part (Source : Source_Id) return Source_Id is
1479 if Source.Unit /= No_Unit_Index then
1482 return Source.Unit.File_Names (Spec);
1484 return Source.Unit.File_Names (Impl);
1497 function Create_Flags
1498 (Report_Error : Error_Handler;
1499 When_No_Sources : Error_Warning;
1500 Require_Sources_Other_Lang : Boolean := True;
1501 Allow_Duplicate_Basenames : Boolean := True;
1502 Compiler_Driver_Mandatory : Boolean := False;
1503 Error_On_Unknown_Language : Boolean := True;
1504 Require_Obj_Dirs : Error_Warning := Error;
1505 Allow_Invalid_External : Error_Warning := Error;
1506 Missing_Source_Files : Error_Warning := Error;
1507 Ignore_Missing_With : Boolean := False)
1508 return Processing_Flags
1511 return Processing_Flags'
1512 (Report_Error => Report_Error,
1513 When_No_Sources => When_No_Sources,
1514 Require_Sources_Other_Lang => Require_Sources_Other_Lang,
1515 Allow_Duplicate_Basenames => Allow_Duplicate_Basenames,
1516 Error_On_Unknown_Language => Error_On_Unknown_Language,
1517 Compiler_Driver_Mandatory => Compiler_Driver_Mandatory,
1518 Require_Obj_Dirs => Require_Obj_Dirs,
1519 Allow_Invalid_External => Allow_Invalid_External,
1520 Missing_Source_Files => Missing_Source_Files,
1521 Ignore_Missing_With => Ignore_Missing_With);
1529 (Table : Name_List_Table.Instance;
1530 List : Name_List_Index) return Natural
1532 Count : Natural := 0;
1533 Tmp : Name_List_Index;
1537 while Tmp /= No_Name_List loop
1539 Tmp := Table.Table (Tmp).Next;
1549 procedure Debug_Output (Str : String) is
1551 if Current_Verbosity > Default then
1552 Write_Line ((1 .. Debug_Level * 2 => ' ') & Str);
1560 procedure Debug_Indent is
1562 if Current_Verbosity = High then
1563 Write_Str ((1 .. Debug_Level * 2 => ' '));
1571 procedure Debug_Output (Str : String; Str2 : Name_Id) is
1573 if Current_Verbosity = High then
1577 if Str2 = No_Name then
1578 Write_Line (" <no_name>");
1580 Write_Line (" """ & Get_Name_String (Str2) & '"');
1585 ---------------------------
1586 -- Debug_Increase_Indent --
1587 ---------------------------
1589 procedure Debug_Increase_Indent
1590 (Str : String := ""; Str2 : Name_Id := No_Name)
1593 if Str2 /= No_Name then
1594 Debug_Output (Str, Str2);
1598 Debug_Level := Debug_Level + 1;
1599 end Debug_Increase_Indent;
1601 ---------------------------
1602 -- Debug_Decrease_Indent --
1603 ---------------------------
1605 procedure Debug_Decrease_Indent (Str : String := "") is
1607 if Debug_Level > 0 then
1608 Debug_Level := Debug_Level - 1;
1614 end Debug_Decrease_Indent;
1620 function Debug_Name (Tree : Project_Tree_Ref) return Name_Id is
1625 Add_Str_To_Name_Buffer ("Tree [");
1628 while P /= null loop
1629 if P /= Tree.Projects then
1630 Add_Char_To_Name_Buffer (',');
1633 Add_Str_To_Name_Buffer (Get_Name_String (P.Project.Name));
1638 Add_Char_To_Name_Buffer (']');
1647 procedure Free (Tree : in out Project_Tree_Appdata) is
1648 pragma Unreferenced (Tree);
1653 --------------------------------
1654 -- For_Project_And_Aggregated --
1655 --------------------------------
1657 procedure For_Project_And_Aggregated
1658 (Root_Project : Project_Id;
1659 Root_Tree : Project_Tree_Ref)
1661 Agg : Aggregated_Project_List;
1664 Action (Root_Project, Root_Tree);
1666 if Root_Project.Qualifier in Aggregate_Project then
1667 Agg := Root_Project.Aggregated_Projects;
1668 while Agg /= null loop
1669 For_Project_And_Aggregated (Agg.Project, Agg.Tree);
1673 end For_Project_And_Aggregated;
1675 -- Package initialization for Prj
1678 -- Make sure that the standard config and user project file extensions are
1679 -- compatible with canonical case file naming.
1681 Canonical_Case_File_Name (Config_Project_File_Extension);
1682 Canonical_Case_File_Name (Project_File_Extension);