gcc/c-family/
[official-gcc.git] / gcc / ada / prj.adb
blob6a0a830fe1038569dd4949ce0a566ac7cb5571a8
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- P R J --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 2001-2013, 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 Debug;
27 with Opt;
28 with Osint; use Osint;
29 with Output; use Output;
30 with Prj.Attr;
31 with Prj.Com;
32 with Prj.Err; use Prj.Err;
33 with Snames; use Snames;
34 with Uintp; use Uintp;
36 with Ada.Characters.Handling; use Ada.Characters.Handling;
37 with Ada.Containers.Ordered_Sets;
38 with Ada.Unchecked_Deallocation;
40 with GNAT.Case_Util; use GNAT.Case_Util;
41 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
42 with GNAT.HTable;
44 package body Prj is
46 type Restricted_Lang;
47 type Restricted_Lang_Access is access Restricted_Lang;
48 type Restricted_Lang is record
49 Name : Name_Id;
50 Next : Restricted_Lang_Access;
51 end record;
53 Restricted_Languages : Restricted_Lang_Access := null;
54 -- When null, all languages are allowed, otherwise only the languages in
55 -- the list are allowed.
57 Object_Suffix : constant String := Get_Target_Object_Suffix.all;
58 -- File suffix for object files
60 Initial_Buffer_Size : constant := 100;
61 -- Initial size for extensible buffer used in Add_To_Buffer
63 The_Empty_String : Name_Id := No_Name;
65 Debug_Level : Integer := 0;
66 -- Current indentation level for debug traces
68 type Cst_String_Access is access constant String;
70 All_Lower_Case_Image : aliased constant String := "lowercase";
71 All_Upper_Case_Image : aliased constant String := "UPPERCASE";
72 Mixed_Case_Image : aliased constant String := "MixedCase";
74 The_Casing_Images : constant array (Known_Casing) of Cst_String_Access :=
75 (All_Lower_Case => All_Lower_Case_Image'Access,
76 All_Upper_Case => All_Upper_Case_Image'Access,
77 Mixed_Case => Mixed_Case_Image'Access);
79 procedure Free (Project : in out Project_Id);
80 -- Free memory allocated for Project
82 procedure Free_List (Languages : in out Language_Ptr);
83 procedure Free_List (Source : in out Source_Id);
84 procedure Free_List (Languages : in out Language_List);
85 -- Free memory allocated for the list of languages or sources
87 procedure Reset_Units_In_Table (Table : in out Units_Htable.Instance);
88 -- Resets all Units to No_Unit_Index Unit.File_Names (Spec).Unit &
89 -- Unit.File_Names (Impl).Unit in the given table.
91 procedure Free_Units (Table : in out Units_Htable.Instance);
92 -- Free memory allocated for unit information in the project
94 procedure Language_Changed (Iter : in out Source_Iterator);
95 procedure Project_Changed (Iter : in out Source_Iterator);
96 -- Called when a new project or language was selected for this iterator
98 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean;
99 -- Return True if there is at least one ALI file in the directory Dir
101 -----------------------------
102 -- Add_Restricted_Language --
103 -----------------------------
105 procedure Add_Restricted_Language (Name : String) is
106 N : String (1 .. Name'Length) := Name;
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 * Last);
146 begin
147 New_Buffer (1 .. Last) := To (1 .. Last);
148 Free (To);
149 To := New_Buffer;
150 end;
151 end loop;
153 To (Last + 1 .. Last + S'Length) := S;
154 Last := Last + S'Length;
155 end Add_To_Buffer;
157 ---------------------------------
158 -- Current_Object_Path_File_Of --
159 ---------------------------------
161 function Current_Object_Path_File_Of
162 (Shared : Shared_Project_Tree_Data_Access) return Path_Name_Type
164 begin
165 return Shared.Private_Part.Current_Object_Path_File;
166 end Current_Object_Path_File_Of;
168 ---------------------------------
169 -- Current_Source_Path_File_Of --
170 ---------------------------------
172 function Current_Source_Path_File_Of
173 (Shared : Shared_Project_Tree_Data_Access)
174 return Path_Name_Type is
175 begin
176 return Shared.Private_Part.Current_Source_Path_File;
177 end Current_Source_Path_File_Of;
179 ---------------------------
180 -- Delete_Temporary_File --
181 ---------------------------
183 procedure Delete_Temporary_File
184 (Shared : Shared_Project_Tree_Data_Access := null;
185 Path : Path_Name_Type)
187 Dont_Care : Boolean;
188 pragma Warnings (Off, Dont_Care);
190 begin
191 if not Debug.Debug_Flag_N then
192 if Current_Verbosity = High then
193 Write_Line ("Removing temp file: " & Get_Name_String (Path));
194 end if;
196 Delete_File (Get_Name_String (Path), Dont_Care);
198 if Shared /= null then
199 for Index in
200 1 .. Temp_Files_Table.Last (Shared.Private_Part.Temp_Files)
201 loop
202 if Shared.Private_Part.Temp_Files.Table (Index) = Path then
203 Shared.Private_Part.Temp_Files.Table (Index) := No_Path;
204 end if;
205 end loop;
206 end if;
207 end if;
208 end Delete_Temporary_File;
210 ------------------------------
211 -- Delete_Temp_Config_Files --
212 ------------------------------
214 procedure Delete_Temp_Config_Files (Project_Tree : Project_Tree_Ref) is
215 Success : Boolean;
216 pragma Warnings (Off, Success);
218 Proj : Project_List;
220 begin
221 if not Debug.Debug_Flag_N then
222 if Project_Tree /= null then
223 Proj := Project_Tree.Projects;
224 while Proj /= null loop
225 if Proj.Project.Config_File_Temp then
226 Delete_Temporary_File
227 (Project_Tree.Shared, Proj.Project.Config_File_Name);
229 -- Make sure that we don't have a config file for this
230 -- project, in case there are several mains. In this case,
231 -- we will recreate another config file: we cannot reuse the
232 -- one that we just deleted.
234 Proj.Project.Config_Checked := False;
235 Proj.Project.Config_File_Name := No_Path;
236 Proj.Project.Config_File_Temp := False;
237 end if;
239 Proj := Proj.Next;
240 end loop;
241 end if;
242 end if;
243 end Delete_Temp_Config_Files;
245 ---------------------------
246 -- Delete_All_Temp_Files --
247 ---------------------------
249 procedure Delete_All_Temp_Files
250 (Shared : Shared_Project_Tree_Data_Access)
252 Dont_Care : Boolean;
253 pragma Warnings (Off, Dont_Care);
255 Path : Path_Name_Type;
257 begin
258 if not Debug.Debug_Flag_N then
259 for Index in
260 1 .. Temp_Files_Table.Last (Shared.Private_Part.Temp_Files)
261 loop
262 Path := Shared.Private_Part.Temp_Files.Table (Index);
264 if Path /= No_Path then
265 if Current_Verbosity = High then
266 Write_Line ("Removing temp file: "
267 & Get_Name_String (Path));
268 end if;
270 Delete_File (Get_Name_String (Path), Dont_Care);
271 end if;
272 end loop;
274 Temp_Files_Table.Free (Shared.Private_Part.Temp_Files);
275 Temp_Files_Table.Init (Shared.Private_Part.Temp_Files);
276 end if;
278 -- If any of the environment variables ADA_PRJ_INCLUDE_FILE or
279 -- ADA_PRJ_OBJECTS_FILE has been set, then reset their value to
280 -- the empty string. On VMS, this has the effect of deassigning
281 -- the logical names.
283 if Shared.Private_Part.Current_Source_Path_File /= No_Path then
284 Setenv (Project_Include_Path_File, "");
285 end if;
287 if Shared.Private_Part.Current_Object_Path_File /= No_Path then
288 Setenv (Project_Objects_Path_File, "");
289 end if;
290 end Delete_All_Temp_Files;
292 ---------------------
293 -- Dependency_Name --
294 ---------------------
296 function Dependency_Name
297 (Source_File_Name : File_Name_Type;
298 Dependency : Dependency_File_Kind) return File_Name_Type
300 begin
301 case Dependency is
302 when None =>
303 return No_File;
305 when Makefile =>
306 return Extend_Name (Source_File_Name, Makefile_Dependency_Suffix);
308 when ALI_File | ALI_Closure =>
309 return Extend_Name (Source_File_Name, ALI_Dependency_Suffix);
310 end case;
311 end Dependency_Name;
313 ----------------
314 -- Empty_File --
315 ----------------
317 function Empty_File return File_Name_Type is
318 begin
319 return File_Name_Type (The_Empty_String);
320 end Empty_File;
322 -------------------
323 -- Empty_Project --
324 -------------------
326 function Empty_Project
327 (Qualifier : Project_Qualifier) return Project_Data
329 begin
330 Prj.Initialize (Tree => No_Project_Tree);
332 declare
333 Data : Project_Data (Qualifier => Qualifier);
335 begin
336 -- Only the fields for which no default value could be provided in
337 -- prj.ads are initialized below.
339 Data.Config := Default_Project_Config;
340 return Data;
341 end;
342 end Empty_Project;
344 ------------------
345 -- Empty_String --
346 ------------------
348 function Empty_String return Name_Id is
349 begin
350 return The_Empty_String;
351 end Empty_String;
353 ------------
354 -- Expect --
355 ------------
357 procedure Expect (The_Token : Token_Type; Token_Image : String) is
358 begin
359 if Token /= The_Token then
361 -- ??? Should pass user flags here instead
363 Error_Msg (Gnatmake_Flags, Token_Image & " expected", Token_Ptr);
364 end if;
365 end Expect;
367 -----------------
368 -- Extend_Name --
369 -----------------
371 function Extend_Name
372 (File : File_Name_Type;
373 With_Suffix : String) return File_Name_Type
375 Last : Positive;
377 begin
378 Get_Name_String (File);
379 Last := Name_Len + 1;
381 while Name_Len /= 0 and then Name_Buffer (Name_Len) /= '.' loop
382 Name_Len := Name_Len - 1;
383 end loop;
385 if Name_Len <= 1 then
386 Name_Len := Last;
387 end if;
389 for J in With_Suffix'Range loop
390 Name_Buffer (Name_Len) := With_Suffix (J);
391 Name_Len := Name_Len + 1;
392 end loop;
394 Name_Len := Name_Len - 1;
395 return Name_Find;
396 end Extend_Name;
398 -------------------------
399 -- Is_Allowed_Language --
400 -------------------------
402 function Is_Allowed_Language (Name : Name_Id) return Boolean is
403 R : Restricted_Lang_Access := Restricted_Languages;
404 Lang : constant String := Get_Name_String (Name);
406 begin
407 if R = null then
408 return True;
410 else
411 while R /= null loop
412 if Get_Name_String (R.Name) = Lang then
413 return True;
414 end if;
416 R := R.Next;
417 end loop;
419 return False;
420 end if;
421 end Is_Allowed_Language;
423 ---------------------
424 -- Project_Changed --
425 ---------------------
427 procedure Project_Changed (Iter : in out Source_Iterator) is
428 begin
429 if Iter.Project /= null then
430 Iter.Language := Iter.Project.Project.Languages;
431 Language_Changed (Iter);
432 end if;
433 end Project_Changed;
435 ----------------------
436 -- Language_Changed --
437 ----------------------
439 procedure Language_Changed (Iter : in out Source_Iterator) is
440 begin
441 Iter.Current := No_Source;
443 if Iter.Language_Name /= No_Name then
444 while Iter.Language /= null
445 and then Iter.Language.Name /= Iter.Language_Name
446 loop
447 Iter.Language := Iter.Language.Next;
448 end loop;
449 end if;
451 -- If there is no matching language in this project, move to next
453 if Iter.Language = No_Language_Index then
454 if Iter.All_Projects then
455 loop
456 Iter.Project := Iter.Project.Next;
457 exit when Iter.Project = null
458 or else Iter.Encapsulated_Libs
459 or else not Iter.Project.From_Encapsulated_Lib;
460 end loop;
462 Project_Changed (Iter);
463 else
464 Iter.Project := null;
465 end if;
467 else
468 Iter.Current := Iter.Language.First_Source;
470 if Iter.Current = No_Source then
471 Iter.Language := Iter.Language.Next;
472 Language_Changed (Iter);
474 elsif not Iter.Locally_Removed
475 and then Iter.Current.Locally_Removed
476 then
477 Next (Iter);
478 end if;
479 end if;
480 end Language_Changed;
482 ---------------------
483 -- For_Each_Source --
484 ---------------------
486 function For_Each_Source
487 (In_Tree : Project_Tree_Ref;
488 Project : Project_Id := No_Project;
489 Language : Name_Id := No_Name;
490 Encapsulated_Libs : Boolean := True;
491 Locally_Removed : Boolean := True) return Source_Iterator
493 Iter : Source_Iterator;
494 begin
495 Iter := Source_Iterator'
496 (In_Tree => In_Tree,
497 Project => In_Tree.Projects,
498 All_Projects => Project = No_Project,
499 Language_Name => Language,
500 Language => No_Language_Index,
501 Current => No_Source,
502 Encapsulated_Libs => Encapsulated_Libs,
503 Locally_Removed => Locally_Removed);
505 if Project /= null then
506 while Iter.Project /= null
507 and then Iter.Project.Project /= Project
508 loop
509 Iter.Project := Iter.Project.Next;
510 end loop;
512 else
513 while not Iter.Encapsulated_Libs
514 and then Iter.Project.From_Encapsulated_Lib
515 loop
516 Iter.Project := Iter.Project.Next;
517 end loop;
518 end if;
520 Project_Changed (Iter);
522 return Iter;
523 end For_Each_Source;
525 -------------
526 -- Element --
527 -------------
529 function Element (Iter : Source_Iterator) return Source_Id is
530 begin
531 return Iter.Current;
532 end Element;
534 ----------
535 -- Next --
536 ----------
538 procedure Next (Iter : in out Source_Iterator) is
539 begin
540 loop
541 Iter.Current := Iter.Current.Next_In_Lang;
543 exit when Iter.Locally_Removed
544 or else Iter.Current = No_Source
545 or else not Iter.Current.Locally_Removed;
546 end loop;
548 if Iter.Current = No_Source then
549 Iter.Language := Iter.Language.Next;
550 Language_Changed (Iter);
551 end if;
552 end Next;
554 --------------------------------
555 -- For_Every_Project_Imported --
556 --------------------------------
558 procedure For_Every_Project_Imported_Context
559 (By : Project_Id;
560 Tree : Project_Tree_Ref;
561 With_State : in out State;
562 Include_Aggregated : Boolean := True;
563 Imported_First : Boolean := False)
565 use Project_Boolean_Htable;
567 procedure Recursive_Check_Context
568 (Project : Project_Id;
569 Tree : Project_Tree_Ref;
570 In_Aggregate_Lib : Boolean;
571 From_Encapsulated_Lib : Boolean);
572 -- Recursively handle the project tree creating a new context for
573 -- keeping track about already handled projects.
575 -----------------------------
576 -- Recursive_Check_Context --
577 -----------------------------
579 procedure Recursive_Check_Context
580 (Project : Project_Id;
581 Tree : Project_Tree_Ref;
582 In_Aggregate_Lib : Boolean;
583 From_Encapsulated_Lib : Boolean)
585 package Name_Id_Set is
586 new Ada.Containers.Ordered_Sets (Element_Type => Name_Id);
588 Seen_Name : Name_Id_Set.Set;
589 -- This set is needed to ensure that we do not handle the same
590 -- project twice in the context of aggregate libraries.
592 procedure Recursive_Check
593 (Project : Project_Id;
594 Tree : Project_Tree_Ref;
595 In_Aggregate_Lib : Boolean;
596 From_Encapsulated_Lib : Boolean);
597 -- Check if project has already been seen. If not, mark it as Seen,
598 -- Call Action, and check all its imported and aggregated projects.
600 ---------------------
601 -- Recursive_Check --
602 ---------------------
604 procedure Recursive_Check
605 (Project : Project_Id;
606 Tree : Project_Tree_Ref;
607 In_Aggregate_Lib : Boolean;
608 From_Encapsulated_Lib : Boolean)
611 function Has_Sources (P : Project_Id) return Boolean;
612 -- Returns True if P has sources
614 function Get_From_Tree (P : Project_Id) return Project_Id;
615 -- Get project P from Tree. If P has no sources get another
616 -- instance of this project with sources. If P has sources,
617 -- returns it.
619 -----------------
620 -- Has_Sources --
621 -----------------
623 function Has_Sources (P : Project_Id) return Boolean is
624 Lang : Language_Ptr;
626 begin
627 Lang := P.Languages;
628 while Lang /= No_Language_Index loop
629 if Lang.First_Source /= No_Source then
630 return True;
631 end if;
633 Lang := Lang.Next;
634 end loop;
636 return False;
637 end Has_Sources;
639 -------------------
640 -- Get_From_Tree --
641 -------------------
643 function Get_From_Tree (P : Project_Id) return Project_Id is
644 List : Project_List := Tree.Projects;
646 begin
647 if not Has_Sources (P) then
648 while List /= null loop
649 if List.Project.Name = P.Name
650 and then Has_Sources (List.Project)
651 then
652 return List.Project;
653 end if;
655 List := List.Next;
656 end loop;
657 end if;
659 return P;
660 end Get_From_Tree;
662 -- Local variables
664 List : Project_List;
666 -- Start of processing for Recursive_Check
668 begin
669 if not Seen_Name.Contains (Project.Name) then
671 -- Even if a project is aggregated multiple times in an
672 -- aggregated library, we will only return it once.
674 Seen_Name.Include (Project.Name);
676 if not Imported_First then
677 Action
678 (Get_From_Tree (Project),
679 Tree,
680 Project_Context'(In_Aggregate_Lib, From_Encapsulated_Lib),
681 With_State);
682 end if;
684 -- Visit all extended projects
686 if Project.Extends /= No_Project then
687 Recursive_Check
688 (Project.Extends, Tree,
689 In_Aggregate_Lib, From_Encapsulated_Lib);
690 end if;
692 -- Visit all imported projects
694 List := Project.Imported_Projects;
695 while List /= null loop
696 Recursive_Check
697 (List.Project, Tree,
698 In_Aggregate_Lib,
699 From_Encapsulated_Lib
700 or else Project.Standalone_Library = Encapsulated);
701 List := List.Next;
702 end loop;
704 -- Visit all aggregated projects
706 if Include_Aggregated
707 and then Project.Qualifier in Aggregate_Project
708 then
709 declare
710 Agg : Aggregated_Project_List;
712 begin
713 Agg := Project.Aggregated_Projects;
714 while Agg /= null loop
715 pragma Assert (Agg.Project /= No_Project);
717 -- For aggregated libraries, the tree must be the one
718 -- of the aggregate library.
720 if Project.Qualifier = Aggregate_Library then
721 Recursive_Check
722 (Agg.Project, Tree,
723 True,
724 From_Encapsulated_Lib
725 or else
726 Project.Standalone_Library = Encapsulated);
728 else
729 -- Use a new context as we want to returns the same
730 -- project in different project tree for aggregated
731 -- projects.
733 Recursive_Check_Context
734 (Agg.Project, Agg.Tree, False, False);
735 end if;
737 Agg := Agg.Next;
738 end loop;
739 end;
740 end if;
742 if Imported_First then
743 Action
744 (Get_From_Tree (Project),
745 Tree,
746 Project_Context'(In_Aggregate_Lib, From_Encapsulated_Lib),
747 With_State);
748 end if;
749 end if;
750 end Recursive_Check;
752 -- Start of processing for Recursive_Check_Context
754 begin
755 Recursive_Check
756 (Project, Tree, In_Aggregate_Lib, From_Encapsulated_Lib);
757 end Recursive_Check_Context;
759 -- Start of processing for For_Every_Project_Imported
761 begin
762 Recursive_Check_Context
763 (Project => By,
764 Tree => Tree,
765 In_Aggregate_Lib => False,
766 From_Encapsulated_Lib => False);
767 end For_Every_Project_Imported_Context;
769 procedure For_Every_Project_Imported
770 (By : Project_Id;
771 Tree : Project_Tree_Ref;
772 With_State : in out State;
773 Include_Aggregated : Boolean := True;
774 Imported_First : Boolean := False)
776 procedure Internal
777 (Project : Project_Id;
778 Tree : Project_Tree_Ref;
779 Context : Project_Context;
780 With_State : in out State);
781 -- Action wrapper for handling the context
783 --------------
784 -- Internal --
785 --------------
787 procedure Internal
788 (Project : Project_Id;
789 Tree : Project_Tree_Ref;
790 Context : Project_Context;
791 With_State : in out State)
793 pragma Unreferenced (Context);
794 begin
795 Action (Project, Tree, With_State);
796 end Internal;
798 procedure For_Projects is
799 new For_Every_Project_Imported_Context (State, Internal);
801 begin
802 For_Projects (By, Tree, With_State, Include_Aggregated, Imported_First);
803 end For_Every_Project_Imported;
805 -----------------
806 -- Find_Source --
807 -----------------
809 function Find_Source
810 (In_Tree : Project_Tree_Ref;
811 Project : Project_Id;
812 In_Imported_Only : Boolean := False;
813 In_Extended_Only : Boolean := False;
814 Base_Name : File_Name_Type;
815 Index : Int := 0) return Source_Id
817 Result : Source_Id := No_Source;
819 procedure Look_For_Sources
820 (Proj : Project_Id;
821 Tree : Project_Tree_Ref;
822 Src : in out Source_Id);
823 -- Look for Base_Name in the sources of Proj
825 ----------------------
826 -- Look_For_Sources --
827 ----------------------
829 procedure Look_For_Sources
830 (Proj : Project_Id;
831 Tree : Project_Tree_Ref;
832 Src : in out Source_Id)
834 Iterator : Source_Iterator;
836 begin
837 Iterator := For_Each_Source (In_Tree => Tree, Project => Proj);
838 while Element (Iterator) /= No_Source loop
839 if Element (Iterator).File = Base_Name
840 and then (Index = 0 or else Element (Iterator).Index = Index)
841 then
842 Src := Element (Iterator);
844 -- If the source has been excluded, continue looking. We will
845 -- get the excluded source only if there is no other source
846 -- with the same base name that is not locally removed.
848 if not Element (Iterator).Locally_Removed then
849 return;
850 end if;
851 end if;
853 Next (Iterator);
854 end loop;
855 end Look_For_Sources;
857 procedure For_Imported_Projects is new For_Every_Project_Imported
858 (State => Source_Id, Action => Look_For_Sources);
860 Proj : Project_Id;
862 -- Start of processing for Find_Source
864 begin
865 if In_Extended_Only then
866 Proj := Project;
867 while Proj /= No_Project loop
868 Look_For_Sources (Proj, In_Tree, Result);
869 exit when Result /= No_Source;
871 Proj := Proj.Extends;
872 end loop;
874 elsif In_Imported_Only then
875 Look_For_Sources (Project, In_Tree, Result);
877 if Result = No_Source then
878 For_Imported_Projects
879 (By => Project,
880 Tree => In_Tree,
881 Include_Aggregated => False,
882 With_State => Result);
883 end if;
885 else
886 Look_For_Sources (No_Project, In_Tree, Result);
887 end if;
889 return Result;
890 end Find_Source;
892 ----------
893 -- Hash --
894 ----------
896 function Hash is new GNAT.HTable.Hash (Header_Num => Header_Num);
897 -- Used in implementation of other functions Hash below
899 function Hash (Name : File_Name_Type) return Header_Num is
900 begin
901 return Hash (Get_Name_String (Name));
902 end Hash;
904 function Hash (Name : Name_Id) return Header_Num is
905 begin
906 return Hash (Get_Name_String (Name));
907 end Hash;
909 function Hash (Name : Path_Name_Type) return Header_Num is
910 begin
911 return Hash (Get_Name_String (Name));
912 end Hash;
914 function Hash (Project : Project_Id) return Header_Num is
915 begin
916 if Project = No_Project then
917 return Header_Num'First;
918 else
919 return Hash (Get_Name_String (Project.Name));
920 end if;
921 end Hash;
923 -----------
924 -- Image --
925 -----------
927 function Image (The_Casing : Casing_Type) return String is
928 begin
929 return The_Casing_Images (The_Casing).all;
930 end Image;
932 -----------------------------
933 -- Is_Standard_GNAT_Naming --
934 -----------------------------
936 function Is_Standard_GNAT_Naming
937 (Naming : Lang_Naming_Data) return Boolean
939 begin
940 return Get_Name_String (Naming.Spec_Suffix) = ".ads"
941 and then Get_Name_String (Naming.Body_Suffix) = ".adb"
942 and then Get_Name_String (Naming.Dot_Replacement) = "-";
943 end Is_Standard_GNAT_Naming;
945 ----------------
946 -- Initialize --
947 ----------------
949 procedure Initialize (Tree : Project_Tree_Ref) is
950 begin
951 if The_Empty_String = No_Name then
952 Uintp.Initialize;
953 Name_Len := 0;
954 The_Empty_String := Name_Find;
956 Prj.Attr.Initialize;
958 -- Make sure that new reserved words after Ada 95 may be used as
959 -- identifiers.
961 Opt.Ada_Version := Opt.Ada_95;
962 Opt.Ada_Version_Pragma := Empty;
964 Set_Name_Table_Byte (Name_Project, Token_Type'Pos (Tok_Project));
965 Set_Name_Table_Byte (Name_Extends, Token_Type'Pos (Tok_Extends));
966 Set_Name_Table_Byte (Name_External, Token_Type'Pos (Tok_External));
967 Set_Name_Table_Byte
968 (Name_External_As_List, Token_Type'Pos (Tok_External_As_List));
969 end if;
971 if Tree /= No_Project_Tree then
972 Reset (Tree);
973 end if;
974 end Initialize;
976 ------------------
977 -- Is_Extending --
978 ------------------
980 function Is_Extending
981 (Extending : Project_Id;
982 Extended : Project_Id) return Boolean
984 Proj : Project_Id;
986 begin
987 Proj := Extending;
988 while Proj /= No_Project loop
989 if Proj = Extended then
990 return True;
991 end if;
993 Proj := Proj.Extends;
994 end loop;
996 return False;
997 end Is_Extending;
999 -----------------
1000 -- Object_Name --
1001 -----------------
1003 function Object_Name
1004 (Source_File_Name : File_Name_Type;
1005 Object_File_Suffix : Name_Id := No_Name) return File_Name_Type
1007 begin
1008 if Object_File_Suffix = No_Name then
1009 return Extend_Name
1010 (Source_File_Name, Object_Suffix);
1011 else
1012 return Extend_Name
1013 (Source_File_Name, Get_Name_String (Object_File_Suffix));
1014 end if;
1015 end Object_Name;
1017 function Object_Name
1018 (Source_File_Name : File_Name_Type;
1019 Source_Index : Int;
1020 Index_Separator : Character;
1021 Object_File_Suffix : Name_Id := No_Name) return File_Name_Type
1023 Index_Img : constant String := Source_Index'Img;
1024 Last : Natural;
1026 begin
1027 Get_Name_String (Source_File_Name);
1029 Last := Name_Len;
1030 while Last > 1 and then Name_Buffer (Last) /= '.' loop
1031 Last := Last - 1;
1032 end loop;
1034 if Last > 1 then
1035 Name_Len := Last - 1;
1036 end if;
1038 Add_Char_To_Name_Buffer (Index_Separator);
1039 Add_Str_To_Name_Buffer (Index_Img (2 .. Index_Img'Last));
1041 if Object_File_Suffix = No_Name then
1042 Add_Str_To_Name_Buffer (Object_Suffix);
1043 else
1044 Add_Str_To_Name_Buffer (Get_Name_String (Object_File_Suffix));
1045 end if;
1047 return Name_Find;
1048 end Object_Name;
1050 ----------------------
1051 -- Record_Temp_File --
1052 ----------------------
1054 procedure Record_Temp_File
1055 (Shared : Shared_Project_Tree_Data_Access;
1056 Path : Path_Name_Type)
1058 begin
1059 Temp_Files_Table.Append (Shared.Private_Part.Temp_Files, Path);
1060 end Record_Temp_File;
1062 ----------
1063 -- Free --
1064 ----------
1066 procedure Free (List : in out Aggregated_Project_List) is
1067 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
1068 (Aggregated_Project, Aggregated_Project_List);
1069 Tmp : Aggregated_Project_List;
1070 begin
1071 while List /= null loop
1072 Tmp := List.Next;
1074 Free (List.Tree);
1076 Unchecked_Free (List);
1077 List := Tmp;
1078 end loop;
1079 end Free;
1081 ----------------------------
1082 -- Add_Aggregated_Project --
1083 ----------------------------
1085 procedure Add_Aggregated_Project
1086 (Project : Project_Id;
1087 Path : Path_Name_Type)
1089 Aggregated : Aggregated_Project_List;
1091 begin
1092 -- Check if the project is already in the aggregated project list. If it
1093 -- is, do not add it again.
1095 Aggregated := Project.Aggregated_Projects;
1096 while Aggregated /= null loop
1097 if Path = Aggregated.Path then
1098 return;
1099 else
1100 Aggregated := Aggregated.Next;
1101 end if;
1102 end loop;
1104 Project.Aggregated_Projects := new Aggregated_Project'
1105 (Path => Path,
1106 Project => No_Project,
1107 Tree => null,
1108 Next => Project.Aggregated_Projects);
1109 end Add_Aggregated_Project;
1111 ----------
1112 -- Free --
1113 ----------
1115 procedure Free (Project : in out Project_Id) is
1116 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
1117 (Project_Data, Project_Id);
1119 begin
1120 if Project /= null then
1121 Free (Project.Ada_Include_Path);
1122 Free (Project.Objects_Path);
1123 Free (Project.Ada_Objects_Path);
1124 Free (Project.Ada_Objects_Path_No_Libs);
1125 Free_List (Project.Imported_Projects, Free_Project => False);
1126 Free_List (Project.All_Imported_Projects, Free_Project => False);
1127 Free_List (Project.Languages);
1129 case Project.Qualifier is
1130 when Aggregate | Aggregate_Library =>
1131 Free (Project.Aggregated_Projects);
1133 when others =>
1134 null;
1135 end case;
1137 Unchecked_Free (Project);
1138 end if;
1139 end Free;
1141 ---------------
1142 -- Free_List --
1143 ---------------
1145 procedure Free_List (Languages : in out Language_List) is
1146 procedure Unchecked_Free is new Ada.Unchecked_Deallocation
1147 (Language_List_Element, Language_List);
1148 Tmp : Language_List;
1149 begin
1150 while Languages /= null loop
1151 Tmp := Languages.Next;
1152 Unchecked_Free (Languages);
1153 Languages := Tmp;
1154 end loop;
1155 end Free_List;
1157 ---------------
1158 -- Free_List --
1159 ---------------
1161 procedure Free_List (Source : in out Source_Id) is
1162 procedure Unchecked_Free is new
1163 Ada.Unchecked_Deallocation (Source_Data, Source_Id);
1165 Tmp : Source_Id;
1167 begin
1168 while Source /= No_Source loop
1169 Tmp := Source.Next_In_Lang;
1170 Free_List (Source.Alternate_Languages);
1172 if Source.Unit /= null
1173 and then Source.Kind in Spec_Or_Body
1174 then
1175 Source.Unit.File_Names (Source.Kind) := null;
1176 end if;
1178 Unchecked_Free (Source);
1179 Source := Tmp;
1180 end loop;
1181 end Free_List;
1183 ---------------
1184 -- Free_List --
1185 ---------------
1187 procedure Free_List
1188 (List : in out Project_List;
1189 Free_Project : Boolean)
1191 procedure Unchecked_Free is new
1192 Ada.Unchecked_Deallocation (Project_List_Element, Project_List);
1194 Tmp : Project_List;
1196 begin
1197 while List /= null loop
1198 Tmp := List.Next;
1200 if Free_Project then
1201 Free (List.Project);
1202 end if;
1204 Unchecked_Free (List);
1205 List := Tmp;
1206 end loop;
1207 end Free_List;
1209 ---------------
1210 -- Free_List --
1211 ---------------
1213 procedure Free_List (Languages : in out Language_Ptr) is
1214 procedure Unchecked_Free is new
1215 Ada.Unchecked_Deallocation (Language_Data, Language_Ptr);
1217 Tmp : Language_Ptr;
1219 begin
1220 while Languages /= null loop
1221 Tmp := Languages.Next;
1222 Free_List (Languages.First_Source);
1223 Unchecked_Free (Languages);
1224 Languages := Tmp;
1225 end loop;
1226 end Free_List;
1228 --------------------------
1229 -- Reset_Units_In_Table --
1230 --------------------------
1232 procedure Reset_Units_In_Table (Table : in out Units_Htable.Instance) is
1233 Unit : Unit_Index;
1235 begin
1236 Unit := Units_Htable.Get_First (Table);
1237 while Unit /= No_Unit_Index loop
1238 if Unit.File_Names (Spec) /= null then
1239 Unit.File_Names (Spec).Unit := No_Unit_Index;
1240 end if;
1242 if Unit.File_Names (Impl) /= null then
1243 Unit.File_Names (Impl).Unit := No_Unit_Index;
1244 end if;
1246 Unit := Units_Htable.Get_Next (Table);
1247 end loop;
1248 end Reset_Units_In_Table;
1250 ----------------
1251 -- Free_Units --
1252 ----------------
1254 procedure Free_Units (Table : in out Units_Htable.Instance) is
1255 procedure Unchecked_Free is new
1256 Ada.Unchecked_Deallocation (Unit_Data, Unit_Index);
1258 Unit : Unit_Index;
1260 begin
1261 Unit := Units_Htable.Get_First (Table);
1262 while Unit /= No_Unit_Index loop
1264 -- We cannot reset Unit.File_Names (Impl or Spec).Unit here as
1265 -- Source_Data buffer is freed by the following instruction
1266 -- Free_List (Tree.Projects, Free_Project => True);
1268 Unchecked_Free (Unit);
1269 Unit := Units_Htable.Get_Next (Table);
1270 end loop;
1272 Units_Htable.Reset (Table);
1273 end Free_Units;
1275 ----------
1276 -- Free --
1277 ----------
1279 procedure Free (Tree : in out Project_Tree_Ref) is
1280 procedure Unchecked_Free is new
1281 Ada.Unchecked_Deallocation
1282 (Project_Tree_Data, Project_Tree_Ref);
1284 procedure Unchecked_Free is new
1285 Ada.Unchecked_Deallocation
1286 (Project_Tree_Appdata'Class, Project_Tree_Appdata_Access);
1288 begin
1289 if Tree /= null then
1290 if Tree.Is_Root_Tree then
1291 Name_List_Table.Free (Tree.Shared.Name_Lists);
1292 Number_List_Table.Free (Tree.Shared.Number_Lists);
1293 String_Element_Table.Free (Tree.Shared.String_Elements);
1294 Variable_Element_Table.Free (Tree.Shared.Variable_Elements);
1295 Array_Element_Table.Free (Tree.Shared.Array_Elements);
1296 Array_Table.Free (Tree.Shared.Arrays);
1297 Package_Table.Free (Tree.Shared.Packages);
1298 Temp_Files_Table.Free (Tree.Shared.Private_Part.Temp_Files);
1299 end if;
1301 if Tree.Appdata /= null then
1302 Free (Tree.Appdata.all);
1303 Unchecked_Free (Tree.Appdata);
1304 end if;
1306 Source_Paths_Htable.Reset (Tree.Source_Paths_HT);
1307 Source_Files_Htable.Reset (Tree.Source_Files_HT);
1309 Reset_Units_In_Table (Tree.Units_HT);
1310 Free_List (Tree.Projects, Free_Project => True);
1311 Free_Units (Tree.Units_HT);
1313 Unchecked_Free (Tree);
1314 end if;
1315 end Free;
1317 -----------
1318 -- Reset --
1319 -----------
1321 procedure Reset (Tree : Project_Tree_Ref) is
1322 begin
1323 -- Visible tables
1325 if Tree.Is_Root_Tree then
1327 -- We cannot use 'Access here:
1328 -- "illegal attribute for discriminant-dependent component"
1329 -- However, we know this is valid since Shared and Shared_Data have
1330 -- the same lifetime and will always exist concurrently.
1332 Tree.Shared := Tree.Shared_Data'Unrestricted_Access;
1333 Name_List_Table.Init (Tree.Shared.Name_Lists);
1334 Number_List_Table.Init (Tree.Shared.Number_Lists);
1335 String_Element_Table.Init (Tree.Shared.String_Elements);
1336 Variable_Element_Table.Init (Tree.Shared.Variable_Elements);
1337 Array_Element_Table.Init (Tree.Shared.Array_Elements);
1338 Array_Table.Init (Tree.Shared.Arrays);
1339 Package_Table.Init (Tree.Shared.Packages);
1341 -- Private part table
1343 Temp_Files_Table.Init (Tree.Shared.Private_Part.Temp_Files);
1345 Tree.Shared.Private_Part.Current_Source_Path_File := No_Path;
1346 Tree.Shared.Private_Part.Current_Object_Path_File := No_Path;
1347 end if;
1349 Source_Paths_Htable.Reset (Tree.Source_Paths_HT);
1350 Source_Files_Htable.Reset (Tree.Source_Files_HT);
1351 Replaced_Source_HTable.Reset (Tree.Replaced_Sources);
1353 Tree.Replaced_Source_Number := 0;
1355 Reset_Units_In_Table (Tree.Units_HT);
1356 Free_List (Tree.Projects, Free_Project => True);
1357 Free_Units (Tree.Units_HT);
1358 end Reset;
1360 -------------------------------------
1361 -- Set_Current_Object_Path_File_Of --
1362 -------------------------------------
1364 procedure Set_Current_Object_Path_File_Of
1365 (Shared : Shared_Project_Tree_Data_Access;
1366 To : Path_Name_Type)
1368 begin
1369 Shared.Private_Part.Current_Object_Path_File := To;
1370 end Set_Current_Object_Path_File_Of;
1372 -------------------------------------
1373 -- Set_Current_Source_Path_File_Of --
1374 -------------------------------------
1376 procedure Set_Current_Source_Path_File_Of
1377 (Shared : Shared_Project_Tree_Data_Access;
1378 To : Path_Name_Type)
1380 begin
1381 Shared.Private_Part.Current_Source_Path_File := To;
1382 end Set_Current_Source_Path_File_Of;
1384 -----------------------
1385 -- Set_Path_File_Var --
1386 -----------------------
1388 procedure Set_Path_File_Var (Name : String; Value : String) is
1389 Host_Spec : String_Access := To_Host_File_Spec (Value);
1390 begin
1391 if Host_Spec = null then
1392 Prj.Com.Fail
1393 ("could not convert file name """ & Value & """ to host spec");
1394 else
1395 Setenv (Name, Host_Spec.all);
1396 Free (Host_Spec);
1397 end if;
1398 end Set_Path_File_Var;
1400 -------------------
1401 -- Switches_Name --
1402 -------------------
1404 function Switches_Name
1405 (Source_File_Name : File_Name_Type) return File_Name_Type
1407 begin
1408 return Extend_Name (Source_File_Name, Switches_Dependency_Suffix);
1409 end Switches_Name;
1411 -----------
1412 -- Value --
1413 -----------
1415 function Value (Image : String) return Casing_Type is
1416 begin
1417 for Casing in The_Casing_Images'Range loop
1418 if To_Lower (Image) = To_Lower (The_Casing_Images (Casing).all) then
1419 return Casing;
1420 end if;
1421 end loop;
1423 raise Constraint_Error;
1424 end Value;
1426 ---------------------
1427 -- Has_Ada_Sources --
1428 ---------------------
1430 function Has_Ada_Sources (Data : Project_Id) return Boolean is
1431 Lang : Language_Ptr;
1433 begin
1434 Lang := Data.Languages;
1435 while Lang /= No_Language_Index loop
1436 if Lang.Name = Name_Ada then
1437 return Lang.First_Source /= No_Source;
1438 end if;
1439 Lang := Lang.Next;
1440 end loop;
1442 return False;
1443 end Has_Ada_Sources;
1445 ------------------------
1446 -- Contains_ALI_Files --
1447 ------------------------
1449 function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean is
1450 Dir_Name : constant String := Get_Name_String (Dir);
1451 Direct : Dir_Type;
1452 Name : String (1 .. 1_000);
1453 Last : Natural;
1454 Result : Boolean := False;
1456 begin
1457 Open (Direct, Dir_Name);
1459 -- For each file in the directory, check if it is an ALI file
1461 loop
1462 Read (Direct, Name, Last);
1463 exit when Last = 0;
1464 Canonical_Case_File_Name (Name (1 .. Last));
1465 Result := Last >= 5 and then Name (Last - 3 .. Last) = ".ali";
1466 exit when Result;
1467 end loop;
1469 Close (Direct);
1470 return Result;
1472 exception
1473 -- If there is any problem, close the directory if open and return True.
1474 -- The library directory will be added to the path.
1476 when others =>
1477 if Is_Open (Direct) then
1478 Close (Direct);
1479 end if;
1481 return True;
1482 end Contains_ALI_Files;
1484 --------------------------
1485 -- Get_Object_Directory --
1486 --------------------------
1488 function Get_Object_Directory
1489 (Project : Project_Id;
1490 Including_Libraries : Boolean;
1491 Only_If_Ada : Boolean := False) return Path_Name_Type
1493 begin
1494 if (Project.Library and then Including_Libraries)
1495 or else
1496 (Project.Object_Directory /= No_Path_Information
1497 and then (not Including_Libraries or else not Project.Library))
1498 then
1499 -- For a library project, add the library ALI directory if there is
1500 -- no object directory or if the library ALI directory contains ALI
1501 -- files; otherwise add the object directory.
1503 if Project.Library then
1504 if Project.Object_Directory = No_Path_Information
1505 or else
1506 (Including_Libraries
1507 and then
1508 Contains_ALI_Files (Project.Library_ALI_Dir.Display_Name))
1509 then
1510 return Project.Library_ALI_Dir.Display_Name;
1511 else
1512 return Project.Object_Directory.Display_Name;
1513 end if;
1515 -- For a non-library project, add object directory if it is not a
1516 -- virtual project, and if there are Ada sources in the project or
1517 -- one of the projects it extends. If there are no Ada sources,
1518 -- adding the object directory could disrupt the order of the
1519 -- object dirs in the path.
1521 elsif not Project.Virtual then
1522 declare
1523 Add_Object_Dir : Boolean;
1524 Prj : Project_Id;
1526 begin
1527 Add_Object_Dir := not Only_If_Ada;
1528 Prj := Project;
1529 while not Add_Object_Dir and then Prj /= No_Project loop
1530 if Has_Ada_Sources (Prj) then
1531 Add_Object_Dir := True;
1532 else
1533 Prj := Prj.Extends;
1534 end if;
1535 end loop;
1537 if Add_Object_Dir then
1538 return Project.Object_Directory.Display_Name;
1539 end if;
1540 end;
1541 end if;
1542 end if;
1544 return No_Path;
1545 end Get_Object_Directory;
1547 -----------------------------------
1548 -- Ultimate_Extending_Project_Of --
1549 -----------------------------------
1551 function Ultimate_Extending_Project_Of
1552 (Proj : Project_Id) return Project_Id
1554 Prj : Project_Id;
1556 begin
1557 Prj := Proj;
1558 while Prj /= null and then Prj.Extended_By /= No_Project loop
1559 Prj := Prj.Extended_By;
1560 end loop;
1562 return Prj;
1563 end Ultimate_Extending_Project_Of;
1565 -----------------------------------
1566 -- Compute_All_Imported_Projects --
1567 -----------------------------------
1569 procedure Compute_All_Imported_Projects
1570 (Root_Project : Project_Id;
1571 Tree : Project_Tree_Ref)
1573 procedure Analyze_Tree
1574 (Local_Root : Project_Id;
1575 Local_Tree : Project_Tree_Ref;
1576 Context : Project_Context);
1577 -- Process Project and all its aggregated project to analyze their own
1578 -- imported projects.
1580 ------------------
1581 -- Analyze_Tree --
1582 ------------------
1584 procedure Analyze_Tree
1585 (Local_Root : Project_Id;
1586 Local_Tree : Project_Tree_Ref;
1587 Context : Project_Context)
1589 pragma Unreferenced (Local_Root);
1591 Project : Project_Id;
1593 procedure Recursive_Add
1594 (Prj : Project_Id;
1595 Tree : Project_Tree_Ref;
1596 Context : Project_Context;
1597 Dummy : in out Boolean);
1598 -- Recursively add the projects imported by project Project, but not
1599 -- those that are extended.
1601 -------------------
1602 -- Recursive_Add --
1603 -------------------
1605 procedure Recursive_Add
1606 (Prj : Project_Id;
1607 Tree : Project_Tree_Ref;
1608 Context : Project_Context;
1609 Dummy : in out Boolean)
1611 pragma Unreferenced (Dummy, Tree);
1613 List : Project_List;
1614 Prj2 : Project_Id;
1616 begin
1617 -- A project is not importing itself
1619 Prj2 := Ultimate_Extending_Project_Of (Prj);
1621 if Project /= Prj2 then
1623 -- Check that the project is not already in the list. We know
1624 -- the one passed to Recursive_Add have never been visited
1625 -- before, but the one passed it are the extended projects.
1627 List := Project.All_Imported_Projects;
1628 while List /= null loop
1629 if List.Project = Prj2 then
1630 return;
1631 end if;
1633 List := List.Next;
1634 end loop;
1636 -- Add it to the list
1638 Project.All_Imported_Projects :=
1639 new Project_List_Element'
1640 (Project => Prj2,
1641 From_Encapsulated_Lib =>
1642 Context.From_Encapsulated_Lib
1643 or else Analyze_Tree.Context.From_Encapsulated_Lib,
1644 Next => Project.All_Imported_Projects);
1645 end if;
1646 end Recursive_Add;
1648 procedure For_All_Projects is
1649 new For_Every_Project_Imported_Context (Boolean, Recursive_Add);
1651 Dummy : Boolean := False;
1652 List : Project_List;
1654 begin
1655 List := Local_Tree.Projects;
1656 while List /= null loop
1657 Project := List.Project;
1658 Free_List
1659 (Project.All_Imported_Projects, Free_Project => False);
1660 For_All_Projects
1661 (Project, Local_Tree, Dummy, Include_Aggregated => False);
1662 List := List.Next;
1663 end loop;
1664 end Analyze_Tree;
1666 procedure For_Aggregates is
1667 new For_Project_And_Aggregated_Context (Analyze_Tree);
1669 -- Start of processing for Compute_All_Imported_Projects
1671 begin
1672 For_Aggregates (Root_Project, Tree);
1673 end Compute_All_Imported_Projects;
1675 -------------------
1676 -- Is_Compilable --
1677 -------------------
1679 function Is_Compilable (Source : Source_Id) return Boolean is
1680 begin
1681 case Source.Compilable is
1682 when Unknown =>
1683 if Source.Language.Config.Compiler_Driver /= No_File
1684 and then
1685 Length_Of_Name (Source.Language.Config.Compiler_Driver) /= 0
1686 and then not Source.Locally_Removed
1687 and then (Source.Language.Config.Kind /= File_Based
1688 or else Source.Kind /= Spec)
1689 then
1690 -- Do not modify Source.Compilable before the source record
1691 -- has been initialized.
1693 if Source.Source_TS /= Empty_Time_Stamp then
1694 Source.Compilable := Yes;
1695 end if;
1697 return True;
1699 else
1700 if Source.Source_TS /= Empty_Time_Stamp then
1701 Source.Compilable := No;
1702 end if;
1704 return False;
1705 end if;
1707 when Yes =>
1708 return True;
1710 when No =>
1711 return False;
1712 end case;
1713 end Is_Compilable;
1715 ------------------------------
1716 -- Object_To_Global_Archive --
1717 ------------------------------
1719 function Object_To_Global_Archive (Source : Source_Id) return Boolean is
1720 begin
1721 return Source.Language.Config.Kind = File_Based
1722 and then Source.Kind = Impl
1723 and then Source.Language.Config.Objects_Linked
1724 and then Is_Compilable (Source)
1725 and then Source.Language.Config.Object_Generated;
1726 end Object_To_Global_Archive;
1728 ----------------------------
1729 -- Get_Language_From_Name --
1730 ----------------------------
1732 function Get_Language_From_Name
1733 (Project : Project_Id;
1734 Name : String) return Language_Ptr
1736 N : Name_Id;
1737 Result : Language_Ptr;
1739 begin
1740 Name_Len := Name'Length;
1741 Name_Buffer (1 .. Name_Len) := Name;
1742 To_Lower (Name_Buffer (1 .. Name_Len));
1743 N := Name_Find;
1745 Result := Project.Languages;
1746 while Result /= No_Language_Index loop
1747 if Result.Name = N then
1748 return Result;
1749 end if;
1751 Result := Result.Next;
1752 end loop;
1754 return No_Language_Index;
1755 end Get_Language_From_Name;
1757 ----------------
1758 -- Other_Part --
1759 ----------------
1761 function Other_Part (Source : Source_Id) return Source_Id is
1762 begin
1763 if Source.Unit /= No_Unit_Index then
1764 case Source.Kind is
1765 when Impl =>
1766 return Source.Unit.File_Names (Spec);
1767 when Spec =>
1768 return Source.Unit.File_Names (Impl);
1769 when Sep =>
1770 return No_Source;
1771 end case;
1772 else
1773 return No_Source;
1774 end if;
1775 end Other_Part;
1777 ------------------
1778 -- Create_Flags --
1779 ------------------
1781 function Create_Flags
1782 (Report_Error : Error_Handler;
1783 When_No_Sources : Error_Warning;
1784 Require_Sources_Other_Lang : Boolean := True;
1785 Allow_Duplicate_Basenames : Boolean := True;
1786 Compiler_Driver_Mandatory : Boolean := False;
1787 Error_On_Unknown_Language : Boolean := True;
1788 Require_Obj_Dirs : Error_Warning := Error;
1789 Allow_Invalid_External : Error_Warning := Error;
1790 Missing_Source_Files : Error_Warning := Error;
1791 Ignore_Missing_With : Boolean := False)
1792 return Processing_Flags
1794 begin
1795 return Processing_Flags'
1796 (Report_Error => Report_Error,
1797 When_No_Sources => When_No_Sources,
1798 Require_Sources_Other_Lang => Require_Sources_Other_Lang,
1799 Allow_Duplicate_Basenames => Allow_Duplicate_Basenames,
1800 Error_On_Unknown_Language => Error_On_Unknown_Language,
1801 Compiler_Driver_Mandatory => Compiler_Driver_Mandatory,
1802 Require_Obj_Dirs => Require_Obj_Dirs,
1803 Allow_Invalid_External => Allow_Invalid_External,
1804 Missing_Source_Files => Missing_Source_Files,
1805 Ignore_Missing_With => Ignore_Missing_With);
1806 end Create_Flags;
1808 ------------
1809 -- Length --
1810 ------------
1812 function Length
1813 (Table : Name_List_Table.Instance;
1814 List : Name_List_Index) return Natural
1816 Count : Natural := 0;
1817 Tmp : Name_List_Index;
1819 begin
1820 Tmp := List;
1821 while Tmp /= No_Name_List loop
1822 Count := Count + 1;
1823 Tmp := Table.Table (Tmp).Next;
1824 end loop;
1826 return Count;
1827 end Length;
1829 ------------------
1830 -- Debug_Output --
1831 ------------------
1833 procedure Debug_Output (Str : String) is
1834 begin
1835 if Current_Verbosity > Default then
1836 Set_Standard_Error;
1837 Write_Line ((1 .. Debug_Level * 2 => ' ') & Str);
1838 Set_Standard_Output;
1839 end if;
1840 end Debug_Output;
1842 ------------------
1843 -- Debug_Indent --
1844 ------------------
1846 procedure Debug_Indent is
1847 begin
1848 if Current_Verbosity = High then
1849 Set_Standard_Error;
1850 Write_Str ((1 .. Debug_Level * 2 => ' '));
1851 Set_Standard_Output;
1852 end if;
1853 end Debug_Indent;
1855 ------------------
1856 -- Debug_Output --
1857 ------------------
1859 procedure Debug_Output (Str : String; Str2 : Name_Id) is
1860 begin
1861 if Current_Verbosity > Default then
1862 Debug_Indent;
1863 Set_Standard_Error;
1864 Write_Str (Str);
1866 if Str2 = No_Name then
1867 Write_Line (" <no_name>");
1868 else
1869 Write_Line (" """ & Get_Name_String (Str2) & '"');
1870 end if;
1872 Set_Standard_Output;
1873 end if;
1874 end Debug_Output;
1876 ---------------------------
1877 -- Debug_Increase_Indent --
1878 ---------------------------
1880 procedure Debug_Increase_Indent
1881 (Str : String := ""; Str2 : Name_Id := No_Name)
1883 begin
1884 if Str2 /= No_Name then
1885 Debug_Output (Str, Str2);
1886 else
1887 Debug_Output (Str);
1888 end if;
1889 Debug_Level := Debug_Level + 1;
1890 end Debug_Increase_Indent;
1892 ---------------------------
1893 -- Debug_Decrease_Indent --
1894 ---------------------------
1896 procedure Debug_Decrease_Indent (Str : String := "") is
1897 begin
1898 if Debug_Level > 0 then
1899 Debug_Level := Debug_Level - 1;
1900 end if;
1902 if Str /= "" then
1903 Debug_Output (Str);
1904 end if;
1905 end Debug_Decrease_Indent;
1907 ----------------
1908 -- Debug_Name --
1909 ----------------
1911 function Debug_Name (Tree : Project_Tree_Ref) return Name_Id is
1912 P : Project_List;
1914 begin
1915 Name_Len := 0;
1916 Add_Str_To_Name_Buffer ("Tree [");
1918 P := Tree.Projects;
1919 while P /= null loop
1920 if P /= Tree.Projects then
1921 Add_Char_To_Name_Buffer (',');
1922 end if;
1924 Add_Str_To_Name_Buffer (Get_Name_String (P.Project.Name));
1926 P := P.Next;
1927 end loop;
1929 Add_Char_To_Name_Buffer (']');
1931 return Name_Find;
1932 end Debug_Name;
1934 ----------
1935 -- Free --
1936 ----------
1938 procedure Free (Tree : in out Project_Tree_Appdata) is
1939 pragma Unreferenced (Tree);
1940 begin
1941 null;
1942 end Free;
1944 --------------------------------
1945 -- For_Project_And_Aggregated --
1946 --------------------------------
1948 procedure For_Project_And_Aggregated
1949 (Root_Project : Project_Id;
1950 Root_Tree : Project_Tree_Ref)
1952 Agg : Aggregated_Project_List;
1954 begin
1955 Action (Root_Project, Root_Tree);
1957 if Root_Project.Qualifier in Aggregate_Project then
1958 Agg := Root_Project.Aggregated_Projects;
1959 while Agg /= null loop
1960 For_Project_And_Aggregated (Agg.Project, Agg.Tree);
1961 Agg := Agg.Next;
1962 end loop;
1963 end if;
1964 end For_Project_And_Aggregated;
1966 ----------------------------------------
1967 -- For_Project_And_Aggregated_Context --
1968 ----------------------------------------
1970 procedure For_Project_And_Aggregated_Context
1971 (Root_Project : Project_Id;
1972 Root_Tree : Project_Tree_Ref)
1975 procedure Recursive_Process
1976 (Project : Project_Id;
1977 Tree : Project_Tree_Ref;
1978 Context : Project_Context);
1979 -- Process Project and all aggregated projects recursively
1981 -----------------------
1982 -- Recursive_Process --
1983 -----------------------
1985 procedure Recursive_Process
1986 (Project : Project_Id;
1987 Tree : Project_Tree_Ref;
1988 Context : Project_Context)
1990 Agg : Aggregated_Project_List;
1991 Ctx : Project_Context;
1993 begin
1994 Action (Project, Tree, Context);
1996 if Project.Qualifier in Aggregate_Project then
1997 Ctx :=
1998 (In_Aggregate_Lib => True,
1999 From_Encapsulated_Lib =>
2000 Context.From_Encapsulated_Lib
2001 or else Project.Standalone_Library = Encapsulated);
2003 Agg := Project.Aggregated_Projects;
2004 while Agg /= null loop
2005 Recursive_Process (Agg.Project, Agg.Tree, Ctx);
2006 Agg := Agg.Next;
2007 end loop;
2008 end if;
2009 end Recursive_Process;
2011 -- Start of processing for For_Project_And_Aggregated_Context
2013 begin
2014 Recursive_Process
2015 (Root_Project, Root_Tree, Project_Context'(False, False));
2016 end For_Project_And_Aggregated_Context;
2018 -- Package initialization for Prj
2020 begin
2021 -- Make sure that the standard config and user project file extensions are
2022 -- compatible with canonical case file naming.
2024 Canonical_Case_File_Name (Config_Project_File_Extension);
2025 Canonical_Case_File_Name (Project_File_Extension);
2026 end Prj;