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;
46 type Restricted_Lang_Access is access Restricted_Lang;
47 type Restricted_Lang is record
49 Next : Restricted_Lang_Access;
52 Restricted_Languages : Restricted_Lang_Access := null;
53 -- When null, all languages are allowed, otherwise only the languages in
54 -- the list are allowed.
56 Object_Suffix : constant String := Get_Target_Object_Suffix.all;
57 -- File suffix for object files
59 Initial_Buffer_Size : constant := 100;
60 -- Initial size for extensible buffer used in Add_To_Buffer
62 The_Empty_String : Name_Id := No_Name;
64 Debug_Level : Integer := 0;
65 -- Current indentation level for debug traces
67 type Cst_String_Access is access constant String;
69 All_Lower_Case_Image : aliased constant String := "lowercase";
70 All_Upper_Case_Image : aliased constant String := "UPPERCASE";
71 Mixed_Case_Image : aliased constant String := "MixedCase";
73 The_Casing_Images : constant array (Known_Casing) of Cst_String_Access :=
74 (All_Lower_Case => All_Lower_Case_Image'Access,
75 All_Upper_Case => All_Upper_Case_Image'Access,
76 Mixed_Case => Mixed_Case_Image'Access);
78 procedure Free (Project : in out Project_Id);
79 -- Free memory allocated for Project
81 procedure Free_List (Languages : in out Language_Ptr);
82 procedure Free_List (Source : in out Source_Id);
83 procedure Free_List (Languages : in out Language_List);
84 -- Free memory allocated for the list of languages or sources
86 procedure Reset_Units_In_Table (Table : in out Units_Htable.Instance);
87 -- Resets all Units to No_Unit_Index Unit.File_Names (Spec).Unit &
88 -- Unit.File_Names (Impl).Unit in the given table.
90 procedure Free_Units (Table : in out Units_Htable.Instance);
91 -- Free memory allocated for unit information in the project
93 procedure Language_Changed (Iter : in out Source_Iterator);
94 procedure Project_Changed (Iter : in out Source_Iterator);
95 -- Called when a new project or language was selected for this iterator
97 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean;
98 -- Return True if there is at least one ALI file in the directory Dir
100 -----------------------------
101 -- Add_Restricted_Language --
102 -----------------------------
104 procedure Add_Restricted_Language (Name : String) is
105 N : String (1 .. Name'Length) := Name;
109 Add_Str_To_Name_Buffer (N);
110 Restricted_Languages :=
111 new Restricted_Lang'(Name => Name_Find, Next => Restricted_Languages);
112 end Add_Restricted_Language;
118 procedure Add_To_Buffer
120 To : in out String_Access;
121 Last : in out Natural)
125 To := new String (1 .. Initial_Buffer_Size);
129 -- If Buffer is too small, double its size
131 while Last + S'Length > To'Last loop
133 New_Buffer : constant String_Access :=
134 new String (1 .. 2 * Last);
137 New_Buffer (1 .. Last) := To (1 .. Last);
143 To (Last + 1 .. Last + S'Length) := S;
144 Last := Last + S'Length;
147 ---------------------------------
148 -- Current_Object_Path_File_Of --
149 ---------------------------------
151 function Current_Object_Path_File_Of
152 (Shared : Shared_Project_Tree_Data_Access) return Path_Name_Type
155 return Shared.Private_Part.Current_Object_Path_File;
156 end Current_Object_Path_File_Of;
158 ---------------------------------
159 -- Current_Source_Path_File_Of --
160 ---------------------------------
162 function Current_Source_Path_File_Of
163 (Shared : Shared_Project_Tree_Data_Access)
164 return Path_Name_Type is
166 return Shared.Private_Part.Current_Source_Path_File;
167 end Current_Source_Path_File_Of;
169 ---------------------------
170 -- Delete_Temporary_File --
171 ---------------------------
173 procedure Delete_Temporary_File
174 (Shared : Shared_Project_Tree_Data_Access := null;
175 Path : Path_Name_Type)
178 pragma Warnings (Off, Dont_Care);
181 if not Debug.Debug_Flag_N then
182 if Current_Verbosity = High then
183 Write_Line ("Removing temp file: " & Get_Name_String (Path));
186 Delete_File (Get_Name_String (Path), Dont_Care);
188 if Shared /= null then
190 1 .. Temp_Files_Table.Last (Shared.Private_Part.Temp_Files)
192 if Shared.Private_Part.Temp_Files.Table (Index) = Path then
193 Shared.Private_Part.Temp_Files.Table (Index) := No_Path;
198 end Delete_Temporary_File;
200 ------------------------------
201 -- Delete_Temp_Config_Files --
202 ------------------------------
204 procedure Delete_Temp_Config_Files (Project_Tree : Project_Tree_Ref) is
206 pragma Warnings (Off, Success);
211 if not Debug.Debug_Flag_N then
212 if Project_Tree /= null then
213 Proj := Project_Tree.Projects;
214 while Proj /= null loop
215 if Proj.Project.Config_File_Temp then
216 Delete_Temporary_File
217 (Project_Tree.Shared, Proj.Project.Config_File_Name);
219 -- Make sure that we don't have a config file for this
220 -- project, in case there are several mains. In this case,
221 -- we will recreate another config file: we cannot reuse the
222 -- one that we just deleted!
224 Proj.Project.Config_Checked := False;
225 Proj.Project.Config_File_Name := No_Path;
226 Proj.Project.Config_File_Temp := False;
233 end Delete_Temp_Config_Files;
235 ---------------------------
236 -- Delete_All_Temp_Files --
237 ---------------------------
239 procedure Delete_All_Temp_Files
240 (Shared : Shared_Project_Tree_Data_Access)
243 pragma Warnings (Off, Dont_Care);
245 Path : Path_Name_Type;
248 if not Debug.Debug_Flag_N then
250 1 .. Temp_Files_Table.Last (Shared.Private_Part.Temp_Files)
252 Path := Shared.Private_Part.Temp_Files.Table (Index);
254 if Path /= No_Path then
255 if Current_Verbosity = High then
256 Write_Line ("Removing temp file: "
257 & Get_Name_String (Path));
260 Delete_File (Get_Name_String (Path), Dont_Care);
264 Temp_Files_Table.Free (Shared.Private_Part.Temp_Files);
265 Temp_Files_Table.Init (Shared.Private_Part.Temp_Files);
268 -- If any of the environment variables ADA_PRJ_INCLUDE_FILE or
269 -- ADA_PRJ_OBJECTS_FILE has been set, then reset their value to
270 -- the empty string. On VMS, this has the effect of deassigning
271 -- the logical names.
273 if Shared.Private_Part.Current_Source_Path_File /= No_Path then
274 Setenv (Project_Include_Path_File, "");
277 if Shared.Private_Part.Current_Object_Path_File /= No_Path then
278 Setenv (Project_Objects_Path_File, "");
280 end Delete_All_Temp_Files;
282 ---------------------
283 -- Dependency_Name --
284 ---------------------
286 function Dependency_Name
287 (Source_File_Name : File_Name_Type;
288 Dependency : Dependency_File_Kind) return File_Name_Type
296 return Extend_Name (Source_File_Name, Makefile_Dependency_Suffix);
299 return Extend_Name (Source_File_Name, ALI_Dependency_Suffix);
307 function Empty_File return File_Name_Type is
309 return File_Name_Type (The_Empty_String);
316 function Empty_Project
317 (Qualifier : Project_Qualifier) return Project_Data
320 Prj.Initialize (Tree => No_Project_Tree);
323 Data : Project_Data (Qualifier => Qualifier);
326 -- Only the fields for which no default value could be provided in
327 -- prj.ads are initialized below.
329 Data.Config := Default_Project_Config;
338 function Empty_String return Name_Id is
340 return The_Empty_String;
347 procedure Expect (The_Token : Token_Type; Token_Image : String) is
349 if Token /= The_Token then
351 -- ??? Should pass user flags here instead
353 Error_Msg (Gnatmake_Flags, Token_Image & " expected", Token_Ptr);
362 (File : File_Name_Type;
363 With_Suffix : String) return File_Name_Type
368 Get_Name_String (File);
369 Last := Name_Len + 1;
371 while Name_Len /= 0 and then Name_Buffer (Name_Len) /= '.' loop
372 Name_Len := Name_Len - 1;
375 if Name_Len <= 1 then
379 for J in With_Suffix'Range loop
380 Name_Buffer (Name_Len) := With_Suffix (J);
381 Name_Len := Name_Len + 1;
384 Name_Len := Name_Len - 1;
388 -------------------------
389 -- Is_Allowed_Language --
390 -------------------------
392 function Is_Allowed_Language (Name : Name_Id) return Boolean is
393 R : Restricted_Lang_Access := Restricted_Languages;
394 Lang : constant String := Get_Name_String (Name);
402 if Get_Name_String (R.Name) = Lang then
411 end Is_Allowed_Language;
413 ---------------------
414 -- Project_Changed --
415 ---------------------
417 procedure Project_Changed (Iter : in out Source_Iterator) is
419 if Iter.Project /= null then
420 Iter.Language := Iter.Project.Project.Languages;
421 Language_Changed (Iter);
425 ----------------------
426 -- Language_Changed --
427 ----------------------
429 procedure Language_Changed (Iter : in out Source_Iterator) is
431 Iter.Current := No_Source;
433 if Iter.Language_Name /= No_Name then
434 while Iter.Language /= null
435 and then Iter.Language.Name /= Iter.Language_Name
437 Iter.Language := Iter.Language.Next;
441 -- If there is no matching language in this project, move to next
443 if Iter.Language = No_Language_Index then
444 if Iter.All_Projects then
445 Iter.Project := Iter.Project.Next;
446 Project_Changed (Iter);
448 Iter.Project := null;
452 Iter.Current := Iter.Language.First_Source;
454 if Iter.Current = No_Source then
455 Iter.Language := Iter.Language.Next;
456 Language_Changed (Iter);
459 end Language_Changed;
461 ---------------------
462 -- For_Each_Source --
463 ---------------------
465 function For_Each_Source
466 (In_Tree : Project_Tree_Ref;
467 Project : Project_Id := No_Project;
468 Language : Name_Id := No_Name) return Source_Iterator
470 Iter : Source_Iterator;
472 Iter := Source_Iterator'
474 Project => In_Tree.Projects,
475 All_Projects => Project = No_Project,
476 Language_Name => Language,
477 Language => No_Language_Index,
478 Current => No_Source);
480 if Project /= null then
481 while Iter.Project /= null
482 and then Iter.Project.Project /= Project
484 Iter.Project := Iter.Project.Next;
488 Project_Changed (Iter);
497 function Element (Iter : Source_Iterator) return Source_Id is
506 procedure Next (Iter : in out Source_Iterator) is
508 Iter.Current := Iter.Current.Next_In_Lang;
509 if Iter.Current = No_Source then
510 Iter.Language := Iter.Language.Next;
511 Language_Changed (Iter);
515 --------------------------------
516 -- For_Every_Project_Imported --
517 --------------------------------
519 procedure For_Every_Project_Imported
521 Tree : Project_Tree_Ref;
522 With_State : in out State;
523 Include_Aggregated : Boolean := True;
524 Imported_First : Boolean := False)
527 use Project_Boolean_Htable;
528 Seen : Project_Boolean_Htable.Instance := Project_Boolean_Htable.Nil;
530 procedure Recursive_Check
531 (Project : Project_Id;
532 Tree : Project_Tree_Ref;
533 In_Aggregate_Lib : Boolean);
534 -- Check if a project has already been seen. If not seen, mark it
535 -- as Seen, Call Action, and check all its imported and aggregated
538 ---------------------
539 -- Recursive_Check --
540 ---------------------
542 procedure Recursive_Check
543 (Project : Project_Id;
544 Tree : Project_Tree_Ref;
545 In_Aggregate_Lib : Boolean)
548 T : Project_Tree_Ref;
551 if not Get (Seen, Project) then
553 -- Even if a project is aggregated multiple times, we will only
556 Set (Seen, Project, True);
558 if not Imported_First then
559 Action (Project, Tree, In_Aggregate_Lib, With_State);
562 -- Visit all extended projects
564 if Project.Extends /= No_Project then
565 Recursive_Check (Project.Extends, Tree, In_Aggregate_Lib);
568 -- Visit all imported projects if needed. This is not needed
569 -- for an aggregate library as imported libraries are just
570 -- there for dependency support.
572 if Project.Qualifier /= Aggregate_Library
573 or else not Include_Aggregated
575 List := Project.Imported_Projects;
576 while List /= null loop
577 Recursive_Check (List.Project, Tree, In_Aggregate_Lib);
582 -- Visit all aggregated projects
584 if Include_Aggregated
585 and then Project.Qualifier in Aggregate_Project
588 Agg : Aggregated_Project_List;
590 Agg := Project.Aggregated_Projects;
591 while Agg /= null loop
592 pragma Assert (Agg.Project /= No_Project);
594 -- For aggregated libraries, the tree must be the one
595 -- of the aggregate library.
597 if Project.Qualifier = Aggregate_Library then
604 (Agg.Project, T, Project.Qualifier = Aggregate_Library);
610 if Imported_First then
611 Action (Project, Tree, In_Aggregate_Lib, With_State);
616 -- Start of processing for For_Every_Project_Imported
619 Recursive_Check (Project => By, Tree => Tree, In_Aggregate_Lib => False);
621 end For_Every_Project_Imported;
628 (In_Tree : Project_Tree_Ref;
629 Project : Project_Id;
630 In_Imported_Only : Boolean := False;
631 In_Extended_Only : Boolean := False;
632 Base_Name : File_Name_Type;
633 Index : Int := 0) return Source_Id
635 Result : Source_Id := No_Source;
637 procedure Look_For_Sources
639 Tree : Project_Tree_Ref;
640 In_Aggregate : Boolean;
641 Src : in out Source_Id);
642 -- Look for Base_Name in the sources of Proj
644 ----------------------
645 -- Look_For_Sources --
646 ----------------------
648 procedure Look_For_Sources
650 Tree : Project_Tree_Ref;
651 In_Aggregate : Boolean;
652 Src : in out Source_Id)
654 pragma Unreferenced (In_Aggregate);
656 Iterator : Source_Iterator;
659 Iterator := For_Each_Source (In_Tree => Tree, Project => Proj);
660 while Element (Iterator) /= No_Source loop
661 if Element (Iterator).File = Base_Name
662 and then (Index = 0 or else Element (Iterator).Index = Index)
664 Src := Element (Iterator);
666 -- If the source has been excluded, continue looking. We will
667 -- get the excluded source only if there is no other source
668 -- with the same base name that is not locally removed.
670 if not Element (Iterator).Locally_Removed then
677 end Look_For_Sources;
679 procedure For_Imported_Projects is new For_Every_Project_Imported
680 (State => Source_Id, Action => Look_For_Sources);
684 -- Start of processing for Find_Source
687 if In_Extended_Only then
689 while Proj /= No_Project loop
690 Look_For_Sources (Proj, In_Tree, False, Result);
691 exit when Result /= No_Source;
693 Proj := Proj.Extends;
696 elsif In_Imported_Only then
697 Look_For_Sources (Project, In_Tree, False, Result);
699 if Result = No_Source then
700 For_Imported_Projects
703 Include_Aggregated => False,
704 With_State => Result);
708 Look_For_Sources (No_Project, In_Tree, False, Result);
718 function Hash is new GNAT.HTable.Hash (Header_Num => Header_Num);
719 -- Used in implementation of other functions Hash below
721 function Hash (Name : File_Name_Type) return Header_Num is
723 return Hash (Get_Name_String (Name));
726 function Hash (Name : Name_Id) return Header_Num is
728 return Hash (Get_Name_String (Name));
731 function Hash (Name : Path_Name_Type) return Header_Num is
733 return Hash (Get_Name_String (Name));
736 function Hash (Project : Project_Id) return Header_Num is
738 if Project = No_Project then
739 return Header_Num'First;
741 return Hash (Get_Name_String (Project.Name));
749 function Image (The_Casing : Casing_Type) return String is
751 return The_Casing_Images (The_Casing).all;
754 -----------------------------
755 -- Is_Standard_GNAT_Naming --
756 -----------------------------
758 function Is_Standard_GNAT_Naming
759 (Naming : Lang_Naming_Data) return Boolean
762 return Get_Name_String (Naming.Spec_Suffix) = ".ads"
763 and then Get_Name_String (Naming.Body_Suffix) = ".adb"
764 and then Get_Name_String (Naming.Dot_Replacement) = "-";
765 end Is_Standard_GNAT_Naming;
771 procedure Initialize (Tree : Project_Tree_Ref) is
773 if The_Empty_String = No_Name then
776 The_Empty_String := Name_Find;
780 -- Make sure that new reserved words after Ada 95 may be used as
783 Opt.Ada_Version := Opt.Ada_95;
785 Set_Name_Table_Byte (Name_Project, Token_Type'Pos (Tok_Project));
786 Set_Name_Table_Byte (Name_Extends, Token_Type'Pos (Tok_Extends));
787 Set_Name_Table_Byte (Name_External, Token_Type'Pos (Tok_External));
789 (Name_External_As_List, Token_Type'Pos (Tok_External_As_List));
792 if Tree /= No_Project_Tree then
801 function Is_Extending
802 (Extending : Project_Id;
803 Extended : Project_Id) return Boolean
809 while Proj /= No_Project loop
810 if Proj = Extended then
814 Proj := Proj.Extends;
825 (Source_File_Name : File_Name_Type;
826 Object_File_Suffix : Name_Id := No_Name) return File_Name_Type
829 if Object_File_Suffix = No_Name then
831 (Source_File_Name, Object_Suffix);
834 (Source_File_Name, Get_Name_String (Object_File_Suffix));
839 (Source_File_Name : File_Name_Type;
841 Index_Separator : Character;
842 Object_File_Suffix : Name_Id := No_Name) return File_Name_Type
844 Index_Img : constant String := Source_Index'Img;
848 Get_Name_String (Source_File_Name);
851 while Last > 1 and then Name_Buffer (Last) /= '.' loop
856 Name_Len := Last - 1;
859 Add_Char_To_Name_Buffer (Index_Separator);
860 Add_Str_To_Name_Buffer (Index_Img (2 .. Index_Img'Last));
862 if Object_File_Suffix = No_Name then
863 Add_Str_To_Name_Buffer (Object_Suffix);
865 Add_Str_To_Name_Buffer (Get_Name_String (Object_File_Suffix));
871 ----------------------
872 -- Record_Temp_File --
873 ----------------------
875 procedure Record_Temp_File
876 (Shared : Shared_Project_Tree_Data_Access;
877 Path : Path_Name_Type)
880 Temp_Files_Table.Append (Shared.Private_Part.Temp_Files, Path);
881 end Record_Temp_File;
887 procedure Free (List : in out Aggregated_Project_List) is
888 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
889 (Aggregated_Project, Aggregated_Project_List);
890 Tmp : Aggregated_Project_List;
892 while List /= null loop
897 Unchecked_Free (List);
902 ----------------------------
903 -- Add_Aggregated_Project --
904 ----------------------------
906 procedure Add_Aggregated_Project
907 (Project : Project_Id; Path : Path_Name_Type) is
909 Project.Aggregated_Projects := new Aggregated_Project'
911 Project => No_Project,
913 Next => Project.Aggregated_Projects);
914 end Add_Aggregated_Project;
920 procedure Free (Project : in out Project_Id) is
921 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
922 (Project_Data, Project_Id);
925 if Project /= null then
926 Free (Project.Ada_Include_Path);
927 Free (Project.Objects_Path);
928 Free (Project.Ada_Objects_Path);
929 Free_List (Project.Imported_Projects, Free_Project => False);
930 Free_List (Project.All_Imported_Projects, Free_Project => False);
931 Free_List (Project.Languages);
933 case Project.Qualifier is
934 when Aggregate | Aggregate_Library =>
935 Free (Project.Aggregated_Projects);
941 Unchecked_Free (Project);
949 procedure Free_List (Languages : in out Language_List) is
950 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
951 (Language_List_Element, Language_List);
954 while Languages /= null loop
955 Tmp := Languages.Next;
956 Unchecked_Free (Languages);
965 procedure Free_List (Source : in out Source_Id) is
966 procedure Unchecked_Free is new
967 Ada.Unchecked_Deallocation (Source_Data, Source_Id);
972 while Source /= No_Source loop
973 Tmp := Source.Next_In_Lang;
974 Free_List (Source.Alternate_Languages);
976 if Source.Unit /= null
977 and then Source.Kind in Spec_Or_Body
979 Source.Unit.File_Names (Source.Kind) := null;
982 Unchecked_Free (Source);
992 (List : in out Project_List;
993 Free_Project : Boolean)
995 procedure Unchecked_Free is new
996 Ada.Unchecked_Deallocation (Project_List_Element, Project_List);
1001 while List /= null loop
1004 if Free_Project then
1005 Free (List.Project);
1008 Unchecked_Free (List);
1017 procedure Free_List (Languages : in out Language_Ptr) is
1018 procedure Unchecked_Free is new
1019 Ada.Unchecked_Deallocation (Language_Data, Language_Ptr);
1024 while Languages /= null loop
1025 Tmp := Languages.Next;
1026 Free_List (Languages.First_Source);
1027 Unchecked_Free (Languages);
1032 --------------------------
1033 -- Reset_Units_In_Table --
1034 --------------------------
1036 procedure Reset_Units_In_Table (Table : in out Units_Htable.Instance) is
1040 Unit := Units_Htable.Get_First (Table);
1041 while Unit /= No_Unit_Index loop
1042 if Unit.File_Names (Spec) /= null then
1043 Unit.File_Names (Spec).Unit := No_Unit_Index;
1046 if Unit.File_Names (Impl) /= null then
1047 Unit.File_Names (Impl).Unit := No_Unit_Index;
1050 Unit := Units_Htable.Get_Next (Table);
1052 end Reset_Units_In_Table;
1058 procedure Free_Units (Table : in out Units_Htable.Instance) is
1059 procedure Unchecked_Free is new
1060 Ada.Unchecked_Deallocation (Unit_Data, Unit_Index);
1065 Unit := Units_Htable.Get_First (Table);
1066 while Unit /= No_Unit_Index loop
1068 -- We cannot reset Unit.File_Names (Impl or Spec).Unit here as
1069 -- Source_Data buffer is freed by the following instruction
1070 -- Free_List (Tree.Projects, Free_Project => True);
1072 Unchecked_Free (Unit);
1073 Unit := Units_Htable.Get_Next (Table);
1076 Units_Htable.Reset (Table);
1083 procedure Free (Tree : in out Project_Tree_Ref) is
1084 procedure Unchecked_Free is new
1085 Ada.Unchecked_Deallocation
1086 (Project_Tree_Data, Project_Tree_Ref);
1088 procedure Unchecked_Free is new
1089 Ada.Unchecked_Deallocation
1090 (Project_Tree_Appdata'Class, Project_Tree_Appdata_Access);
1093 if Tree /= null then
1094 if Tree.Is_Root_Tree then
1095 Name_List_Table.Free (Tree.Shared.Name_Lists);
1096 Number_List_Table.Free (Tree.Shared.Number_Lists);
1097 String_Element_Table.Free (Tree.Shared.String_Elements);
1098 Variable_Element_Table.Free (Tree.Shared.Variable_Elements);
1099 Array_Element_Table.Free (Tree.Shared.Array_Elements);
1100 Array_Table.Free (Tree.Shared.Arrays);
1101 Package_Table.Free (Tree.Shared.Packages);
1102 Temp_Files_Table.Free (Tree.Shared.Private_Part.Temp_Files);
1105 if Tree.Appdata /= null then
1106 Free (Tree.Appdata.all);
1107 Unchecked_Free (Tree.Appdata);
1110 Source_Paths_Htable.Reset (Tree.Source_Paths_HT);
1111 Source_Files_Htable.Reset (Tree.Source_Files_HT);
1113 Reset_Units_In_Table (Tree.Units_HT);
1114 Free_List (Tree.Projects, Free_Project => True);
1115 Free_Units (Tree.Units_HT);
1117 Unchecked_Free (Tree);
1125 procedure Reset (Tree : Project_Tree_Ref) is
1129 if Tree.Is_Root_Tree then
1131 -- We cannot use 'Access here:
1132 -- "illegal attribute for discriminant-dependent component"
1133 -- However, we know this is valid since Shared and Shared_Data have
1134 -- the same lifetime and will always exist concurrently.
1136 Tree.Shared := Tree.Shared_Data'Unrestricted_Access;
1137 Name_List_Table.Init (Tree.Shared.Name_Lists);
1138 Number_List_Table.Init (Tree.Shared.Number_Lists);
1139 String_Element_Table.Init (Tree.Shared.String_Elements);
1140 Variable_Element_Table.Init (Tree.Shared.Variable_Elements);
1141 Array_Element_Table.Init (Tree.Shared.Array_Elements);
1142 Array_Table.Init (Tree.Shared.Arrays);
1143 Package_Table.Init (Tree.Shared.Packages);
1145 -- Private part table
1147 Temp_Files_Table.Init (Tree.Shared.Private_Part.Temp_Files);
1149 Tree.Shared.Private_Part.Current_Source_Path_File := No_Path;
1150 Tree.Shared.Private_Part.Current_Object_Path_File := No_Path;
1153 Source_Paths_Htable.Reset (Tree.Source_Paths_HT);
1154 Source_Files_Htable.Reset (Tree.Source_Files_HT);
1155 Replaced_Source_HTable.Reset (Tree.Replaced_Sources);
1157 Tree.Replaced_Source_Number := 0;
1159 Reset_Units_In_Table (Tree.Units_HT);
1160 Free_List (Tree.Projects, Free_Project => True);
1161 Free_Units (Tree.Units_HT);
1164 -------------------------------------
1165 -- Set_Current_Object_Path_File_Of --
1166 -------------------------------------
1168 procedure Set_Current_Object_Path_File_Of
1169 (Shared : Shared_Project_Tree_Data_Access;
1170 To : Path_Name_Type)
1173 Shared.Private_Part.Current_Object_Path_File := To;
1174 end Set_Current_Object_Path_File_Of;
1176 -------------------------------------
1177 -- Set_Current_Source_Path_File_Of --
1178 -------------------------------------
1180 procedure Set_Current_Source_Path_File_Of
1181 (Shared : Shared_Project_Tree_Data_Access;
1182 To : Path_Name_Type)
1185 Shared.Private_Part.Current_Source_Path_File := To;
1186 end Set_Current_Source_Path_File_Of;
1188 -----------------------
1189 -- Set_Path_File_Var --
1190 -----------------------
1192 procedure Set_Path_File_Var (Name : String; Value : String) is
1193 Host_Spec : String_Access := To_Host_File_Spec (Value);
1195 if Host_Spec = null then
1197 ("could not convert file name """ & Value & """ to host spec");
1199 Setenv (Name, Host_Spec.all);
1202 end Set_Path_File_Var;
1208 function Switches_Name
1209 (Source_File_Name : File_Name_Type) return File_Name_Type
1212 return Extend_Name (Source_File_Name, Switches_Dependency_Suffix);
1219 function Value (Image : String) return Casing_Type is
1221 for Casing in The_Casing_Images'Range loop
1222 if To_Lower (Image) = To_Lower (The_Casing_Images (Casing).all) then
1227 raise Constraint_Error;
1230 ---------------------
1231 -- Has_Ada_Sources --
1232 ---------------------
1234 function Has_Ada_Sources (Data : Project_Id) return Boolean is
1235 Lang : Language_Ptr;
1238 Lang := Data.Languages;
1239 while Lang /= No_Language_Index loop
1240 if Lang.Name = Name_Ada then
1241 return Lang.First_Source /= No_Source;
1247 end Has_Ada_Sources;
1249 ------------------------
1250 -- Contains_ALI_Files --
1251 ------------------------
1253 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean is
1254 Dir_Name : constant String := Get_Name_String (Dir);
1256 Name : String (1 .. 1_000);
1258 Result : Boolean := False;
1261 Open (Direct, Dir_Name);
1263 -- For each file in the directory, check if it is an ALI file
1266 Read (Direct, Name, Last);
1268 Canonical_Case_File_Name (Name (1 .. Last));
1269 Result := Last >= 5 and then Name (Last - 3 .. Last) = ".ali";
1277 -- If there is any problem, close the directory if open and return True.
1278 -- The library directory will be added to the path.
1281 if Is_Open (Direct) then
1286 end Contains_ALI_Files;
1288 --------------------------
1289 -- Get_Object_Directory --
1290 --------------------------
1292 function Get_Object_Directory
1293 (Project : Project_Id;
1294 Including_Libraries : Boolean;
1295 Only_If_Ada : Boolean := False) return Path_Name_Type
1298 if (Project.Library and then Including_Libraries)
1300 (Project.Object_Directory /= No_Path_Information
1301 and then (not Including_Libraries or else not Project.Library))
1303 -- For a library project, add the library ALI directory if there is
1304 -- no object directory or if the library ALI directory contains ALI
1305 -- files; otherwise add the object directory.
1307 if Project.Library then
1308 if Project.Object_Directory = No_Path_Information
1309 or else Contains_ALI_Files (Project.Library_ALI_Dir.Display_Name)
1311 return Project.Library_ALI_Dir.Display_Name;
1313 return Project.Object_Directory.Display_Name;
1316 -- For a non-library project, add object directory if it is not a
1317 -- virtual project, and if there are Ada sources in the project or
1318 -- one of the projects it extends. If there are no Ada sources,
1319 -- adding the object directory could disrupt the order of the
1320 -- object dirs in the path.
1322 elsif not Project.Virtual then
1324 Add_Object_Dir : Boolean;
1328 Add_Object_Dir := not Only_If_Ada;
1330 while not Add_Object_Dir and then Prj /= No_Project loop
1331 if Has_Ada_Sources (Prj) then
1332 Add_Object_Dir := True;
1338 if Add_Object_Dir then
1339 return Project.Object_Directory.Display_Name;
1346 end Get_Object_Directory;
1348 -----------------------------------
1349 -- Ultimate_Extending_Project_Of --
1350 -----------------------------------
1352 function Ultimate_Extending_Project_Of
1353 (Proj : Project_Id) return Project_Id
1359 while Prj /= null and then Prj.Extended_By /= No_Project loop
1360 Prj := Prj.Extended_By;
1364 end Ultimate_Extending_Project_Of;
1366 -----------------------------------
1367 -- Compute_All_Imported_Projects --
1368 -----------------------------------
1370 procedure Compute_All_Imported_Projects
1371 (Root_Project : Project_Id;
1372 Tree : Project_Tree_Ref)
1374 procedure Analyze_Tree
1375 (Local_Root : Project_Id;
1376 Local_Tree : Project_Tree_Ref);
1377 -- Process Project and all its aggregated project to analyze their own
1378 -- imported projects.
1384 procedure Analyze_Tree
1385 (Local_Root : Project_Id;
1386 Local_Tree : Project_Tree_Ref)
1388 pragma Unreferenced (Local_Root);
1390 Project : Project_Id;
1392 procedure Recursive_Add
1394 Tree : Project_Tree_Ref;
1395 In_Aggregate_Lib : Boolean;
1396 Dummy : in out Boolean);
1397 -- Recursively add the projects imported by project Project, but not
1398 -- those that are extended.
1404 procedure Recursive_Add
1406 Tree : Project_Tree_Ref;
1407 In_Aggregate_Lib : Boolean;
1408 Dummy : in out Boolean)
1410 pragma Unreferenced (Dummy, Tree, In_Aggregate_Lib);
1412 List : Project_List;
1416 -- A project is not importing itself
1418 Prj2 := Ultimate_Extending_Project_Of (Prj);
1420 if Project /= Prj2 then
1422 -- Check that the project is not already in the list. We know
1423 -- the one passed to Recursive_Add have never been visited
1424 -- before, but the one passed it are the extended projects.
1426 List := Project.All_Imported_Projects;
1427 while List /= null loop
1428 if List.Project = Prj2 then
1435 -- Add it to the list
1437 Project.All_Imported_Projects :=
1438 new Project_List_Element'
1440 Next => Project.All_Imported_Projects);
1444 procedure For_All_Projects is
1445 new For_Every_Project_Imported (Boolean, Recursive_Add);
1447 Dummy : Boolean := False;
1448 List : Project_List;
1451 List := Local_Tree.Projects;
1452 while List /= null loop
1453 Project := List.Project;
1455 (Project.All_Imported_Projects, Free_Project => False);
1457 (Project, Local_Tree, Dummy, Include_Aggregated => False);
1462 procedure For_Aggregates is
1463 new For_Project_And_Aggregated (Analyze_Tree);
1465 -- Start of processing for Compute_All_Imported_Projects
1468 For_Aggregates (Root_Project, Tree);
1469 end Compute_All_Imported_Projects;
1475 function Is_Compilable (Source : Source_Id) return Boolean is
1477 case Source.Compilable is
1479 if Source.Language.Config.Compiler_Driver /= No_File
1481 Length_Of_Name (Source.Language.Config.Compiler_Driver) /= 0
1482 and then not Source.Locally_Removed
1483 and then (Source.Language.Config.Kind /= File_Based
1484 or else Source.Kind /= Spec)
1486 -- Do not modify Source.Compilable before the source record
1487 -- has been initialized.
1489 if Source.Source_TS /= Empty_Time_Stamp then
1490 Source.Compilable := Yes;
1496 if Source.Source_TS /= Empty_Time_Stamp then
1497 Source.Compilable := No;
1511 ------------------------------
1512 -- Object_To_Global_Archive --
1513 ------------------------------
1515 function Object_To_Global_Archive (Source : Source_Id) return Boolean is
1517 return Source.Language.Config.Kind = File_Based
1518 and then Source.Kind = Impl
1519 and then Source.Language.Config.Objects_Linked
1520 and then Is_Compilable (Source)
1521 and then Source.Language.Config.Object_Generated;
1522 end Object_To_Global_Archive;
1524 ----------------------------
1525 -- Get_Language_From_Name --
1526 ----------------------------
1528 function Get_Language_From_Name
1529 (Project : Project_Id;
1530 Name : String) return Language_Ptr
1533 Result : Language_Ptr;
1536 Name_Len := Name'Length;
1537 Name_Buffer (1 .. Name_Len) := Name;
1538 To_Lower (Name_Buffer (1 .. Name_Len));
1541 Result := Project.Languages;
1542 while Result /= No_Language_Index loop
1543 if Result.Name = N then
1547 Result := Result.Next;
1550 return No_Language_Index;
1551 end Get_Language_From_Name;
1557 function Other_Part (Source : Source_Id) return Source_Id is
1559 if Source.Unit /= No_Unit_Index then
1562 return Source.Unit.File_Names (Spec);
1564 return Source.Unit.File_Names (Impl);
1577 function Create_Flags
1578 (Report_Error : Error_Handler;
1579 When_No_Sources : Error_Warning;
1580 Require_Sources_Other_Lang : Boolean := True;
1581 Allow_Duplicate_Basenames : Boolean := True;
1582 Compiler_Driver_Mandatory : Boolean := False;
1583 Error_On_Unknown_Language : Boolean := True;
1584 Require_Obj_Dirs : Error_Warning := Error;
1585 Allow_Invalid_External : Error_Warning := Error;
1586 Missing_Source_Files : Error_Warning := Error;
1587 Ignore_Missing_With : Boolean := False)
1588 return Processing_Flags
1591 return Processing_Flags'
1592 (Report_Error => Report_Error,
1593 When_No_Sources => When_No_Sources,
1594 Require_Sources_Other_Lang => Require_Sources_Other_Lang,
1595 Allow_Duplicate_Basenames => Allow_Duplicate_Basenames,
1596 Error_On_Unknown_Language => Error_On_Unknown_Language,
1597 Compiler_Driver_Mandatory => Compiler_Driver_Mandatory,
1598 Require_Obj_Dirs => Require_Obj_Dirs,
1599 Allow_Invalid_External => Allow_Invalid_External,
1600 Missing_Source_Files => Missing_Source_Files,
1601 Ignore_Missing_With => Ignore_Missing_With);
1609 (Table : Name_List_Table.Instance;
1610 List : Name_List_Index) return Natural
1612 Count : Natural := 0;
1613 Tmp : Name_List_Index;
1617 while Tmp /= No_Name_List loop
1619 Tmp := Table.Table (Tmp).Next;
1629 procedure Debug_Output (Str : String) is
1631 if Current_Verbosity > Default then
1633 Write_Line ((1 .. Debug_Level * 2 => ' ') & Str);
1634 Set_Standard_Output;
1642 procedure Debug_Indent is
1644 if Current_Verbosity = High then
1646 Write_Str ((1 .. Debug_Level * 2 => ' '));
1647 Set_Standard_Output;
1655 procedure Debug_Output (Str : String; Str2 : Name_Id) is
1657 if Current_Verbosity = High then
1662 if Str2 = No_Name then
1663 Write_Line (" <no_name>");
1665 Write_Line (" """ & Get_Name_String (Str2) & '"');
1668 Set_Standard_Output;
1672 ---------------------------
1673 -- Debug_Increase_Indent --
1674 ---------------------------
1676 procedure Debug_Increase_Indent
1677 (Str : String := ""; Str2 : Name_Id := No_Name)
1680 if Str2 /= No_Name then
1681 Debug_Output (Str, Str2);
1685 Debug_Level := Debug_Level + 1;
1686 end Debug_Increase_Indent;
1688 ---------------------------
1689 -- Debug_Decrease_Indent --
1690 ---------------------------
1692 procedure Debug_Decrease_Indent (Str : String := "") is
1694 if Debug_Level > 0 then
1695 Debug_Level := Debug_Level - 1;
1701 end Debug_Decrease_Indent;
1707 function Debug_Name (Tree : Project_Tree_Ref) return Name_Id is
1712 Add_Str_To_Name_Buffer ("Tree [");
1715 while P /= null loop
1716 if P /= Tree.Projects then
1717 Add_Char_To_Name_Buffer (',');
1720 Add_Str_To_Name_Buffer (Get_Name_String (P.Project.Name));
1725 Add_Char_To_Name_Buffer (']');
1734 procedure Free (Tree : in out Project_Tree_Appdata) is
1735 pragma Unreferenced (Tree);
1740 --------------------------------
1741 -- For_Project_And_Aggregated --
1742 --------------------------------
1744 procedure For_Project_And_Aggregated
1745 (Root_Project : Project_Id;
1746 Root_Tree : Project_Tree_Ref)
1748 Agg : Aggregated_Project_List;
1751 Action (Root_Project, Root_Tree);
1753 if Root_Project.Qualifier in Aggregate_Project then
1754 Agg := Root_Project.Aggregated_Projects;
1755 while Agg /= null loop
1756 For_Project_And_Aggregated (Agg.Project, Agg.Tree);
1760 end For_Project_And_Aggregated;
1762 -- Package initialization for Prj
1765 -- Make sure that the standard config and user project file extensions are
1766 -- compatible with canonical case file naming.
1768 Canonical_Case_File_Name (Config_Project_File_Extension);
1769 Canonical_Case_File_Name (Project_File_Extension);