2015-05-05 Yvan Roux <yvan.roux@linaro.org>
[official-gcc.git] / gcc / ada / prj.adb
blob9da0f4485646c5e3f78936a1889a89e06fd7e8a7
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- P R J --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2001-2014, Free Software Foundation, Inc. --
10 -- --
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. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
26 with Opt;
27 with Osint; use Osint;
28 with Output; use Output;
29 with Prj.Attr;
30 with Prj.Com;
31 with Prj.Err; use Prj.Err;
32 with Snames; use Snames;
33 with Uintp; use Uintp;
35 with Ada.Characters.Handling; use Ada.Characters.Handling;
36 with Ada.Containers.Ordered_Sets;
37 with Ada.Unchecked_Deallocation;
39 with GNAT.Case_Util; use GNAT.Case_Util;
40 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
41 with GNAT.HTable;
43 package body Prj is
45 type Restricted_Lang;
46 type Restricted_Lang_Access is access Restricted_Lang;
47 type Restricted_Lang is record
48 Name : Name_Id;
49 Next : Restricted_Lang_Access;
50 end record;
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;
63 The_Dot_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;
107 begin
108 To_Lower (N);
109 Name_Len := 0;
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;
115 -------------------------------------
116 -- Remove_All_Restricted_Languages --
117 -------------------------------------
119 procedure Remove_All_Restricted_Languages is
120 begin
121 Restricted_Languages := null;
122 end Remove_All_Restricted_Languages;
124 -------------------
125 -- Add_To_Buffer --
126 -------------------
128 procedure Add_To_Buffer
129 (S : String;
130 To : in out String_Access;
131 Last : in out Natural)
133 begin
134 if To = null then
135 To := new String (1 .. Initial_Buffer_Size);
136 Last := 0;
137 end if;
139 -- If Buffer is too small, double its size
141 while Last + S'Length > To'Last loop
142 declare
143 New_Buffer : constant String_Access :=
144 new String (1 .. 2 * To'Length);
145 begin
146 New_Buffer (1 .. Last) := To (1 .. Last);
147 Free (To);
148 To := New_Buffer;
149 end;
150 end loop;
152 To (Last + 1 .. Last + S'Length) := S;
153 Last := Last + S'Length;
154 end Add_To_Buffer;
156 ---------------------------------
157 -- Current_Object_Path_File_Of --
158 ---------------------------------
160 function Current_Object_Path_File_Of
161 (Shared : Shared_Project_Tree_Data_Access) return Path_Name_Type
163 begin
164 return Shared.Private_Part.Current_Object_Path_File;
165 end Current_Object_Path_File_Of;
167 ---------------------------------
168 -- Current_Source_Path_File_Of --
169 ---------------------------------
171 function Current_Source_Path_File_Of
172 (Shared : Shared_Project_Tree_Data_Access)
173 return Path_Name_Type is
174 begin
175 return Shared.Private_Part.Current_Source_Path_File;
176 end Current_Source_Path_File_Of;
178 ---------------------------
179 -- Delete_Temporary_File --
180 ---------------------------
182 procedure Delete_Temporary_File
183 (Shared : Shared_Project_Tree_Data_Access := null;
184 Path : Path_Name_Type)
186 Dont_Care : Boolean;
187 pragma Warnings (Off, Dont_Care);
189 begin
190 if not Opt.Keep_Temporary_Files then
191 if Current_Verbosity = High then
192 Write_Line ("Removing temp file: " & Get_Name_String (Path));
193 end if;
195 Delete_File (Get_Name_String (Path), Dont_Care);
197 if Shared /= null then
198 for Index in
199 1 .. Temp_Files_Table.Last (Shared.Private_Part.Temp_Files)
200 loop
201 if Shared.Private_Part.Temp_Files.Table (Index) = Path then
202 Shared.Private_Part.Temp_Files.Table (Index) := No_Path;
203 end if;
204 end loop;
205 end if;
206 end if;
207 end Delete_Temporary_File;
209 ------------------------------
210 -- Delete_Temp_Config_Files --
211 ------------------------------
213 procedure Delete_Temp_Config_Files (Project_Tree : Project_Tree_Ref) is
214 Success : Boolean;
215 pragma Warnings (Off, Success);
217 Proj : Project_List;
219 begin
220 if not Opt.Keep_Temporary_Files then
221 if Project_Tree /= null then
222 Proj := Project_Tree.Projects;
223 while Proj /= null loop
224 if Proj.Project.Config_File_Temp then
225 Delete_Temporary_File
226 (Project_Tree.Shared, Proj.Project.Config_File_Name);
228 -- Make sure that we don't have a config file for this
229 -- project, in case there are several mains. In this case,
230 -- we will recreate another config file: we cannot reuse the
231 -- one that we just deleted.
233 Proj.Project.Config_Checked := False;
234 Proj.Project.Config_File_Name := No_Path;
235 Proj.Project.Config_File_Temp := False;
236 end if;
238 Proj := Proj.Next;
239 end loop;
240 end if;
241 end if;
242 end Delete_Temp_Config_Files;
244 ---------------------------
245 -- Delete_All_Temp_Files --
246 ---------------------------
248 procedure Delete_All_Temp_Files
249 (Shared : Shared_Project_Tree_Data_Access)
251 Dont_Care : Boolean;
252 pragma Warnings (Off, Dont_Care);
254 Path : Path_Name_Type;
256 begin
257 if not Opt.Keep_Temporary_Files then
258 for Index in
259 1 .. Temp_Files_Table.Last (Shared.Private_Part.Temp_Files)
260 loop
261 Path := Shared.Private_Part.Temp_Files.Table (Index);
263 if Path /= No_Path then
264 if Current_Verbosity = High then
265 Write_Line ("Removing temp file: "
266 & Get_Name_String (Path));
267 end if;
269 Delete_File (Get_Name_String (Path), Dont_Care);
270 end if;
271 end loop;
273 Temp_Files_Table.Free (Shared.Private_Part.Temp_Files);
274 Temp_Files_Table.Init (Shared.Private_Part.Temp_Files);
275 end if;
277 -- If any of the environment variables ADA_PRJ_INCLUDE_FILE or
278 -- ADA_PRJ_OBJECTS_FILE has been set, then reset their value to
279 -- the empty string.
281 if Shared.Private_Part.Current_Source_Path_File /= No_Path then
282 Setenv (Project_Include_Path_File, "");
283 end if;
285 if Shared.Private_Part.Current_Object_Path_File /= No_Path then
286 Setenv (Project_Objects_Path_File, "");
287 end if;
288 end Delete_All_Temp_Files;
290 ---------------------
291 -- Dependency_Name --
292 ---------------------
294 function Dependency_Name
295 (Source_File_Name : File_Name_Type;
296 Dependency : Dependency_File_Kind) return File_Name_Type
298 begin
299 case Dependency is
300 when None =>
301 return No_File;
303 when Makefile =>
304 return Extend_Name (Source_File_Name, Makefile_Dependency_Suffix);
306 when ALI_File | ALI_Closure =>
307 return Extend_Name (Source_File_Name, ALI_Dependency_Suffix);
308 end case;
309 end Dependency_Name;
311 ----------------
312 -- Dot_String --
313 ----------------
315 function Dot_String return Name_Id is
316 begin
317 return The_Dot_String;
318 end Dot_String;
320 ----------------
321 -- Empty_File --
322 ----------------
324 function Empty_File return File_Name_Type is
325 begin
326 return File_Name_Type (The_Empty_String);
327 end Empty_File;
329 -------------------
330 -- Empty_Project --
331 -------------------
333 function Empty_Project
334 (Qualifier : Project_Qualifier) return Project_Data
336 begin
337 Prj.Initialize (Tree => No_Project_Tree);
339 declare
340 Data : Project_Data (Qualifier => Qualifier);
342 begin
343 -- Only the fields for which no default value could be provided in
344 -- prj.ads are initialized below.
346 Data.Config := Default_Project_Config;
347 return Data;
348 end;
349 end Empty_Project;
351 ------------------
352 -- Empty_String --
353 ------------------
355 function Empty_String return Name_Id is
356 begin
357 return The_Empty_String;
358 end Empty_String;
360 ------------
361 -- Expect --
362 ------------
364 procedure Expect (The_Token : Token_Type; Token_Image : String) is
365 begin
366 if Token /= The_Token then
368 -- ??? Should pass user flags here instead
370 Error_Msg (Gnatmake_Flags, Token_Image & " expected", Token_Ptr);
371 end if;
372 end Expect;
374 -----------------
375 -- Extend_Name --
376 -----------------
378 function Extend_Name
379 (File : File_Name_Type;
380 With_Suffix : String) return File_Name_Type
382 Last : Positive;
384 begin
385 Get_Name_String (File);
386 Last := Name_Len + 1;
388 while Name_Len /= 0 and then Name_Buffer (Name_Len) /= '.' loop
389 Name_Len := Name_Len - 1;
390 end loop;
392 if Name_Len <= 1 then
393 Name_Len := Last;
394 end if;
396 for J in With_Suffix'Range loop
397 Name_Buffer (Name_Len) := With_Suffix (J);
398 Name_Len := Name_Len + 1;
399 end loop;
401 Name_Len := Name_Len - 1;
402 return Name_Find;
403 end Extend_Name;
405 -------------------------
406 -- Is_Allowed_Language --
407 -------------------------
409 function Is_Allowed_Language (Name : Name_Id) return Boolean is
410 R : Restricted_Lang_Access := Restricted_Languages;
411 Lang : constant String := Get_Name_String (Name);
413 begin
414 if R = null then
415 return True;
417 else
418 while R /= null loop
419 if Get_Name_String (R.Name) = Lang then
420 return True;
421 end if;
423 R := R.Next;
424 end loop;
426 return False;
427 end if;
428 end Is_Allowed_Language;
430 ---------------------
431 -- Project_Changed --
432 ---------------------
434 procedure Project_Changed (Iter : in out Source_Iterator) is
435 begin
436 if Iter.Project /= null then
437 Iter.Language := Iter.Project.Project.Languages;
438 Language_Changed (Iter);
439 end if;
440 end Project_Changed;
442 ----------------------
443 -- Language_Changed --
444 ----------------------
446 procedure Language_Changed (Iter : in out Source_Iterator) is
447 begin
448 Iter.Current := No_Source;
450 if Iter.Language_Name /= No_Name then
451 while Iter.Language /= null
452 and then Iter.Language.Name /= Iter.Language_Name
453 loop
454 Iter.Language := Iter.Language.Next;
455 end loop;
456 end if;
458 -- If there is no matching language in this project, move to next
460 if Iter.Language = No_Language_Index then
461 if Iter.All_Projects then
462 loop
463 Iter.Project := Iter.Project.Next;
464 exit when Iter.Project = null
465 or else Iter.Encapsulated_Libs
466 or else not Iter.Project.From_Encapsulated_Lib;
467 end loop;
469 Project_Changed (Iter);
470 else
471 Iter.Project := null;
472 end if;
474 else
475 Iter.Current := Iter.Language.First_Source;
477 if Iter.Current = No_Source then
478 Iter.Language := Iter.Language.Next;
479 Language_Changed (Iter);
481 elsif not Iter.Locally_Removed
482 and then Iter.Current.Locally_Removed
483 then
484 Next (Iter);
485 end if;
486 end if;
487 end Language_Changed;
489 ---------------------
490 -- For_Each_Source --
491 ---------------------
493 function For_Each_Source
494 (In_Tree : Project_Tree_Ref;
495 Project : Project_Id := No_Project;
496 Language : Name_Id := No_Name;
497 Encapsulated_Libs : Boolean := True;
498 Locally_Removed : Boolean := True) return Source_Iterator
500 Iter : Source_Iterator;
501 begin
502 Iter := Source_Iterator'
503 (In_Tree => In_Tree,
504 Project => In_Tree.Projects,
505 All_Projects => Project = No_Project,
506 Language_Name => Language,
507 Language => No_Language_Index,
508 Current => No_Source,
509 Encapsulated_Libs => Encapsulated_Libs,
510 Locally_Removed => Locally_Removed);
512 if Project /= null then
513 while Iter.Project /= null
514 and then Iter.Project.Project /= Project
515 loop
516 Iter.Project := Iter.Project.Next;
517 end loop;
519 else
520 while not Iter.Encapsulated_Libs
521 and then Iter.Project.From_Encapsulated_Lib
522 loop
523 Iter.Project := Iter.Project.Next;
524 end loop;
525 end if;
527 Project_Changed (Iter);
529 return Iter;
530 end For_Each_Source;
532 -------------
533 -- Element --
534 -------------
536 function Element (Iter : Source_Iterator) return Source_Id is
537 begin
538 return Iter.Current;
539 end Element;
541 ----------
542 -- Next --
543 ----------
545 procedure Next (Iter : in out Source_Iterator) is
546 begin
547 loop
548 Iter.Current := Iter.Current.Next_In_Lang;
550 exit when Iter.Locally_Removed
551 or else Iter.Current = No_Source
552 or else not Iter.Current.Locally_Removed;
553 end loop;
555 if Iter.Current = No_Source then
556 Iter.Language := Iter.Language.Next;
557 Language_Changed (Iter);
558 end if;
559 end Next;
561 --------------------------------
562 -- For_Every_Project_Imported --
563 --------------------------------
565 procedure For_Every_Project_Imported_Context
566 (By : Project_Id;
567 Tree : Project_Tree_Ref;
568 With_State : in out State;
569 Include_Aggregated : Boolean := True;
570 Imported_First : Boolean := False)
572 use Project_Boolean_Htable;
574 procedure Recursive_Check_Context
575 (Project : Project_Id;
576 Tree : Project_Tree_Ref;
577 In_Aggregate_Lib : Boolean;
578 From_Encapsulated_Lib : Boolean);
579 -- Recursively handle the project tree creating a new context for
580 -- keeping track about already handled projects.
582 -----------------------------
583 -- Recursive_Check_Context --
584 -----------------------------
586 procedure Recursive_Check_Context
587 (Project : Project_Id;
588 Tree : Project_Tree_Ref;
589 In_Aggregate_Lib : Boolean;
590 From_Encapsulated_Lib : Boolean)
592 package Name_Id_Set is
593 new Ada.Containers.Ordered_Sets (Element_Type => Name_Id);
595 Seen_Name : Name_Id_Set.Set;
596 -- This set is needed to ensure that we do not handle the same
597 -- project twice in the context of aggregate libraries.
599 procedure Recursive_Check
600 (Project : Project_Id;
601 Tree : Project_Tree_Ref;
602 In_Aggregate_Lib : Boolean;
603 From_Encapsulated_Lib : Boolean);
604 -- Check if project has already been seen. If not, mark it as Seen,
605 -- Call Action, and check all its imported and aggregated projects.
607 ---------------------
608 -- Recursive_Check --
609 ---------------------
611 procedure Recursive_Check
612 (Project : Project_Id;
613 Tree : Project_Tree_Ref;
614 In_Aggregate_Lib : Boolean;
615 From_Encapsulated_Lib : Boolean)
618 function Has_Sources (P : Project_Id) return Boolean;
619 -- Returns True if P has sources
621 function Get_From_Tree (P : Project_Id) return Project_Id;
622 -- Get project P from Tree. If P has no sources get another
623 -- instance of this project with sources. If P has sources,
624 -- returns it.
626 -----------------
627 -- Has_Sources --
628 -----------------
630 function Has_Sources (P : Project_Id) return Boolean is
631 Lang : Language_Ptr;
633 begin
634 Lang := P.Languages;
635 while Lang /= No_Language_Index loop
636 if Lang.First_Source /= No_Source then
637 return True;
638 end if;
640 Lang := Lang.Next;
641 end loop;
643 return False;
644 end Has_Sources;
646 -------------------
647 -- Get_From_Tree --
648 -------------------
650 function Get_From_Tree (P : Project_Id) return Project_Id is
651 List : Project_List := Tree.Projects;
653 begin
654 if not Has_Sources (P) then
655 while List /= null loop
656 if List.Project.Name = P.Name
657 and then Has_Sources (List.Project)
658 then
659 return List.Project;
660 end if;
662 List := List.Next;
663 end loop;
664 end if;
666 return P;
667 end Get_From_Tree;
669 -- Local variables
671 List : Project_List;
673 -- Start of processing for Recursive_Check
675 begin
676 if not Seen_Name.Contains (Project.Name) then
678 -- Even if a project is aggregated multiple times in an
679 -- aggregated library, we will only return it once.
681 Seen_Name.Include (Project.Name);
683 if not Imported_First then
684 Action
685 (Get_From_Tree (Project),
686 Tree,
687 Project_Context'(In_Aggregate_Lib, From_Encapsulated_Lib),
688 With_State);
689 end if;
691 -- Visit all extended projects
693 if Project.Extends /= No_Project then
694 Recursive_Check
695 (Project.Extends, Tree,
696 In_Aggregate_Lib, From_Encapsulated_Lib);
697 end if;
699 -- Visit all imported projects
701 List := Project.Imported_Projects;
702 while List /= null loop
703 Recursive_Check
704 (List.Project, Tree,
705 In_Aggregate_Lib,
706 From_Encapsulated_Lib
707 or else Project.Standalone_Library = Encapsulated);
708 List := List.Next;
709 end loop;
711 -- Visit all aggregated projects
713 if Include_Aggregated
714 and then Project.Qualifier in Aggregate_Project
715 then
716 declare
717 Agg : Aggregated_Project_List;
719 begin
720 Agg := Project.Aggregated_Projects;
721 while Agg /= null loop
722 pragma Assert (Agg.Project /= No_Project);
724 -- For aggregated libraries, the tree must be the one
725 -- of the aggregate library.
727 if Project.Qualifier = Aggregate_Library then
728 Recursive_Check
729 (Agg.Project, Tree,
730 True,
731 From_Encapsulated_Lib
732 or else
733 Project.Standalone_Library = Encapsulated);
735 else
736 -- Use a new context as we want to returns the same
737 -- project in different project tree for aggregated
738 -- projects.
740 Recursive_Check_Context
741 (Agg.Project, Agg.Tree, False, False);
742 end if;
744 Agg := Agg.Next;
745 end loop;
746 end;
747 end if;
749 if Imported_First then
750 Action
751 (Get_From_Tree (Project),
752 Tree,
753 Project_Context'(In_Aggregate_Lib, From_Encapsulated_Lib),
754 With_State);
755 end if;
756 end if;
757 end Recursive_Check;
759 -- Start of processing for Recursive_Check_Context
761 begin
762 Recursive_Check
763 (Project, Tree, In_Aggregate_Lib, From_Encapsulated_Lib);
764 end Recursive_Check_Context;
766 -- Start of processing for For_Every_Project_Imported
768 begin
769 Recursive_Check_Context
770 (Project => By,
771 Tree => Tree,
772 In_Aggregate_Lib => False,
773 From_Encapsulated_Lib => False);
774 end For_Every_Project_Imported_Context;
776 procedure For_Every_Project_Imported
777 (By : Project_Id;
778 Tree : Project_Tree_Ref;
779 With_State : in out State;
780 Include_Aggregated : Boolean := True;
781 Imported_First : Boolean := False)
783 procedure Internal
784 (Project : Project_Id;
785 Tree : Project_Tree_Ref;
786 Context : Project_Context;
787 With_State : in out State);
788 -- Action wrapper for handling the context
790 --------------
791 -- Internal --
792 --------------
794 procedure Internal
795 (Project : Project_Id;
796 Tree : Project_Tree_Ref;
797 Context : Project_Context;
798 With_State : in out State)
800 pragma Unreferenced (Context);
801 begin
802 Action (Project, Tree, With_State);
803 end Internal;
805 procedure For_Projects is
806 new For_Every_Project_Imported_Context (State, Internal);
808 begin
809 For_Projects (By, Tree, With_State, Include_Aggregated, Imported_First);
810 end For_Every_Project_Imported;
812 -----------------
813 -- Find_Source --
814 -----------------
816 function Find_Source
817 (In_Tree : Project_Tree_Ref;
818 Project : Project_Id;
819 In_Imported_Only : Boolean := False;
820 In_Extended_Only : Boolean := False;
821 Base_Name : File_Name_Type;
822 Index : Int := 0) return Source_Id
824 Result : Source_Id := No_Source;
826 procedure Look_For_Sources
827 (Proj : Project_Id;
828 Tree : Project_Tree_Ref;
829 Src : in out Source_Id);
830 -- Look for Base_Name in the sources of Proj
832 ----------------------
833 -- Look_For_Sources --
834 ----------------------
836 procedure Look_For_Sources
837 (Proj : Project_Id;
838 Tree : Project_Tree_Ref;
839 Src : in out Source_Id)
841 Iterator : Source_Iterator;
843 begin
844 Iterator := For_Each_Source (In_Tree => Tree, Project => Proj);
845 while Element (Iterator) /= No_Source loop
846 if Element (Iterator).File = Base_Name
847 and then (Index = 0 or else Element (Iterator).Index = Index)
848 then
849 Src := Element (Iterator);
851 -- If the source has been excluded, continue looking. We will
852 -- get the excluded source only if there is no other source
853 -- with the same base name that is not locally removed.
855 if not Element (Iterator).Locally_Removed then
856 return;
857 end if;
858 end if;
860 Next (Iterator);
861 end loop;
862 end Look_For_Sources;
864 procedure For_Imported_Projects is new For_Every_Project_Imported
865 (State => Source_Id, Action => Look_For_Sources);
867 Proj : Project_Id;
869 -- Start of processing for Find_Source
871 begin
872 if In_Extended_Only then
873 Proj := Project;
874 while Proj /= No_Project loop
875 Look_For_Sources (Proj, In_Tree, Result);
876 exit when Result /= No_Source;
878 Proj := Proj.Extends;
879 end loop;
881 elsif In_Imported_Only then
882 Look_For_Sources (Project, In_Tree, Result);
884 if Result = No_Source then
885 For_Imported_Projects
886 (By => Project,
887 Tree => In_Tree,
888 Include_Aggregated => False,
889 With_State => Result);
890 end if;
892 else
893 Look_For_Sources (No_Project, In_Tree, Result);
894 end if;
896 return Result;
897 end Find_Source;
899 ----------------------
900 -- Find_All_Sources --
901 ----------------------
903 function Find_All_Sources
904 (In_Tree : Project_Tree_Ref;
905 Project : Project_Id;
906 In_Imported_Only : Boolean := False;
907 In_Extended_Only : Boolean := False;
908 Base_Name : File_Name_Type;
909 Index : Int := 0) return Source_Ids
911 Result : Source_Ids (1 .. 1_000);
912 Last : Natural := 0;
914 type Empty_State is null record;
915 No_State : Empty_State;
916 -- This is needed for the State parameter of procedure Look_For_Sources
917 -- below, because of the instantiation For_Imported_Projects of generic
918 -- procedure For_Every_Project_Imported. As procedure Look_For_Sources
919 -- does not modify parameter State, there is no need to give its type
920 -- more than one value.
922 procedure Look_For_Sources
923 (Proj : Project_Id;
924 Tree : Project_Tree_Ref;
925 State : in out Empty_State);
926 -- Look for Base_Name in the sources of Proj
928 ----------------------
929 -- Look_For_Sources --
930 ----------------------
932 procedure Look_For_Sources
933 (Proj : Project_Id;
934 Tree : Project_Tree_Ref;
935 State : in out Empty_State)
937 Iterator : Source_Iterator;
938 Src : Source_Id;
940 begin
941 State := No_State;
943 Iterator := For_Each_Source (In_Tree => Tree, Project => Proj);
944 while Element (Iterator) /= No_Source loop
945 if Element (Iterator).File = Base_Name
946 and then (Index = 0
947 or else
948 (Element (Iterator).Unit /= No_Unit_Index
949 and then
950 Element (Iterator).Index = Index))
951 then
952 Src := Element (Iterator);
954 -- If the source has been excluded, continue looking. We will
955 -- get the excluded source only if there is no other source
956 -- with the same base name that is not locally removed.
958 if not Element (Iterator).Locally_Removed then
959 Last := Last + 1;
960 Result (Last) := Src;
961 end if;
962 end if;
964 Next (Iterator);
965 end loop;
966 end Look_For_Sources;
968 procedure For_Imported_Projects is new For_Every_Project_Imported
969 (State => Empty_State, Action => Look_For_Sources);
971 Proj : Project_Id;
973 -- Start of processing for Find_All_Sources
975 begin
976 if In_Extended_Only then
977 Proj := Project;
978 while Proj /= No_Project loop
979 Look_For_Sources (Proj, In_Tree, No_State);
980 exit when Last > 0;
981 Proj := Proj.Extends;
982 end loop;
984 elsif In_Imported_Only then
985 Look_For_Sources (Project, In_Tree, No_State);
987 if Last = 0 then
988 For_Imported_Projects
989 (By => Project,
990 Tree => In_Tree,
991 Include_Aggregated => False,
992 With_State => No_State);
993 end if;
995 else
996 Look_For_Sources (No_Project, In_Tree, No_State);
997 end if;
999 return Result (1 .. Last);
1000 end Find_All_Sources;
1002 ----------
1003 -- Hash --
1004 ----------
1006 function Hash is new GNAT.HTable.Hash (Header_Num => Header_Num);
1007 -- Used in implementation of other functions Hash below
1009 ----------
1010 -- Hash --
1011 ----------
1013 function Hash (Name : File_Name_Type) return Header_Num is
1014 begin
1015 return Hash (Get_Name_String (Name));
1016 end Hash;
1018 function Hash (Name : Name_Id) return Header_Num is
1019 begin
1020 return Hash (Get_Name_String (Name));
1021 end Hash;
1023 function Hash (Name : Path_Name_Type) return Header_Num is
1024 begin
1025 return Hash (Get_Name_String (Name));
1026 end Hash;
1028 function Hash (Project : Project_Id) return Header_Num is
1029 begin
1030 if Project = No_Project then
1031 return Header_Num'First;
1032 else
1033 return Hash (Get_Name_String (Project.Name));
1034 end if;
1035 end Hash;
1037 -----------
1038 -- Image --
1039 -----------
1041 function Image (The_Casing : Casing_Type) return String is
1042 begin
1043 return The_Casing_Images (The_Casing).all;
1044 end Image;
1046 -----------------------------
1047 -- Is_Standard_GNAT_Naming --
1048 -----------------------------
1050 function Is_Standard_GNAT_Naming
1051 (Naming : Lang_Naming_Data) return Boolean
1053 begin
1054 return Get_Name_String (Naming.Spec_Suffix) = ".ads"
1055 and then Get_Name_String (Naming.Body_Suffix) = ".adb"
1056 and then Get_Name_String (Naming.Dot_Replacement) = "-";
1057 end Is_Standard_GNAT_Naming;
1059 ----------------
1060 -- Initialize --
1061 ----------------
1063 procedure Initialize (Tree : Project_Tree_Ref) is
1064 begin
1065 if The_Empty_String = No_Name then
1066 Uintp.Initialize;
1067 Name_Len := 0;
1068 The_Empty_String := Name_Find;
1070 Name_Len := 1;
1071 Name_Buffer (1) := '.';
1072 The_Dot_String := Name_Find;
1074 Prj.Attr.Initialize;
1076 -- Make sure that new reserved words after Ada 95 may be used as
1077 -- identifiers.
1079 Opt.Ada_Version := Opt.Ada_95;
1080 Opt.Ada_Version_Pragma := Empty;
1082 Set_Name_Table_Byte (Name_Project, Token_Type'Pos (Tok_Project));
1083 Set_Name_Table_Byte (Name_Extends, Token_Type'Pos (Tok_Extends));
1084 Set_Name_Table_Byte (Name_External, Token_Type'Pos (Tok_External));
1085 Set_Name_Table_Byte
1086 (Name_External_As_List, Token_Type'Pos (Tok_External_As_List));
1087 end if;
1089 if Tree /= No_Project_Tree then
1090 Reset (Tree);
1091 end if;
1092 end Initialize;
1094 ------------------
1095 -- Is_Extending --
1096 ------------------
1098 function Is_Extending
1099 (Extending : Project_Id;
1100 Extended : Project_Id) return Boolean
1102 Proj : Project_Id;
1104 begin
1105 Proj := Extending;
1106 while Proj /= No_Project loop
1107 if Proj = Extended then
1108 return True;
1109 end if;
1111 Proj := Proj.Extends;
1112 end loop;
1114 return False;
1115 end Is_Extending;
1117 -----------------
1118 -- Object_Name --
1119 -----------------
1121 function Object_Name
1122 (Source_File_Name : File_Name_Type;
1123 Object_File_Suffix : Name_Id := No_Name) return File_Name_Type
1125 begin
1126 if Object_File_Suffix = No_Name then
1127 return Extend_Name
1128 (Source_File_Name, Object_Suffix);
1129 else
1130 return Extend_Name
1131 (Source_File_Name, Get_Name_String (Object_File_Suffix));
1132 end if;
1133 end Object_Name;
1135 function Object_Name
1136 (Source_File_Name : File_Name_Type;
1137 Source_Index : Int;
1138 Index_Separator : Character;
1139 Object_File_Suffix : Name_Id := No_Name) return File_Name_Type
1141 Index_Img : constant String := Source_Index'Img;
1142 Last : Natural;
1144 begin
1145 Get_Name_String (Source_File_Name);
1147 Last := Name_Len;
1148 while Last > 1 and then Name_Buffer (Last) /= '.' loop
1149 Last := Last - 1;
1150 end loop;
1152 if Last > 1 then
1153 Name_Len := Last - 1;
1154 end if;
1156 Add_Char_To_Name_Buffer (Index_Separator);
1157 Add_Str_To_Name_Buffer (Index_Img (2 .. Index_Img'Last));
1159 if Object_File_Suffix = No_Name then
1160 Add_Str_To_Name_Buffer (Object_Suffix);
1161 else
1162 Add_Str_To_Name_Buffer (Get_Name_String (Object_File_Suffix));
1163 end if;
1165 return Name_Find;
1166 end Object_Name;
1168 ----------------------
1169 -- Record_Temp_File --
1170 ----------------------
1172 procedure Record_Temp_File
1173 (Shared : Shared_Project_Tree_Data_Access;
1174 Path : Path_Name_Type)
1176 begin
1177 Temp_Files_Table.Append (Shared.Private_Part.Temp_Files, Path);
1178 end Record_Temp_File;
1180 ----------
1181 -- Free --
1182 ----------
1184 procedure Free (List : in out Aggregated_Project_List) is
1185 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
1186 (Aggregated_Project, Aggregated_Project_List);
1187 Tmp : Aggregated_Project_List;
1188 begin
1189 while List /= null loop
1190 Tmp := List.Next;
1192 Free (List.Tree);
1194 Unchecked_Free (List);
1195 List := Tmp;
1196 end loop;
1197 end Free;
1199 ----------------------------
1200 -- Add_Aggregated_Project --
1201 ----------------------------
1203 procedure Add_Aggregated_Project
1204 (Project : Project_Id;
1205 Path : Path_Name_Type)
1207 Aggregated : Aggregated_Project_List;
1209 begin
1210 -- Check if the project is already in the aggregated project list. If it
1211 -- is, do not add it again.
1213 Aggregated := Project.Aggregated_Projects;
1214 while Aggregated /= null loop
1215 if Path = Aggregated.Path then
1216 return;
1217 else
1218 Aggregated := Aggregated.Next;
1219 end if;
1220 end loop;
1222 Project.Aggregated_Projects := new Aggregated_Project'
1223 (Path => Path,
1224 Project => No_Project,
1225 Tree => null,
1226 Next => Project.Aggregated_Projects);
1227 end Add_Aggregated_Project;
1229 ----------
1230 -- Free --
1231 ----------
1233 procedure Free (Project : in out Project_Id) is
1234 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
1235 (Project_Data, Project_Id);
1237 begin
1238 if Project /= null then
1239 Free (Project.Ada_Include_Path);
1240 Free (Project.Objects_Path);
1241 Free (Project.Ada_Objects_Path);
1242 Free (Project.Ada_Objects_Path_No_Libs);
1243 Free_List (Project.Imported_Projects, Free_Project => False);
1244 Free_List (Project.All_Imported_Projects, Free_Project => False);
1245 Free_List (Project.Languages);
1247 case Project.Qualifier is
1248 when Aggregate | Aggregate_Library =>
1249 Free (Project.Aggregated_Projects);
1251 when others =>
1252 null;
1253 end case;
1255 Unchecked_Free (Project);
1256 end if;
1257 end Free;
1259 ---------------
1260 -- Free_List --
1261 ---------------
1263 procedure Free_List (Languages : in out Language_List) is
1264 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
1265 (Language_List_Element, Language_List);
1266 Tmp : Language_List;
1267 begin
1268 while Languages /= null loop
1269 Tmp := Languages.Next;
1270 Unchecked_Free (Languages);
1271 Languages := Tmp;
1272 end loop;
1273 end Free_List;
1275 ---------------
1276 -- Free_List --
1277 ---------------
1279 procedure Free_List (Source : in out Source_Id) is
1280 procedure Unchecked_Free is new
1281 Ada.Unchecked_Deallocation (Source_Data, Source_Id);
1283 Tmp : Source_Id;
1285 begin
1286 while Source /= No_Source loop
1287 Tmp := Source.Next_In_Lang;
1288 Free_List (Source.Alternate_Languages);
1290 if Source.Unit /= null
1291 and then Source.Kind in Spec_Or_Body
1292 then
1293 Source.Unit.File_Names (Source.Kind) := null;
1294 end if;
1296 Unchecked_Free (Source);
1297 Source := Tmp;
1298 end loop;
1299 end Free_List;
1301 ---------------
1302 -- Free_List --
1303 ---------------
1305 procedure Free_List
1306 (List : in out Project_List;
1307 Free_Project : Boolean)
1309 procedure Unchecked_Free is new
1310 Ada.Unchecked_Deallocation (Project_List_Element, Project_List);
1312 Tmp : Project_List;
1314 begin
1315 while List /= null loop
1316 Tmp := List.Next;
1318 if Free_Project then
1319 Free (List.Project);
1320 end if;
1322 Unchecked_Free (List);
1323 List := Tmp;
1324 end loop;
1325 end Free_List;
1327 ---------------
1328 -- Free_List --
1329 ---------------
1331 procedure Free_List (Languages : in out Language_Ptr) is
1332 procedure Unchecked_Free is new
1333 Ada.Unchecked_Deallocation (Language_Data, Language_Ptr);
1335 Tmp : Language_Ptr;
1337 begin
1338 while Languages /= null loop
1339 Tmp := Languages.Next;
1340 Free_List (Languages.First_Source);
1341 Unchecked_Free (Languages);
1342 Languages := Tmp;
1343 end loop;
1344 end Free_List;
1346 --------------------------
1347 -- Reset_Units_In_Table --
1348 --------------------------
1350 procedure Reset_Units_In_Table (Table : in out Units_Htable.Instance) is
1351 Unit : Unit_Index;
1353 begin
1354 Unit := Units_Htable.Get_First (Table);
1355 while Unit /= No_Unit_Index loop
1356 if Unit.File_Names (Spec) /= null then
1357 Unit.File_Names (Spec).Unit := No_Unit_Index;
1358 end if;
1360 if Unit.File_Names (Impl) /= null then
1361 Unit.File_Names (Impl).Unit := No_Unit_Index;
1362 end if;
1364 Unit := Units_Htable.Get_Next (Table);
1365 end loop;
1366 end Reset_Units_In_Table;
1368 ----------------
1369 -- Free_Units --
1370 ----------------
1372 procedure Free_Units (Table : in out Units_Htable.Instance) is
1373 procedure Unchecked_Free is new
1374 Ada.Unchecked_Deallocation (Unit_Data, Unit_Index);
1376 Unit : Unit_Index;
1378 begin
1379 Unit := Units_Htable.Get_First (Table);
1380 while Unit /= No_Unit_Index loop
1382 -- We cannot reset Unit.File_Names (Impl or Spec).Unit here as
1383 -- Source_Data buffer is freed by the following instruction
1384 -- Free_List (Tree.Projects, Free_Project => True);
1386 Unchecked_Free (Unit);
1387 Unit := Units_Htable.Get_Next (Table);
1388 end loop;
1390 Units_Htable.Reset (Table);
1391 end Free_Units;
1393 ----------
1394 -- Free --
1395 ----------
1397 procedure Free (Tree : in out Project_Tree_Ref) is
1398 procedure Unchecked_Free is new
1399 Ada.Unchecked_Deallocation
1400 (Project_Tree_Data, Project_Tree_Ref);
1402 procedure Unchecked_Free is new
1403 Ada.Unchecked_Deallocation
1404 (Project_Tree_Appdata'Class, Project_Tree_Appdata_Access);
1406 begin
1407 if Tree /= null then
1408 if Tree.Is_Root_Tree then
1409 Name_List_Table.Free (Tree.Shared.Name_Lists);
1410 Number_List_Table.Free (Tree.Shared.Number_Lists);
1411 String_Element_Table.Free (Tree.Shared.String_Elements);
1412 Variable_Element_Table.Free (Tree.Shared.Variable_Elements);
1413 Array_Element_Table.Free (Tree.Shared.Array_Elements);
1414 Array_Table.Free (Tree.Shared.Arrays);
1415 Package_Table.Free (Tree.Shared.Packages);
1416 Temp_Files_Table.Free (Tree.Shared.Private_Part.Temp_Files);
1417 end if;
1419 if Tree.Appdata /= null then
1420 Free (Tree.Appdata.all);
1421 Unchecked_Free (Tree.Appdata);
1422 end if;
1424 Source_Paths_Htable.Reset (Tree.Source_Paths_HT);
1425 Source_Files_Htable.Reset (Tree.Source_Files_HT);
1427 Reset_Units_In_Table (Tree.Units_HT);
1428 Free_List (Tree.Projects, Free_Project => True);
1429 Free_Units (Tree.Units_HT);
1431 Unchecked_Free (Tree);
1432 end if;
1433 end Free;
1435 -----------
1436 -- Reset --
1437 -----------
1439 procedure Reset (Tree : Project_Tree_Ref) is
1440 begin
1441 -- Visible tables
1443 if Tree.Is_Root_Tree then
1445 -- We cannot use 'Access here:
1446 -- "illegal attribute for discriminant-dependent component"
1447 -- However, we know this is valid since Shared and Shared_Data have
1448 -- the same lifetime and will always exist concurrently.
1450 Tree.Shared := Tree.Shared_Data'Unrestricted_Access;
1451 Name_List_Table.Init (Tree.Shared.Name_Lists);
1452 Number_List_Table.Init (Tree.Shared.Number_Lists);
1453 String_Element_Table.Init (Tree.Shared.String_Elements);
1454 Variable_Element_Table.Init (Tree.Shared.Variable_Elements);
1455 Array_Element_Table.Init (Tree.Shared.Array_Elements);
1456 Array_Table.Init (Tree.Shared.Arrays);
1457 Package_Table.Init (Tree.Shared.Packages);
1459 -- Create Dot_String_List
1461 String_Element_Table.Append
1462 (Tree.Shared.String_Elements,
1463 String_Element'
1464 (Value => The_Dot_String,
1465 Index => 0,
1466 Display_Value => The_Dot_String,
1467 Location => No_Location,
1468 Flag => False,
1469 Next => Nil_String));
1470 Tree.Shared.Dot_String_List :=
1471 String_Element_Table.Last (Tree.Shared.String_Elements);
1473 -- Private part table
1475 Temp_Files_Table.Init (Tree.Shared.Private_Part.Temp_Files);
1477 Tree.Shared.Private_Part.Current_Source_Path_File := No_Path;
1478 Tree.Shared.Private_Part.Current_Object_Path_File := No_Path;
1479 end if;
1481 Source_Paths_Htable.Reset (Tree.Source_Paths_HT);
1482 Source_Files_Htable.Reset (Tree.Source_Files_HT);
1483 Replaced_Source_HTable.Reset (Tree.Replaced_Sources);
1485 Tree.Replaced_Source_Number := 0;
1487 Reset_Units_In_Table (Tree.Units_HT);
1488 Free_List (Tree.Projects, Free_Project => True);
1489 Free_Units (Tree.Units_HT);
1490 end Reset;
1492 -------------------------------------
1493 -- Set_Current_Object_Path_File_Of --
1494 -------------------------------------
1496 procedure Set_Current_Object_Path_File_Of
1497 (Shared : Shared_Project_Tree_Data_Access;
1498 To : Path_Name_Type)
1500 begin
1501 Shared.Private_Part.Current_Object_Path_File := To;
1502 end Set_Current_Object_Path_File_Of;
1504 -------------------------------------
1505 -- Set_Current_Source_Path_File_Of --
1506 -------------------------------------
1508 procedure Set_Current_Source_Path_File_Of
1509 (Shared : Shared_Project_Tree_Data_Access;
1510 To : Path_Name_Type)
1512 begin
1513 Shared.Private_Part.Current_Source_Path_File := To;
1514 end Set_Current_Source_Path_File_Of;
1516 -----------------------
1517 -- Set_Path_File_Var --
1518 -----------------------
1520 procedure Set_Path_File_Var (Name : String; Value : String) is
1521 Host_Spec : String_Access := To_Host_File_Spec (Value);
1522 begin
1523 if Host_Spec = null then
1524 Prj.Com.Fail
1525 ("could not convert file name """ & Value & """ to host spec");
1526 else
1527 Setenv (Name, Host_Spec.all);
1528 Free (Host_Spec);
1529 end if;
1530 end Set_Path_File_Var;
1532 -------------------
1533 -- Switches_Name --
1534 -------------------
1536 function Switches_Name
1537 (Source_File_Name : File_Name_Type) return File_Name_Type
1539 begin
1540 return Extend_Name (Source_File_Name, Switches_Dependency_Suffix);
1541 end Switches_Name;
1543 -----------
1544 -- Value --
1545 -----------
1547 function Value (Image : String) return Casing_Type is
1548 begin
1549 for Casing in The_Casing_Images'Range loop
1550 if To_Lower (Image) = To_Lower (The_Casing_Images (Casing).all) then
1551 return Casing;
1552 end if;
1553 end loop;
1555 raise Constraint_Error;
1556 end Value;
1558 ---------------------
1559 -- Has_Ada_Sources --
1560 ---------------------
1562 function Has_Ada_Sources (Data : Project_Id) return Boolean is
1563 Lang : Language_Ptr;
1565 begin
1566 Lang := Data.Languages;
1567 while Lang /= No_Language_Index loop
1568 if Lang.Name = Name_Ada then
1569 return Lang.First_Source /= No_Source;
1570 end if;
1571 Lang := Lang.Next;
1572 end loop;
1574 return False;
1575 end Has_Ada_Sources;
1577 ------------------------
1578 -- Contains_ALI_Files --
1579 ------------------------
1581 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean is
1582 Dir_Name : constant String := Get_Name_String (Dir);
1583 Direct : Dir_Type;
1584 Name : String (1 .. 1_000);
1585 Last : Natural;
1586 Result : Boolean := False;
1588 begin
1589 Open (Direct, Dir_Name);
1591 -- For each file in the directory, check if it is an ALI file
1593 loop
1594 Read (Direct, Name, Last);
1595 exit when Last = 0;
1596 Canonical_Case_File_Name (Name (1 .. Last));
1597 Result := Last >= 5 and then Name (Last - 3 .. Last) = ".ali";
1598 exit when Result;
1599 end loop;
1601 Close (Direct);
1602 return Result;
1604 exception
1605 -- If there is any problem, close the directory if open and return True.
1606 -- The library directory will be added to the path.
1608 when others =>
1609 if Is_Open (Direct) then
1610 Close (Direct);
1611 end if;
1613 return True;
1614 end Contains_ALI_Files;
1616 --------------------------
1617 -- Get_Object_Directory --
1618 --------------------------
1620 function Get_Object_Directory
1621 (Project : Project_Id;
1622 Including_Libraries : Boolean;
1623 Only_If_Ada : Boolean := False) return Path_Name_Type
1625 begin
1626 if (Project.Library and then Including_Libraries)
1627 or else
1628 (Project.Object_Directory /= No_Path_Information
1629 and then (not Including_Libraries or else not Project.Library))
1630 then
1631 -- For a library project, add the library ALI directory if there is
1632 -- no object directory or if the library ALI directory contains ALI
1633 -- files; otherwise add the object directory.
1635 if Project.Library then
1636 if Project.Object_Directory = No_Path_Information
1637 or else
1638 (Including_Libraries
1639 and then
1640 Contains_ALI_Files (Project.Library_ALI_Dir.Display_Name))
1641 then
1642 return Project.Library_ALI_Dir.Display_Name;
1643 else
1644 return Project.Object_Directory.Display_Name;
1645 end if;
1647 -- For a non-library project, add object directory if it is not a
1648 -- virtual project, and if there are Ada sources in the project or
1649 -- one of the projects it extends. If there are no Ada sources,
1650 -- adding the object directory could disrupt the order of the
1651 -- object dirs in the path.
1653 elsif not Project.Virtual then
1654 declare
1655 Add_Object_Dir : Boolean;
1656 Prj : Project_Id;
1658 begin
1659 Add_Object_Dir := not Only_If_Ada;
1660 Prj := Project;
1661 while not Add_Object_Dir and then Prj /= No_Project loop
1662 if Has_Ada_Sources (Prj) then
1663 Add_Object_Dir := True;
1664 else
1665 Prj := Prj.Extends;
1666 end if;
1667 end loop;
1669 if Add_Object_Dir then
1670 return Project.Object_Directory.Display_Name;
1671 end if;
1672 end;
1673 end if;
1674 end if;
1676 return No_Path;
1677 end Get_Object_Directory;
1679 -----------------------------------
1680 -- Ultimate_Extending_Project_Of --
1681 -----------------------------------
1683 function Ultimate_Extending_Project_Of
1684 (Proj : Project_Id) return Project_Id
1686 Prj : Project_Id;
1688 begin
1689 Prj := Proj;
1690 while Prj /= null and then Prj.Extended_By /= No_Project loop
1691 Prj := Prj.Extended_By;
1692 end loop;
1694 return Prj;
1695 end Ultimate_Extending_Project_Of;
1697 -----------------------------------
1698 -- Compute_All_Imported_Projects --
1699 -----------------------------------
1701 procedure Compute_All_Imported_Projects
1702 (Root_Project : Project_Id;
1703 Tree : Project_Tree_Ref)
1705 procedure Analyze_Tree
1706 (Local_Root : Project_Id;
1707 Local_Tree : Project_Tree_Ref;
1708 Context : Project_Context);
1709 -- Process Project and all its aggregated project to analyze their own
1710 -- imported projects.
1712 ------------------
1713 -- Analyze_Tree --
1714 ------------------
1716 procedure Analyze_Tree
1717 (Local_Root : Project_Id;
1718 Local_Tree : Project_Tree_Ref;
1719 Context : Project_Context)
1721 pragma Unreferenced (Local_Root);
1723 Project : Project_Id;
1725 procedure Recursive_Add
1726 (Prj : Project_Id;
1727 Tree : Project_Tree_Ref;
1728 Context : Project_Context;
1729 Dummy : in out Boolean);
1730 -- Recursively add the projects imported by project Project, but not
1731 -- those that are extended.
1733 -------------------
1734 -- Recursive_Add --
1735 -------------------
1737 procedure Recursive_Add
1738 (Prj : Project_Id;
1739 Tree : Project_Tree_Ref;
1740 Context : Project_Context;
1741 Dummy : in out Boolean)
1743 pragma Unreferenced (Tree);
1745 List : Project_List;
1746 Prj2 : Project_Id;
1748 begin
1749 -- A project is not importing itself
1751 Prj2 := Ultimate_Extending_Project_Of (Prj);
1753 if Project /= Prj2 then
1755 -- Check that the project is not already in the list. We know
1756 -- the one passed to Recursive_Add have never been visited
1757 -- before, but the one passed it are the extended projects.
1759 List := Project.All_Imported_Projects;
1760 while List /= null loop
1761 if List.Project = Prj2 then
1762 return;
1763 end if;
1765 List := List.Next;
1766 end loop;
1768 -- Add it to the list
1770 Project.All_Imported_Projects :=
1771 new Project_List_Element'
1772 (Project => Prj2,
1773 From_Encapsulated_Lib =>
1774 Context.From_Encapsulated_Lib
1775 or else Analyze_Tree.Context.From_Encapsulated_Lib,
1776 Next => Project.All_Imported_Projects);
1777 end if;
1778 end Recursive_Add;
1780 procedure For_All_Projects is
1781 new For_Every_Project_Imported_Context (Boolean, Recursive_Add);
1783 Dummy : Boolean := False;
1784 List : Project_List;
1786 begin
1787 List := Local_Tree.Projects;
1788 while List /= null loop
1789 Project := List.Project;
1790 Free_List
1791 (Project.All_Imported_Projects, Free_Project => False);
1792 For_All_Projects
1793 (Project, Local_Tree, Dummy, Include_Aggregated => False);
1794 List := List.Next;
1795 end loop;
1796 end Analyze_Tree;
1798 procedure For_Aggregates is
1799 new For_Project_And_Aggregated_Context (Analyze_Tree);
1801 -- Start of processing for Compute_All_Imported_Projects
1803 begin
1804 For_Aggregates (Root_Project, Tree);
1805 end Compute_All_Imported_Projects;
1807 -------------------
1808 -- Is_Compilable --
1809 -------------------
1811 function Is_Compilable (Source : Source_Id) return Boolean is
1812 begin
1813 case Source.Compilable is
1814 when Unknown =>
1815 if Source.Language.Config.Compiler_Driver /= No_File
1816 and then
1817 Length_Of_Name (Source.Language.Config.Compiler_Driver) /= 0
1818 and then not Source.Locally_Removed
1819 and then (Source.Language.Config.Kind /= File_Based
1820 or else Source.Kind /= Spec)
1821 then
1822 -- Do not modify Source.Compilable before the source record
1823 -- has been initialized.
1825 if Source.Source_TS /= Empty_Time_Stamp then
1826 Source.Compilable := Yes;
1827 end if;
1829 return True;
1831 else
1832 if Source.Source_TS /= Empty_Time_Stamp then
1833 Source.Compilable := No;
1834 end if;
1836 return False;
1837 end if;
1839 when Yes =>
1840 return True;
1842 when No =>
1843 return False;
1844 end case;
1845 end Is_Compilable;
1847 ------------------------------
1848 -- Object_To_Global_Archive --
1849 ------------------------------
1851 function Object_To_Global_Archive (Source : Source_Id) return Boolean is
1852 begin
1853 return Source.Language.Config.Kind = File_Based
1854 and then Source.Kind = Impl
1855 and then Source.Language.Config.Objects_Linked
1856 and then Is_Compilable (Source)
1857 and then Source.Language.Config.Object_Generated;
1858 end Object_To_Global_Archive;
1860 ----------------------------
1861 -- Get_Language_From_Name --
1862 ----------------------------
1864 function Get_Language_From_Name
1865 (Project : Project_Id;
1866 Name : String) return Language_Ptr
1868 N : Name_Id;
1869 Result : Language_Ptr;
1871 begin
1872 Name_Len := Name'Length;
1873 Name_Buffer (1 .. Name_Len) := Name;
1874 To_Lower (Name_Buffer (1 .. Name_Len));
1875 N := Name_Find;
1877 Result := Project.Languages;
1878 while Result /= No_Language_Index loop
1879 if Result.Name = N then
1880 return Result;
1881 end if;
1883 Result := Result.Next;
1884 end loop;
1886 return No_Language_Index;
1887 end Get_Language_From_Name;
1889 ----------------
1890 -- Other_Part --
1891 ----------------
1893 function Other_Part (Source : Source_Id) return Source_Id is
1894 begin
1895 if Source.Unit /= No_Unit_Index then
1896 case Source.Kind is
1897 when Impl =>
1898 return Source.Unit.File_Names (Spec);
1899 when Spec =>
1900 return Source.Unit.File_Names (Impl);
1901 when Sep =>
1902 return No_Source;
1903 end case;
1904 else
1905 return No_Source;
1906 end if;
1907 end Other_Part;
1909 ------------------
1910 -- Create_Flags --
1911 ------------------
1913 function Create_Flags
1914 (Report_Error : Error_Handler;
1915 When_No_Sources : Error_Warning;
1916 Require_Sources_Other_Lang : Boolean := True;
1917 Allow_Duplicate_Basenames : Boolean := True;
1918 Compiler_Driver_Mandatory : Boolean := False;
1919 Error_On_Unknown_Language : Boolean := True;
1920 Require_Obj_Dirs : Error_Warning := Error;
1921 Allow_Invalid_External : Error_Warning := Error;
1922 Missing_Source_Files : Error_Warning := Error;
1923 Ignore_Missing_With : Boolean := False)
1924 return Processing_Flags
1926 begin
1927 return Processing_Flags'
1928 (Report_Error => Report_Error,
1929 When_No_Sources => When_No_Sources,
1930 Require_Sources_Other_Lang => Require_Sources_Other_Lang,
1931 Allow_Duplicate_Basenames => Allow_Duplicate_Basenames,
1932 Error_On_Unknown_Language => Error_On_Unknown_Language,
1933 Compiler_Driver_Mandatory => Compiler_Driver_Mandatory,
1934 Require_Obj_Dirs => Require_Obj_Dirs,
1935 Allow_Invalid_External => Allow_Invalid_External,
1936 Missing_Source_Files => Missing_Source_Files,
1937 Ignore_Missing_With => Ignore_Missing_With,
1938 Incomplete_Withs => False);
1939 end Create_Flags;
1941 ------------
1942 -- Length --
1943 ------------
1945 function Length
1946 (Table : Name_List_Table.Instance;
1947 List : Name_List_Index) return Natural
1949 Count : Natural := 0;
1950 Tmp : Name_List_Index;
1952 begin
1953 Tmp := List;
1954 while Tmp /= No_Name_List loop
1955 Count := Count + 1;
1956 Tmp := Table.Table (Tmp).Next;
1957 end loop;
1959 return Count;
1960 end Length;
1962 ------------------
1963 -- Debug_Output --
1964 ------------------
1966 procedure Debug_Output (Str : String) is
1967 begin
1968 if Current_Verbosity > Default then
1969 Set_Standard_Error;
1970 Write_Line ((1 .. Debug_Level * 2 => ' ') & Str);
1971 Set_Standard_Output;
1972 end if;
1973 end Debug_Output;
1975 ------------------
1976 -- Debug_Indent --
1977 ------------------
1979 procedure Debug_Indent is
1980 begin
1981 if Current_Verbosity = High then
1982 Set_Standard_Error;
1983 Write_Str ((1 .. Debug_Level * 2 => ' '));
1984 Set_Standard_Output;
1985 end if;
1986 end Debug_Indent;
1988 ------------------
1989 -- Debug_Output --
1990 ------------------
1992 procedure Debug_Output (Str : String; Str2 : Name_Id) is
1993 begin
1994 if Current_Verbosity > Default then
1995 Debug_Indent;
1996 Set_Standard_Error;
1997 Write_Str (Str);
1999 if Str2 = No_Name then
2000 Write_Line (" <no_name>");
2001 else
2002 Write_Line (" """ & Get_Name_String (Str2) & '"');
2003 end if;
2005 Set_Standard_Output;
2006 end if;
2007 end Debug_Output;
2009 ---------------------------
2010 -- Debug_Increase_Indent --
2011 ---------------------------
2013 procedure Debug_Increase_Indent
2014 (Str : String := ""; Str2 : Name_Id := No_Name)
2016 begin
2017 if Str2 /= No_Name then
2018 Debug_Output (Str, Str2);
2019 else
2020 Debug_Output (Str);
2021 end if;
2022 Debug_Level := Debug_Level + 1;
2023 end Debug_Increase_Indent;
2025 ---------------------------
2026 -- Debug_Decrease_Indent --
2027 ---------------------------
2029 procedure Debug_Decrease_Indent (Str : String := "") is
2030 begin
2031 if Debug_Level > 0 then
2032 Debug_Level := Debug_Level - 1;
2033 end if;
2035 if Str /= "" then
2036 Debug_Output (Str);
2037 end if;
2038 end Debug_Decrease_Indent;
2040 ----------------
2041 -- Debug_Name --
2042 ----------------
2044 function Debug_Name (Tree : Project_Tree_Ref) return Name_Id is
2045 P : Project_List;
2047 begin
2048 Name_Len := 0;
2049 Add_Str_To_Name_Buffer ("Tree [");
2051 P := Tree.Projects;
2052 while P /= null loop
2053 if P /= Tree.Projects then
2054 Add_Char_To_Name_Buffer (',');
2055 end if;
2057 Add_Str_To_Name_Buffer (Get_Name_String (P.Project.Name));
2059 P := P.Next;
2060 end loop;
2062 Add_Char_To_Name_Buffer (']');
2064 return Name_Find;
2065 end Debug_Name;
2067 ----------
2068 -- Free --
2069 ----------
2071 procedure Free (Tree : in out Project_Tree_Appdata) is
2072 pragma Unreferenced (Tree);
2073 begin
2074 null;
2075 end Free;
2077 --------------------------------
2078 -- For_Project_And_Aggregated --
2079 --------------------------------
2081 procedure For_Project_And_Aggregated
2082 (Root_Project : Project_Id;
2083 Root_Tree : Project_Tree_Ref)
2085 Agg : Aggregated_Project_List;
2087 begin
2088 Action (Root_Project, Root_Tree);
2090 if Root_Project.Qualifier in Aggregate_Project then
2091 Agg := Root_Project.Aggregated_Projects;
2092 while Agg /= null loop
2093 For_Project_And_Aggregated (Agg.Project, Agg.Tree);
2094 Agg := Agg.Next;
2095 end loop;
2096 end if;
2097 end For_Project_And_Aggregated;
2099 ----------------------------------------
2100 -- For_Project_And_Aggregated_Context --
2101 ----------------------------------------
2103 procedure For_Project_And_Aggregated_Context
2104 (Root_Project : Project_Id;
2105 Root_Tree : Project_Tree_Ref)
2108 procedure Recursive_Process
2109 (Project : Project_Id;
2110 Tree : Project_Tree_Ref;
2111 Context : Project_Context);
2112 -- Process Project and all aggregated projects recursively
2114 -----------------------
2115 -- Recursive_Process --
2116 -----------------------
2118 procedure Recursive_Process
2119 (Project : Project_Id;
2120 Tree : Project_Tree_Ref;
2121 Context : Project_Context)
2123 Agg : Aggregated_Project_List;
2124 Ctx : Project_Context;
2126 begin
2127 Action (Project, Tree, Context);
2129 if Project.Qualifier in Aggregate_Project then
2130 Ctx :=
2131 (In_Aggregate_Lib => Project.Qualifier = Aggregate_Library,
2132 From_Encapsulated_Lib =>
2133 Context.From_Encapsulated_Lib
2134 or else Project.Standalone_Library = Encapsulated);
2136 Agg := Project.Aggregated_Projects;
2137 while Agg /= null loop
2138 Recursive_Process (Agg.Project, Agg.Tree, Ctx);
2139 Agg := Agg.Next;
2140 end loop;
2141 end if;
2142 end Recursive_Process;
2144 -- Start of processing for For_Project_And_Aggregated_Context
2146 begin
2147 Recursive_Process
2148 (Root_Project, Root_Tree, Project_Context'(False, False));
2149 end For_Project_And_Aggregated_Context;
2151 -----------------------------
2152 -- Set_Ignore_Missing_With --
2153 -----------------------------
2155 procedure Set_Ignore_Missing_With
2156 (Flags : in out Processing_Flags;
2157 Value : Boolean)
2159 begin
2160 Flags.Ignore_Missing_With := Value;
2161 end Set_Ignore_Missing_With;
2163 -- Package initialization for Prj
2165 begin
2166 -- Make sure that the standard config and user project file extensions are
2167 -- compatible with canonical case file naming.
2169 Canonical_Case_File_Name (Config_Project_File_Extension);
2170 Canonical_Case_File_Name (Project_File_Extension);
2171 end Prj;