1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2001-2012, 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.Containers.Ordered_Sets;
38 with Ada.Unchecked_Deallocation;
40 with GNAT.Case_Util; use GNAT.Case_Util;
41 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
47 type Restricted_Lang_Access is access Restricted_Lang;
48 type Restricted_Lang is record
50 Next : Restricted_Lang_Access;
53 Restricted_Languages : Restricted_Lang_Access := null;
54 -- When null, all languages are allowed, otherwise only the languages in
55 -- the list are allowed.
57 Object_Suffix : constant String := Get_Target_Object_Suffix.all;
58 -- File suffix for object files
60 Initial_Buffer_Size : constant := 100;
61 -- Initial size for extensible buffer used in Add_To_Buffer
63 The_Empty_String : Name_Id := No_Name;
65 Debug_Level : Integer := 0;
66 -- Current indentation level for debug traces
68 type Cst_String_Access is access constant String;
70 All_Lower_Case_Image : aliased constant String := "lowercase";
71 All_Upper_Case_Image : aliased constant String := "UPPERCASE";
72 Mixed_Case_Image : aliased constant String := "MixedCase";
74 The_Casing_Images : constant array (Known_Casing) of Cst_String_Access :=
75 (All_Lower_Case => All_Lower_Case_Image'Access,
76 All_Upper_Case => All_Upper_Case_Image'Access,
77 Mixed_Case => Mixed_Case_Image'Access);
79 procedure Free (Project : in out Project_Id);
80 -- Free memory allocated for Project
82 procedure Free_List (Languages : in out Language_Ptr);
83 procedure Free_List (Source : in out Source_Id);
84 procedure Free_List (Languages : in out Language_List);
85 -- Free memory allocated for the list of languages or sources
87 procedure Reset_Units_In_Table (Table : in out Units_Htable.Instance);
88 -- Resets all Units to No_Unit_Index Unit.File_Names (Spec).Unit &
89 -- Unit.File_Names (Impl).Unit in the given table.
91 procedure Free_Units (Table : in out Units_Htable.Instance);
92 -- Free memory allocated for unit information in the project
94 procedure Language_Changed (Iter : in out Source_Iterator);
95 procedure Project_Changed (Iter : in out Source_Iterator);
96 -- Called when a new project or language was selected for this iterator
98 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean;
99 -- Return True if there is at least one ALI file in the directory Dir
101 -----------------------------
102 -- Add_Restricted_Language --
103 -----------------------------
105 procedure Add_Restricted_Language (Name : String) is
106 N : String (1 .. Name'Length) := Name;
110 Add_Str_To_Name_Buffer (N);
111 Restricted_Languages :=
112 new Restricted_Lang'(Name => Name_Find, Next => Restricted_Languages);
113 end Add_Restricted_Language;
119 procedure Add_To_Buffer
121 To : in out String_Access;
122 Last : in out Natural)
126 To := new String (1 .. Initial_Buffer_Size);
130 -- If Buffer is too small, double its size
132 while Last + S'Length > To'Last loop
134 New_Buffer : constant String_Access :=
135 new String (1 .. 2 * Last);
138 New_Buffer (1 .. Last) := To (1 .. Last);
144 To (Last + 1 .. Last + S'Length) := S;
145 Last := Last + S'Length;
148 ---------------------------------
149 -- Current_Object_Path_File_Of --
150 ---------------------------------
152 function Current_Object_Path_File_Of
153 (Shared : Shared_Project_Tree_Data_Access) return Path_Name_Type
156 return Shared.Private_Part.Current_Object_Path_File;
157 end Current_Object_Path_File_Of;
159 ---------------------------------
160 -- Current_Source_Path_File_Of --
161 ---------------------------------
163 function Current_Source_Path_File_Of
164 (Shared : Shared_Project_Tree_Data_Access)
165 return Path_Name_Type is
167 return Shared.Private_Part.Current_Source_Path_File;
168 end Current_Source_Path_File_Of;
170 ---------------------------
171 -- Delete_Temporary_File --
172 ---------------------------
174 procedure Delete_Temporary_File
175 (Shared : Shared_Project_Tree_Data_Access := null;
176 Path : Path_Name_Type)
179 pragma Warnings (Off, Dont_Care);
182 if not Debug.Debug_Flag_N then
183 if Current_Verbosity = High then
184 Write_Line ("Removing temp file: " & Get_Name_String (Path));
187 Delete_File (Get_Name_String (Path), Dont_Care);
189 if Shared /= null then
191 1 .. Temp_Files_Table.Last (Shared.Private_Part.Temp_Files)
193 if Shared.Private_Part.Temp_Files.Table (Index) = Path then
194 Shared.Private_Part.Temp_Files.Table (Index) := No_Path;
199 end Delete_Temporary_File;
201 ------------------------------
202 -- Delete_Temp_Config_Files --
203 ------------------------------
205 procedure Delete_Temp_Config_Files (Project_Tree : Project_Tree_Ref) is
207 pragma Warnings (Off, Success);
212 if not Debug.Debug_Flag_N then
213 if Project_Tree /= null then
214 Proj := Project_Tree.Projects;
215 while Proj /= null loop
216 if Proj.Project.Config_File_Temp then
217 Delete_Temporary_File
218 (Project_Tree.Shared, Proj.Project.Config_File_Name);
220 -- Make sure that we don't have a config file for this
221 -- project, in case there are several mains. In this case,
222 -- we will recreate another config file: we cannot reuse the
223 -- one that we just deleted!
225 Proj.Project.Config_Checked := False;
226 Proj.Project.Config_File_Name := No_Path;
227 Proj.Project.Config_File_Temp := False;
234 end Delete_Temp_Config_Files;
236 ---------------------------
237 -- Delete_All_Temp_Files --
238 ---------------------------
240 procedure Delete_All_Temp_Files
241 (Shared : Shared_Project_Tree_Data_Access)
244 pragma Warnings (Off, Dont_Care);
246 Path : Path_Name_Type;
249 if not Debug.Debug_Flag_N then
251 1 .. Temp_Files_Table.Last (Shared.Private_Part.Temp_Files)
253 Path := Shared.Private_Part.Temp_Files.Table (Index);
255 if Path /= No_Path then
256 if Current_Verbosity = High then
257 Write_Line ("Removing temp file: "
258 & Get_Name_String (Path));
261 Delete_File (Get_Name_String (Path), Dont_Care);
265 Temp_Files_Table.Free (Shared.Private_Part.Temp_Files);
266 Temp_Files_Table.Init (Shared.Private_Part.Temp_Files);
269 -- If any of the environment variables ADA_PRJ_INCLUDE_FILE or
270 -- ADA_PRJ_OBJECTS_FILE has been set, then reset their value to
271 -- the empty string. On VMS, this has the effect of deassigning
272 -- the logical names.
274 if Shared.Private_Part.Current_Source_Path_File /= No_Path then
275 Setenv (Project_Include_Path_File, "");
278 if Shared.Private_Part.Current_Object_Path_File /= No_Path then
279 Setenv (Project_Objects_Path_File, "");
281 end Delete_All_Temp_Files;
283 ---------------------
284 -- Dependency_Name --
285 ---------------------
287 function Dependency_Name
288 (Source_File_Name : File_Name_Type;
289 Dependency : Dependency_File_Kind) return File_Name_Type
297 return Extend_Name (Source_File_Name, Makefile_Dependency_Suffix);
300 return Extend_Name (Source_File_Name, ALI_Dependency_Suffix);
308 function Empty_File return File_Name_Type is
310 return File_Name_Type (The_Empty_String);
317 function Empty_Project
318 (Qualifier : Project_Qualifier) return Project_Data
321 Prj.Initialize (Tree => No_Project_Tree);
324 Data : Project_Data (Qualifier => Qualifier);
327 -- Only the fields for which no default value could be provided in
328 -- prj.ads are initialized below.
330 Data.Config := Default_Project_Config;
339 function Empty_String return Name_Id is
341 return The_Empty_String;
348 procedure Expect (The_Token : Token_Type; Token_Image : String) is
350 if Token /= The_Token then
352 -- ??? Should pass user flags here instead
354 Error_Msg (Gnatmake_Flags, Token_Image & " expected", Token_Ptr);
363 (File : File_Name_Type;
364 With_Suffix : String) return File_Name_Type
369 Get_Name_String (File);
370 Last := Name_Len + 1;
372 while Name_Len /= 0 and then Name_Buffer (Name_Len) /= '.' loop
373 Name_Len := Name_Len - 1;
376 if Name_Len <= 1 then
380 for J in With_Suffix'Range loop
381 Name_Buffer (Name_Len) := With_Suffix (J);
382 Name_Len := Name_Len + 1;
385 Name_Len := Name_Len - 1;
389 -------------------------
390 -- Is_Allowed_Language --
391 -------------------------
393 function Is_Allowed_Language (Name : Name_Id) return Boolean is
394 R : Restricted_Lang_Access := Restricted_Languages;
395 Lang : constant String := Get_Name_String (Name);
403 if Get_Name_String (R.Name) = Lang then
412 end Is_Allowed_Language;
414 ---------------------
415 -- Project_Changed --
416 ---------------------
418 procedure Project_Changed (Iter : in out Source_Iterator) is
420 if Iter.Project /= null then
421 Iter.Language := Iter.Project.Project.Languages;
422 Language_Changed (Iter);
426 ----------------------
427 -- Language_Changed --
428 ----------------------
430 procedure Language_Changed (Iter : in out Source_Iterator) is
432 Iter.Current := No_Source;
434 if Iter.Language_Name /= No_Name then
435 while Iter.Language /= null
436 and then Iter.Language.Name /= Iter.Language_Name
438 Iter.Language := Iter.Language.Next;
442 -- If there is no matching language in this project, move to next
444 if Iter.Language = No_Language_Index then
445 if Iter.All_Projects then
447 Iter.Project := Iter.Project.Next;
448 exit when Iter.Project = null
449 or else Iter.Encapsulated_Libs
450 or else not Iter.Project.From_Encapsulated_Lib;
453 Project_Changed (Iter);
455 Iter.Project := null;
459 Iter.Current := Iter.Language.First_Source;
461 if Iter.Current = No_Source then
462 Iter.Language := Iter.Language.Next;
463 Language_Changed (Iter);
466 end Language_Changed;
468 ---------------------
469 -- For_Each_Source --
470 ---------------------
472 function For_Each_Source
473 (In_Tree : Project_Tree_Ref;
474 Project : Project_Id := No_Project;
475 Language : Name_Id := No_Name;
476 Encapsulated_Libs : Boolean := True) return Source_Iterator
478 Iter : Source_Iterator;
480 Iter := Source_Iterator'
482 Project => In_Tree.Projects,
483 All_Projects => Project = No_Project,
484 Language_Name => Language,
485 Language => No_Language_Index,
486 Current => No_Source,
487 Encapsulated_Libs => Encapsulated_Libs);
489 if Project /= null then
490 while Iter.Project /= null
491 and then Iter.Project.Project /= Project
493 Iter.Project := Iter.Project.Next;
497 while not Iter.Encapsulated_Libs
498 and then Iter.Project.From_Encapsulated_Lib
500 Iter.Project := Iter.Project.Next;
504 Project_Changed (Iter);
513 function Element (Iter : Source_Iterator) return Source_Id is
522 procedure Next (Iter : in out Source_Iterator) is
524 Iter.Current := Iter.Current.Next_In_Lang;
525 if Iter.Current = No_Source then
526 Iter.Language := Iter.Language.Next;
527 Language_Changed (Iter);
531 --------------------------------
532 -- For_Every_Project_Imported --
533 --------------------------------
535 procedure For_Every_Project_Imported_Context
537 Tree : Project_Tree_Ref;
538 With_State : in out State;
539 Include_Aggregated : Boolean := True;
540 Imported_First : Boolean := False)
542 use Project_Boolean_Htable;
544 procedure Recursive_Check_Context
545 (Project : Project_Id;
546 Tree : Project_Tree_Ref;
547 In_Aggregate_Lib : Boolean;
548 From_Encapsulated_Lib : Boolean);
549 -- Recursively handle the project tree creating a new context for
550 -- keeping track about already handled projects.
552 -----------------------------
553 -- Recursive_Check_Context --
554 -----------------------------
556 procedure Recursive_Check_Context
557 (Project : Project_Id;
558 Tree : Project_Tree_Ref;
559 In_Aggregate_Lib : Boolean;
560 From_Encapsulated_Lib : Boolean)
562 package Name_Id_Set is
563 new Ada.Containers.Ordered_Sets (Element_Type => Name_Id);
565 Seen_Name : Name_Id_Set.Set;
566 -- This set is needed to ensure that we do not haandle the same
567 -- project twice in the context of aggregate libraries.
569 procedure Recursive_Check
570 (Project : Project_Id;
571 Tree : Project_Tree_Ref;
572 In_Aggregate_Lib : Boolean;
573 From_Encapsulated_Lib : Boolean);
574 -- Check if project has already been seen. If not, mark it as Seen,
575 -- Call Action, and check all its imported and aggregated projects.
577 ---------------------
578 -- Recursive_Check --
579 ---------------------
581 procedure Recursive_Check
582 (Project : Project_Id;
583 Tree : Project_Tree_Ref;
584 In_Aggregate_Lib : Boolean;
585 From_Encapsulated_Lib : Boolean)
588 T : Project_Tree_Ref;
591 if not Seen_Name.Contains (Project.Name) then
593 -- Even if a project is aggregated multiple times in an
594 -- aggregated library, we will only return it once.
596 Seen_Name.Include (Project.Name);
598 if not Imported_First then
602 Project_Context'(In_Aggregate_Lib, From_Encapsulated_Lib),
606 -- Visit all extended projects
608 if Project.Extends /= No_Project then
610 (Project.Extends, Tree,
611 In_Aggregate_Lib, From_Encapsulated_Lib);
614 -- Visit all imported projects
616 List := Project.Imported_Projects;
617 while List /= null loop
621 From_Encapsulated_Lib
622 or else Project.Standalone_Library = Encapsulated);
626 -- Visit all aggregated projects
628 if Include_Aggregated
629 and then Project.Qualifier in Aggregate_Project
632 Agg : Aggregated_Project_List;
635 Agg := Project.Aggregated_Projects;
636 while Agg /= null loop
637 pragma Assert (Agg.Project /= No_Project);
639 -- For aggregated libraries, the tree must be the one
640 -- of the aggregate library.
642 if Project.Qualifier = Aggregate_Library then
647 From_Encapsulated_Lib
649 Project.Standalone_Library = Encapsulated);
654 -- Use a new context as we want to returns the same
655 -- project in different project tree for aggregated
658 Recursive_Check_Context
659 (Agg.Project, T, False, False);
667 if Imported_First then
671 Project_Context'(In_Aggregate_Lib, From_Encapsulated_Lib),
677 -- Start of processing for Recursive_Check_Context
681 (Project, Tree, In_Aggregate_Lib, From_Encapsulated_Lib);
682 end Recursive_Check_Context;
684 -- Start of processing for For_Every_Project_Imported
687 Recursive_Check_Context
690 In_Aggregate_Lib => False,
691 From_Encapsulated_Lib => False);
692 end For_Every_Project_Imported_Context;
694 procedure For_Every_Project_Imported
696 Tree : Project_Tree_Ref;
697 With_State : in out State;
698 Include_Aggregated : Boolean := True;
699 Imported_First : Boolean := False)
702 (Project : Project_Id;
703 Tree : Project_Tree_Ref;
704 Context : Project_Context;
705 With_State : in out State);
706 -- Action wrapper for handling the context
713 (Project : Project_Id;
714 Tree : Project_Tree_Ref;
715 Context : Project_Context;
716 With_State : in out State)
718 pragma Unreferenced (Context);
720 Action (Project, Tree, With_State);
723 procedure For_Projects is
724 new For_Every_Project_Imported_Context (State, Internal);
727 For_Projects (By, Tree, With_State, Include_Aggregated, Imported_First);
728 end For_Every_Project_Imported;
735 (In_Tree : Project_Tree_Ref;
736 Project : Project_Id;
737 In_Imported_Only : Boolean := False;
738 In_Extended_Only : Boolean := False;
739 Base_Name : File_Name_Type;
740 Index : Int := 0) return Source_Id
742 Result : Source_Id := No_Source;
744 procedure Look_For_Sources
746 Tree : Project_Tree_Ref;
747 Src : in out Source_Id);
748 -- Look for Base_Name in the sources of Proj
750 ----------------------
751 -- Look_For_Sources --
752 ----------------------
754 procedure Look_For_Sources
756 Tree : Project_Tree_Ref;
757 Src : in out Source_Id)
759 Iterator : Source_Iterator;
762 Iterator := For_Each_Source (In_Tree => Tree, Project => Proj);
763 while Element (Iterator) /= No_Source loop
764 if Element (Iterator).File = Base_Name
765 and then (Index = 0 or else Element (Iterator).Index = Index)
767 Src := Element (Iterator);
769 -- If the source has been excluded, continue looking. We will
770 -- get the excluded source only if there is no other source
771 -- with the same base name that is not locally removed.
773 if not Element (Iterator).Locally_Removed then
780 end Look_For_Sources;
782 procedure For_Imported_Projects is new For_Every_Project_Imported
783 (State => Source_Id, Action => Look_For_Sources);
787 -- Start of processing for Find_Source
790 if In_Extended_Only then
792 while Proj /= No_Project loop
793 Look_For_Sources (Proj, In_Tree, Result);
794 exit when Result /= No_Source;
796 Proj := Proj.Extends;
799 elsif In_Imported_Only then
800 Look_For_Sources (Project, In_Tree, Result);
802 if Result = No_Source then
803 For_Imported_Projects
806 Include_Aggregated => False,
807 With_State => Result);
811 Look_For_Sources (No_Project, In_Tree, Result);
821 function Hash is new GNAT.HTable.Hash (Header_Num => Header_Num);
822 -- Used in implementation of other functions Hash below
824 function Hash (Name : File_Name_Type) return Header_Num is
826 return Hash (Get_Name_String (Name));
829 function Hash (Name : Name_Id) return Header_Num is
831 return Hash (Get_Name_String (Name));
834 function Hash (Name : Path_Name_Type) return Header_Num is
836 return Hash (Get_Name_String (Name));
839 function Hash (Project : Project_Id) return Header_Num is
841 if Project = No_Project then
842 return Header_Num'First;
844 return Hash (Get_Name_String (Project.Name));
852 function Image (The_Casing : Casing_Type) return String is
854 return The_Casing_Images (The_Casing).all;
857 -----------------------------
858 -- Is_Standard_GNAT_Naming --
859 -----------------------------
861 function Is_Standard_GNAT_Naming
862 (Naming : Lang_Naming_Data) return Boolean
865 return Get_Name_String (Naming.Spec_Suffix) = ".ads"
866 and then Get_Name_String (Naming.Body_Suffix) = ".adb"
867 and then Get_Name_String (Naming.Dot_Replacement) = "-";
868 end Is_Standard_GNAT_Naming;
874 procedure Initialize (Tree : Project_Tree_Ref) is
876 if The_Empty_String = No_Name then
879 The_Empty_String := Name_Find;
883 -- Make sure that new reserved words after Ada 95 may be used as
886 Opt.Ada_Version := Opt.Ada_95;
888 Set_Name_Table_Byte (Name_Project, Token_Type'Pos (Tok_Project));
889 Set_Name_Table_Byte (Name_Extends, Token_Type'Pos (Tok_Extends));
890 Set_Name_Table_Byte (Name_External, Token_Type'Pos (Tok_External));
892 (Name_External_As_List, Token_Type'Pos (Tok_External_As_List));
895 if Tree /= No_Project_Tree then
904 function Is_Extending
905 (Extending : Project_Id;
906 Extended : Project_Id) return Boolean
912 while Proj /= No_Project loop
913 if Proj = Extended then
917 Proj := Proj.Extends;
928 (Source_File_Name : File_Name_Type;
929 Object_File_Suffix : Name_Id := No_Name) return File_Name_Type
932 if Object_File_Suffix = No_Name then
934 (Source_File_Name, Object_Suffix);
937 (Source_File_Name, Get_Name_String (Object_File_Suffix));
942 (Source_File_Name : File_Name_Type;
944 Index_Separator : Character;
945 Object_File_Suffix : Name_Id := No_Name) return File_Name_Type
947 Index_Img : constant String := Source_Index'Img;
951 Get_Name_String (Source_File_Name);
954 while Last > 1 and then Name_Buffer (Last) /= '.' loop
959 Name_Len := Last - 1;
962 Add_Char_To_Name_Buffer (Index_Separator);
963 Add_Str_To_Name_Buffer (Index_Img (2 .. Index_Img'Last));
965 if Object_File_Suffix = No_Name then
966 Add_Str_To_Name_Buffer (Object_Suffix);
968 Add_Str_To_Name_Buffer (Get_Name_String (Object_File_Suffix));
974 ----------------------
975 -- Record_Temp_File --
976 ----------------------
978 procedure Record_Temp_File
979 (Shared : Shared_Project_Tree_Data_Access;
980 Path : Path_Name_Type)
983 Temp_Files_Table.Append (Shared.Private_Part.Temp_Files, Path);
984 end Record_Temp_File;
990 procedure Free (List : in out Aggregated_Project_List) is
991 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
992 (Aggregated_Project, Aggregated_Project_List);
993 Tmp : Aggregated_Project_List;
995 while List /= null loop
1000 Unchecked_Free (List);
1005 ----------------------------
1006 -- Add_Aggregated_Project --
1007 ----------------------------
1009 procedure Add_Aggregated_Project
1010 (Project : Project_Id; Path : Path_Name_Type) is
1012 Project.Aggregated_Projects := new Aggregated_Project'
1014 Project => No_Project,
1016 Next => Project.Aggregated_Projects);
1017 end Add_Aggregated_Project;
1023 procedure Free (Project : in out Project_Id) is
1024 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
1025 (Project_Data, Project_Id);
1028 if Project /= null then
1029 Free (Project.Ada_Include_Path);
1030 Free (Project.Objects_Path);
1031 Free (Project.Ada_Objects_Path);
1032 Free_List (Project.Imported_Projects, Free_Project => False);
1033 Free_List (Project.All_Imported_Projects, Free_Project => False);
1034 Free_List (Project.Languages);
1036 case Project.Qualifier is
1037 when Aggregate | Aggregate_Library =>
1038 Free (Project.Aggregated_Projects);
1044 Unchecked_Free (Project);
1052 procedure Free_List (Languages : in out Language_List) is
1053 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
1054 (Language_List_Element, Language_List);
1055 Tmp : Language_List;
1057 while Languages /= null loop
1058 Tmp := Languages.Next;
1059 Unchecked_Free (Languages);
1068 procedure Free_List (Source : in out Source_Id) is
1069 procedure Unchecked_Free is new
1070 Ada.Unchecked_Deallocation (Source_Data, Source_Id);
1075 while Source /= No_Source loop
1076 Tmp := Source.Next_In_Lang;
1077 Free_List (Source.Alternate_Languages);
1079 if Source.Unit /= null
1080 and then Source.Kind in Spec_Or_Body
1082 Source.Unit.File_Names (Source.Kind) := null;
1085 Unchecked_Free (Source);
1095 (List : in out Project_List;
1096 Free_Project : Boolean)
1098 procedure Unchecked_Free is new
1099 Ada.Unchecked_Deallocation (Project_List_Element, Project_List);
1104 while List /= null loop
1107 if Free_Project then
1108 Free (List.Project);
1111 Unchecked_Free (List);
1120 procedure Free_List (Languages : in out Language_Ptr) is
1121 procedure Unchecked_Free is new
1122 Ada.Unchecked_Deallocation (Language_Data, Language_Ptr);
1127 while Languages /= null loop
1128 Tmp := Languages.Next;
1129 Free_List (Languages.First_Source);
1130 Unchecked_Free (Languages);
1135 --------------------------
1136 -- Reset_Units_In_Table --
1137 --------------------------
1139 procedure Reset_Units_In_Table (Table : in out Units_Htable.Instance) is
1143 Unit := Units_Htable.Get_First (Table);
1144 while Unit /= No_Unit_Index loop
1145 if Unit.File_Names (Spec) /= null then
1146 Unit.File_Names (Spec).Unit := No_Unit_Index;
1149 if Unit.File_Names (Impl) /= null then
1150 Unit.File_Names (Impl).Unit := No_Unit_Index;
1153 Unit := Units_Htable.Get_Next (Table);
1155 end Reset_Units_In_Table;
1161 procedure Free_Units (Table : in out Units_Htable.Instance) is
1162 procedure Unchecked_Free is new
1163 Ada.Unchecked_Deallocation (Unit_Data, Unit_Index);
1168 Unit := Units_Htable.Get_First (Table);
1169 while Unit /= No_Unit_Index loop
1171 -- We cannot reset Unit.File_Names (Impl or Spec).Unit here as
1172 -- Source_Data buffer is freed by the following instruction
1173 -- Free_List (Tree.Projects, Free_Project => True);
1175 Unchecked_Free (Unit);
1176 Unit := Units_Htable.Get_Next (Table);
1179 Units_Htable.Reset (Table);
1186 procedure Free (Tree : in out Project_Tree_Ref) is
1187 procedure Unchecked_Free is new
1188 Ada.Unchecked_Deallocation
1189 (Project_Tree_Data, Project_Tree_Ref);
1191 procedure Unchecked_Free is new
1192 Ada.Unchecked_Deallocation
1193 (Project_Tree_Appdata'Class, Project_Tree_Appdata_Access);
1196 if Tree /= null then
1197 if Tree.Is_Root_Tree then
1198 Name_List_Table.Free (Tree.Shared.Name_Lists);
1199 Number_List_Table.Free (Tree.Shared.Number_Lists);
1200 String_Element_Table.Free (Tree.Shared.String_Elements);
1201 Variable_Element_Table.Free (Tree.Shared.Variable_Elements);
1202 Array_Element_Table.Free (Tree.Shared.Array_Elements);
1203 Array_Table.Free (Tree.Shared.Arrays);
1204 Package_Table.Free (Tree.Shared.Packages);
1205 Temp_Files_Table.Free (Tree.Shared.Private_Part.Temp_Files);
1208 if Tree.Appdata /= null then
1209 Free (Tree.Appdata.all);
1210 Unchecked_Free (Tree.Appdata);
1213 Source_Paths_Htable.Reset (Tree.Source_Paths_HT);
1214 Source_Files_Htable.Reset (Tree.Source_Files_HT);
1216 Reset_Units_In_Table (Tree.Units_HT);
1217 Free_List (Tree.Projects, Free_Project => True);
1218 Free_Units (Tree.Units_HT);
1220 Unchecked_Free (Tree);
1228 procedure Reset (Tree : Project_Tree_Ref) is
1232 if Tree.Is_Root_Tree then
1234 -- We cannot use 'Access here:
1235 -- "illegal attribute for discriminant-dependent component"
1236 -- However, we know this is valid since Shared and Shared_Data have
1237 -- the same lifetime and will always exist concurrently.
1239 Tree.Shared := Tree.Shared_Data'Unrestricted_Access;
1240 Name_List_Table.Init (Tree.Shared.Name_Lists);
1241 Number_List_Table.Init (Tree.Shared.Number_Lists);
1242 String_Element_Table.Init (Tree.Shared.String_Elements);
1243 Variable_Element_Table.Init (Tree.Shared.Variable_Elements);
1244 Array_Element_Table.Init (Tree.Shared.Array_Elements);
1245 Array_Table.Init (Tree.Shared.Arrays);
1246 Package_Table.Init (Tree.Shared.Packages);
1248 -- Private part table
1250 Temp_Files_Table.Init (Tree.Shared.Private_Part.Temp_Files);
1252 Tree.Shared.Private_Part.Current_Source_Path_File := No_Path;
1253 Tree.Shared.Private_Part.Current_Object_Path_File := No_Path;
1256 Source_Paths_Htable.Reset (Tree.Source_Paths_HT);
1257 Source_Files_Htable.Reset (Tree.Source_Files_HT);
1258 Replaced_Source_HTable.Reset (Tree.Replaced_Sources);
1260 Tree.Replaced_Source_Number := 0;
1262 Reset_Units_In_Table (Tree.Units_HT);
1263 Free_List (Tree.Projects, Free_Project => True);
1264 Free_Units (Tree.Units_HT);
1267 -------------------------------------
1268 -- Set_Current_Object_Path_File_Of --
1269 -------------------------------------
1271 procedure Set_Current_Object_Path_File_Of
1272 (Shared : Shared_Project_Tree_Data_Access;
1273 To : Path_Name_Type)
1276 Shared.Private_Part.Current_Object_Path_File := To;
1277 end Set_Current_Object_Path_File_Of;
1279 -------------------------------------
1280 -- Set_Current_Source_Path_File_Of --
1281 -------------------------------------
1283 procedure Set_Current_Source_Path_File_Of
1284 (Shared : Shared_Project_Tree_Data_Access;
1285 To : Path_Name_Type)
1288 Shared.Private_Part.Current_Source_Path_File := To;
1289 end Set_Current_Source_Path_File_Of;
1291 -----------------------
1292 -- Set_Path_File_Var --
1293 -----------------------
1295 procedure Set_Path_File_Var (Name : String; Value : String) is
1296 Host_Spec : String_Access := To_Host_File_Spec (Value);
1298 if Host_Spec = null then
1300 ("could not convert file name """ & Value & """ to host spec");
1302 Setenv (Name, Host_Spec.all);
1305 end Set_Path_File_Var;
1311 function Switches_Name
1312 (Source_File_Name : File_Name_Type) return File_Name_Type
1315 return Extend_Name (Source_File_Name, Switches_Dependency_Suffix);
1322 function Value (Image : String) return Casing_Type is
1324 for Casing in The_Casing_Images'Range loop
1325 if To_Lower (Image) = To_Lower (The_Casing_Images (Casing).all) then
1330 raise Constraint_Error;
1333 ---------------------
1334 -- Has_Ada_Sources --
1335 ---------------------
1337 function Has_Ada_Sources (Data : Project_Id) return Boolean is
1338 Lang : Language_Ptr;
1341 Lang := Data.Languages;
1342 while Lang /= No_Language_Index loop
1343 if Lang.Name = Name_Ada then
1344 return Lang.First_Source /= No_Source;
1350 end Has_Ada_Sources;
1352 ------------------------
1353 -- Contains_ALI_Files --
1354 ------------------------
1356 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean is
1357 Dir_Name : constant String := Get_Name_String (Dir);
1359 Name : String (1 .. 1_000);
1361 Result : Boolean := False;
1364 Open (Direct, Dir_Name);
1366 -- For each file in the directory, check if it is an ALI file
1369 Read (Direct, Name, Last);
1371 Canonical_Case_File_Name (Name (1 .. Last));
1372 Result := Last >= 5 and then Name (Last - 3 .. Last) = ".ali";
1380 -- If there is any problem, close the directory if open and return True.
1381 -- The library directory will be added to the path.
1384 if Is_Open (Direct) then
1389 end Contains_ALI_Files;
1391 --------------------------
1392 -- Get_Object_Directory --
1393 --------------------------
1395 function Get_Object_Directory
1396 (Project : Project_Id;
1397 Including_Libraries : Boolean;
1398 Only_If_Ada : Boolean := False) return Path_Name_Type
1401 if (Project.Library and then Including_Libraries)
1403 (Project.Object_Directory /= No_Path_Information
1404 and then (not Including_Libraries or else not Project.Library))
1406 -- For a library project, add the library ALI directory if there is
1407 -- no object directory or if the library ALI directory contains ALI
1408 -- files; otherwise add the object directory.
1410 if Project.Library then
1411 if Project.Object_Directory = No_Path_Information
1412 or else Contains_ALI_Files (Project.Library_ALI_Dir.Display_Name)
1414 return Project.Library_ALI_Dir.Display_Name;
1416 return Project.Object_Directory.Display_Name;
1419 -- For a non-library project, add object directory if it is not a
1420 -- virtual project, and if there are Ada sources in the project or
1421 -- one of the projects it extends. If there are no Ada sources,
1422 -- adding the object directory could disrupt the order of the
1423 -- object dirs in the path.
1425 elsif not Project.Virtual then
1427 Add_Object_Dir : Boolean;
1431 Add_Object_Dir := not Only_If_Ada;
1433 while not Add_Object_Dir and then Prj /= No_Project loop
1434 if Has_Ada_Sources (Prj) then
1435 Add_Object_Dir := True;
1441 if Add_Object_Dir then
1442 return Project.Object_Directory.Display_Name;
1449 end Get_Object_Directory;
1451 -----------------------------------
1452 -- Ultimate_Extending_Project_Of --
1453 -----------------------------------
1455 function Ultimate_Extending_Project_Of
1456 (Proj : Project_Id) return Project_Id
1462 while Prj /= null and then Prj.Extended_By /= No_Project loop
1463 Prj := Prj.Extended_By;
1467 end Ultimate_Extending_Project_Of;
1469 -----------------------------------
1470 -- Compute_All_Imported_Projects --
1471 -----------------------------------
1473 procedure Compute_All_Imported_Projects
1474 (Root_Project : Project_Id;
1475 Tree : Project_Tree_Ref)
1477 procedure Analyze_Tree
1478 (Local_Root : Project_Id;
1479 Local_Tree : Project_Tree_Ref);
1480 -- Process Project and all its aggregated project to analyze their own
1481 -- imported projects.
1487 procedure Analyze_Tree
1488 (Local_Root : Project_Id;
1489 Local_Tree : Project_Tree_Ref)
1491 pragma Unreferenced (Local_Root);
1493 Project : Project_Id;
1495 procedure Recursive_Add
1497 Tree : Project_Tree_Ref;
1498 Context : Project_Context;
1499 Dummy : in out Boolean);
1500 -- Recursively add the projects imported by project Project, but not
1501 -- those that are extended.
1507 procedure Recursive_Add
1509 Tree : Project_Tree_Ref;
1510 Context : Project_Context;
1511 Dummy : in out Boolean)
1513 pragma Unreferenced (Dummy, Tree);
1515 List : Project_List;
1519 -- A project is not importing itself
1521 Prj2 := Ultimate_Extending_Project_Of (Prj);
1523 if Project /= Prj2 then
1525 -- Check that the project is not already in the list. We know
1526 -- the one passed to Recursive_Add have never been visited
1527 -- before, but the one passed it are the extended projects.
1529 List := Project.All_Imported_Projects;
1530 while List /= null loop
1531 if List.Project = Prj2 then
1538 -- Add it to the list
1540 Project.All_Imported_Projects :=
1541 new Project_List_Element'
1543 From_Encapsulated_Lib => Context.From_Encapsulated_Lib,
1544 Next => Project.All_Imported_Projects);
1548 procedure For_All_Projects is
1549 new For_Every_Project_Imported_Context (Boolean, Recursive_Add);
1551 Dummy : Boolean := False;
1552 List : Project_List;
1555 List := Local_Tree.Projects;
1556 while List /= null loop
1557 Project := List.Project;
1559 (Project.All_Imported_Projects, Free_Project => False);
1561 (Project, Local_Tree, Dummy, Include_Aggregated => False);
1566 procedure For_Aggregates is
1567 new For_Project_And_Aggregated (Analyze_Tree);
1569 -- Start of processing for Compute_All_Imported_Projects
1572 For_Aggregates (Root_Project, Tree);
1573 end Compute_All_Imported_Projects;
1579 function Is_Compilable (Source : Source_Id) return Boolean is
1581 case Source.Compilable is
1583 if Source.Language.Config.Compiler_Driver /= No_File
1585 Length_Of_Name (Source.Language.Config.Compiler_Driver) /= 0
1586 and then not Source.Locally_Removed
1587 and then (Source.Language.Config.Kind /= File_Based
1588 or else Source.Kind /= Spec)
1590 -- Do not modify Source.Compilable before the source record
1591 -- has been initialized.
1593 if Source.Source_TS /= Empty_Time_Stamp then
1594 Source.Compilable := Yes;
1600 if Source.Source_TS /= Empty_Time_Stamp then
1601 Source.Compilable := No;
1615 ------------------------------
1616 -- Object_To_Global_Archive --
1617 ------------------------------
1619 function Object_To_Global_Archive (Source : Source_Id) return Boolean is
1621 return Source.Language.Config.Kind = File_Based
1622 and then Source.Kind = Impl
1623 and then Source.Language.Config.Objects_Linked
1624 and then Is_Compilable (Source)
1625 and then Source.Language.Config.Object_Generated;
1626 end Object_To_Global_Archive;
1628 ----------------------------
1629 -- Get_Language_From_Name --
1630 ----------------------------
1632 function Get_Language_From_Name
1633 (Project : Project_Id;
1634 Name : String) return Language_Ptr
1637 Result : Language_Ptr;
1640 Name_Len := Name'Length;
1641 Name_Buffer (1 .. Name_Len) := Name;
1642 To_Lower (Name_Buffer (1 .. Name_Len));
1645 Result := Project.Languages;
1646 while Result /= No_Language_Index loop
1647 if Result.Name = N then
1651 Result := Result.Next;
1654 return No_Language_Index;
1655 end Get_Language_From_Name;
1661 function Other_Part (Source : Source_Id) return Source_Id is
1663 if Source.Unit /= No_Unit_Index then
1666 return Source.Unit.File_Names (Spec);
1668 return Source.Unit.File_Names (Impl);
1681 function Create_Flags
1682 (Report_Error : Error_Handler;
1683 When_No_Sources : Error_Warning;
1684 Require_Sources_Other_Lang : Boolean := True;
1685 Allow_Duplicate_Basenames : Boolean := True;
1686 Compiler_Driver_Mandatory : Boolean := False;
1687 Error_On_Unknown_Language : Boolean := True;
1688 Require_Obj_Dirs : Error_Warning := Error;
1689 Allow_Invalid_External : Error_Warning := Error;
1690 Missing_Source_Files : Error_Warning := Error;
1691 Ignore_Missing_With : Boolean := False)
1692 return Processing_Flags
1695 return Processing_Flags'
1696 (Report_Error => Report_Error,
1697 When_No_Sources => When_No_Sources,
1698 Require_Sources_Other_Lang => Require_Sources_Other_Lang,
1699 Allow_Duplicate_Basenames => Allow_Duplicate_Basenames,
1700 Error_On_Unknown_Language => Error_On_Unknown_Language,
1701 Compiler_Driver_Mandatory => Compiler_Driver_Mandatory,
1702 Require_Obj_Dirs => Require_Obj_Dirs,
1703 Allow_Invalid_External => Allow_Invalid_External,
1704 Missing_Source_Files => Missing_Source_Files,
1705 Ignore_Missing_With => Ignore_Missing_With);
1713 (Table : Name_List_Table.Instance;
1714 List : Name_List_Index) return Natural
1716 Count : Natural := 0;
1717 Tmp : Name_List_Index;
1721 while Tmp /= No_Name_List loop
1723 Tmp := Table.Table (Tmp).Next;
1733 procedure Debug_Output (Str : String) is
1735 if Current_Verbosity > Default then
1737 Write_Line ((1 .. Debug_Level * 2 => ' ') & Str);
1738 Set_Standard_Output;
1746 procedure Debug_Indent is
1748 if Current_Verbosity = High then
1750 Write_Str ((1 .. Debug_Level * 2 => ' '));
1751 Set_Standard_Output;
1759 procedure Debug_Output (Str : String; Str2 : Name_Id) is
1761 if Current_Verbosity = High then
1766 if Str2 = No_Name then
1767 Write_Line (" <no_name>");
1769 Write_Line (" """ & Get_Name_String (Str2) & '"');
1772 Set_Standard_Output;
1776 ---------------------------
1777 -- Debug_Increase_Indent --
1778 ---------------------------
1780 procedure Debug_Increase_Indent
1781 (Str : String := ""; Str2 : Name_Id := No_Name)
1784 if Str2 /= No_Name then
1785 Debug_Output (Str, Str2);
1789 Debug_Level := Debug_Level + 1;
1790 end Debug_Increase_Indent;
1792 ---------------------------
1793 -- Debug_Decrease_Indent --
1794 ---------------------------
1796 procedure Debug_Decrease_Indent (Str : String := "") is
1798 if Debug_Level > 0 then
1799 Debug_Level := Debug_Level - 1;
1805 end Debug_Decrease_Indent;
1811 function Debug_Name (Tree : Project_Tree_Ref) return Name_Id is
1816 Add_Str_To_Name_Buffer ("Tree [");
1819 while P /= null loop
1820 if P /= Tree.Projects then
1821 Add_Char_To_Name_Buffer (',');
1824 Add_Str_To_Name_Buffer (Get_Name_String (P.Project.Name));
1829 Add_Char_To_Name_Buffer (']');
1838 procedure Free (Tree : in out Project_Tree_Appdata) is
1839 pragma Unreferenced (Tree);
1844 --------------------------------
1845 -- For_Project_And_Aggregated --
1846 --------------------------------
1848 procedure For_Project_And_Aggregated
1849 (Root_Project : Project_Id;
1850 Root_Tree : Project_Tree_Ref)
1852 Agg : Aggregated_Project_List;
1855 Action (Root_Project, Root_Tree);
1857 if Root_Project.Qualifier in Aggregate_Project then
1858 Agg := Root_Project.Aggregated_Projects;
1859 while Agg /= null loop
1860 For_Project_And_Aggregated (Agg.Project, Agg.Tree);
1864 end For_Project_And_Aggregated;
1866 -- Package initialization for Prj
1869 -- Make sure that the standard config and user project file extensions are
1870 -- compatible with canonical case file naming.
1872 Canonical_Case_File_Name (Config_Project_File_Extension);
1873 Canonical_Case_File_Name (Project_File_Extension);