OSDN Git Service

* gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Subtype>: Factor
[pf3gnuchains/gcc-fork.git] / gcc / ada / prj.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                                  P R J                                   --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 2001-2009, 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 ------------------------------------------------------------------------------
25
26 with Ada.Characters.Handling; use Ada.Characters.Handling;
27 with Ada.Unchecked_Deallocation;
28
29 with Debug;
30 with Osint;    use Osint;
31 with Prj.Attr;
32 with Prj.Err;  use Prj.Err;
33 with Snames;   use Snames;
34 with Table;
35 with Uintp;    use Uintp;
36
37 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
38
39 with System.Case_Util; use System.Case_Util;
40 with System.HTable;
41
42 package body Prj is
43
44    Object_Suffix : constant String := Get_Target_Object_Suffix.all;
45    --  File suffix for object files
46
47    Initial_Buffer_Size : constant := 100;
48    --  Initial size for extensible buffer used in Add_To_Buffer
49
50    Current_Mode : Mode := Ada_Only;
51
52    The_Empty_String : Name_Id;
53
54    Default_Ada_Spec_Suffix_Id : File_Name_Type;
55    Default_Ada_Body_Suffix_Id : File_Name_Type;
56    --  Initialized in Prj.Initialize, then never modified
57
58    subtype Known_Casing is Casing_Type range All_Upper_Case .. Mixed_Case;
59
60    The_Casing_Images : constant array (Known_Casing) of String_Access :=
61      (All_Lower_Case => new String'("lowercase"),
62       All_Upper_Case => new String'("UPPERCASE"),
63       Mixed_Case     => new String'("MixedCase"));
64
65    Initialized : Boolean := False;
66
67    Project_Empty : constant Project_Data :=
68                      (Qualifier                      => Unspecified,
69                       Externally_Built               => False,
70                       Config                         => Default_Project_Config,
71                       Name                           => No_Name,
72                       Display_Name                   => No_Name,
73                       Path                           => No_Path_Information,
74                       Virtual                        => False,
75                       Location                       => No_Location,
76                       Mains                          => Nil_String,
77                       Directory                      => No_Path_Information,
78                       Library                        => False,
79                       Library_Dir                    => No_Path_Information,
80                       Library_Src_Dir                => No_Path_Information,
81                       Library_ALI_Dir                => No_Path_Information,
82                       Library_Name                   => No_Name,
83                       Library_Kind                   => Static,
84                       Lib_Internal_Name              => No_Name,
85                       Standalone_Library             => False,
86                       Lib_Interface_ALIs             => Nil_String,
87                       Lib_Auto_Init                  => False,
88                       Libgnarl_Needed                => Unknown,
89                       Symbol_Data                    => No_Symbols,
90                       Interfaces_Defined             => False,
91                       Include_Path                   => null,
92                       Include_Data_Set               => False,
93                       Source_Dirs                    => Nil_String,
94                       Known_Order_Of_Source_Dirs     => True,
95                       Object_Directory               => No_Path_Information,
96                       Library_TS                     => Empty_Time_Stamp,
97                       Exec_Directory                 => No_Path_Information,
98                       Extends                        => No_Project,
99                       Extended_By                    => No_Project,
100                       Languages                      => No_Language_Index,
101                       Decl                           => No_Declarations,
102                       Imported_Projects              => null,
103                       All_Imported_Projects          => null,
104                       Ada_Include_Path               => null,
105                       Ada_Objects_Path               => null,
106                       Objects_Path                   => null,
107                       Include_Path_File              => No_Path,
108                       Objects_Path_File_With_Libs    => No_Path,
109                       Objects_Path_File_Without_Libs => No_Path,
110                       Config_File_Name               => No_Path,
111                       Config_File_Temp               => False,
112                       Config_Checked                 => False,
113                       Need_To_Build_Lib              => False,
114                       Depth                          => 0,
115                       Unkept_Comments                => False);
116
117    package Temp_Files is new Table.Table
118      (Table_Component_Type => Path_Name_Type,
119       Table_Index_Type     => Integer,
120       Table_Low_Bound      => 1,
121       Table_Initial        => 20,
122       Table_Increment      => 100,
123       Table_Name           => "Makegpr.Temp_Files");
124    --  Table to store the path name of all the created temporary files, so that
125    --  they can be deleted at the end, or when the program is interrupted.
126
127    procedure Free (Project : in out Project_Id);
128    --  Free memory allocated for Project
129
130    procedure Free_List (Languages : in out Language_Ptr);
131    procedure Free_List (Source : in out Source_Id);
132    procedure Free_List (Languages : in out Language_List);
133    --  Free memory allocated for the list of languages or sources
134
135    procedure Free_Units (Table : in out Units_Htable.Instance);
136    --  Free memory allocated for unit information in the project
137
138    procedure Language_Changed (Iter : in out Source_Iterator);
139    procedure Project_Changed (Iter : in out Source_Iterator);
140    --  Called when a new project or language was selected for this iterator
141
142    function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean;
143    --  Return True if there is at least one ALI file in the directory Dir
144
145    -------------------
146    -- Add_To_Buffer --
147    -------------------
148
149    procedure Add_To_Buffer
150      (S    : String;
151       To   : in out String_Access;
152       Last : in out Natural)
153    is
154    begin
155       if To = null then
156          To := new String (1 .. Initial_Buffer_Size);
157          Last := 0;
158       end if;
159
160       --  If Buffer is too small, double its size
161
162       while Last + S'Length > To'Last loop
163          declare
164             New_Buffer : constant  String_Access :=
165                            new String (1 .. 2 * Last);
166
167          begin
168             New_Buffer (1 .. Last) := To (1 .. Last);
169             Free (To);
170             To := New_Buffer;
171          end;
172       end loop;
173
174       To (Last + 1 .. Last + S'Length) := S;
175       Last := Last + S'Length;
176    end Add_To_Buffer;
177
178    -----------------------------
179    -- Default_Ada_Body_Suffix --
180    -----------------------------
181
182    function Default_Ada_Body_Suffix return File_Name_Type is
183    begin
184       return Default_Ada_Body_Suffix_Id;
185    end Default_Ada_Body_Suffix;
186
187    -----------------------------
188    -- Default_Ada_Spec_Suffix --
189    -----------------------------
190
191    function Default_Ada_Spec_Suffix return File_Name_Type is
192    begin
193       return Default_Ada_Spec_Suffix_Id;
194    end Default_Ada_Spec_Suffix;
195
196    ---------------------------
197    -- Delete_All_Temp_Files --
198    ---------------------------
199
200    procedure Delete_All_Temp_Files is
201       Dont_Care : Boolean;
202       pragma Warnings (Off, Dont_Care);
203    begin
204       if not Debug.Debug_Flag_N then
205          for Index in 1 .. Temp_Files.Last loop
206             Delete_File
207               (Get_Name_String (Temp_Files.Table (Index)), Dont_Care);
208          end loop;
209       end if;
210    end Delete_All_Temp_Files;
211
212    ---------------------
213    -- Dependency_Name --
214    ---------------------
215
216    function Dependency_Name
217      (Source_File_Name : File_Name_Type;
218       Dependency       : Dependency_File_Kind) return File_Name_Type
219    is
220    begin
221       case Dependency is
222          when None =>
223             return No_File;
224
225          when Makefile =>
226             return
227               File_Name_Type
228                 (Extend_Name
229                    (Source_File_Name, Makefile_Dependency_Suffix));
230
231          when ALI_File =>
232             return
233               File_Name_Type
234                 (Extend_Name
235                    (Source_File_Name, ALI_Dependency_Suffix));
236       end case;
237    end Dependency_Name;
238
239    ----------------
240    -- Empty_File --
241    ----------------
242
243    function Empty_File return File_Name_Type is
244    begin
245       return File_Name_Type (The_Empty_String);
246    end Empty_File;
247
248    -------------------
249    -- Empty_Project --
250    -------------------
251
252    function Empty_Project return Project_Data is
253    begin
254       Prj.Initialize (Tree => No_Project_Tree);
255       return Project_Empty;
256    end Empty_Project;
257
258    ------------------
259    -- Empty_String --
260    ------------------
261
262    function Empty_String return Name_Id is
263    begin
264       return The_Empty_String;
265    end Empty_String;
266
267    ------------
268    -- Expect --
269    ------------
270
271    procedure Expect (The_Token : Token_Type; Token_Image : String) is
272    begin
273       if Token /= The_Token then
274          Error_Msg (Token_Image & " expected", Token_Ptr);
275       end if;
276    end Expect;
277
278    -----------------
279    -- Extend_Name --
280    -----------------
281
282    function Extend_Name
283      (File        : File_Name_Type;
284       With_Suffix : String) return File_Name_Type
285    is
286       Last : Positive;
287
288    begin
289       Get_Name_String (File);
290       Last := Name_Len + 1;
291
292       while Name_Len /= 0 and then Name_Buffer (Name_Len) /= '.' loop
293          Name_Len := Name_Len - 1;
294       end loop;
295
296       if Name_Len <= 1 then
297          Name_Len := Last;
298       end if;
299
300       for J in With_Suffix'Range loop
301          Name_Buffer (Name_Len) := With_Suffix (J);
302          Name_Len := Name_Len + 1;
303       end loop;
304
305       Name_Len := Name_Len - 1;
306       return Name_Find;
307
308    end Extend_Name;
309
310    ---------------------
311    -- Project_Changed --
312    ---------------------
313
314    procedure Project_Changed (Iter : in out Source_Iterator) is
315    begin
316       Iter.Language := Iter.Project.Project.Languages;
317       Language_Changed (Iter);
318    end Project_Changed;
319
320    ----------------------
321    -- Language_Changed --
322    ----------------------
323
324    procedure Language_Changed (Iter : in out Source_Iterator) is
325    begin
326       Iter.Current  := No_Source;
327
328       if Iter.Language_Name /= No_Name then
329          while Iter.Language /= null
330            and then Iter.Language.Name /= Iter.Language_Name
331          loop
332             Iter.Language := Iter.Language.Next;
333          end loop;
334       end if;
335
336       --  If there is no matching language in this project, move to next
337
338       if Iter.Language = No_Language_Index then
339          if Iter.All_Projects then
340             Iter.Project := Iter.Project.Next;
341
342             if Iter.Project /= null then
343                Project_Changed (Iter);
344             end if;
345
346          else
347             Iter.Project := null;
348          end if;
349
350       else
351          Iter.Current := Iter.Language.First_Source;
352
353          if Iter.Current = No_Source then
354             Iter.Language := Iter.Language.Next;
355             Language_Changed (Iter);
356          end if;
357       end if;
358    end Language_Changed;
359
360    ---------------------
361    -- For_Each_Source --
362    ---------------------
363
364    function For_Each_Source
365      (In_Tree  : Project_Tree_Ref;
366       Project  : Project_Id := No_Project;
367       Language : Name_Id := No_Name) return Source_Iterator
368    is
369       Iter : Source_Iterator;
370    begin
371       Iter := Source_Iterator'
372         (In_Tree       => In_Tree,
373          Project       => In_Tree.Projects,
374          All_Projects  => Project = No_Project,
375          Language_Name => Language,
376          Language      => No_Language_Index,
377          Current       => No_Source);
378
379       if Project /= null then
380          while Iter.Project /= null
381            and then Iter.Project.Project /= Project
382          loop
383             Iter.Project := Iter.Project.Next;
384          end loop;
385       end if;
386
387       Project_Changed (Iter);
388
389       return Iter;
390    end For_Each_Source;
391
392    -------------
393    -- Element --
394    -------------
395
396    function Element (Iter : Source_Iterator) return Source_Id is
397    begin
398       return Iter.Current;
399    end Element;
400
401    ----------
402    -- Next --
403    ----------
404
405    procedure Next (Iter : in out Source_Iterator) is
406    begin
407       Iter.Current := Iter.Current.Next_In_Lang;
408       if Iter.Current = No_Source then
409          Iter.Language := Iter.Language.Next;
410          Language_Changed (Iter);
411       end if;
412    end Next;
413
414    --------------------------------
415    -- For_Every_Project_Imported --
416    --------------------------------
417
418    procedure For_Every_Project_Imported
419      (By             : Project_Id;
420       With_State     : in out State;
421       Imported_First : Boolean := False)
422    is
423       use Project_Boolean_Htable;
424       Seen : Project_Boolean_Htable.Instance := Project_Boolean_Htable.Nil;
425
426       procedure Recursive_Check (Project : Project_Id);
427       --  Check if a project has already been seen. If not seen, mark it as
428       --  Seen, Call Action, and check all its imported projects.
429
430       ---------------------
431       -- Recursive_Check --
432       ---------------------
433
434       procedure Recursive_Check (Project : Project_Id) is
435          List : Project_List;
436
437       begin
438          if not Get (Seen, Project) then
439             Set (Seen, Project, True);
440
441             if not Imported_First then
442                Action (Project, With_State);
443             end if;
444
445             --  Visited all extended projects
446
447             if Project.Extends /= No_Project then
448                Recursive_Check (Project.Extends);
449             end if;
450
451             --  Visited all imported projects
452
453             List := Project.Imported_Projects;
454             while List /= null loop
455                Recursive_Check (List.Project);
456                List := List.Next;
457             end loop;
458
459             if Imported_First then
460                Action (Project, With_State);
461             end if;
462          end if;
463       end Recursive_Check;
464
465    --  Start of processing for For_Every_Project_Imported
466
467    begin
468       Recursive_Check (Project => By);
469       Reset (Seen);
470    end For_Every_Project_Imported;
471
472    --------------
473    -- Get_Mode --
474    --------------
475
476    function Get_Mode return Mode is
477    begin
478       return Current_Mode;
479    end Get_Mode;
480
481    ----------
482    -- Hash --
483    ----------
484
485    function Hash is new System.HTable.Hash (Header_Num => Header_Num);
486    --  Used in implementation of other functions Hash below
487
488    function Hash (Name : File_Name_Type) return Header_Num is
489    begin
490       return Hash (Get_Name_String (Name));
491    end Hash;
492
493    function Hash (Name : Name_Id) return Header_Num is
494    begin
495       return Hash (Get_Name_String (Name));
496    end Hash;
497
498    function Hash (Name : Path_Name_Type) return Header_Num is
499    begin
500       return Hash (Get_Name_String (Name));
501    end Hash;
502
503    function Hash (Project : Project_Id) return Header_Num is
504    begin
505       if Project = No_Project then
506          return Header_Num'First;
507       else
508          return Hash (Get_Name_String (Project.Name));
509       end if;
510    end Hash;
511
512    -----------
513    -- Image --
514    -----------
515
516    function Image (Casing : Casing_Type) return String is
517    begin
518       return The_Casing_Images (Casing).all;
519    end Image;
520
521    ----------------
522    -- Initialize --
523    ----------------
524
525    procedure Initialize (Tree : Project_Tree_Ref) is
526    begin
527       if not Initialized then
528          Initialized := True;
529          Uintp.Initialize;
530          Name_Len := 0;
531          The_Empty_String := Name_Find;
532          Empty_Name := The_Empty_String;
533          Empty_File_Name := File_Name_Type (The_Empty_String);
534          Name_Len := 4;
535          Name_Buffer (1 .. 4) := ".ads";
536          Default_Ada_Spec_Suffix_Id := Name_Find;
537          Name_Len := 4;
538          Name_Buffer (1 .. 4) := ".adb";
539          Default_Ada_Body_Suffix_Id := Name_Find;
540
541          Prj.Attr.Initialize;
542          Set_Name_Table_Byte (Name_Project,  Token_Type'Pos (Tok_Project));
543          Set_Name_Table_Byte (Name_Extends,  Token_Type'Pos (Tok_Extends));
544          Set_Name_Table_Byte (Name_External, Token_Type'Pos (Tok_External));
545       end if;
546
547       if Tree /= No_Project_Tree then
548          Reset (Tree);
549       end if;
550    end Initialize;
551
552    -------------------
553    -- Is_A_Language --
554    -------------------
555
556    function Is_A_Language
557      (Project       : Project_Id;
558       Language_Name : Name_Id) return Boolean is
559    begin
560       return Get_Language_From_Name
561         (Project, Get_Name_String (Language_Name)) /= null;
562    end Is_A_Language;
563
564    ------------------
565    -- Is_Extending --
566    ------------------
567
568    function Is_Extending
569      (Extending : Project_Id;
570       Extended  : Project_Id) return Boolean
571    is
572       Proj : Project_Id;
573
574    begin
575       Proj := Extending;
576       while Proj /= No_Project loop
577          if Proj = Extended then
578             return True;
579          end if;
580
581          Proj := Proj.Extends;
582       end loop;
583
584       return False;
585    end Is_Extending;
586
587    -----------------
588    -- Object_Name --
589    -----------------
590
591    function Object_Name
592      (Source_File_Name   : File_Name_Type;
593       Object_File_Suffix : Name_Id := No_Name) return File_Name_Type
594    is
595    begin
596       if Object_File_Suffix = No_Name then
597          return Extend_Name
598            (Source_File_Name, Object_Suffix);
599       else
600          return Extend_Name
601            (Source_File_Name, Get_Name_String (Object_File_Suffix));
602       end if;
603    end Object_Name;
604
605    ----------------------
606    -- Record_Temp_File --
607    ----------------------
608
609    procedure Record_Temp_File (Path : Path_Name_Type) is
610    begin
611       Temp_Files.Increment_Last;
612       Temp_Files.Table (Temp_Files.Last) := Path;
613    end Record_Temp_File;
614
615    ----------
616    -- Free --
617    ----------
618
619    procedure Free (Project : in out Project_Id) is
620       procedure Unchecked_Free is new Ada.Unchecked_Deallocation
621         (Project_Data, Project_Id);
622
623    begin
624       if Project /= null then
625          Free (Project.Include_Path);
626          Free (Project.Ada_Include_Path);
627          Free (Project.Objects_Path);
628          Free (Project.Ada_Objects_Path);
629          Free_List (Project.Imported_Projects, Free_Project => False);
630          Free_List (Project.All_Imported_Projects, Free_Project => False);
631          Free_List (Project.Languages);
632
633          Unchecked_Free (Project);
634       end if;
635    end Free;
636
637    ---------------
638    -- Free_List --
639    ---------------
640
641    procedure Free_List (Languages : in out Language_List) is
642       procedure Unchecked_Free is new Ada.Unchecked_Deallocation
643         (Language_List_Element, Language_List);
644       Tmp : Language_List;
645    begin
646       while Languages /= null loop
647          Tmp := Languages.Next;
648          Unchecked_Free (Languages);
649          Languages := Tmp;
650       end loop;
651    end Free_List;
652
653    ---------------
654    -- Free_List --
655    ---------------
656
657    procedure Free_List (Source : in out Source_Id) is
658       procedure Unchecked_Free is new
659         Ada.Unchecked_Deallocation (Source_Data, Source_Id);
660
661       Tmp : Source_Id;
662
663    begin
664       while Source /= No_Source loop
665          Tmp := Source.Next_In_Lang;
666          Free_List (Source.Alternate_Languages);
667
668          if Source.Unit /= null
669            and then Source.Kind in Spec_Or_Body
670          then
671             Source.Unit.File_Names (Source.Kind) := null;
672          end if;
673
674          Unchecked_Free (Source);
675          Source := Tmp;
676       end loop;
677    end Free_List;
678
679    ---------------
680    -- Free_List --
681    ---------------
682
683    procedure Free_List
684      (List         : in out Project_List;
685       Free_Project : Boolean)
686    is
687       procedure Unchecked_Free is new
688         Ada.Unchecked_Deallocation (Project_List_Element, Project_List);
689
690       Tmp : Project_List;
691
692    begin
693       while List /= null loop
694          Tmp := List.Next;
695
696          if Free_Project then
697             Free (List.Project);
698          end if;
699
700          Unchecked_Free (List);
701          List := Tmp;
702       end loop;
703    end Free_List;
704
705    ---------------
706    -- Free_List --
707    ---------------
708
709    procedure Free_List (Languages : in out Language_Ptr) is
710       procedure Unchecked_Free is new
711         Ada.Unchecked_Deallocation (Language_Data, Language_Ptr);
712
713       Tmp : Language_Ptr;
714
715    begin
716       while Languages /= null loop
717          Tmp := Languages.Next;
718          Free_List (Languages.First_Source);
719          Unchecked_Free (Languages);
720          Languages := Tmp;
721       end loop;
722    end Free_List;
723
724    ----------------
725    -- Free_Units --
726    ----------------
727
728    procedure Free_Units (Table : in out Units_Htable.Instance) is
729       procedure Unchecked_Free is new
730         Ada.Unchecked_Deallocation (Unit_Data, Unit_Index);
731
732       Unit : Unit_Index;
733
734    begin
735       Unit := Units_Htable.Get_First (Table);
736       while Unit /= No_Unit_Index loop
737          if Unit.File_Names (Spec) /= null then
738             Unit.File_Names (Spec).Unit := No_Unit_Index;
739          end if;
740
741          if Unit.File_Names (Impl) /= null then
742             Unit.File_Names (Impl).Unit := No_Unit_Index;
743          end if;
744
745          Unchecked_Free (Unit);
746          Unit := Units_Htable.Get_Next (Table);
747       end loop;
748
749       Units_Htable.Reset (Table);
750    end Free_Units;
751
752    ----------
753    -- Free --
754    ----------
755
756    procedure Free (Tree : in out Project_Tree_Ref) is
757       procedure Unchecked_Free is new
758         Ada.Unchecked_Deallocation (Project_Tree_Data, Project_Tree_Ref);
759
760    begin
761       if Tree /= null then
762          Name_List_Table.Free (Tree.Name_Lists);
763          String_Element_Table.Free (Tree.String_Elements);
764          Variable_Element_Table.Free (Tree.Variable_Elements);
765          Array_Element_Table.Free (Tree.Array_Elements);
766          Array_Table.Free (Tree.Arrays);
767          Package_Table.Free (Tree.Packages);
768          Source_Paths_Htable.Reset (Tree.Source_Paths_HT);
769          Unit_Sources_Htable.Reset (Tree.Unit_Sources_HT);
770
771          Free_List (Tree.Projects, Free_Project => True);
772          Free_Units (Tree.Units_HT);
773
774          --  Private part
775
776          Path_File_Table.Free   (Tree.Private_Part.Path_Files);
777          Source_Path_Table.Free (Tree.Private_Part.Source_Paths);
778          Object_Path_Table.Free (Tree.Private_Part.Object_Paths);
779
780          Free (Tree.Private_Part.Ada_Path_Buffer);
781
782          --  Naming data (nothing to free ???)
783
784          null;
785
786          Unchecked_Free (Tree);
787       end if;
788    end Free;
789
790    -----------
791    -- Reset --
792    -----------
793
794    procedure Reset (Tree : Project_Tree_Ref) is
795    begin
796       --  Visible tables
797
798       Name_List_Table.Init          (Tree.Name_Lists);
799       String_Element_Table.Init     (Tree.String_Elements);
800       Variable_Element_Table.Init   (Tree.Variable_Elements);
801       Array_Element_Table.Init      (Tree.Array_Elements);
802       Array_Table.Init              (Tree.Arrays);
803       Package_Table.Init            (Tree.Packages);
804       Source_Paths_Htable.Reset     (Tree.Source_Paths_HT);
805       Unit_Sources_Htable.Reset     (Tree.Unit_Sources_HT);
806
807       Free_List (Tree.Projects, Free_Project => True);
808       Free_Units (Tree.Units_HT);
809
810       --  Private part table
811
812       Path_File_Table.Init        (Tree.Private_Part.Path_Files);
813       Source_Path_Table.Init      (Tree.Private_Part.Source_Paths);
814       Object_Path_Table.Init      (Tree.Private_Part.Object_Paths);
815
816       if Current_Mode = Ada_Only then
817          Tree.Private_Part.Current_Source_Path_File := No_Path;
818          Tree.Private_Part.Current_Object_Path_File := No_Path;
819          Tree.Private_Part.Ada_Path_Length := 0;
820          Tree.Private_Part.Ada_Prj_Include_File_Set := False;
821          Tree.Private_Part.Ada_Prj_Objects_File_Set := False;
822          Tree.Private_Part.Fill_Mapping_File := True;
823       end if;
824    end Reset;
825
826    --------------
827    -- Set_Mode --
828    --------------
829
830    procedure Set_Mode (New_Mode : Mode) is
831    begin
832       Current_Mode := New_Mode;
833
834       case New_Mode is
835          when Ada_Only =>
836             Default_Language_Is_Ada := True;
837             Must_Check_Configuration := False;
838          when Multi_Language =>
839             Default_Language_Is_Ada := False;
840             Must_Check_Configuration := True;
841       end case;
842    end Set_Mode;
843
844    -------------------
845    -- Switches_Name --
846    -------------------
847
848    function Switches_Name
849      (Source_File_Name : File_Name_Type) return File_Name_Type
850    is
851    begin
852       return Extend_Name (Source_File_Name, Switches_Dependency_Suffix);
853    end Switches_Name;
854
855    -----------
856    -- Value --
857    -----------
858
859    function Value (Image : String) return Casing_Type is
860    begin
861       for Casing in The_Casing_Images'Range loop
862          if To_Lower (Image) = To_Lower (The_Casing_Images (Casing).all) then
863             return Casing;
864          end if;
865       end loop;
866
867       raise Constraint_Error;
868    end Value;
869
870    ---------------------
871    -- Has_Ada_Sources --
872    ---------------------
873
874    function Has_Ada_Sources (Data : Project_Id) return Boolean is
875       Lang : Language_Ptr;
876
877    begin
878       Lang := Data.Languages;
879       while Lang /= No_Language_Index loop
880          if Lang.Name = Name_Ada then
881             return Lang.First_Source /= No_Source;
882          end if;
883          Lang := Lang.Next;
884       end loop;
885
886       return False;
887    end Has_Ada_Sources;
888
889    -------------------------
890    -- Has_Foreign_Sources --
891    -------------------------
892
893    function Has_Foreign_Sources (Data : Project_Id) return Boolean is
894       Lang : Language_Ptr;
895
896    begin
897       Lang := Data.Languages;
898       while Lang /= No_Language_Index loop
899          if Lang.Name /= Name_Ada
900            and then
901              (Current_Mode = Ada_Only or else Lang.First_Source /= No_Source)
902          then
903             return True;
904          end if;
905
906          Lang := Lang.Next;
907       end loop;
908
909       return False;
910    end Has_Foreign_Sources;
911
912    ------------------------
913    -- Contains_ALI_Files --
914    ------------------------
915
916    function Contains_ALI_Files (Dir : Path_Name_Type) return Boolean is
917       Dir_Name : constant String := Get_Name_String (Dir);
918       Direct   : Dir_Type;
919       Name     : String (1 .. 1_000);
920       Last     : Natural;
921       Result   : Boolean := False;
922
923    begin
924       Open (Direct, Dir_Name);
925
926       --  For each file in the directory, check if it is an ALI file
927
928       loop
929          Read (Direct, Name, Last);
930          exit when Last = 0;
931          Canonical_Case_File_Name (Name (1 .. Last));
932          Result := Last >= 5 and then Name (Last - 3 .. Last) = ".ali";
933          exit when Result;
934       end loop;
935
936       Close (Direct);
937       return Result;
938
939    exception
940       --  If there is any problem, close the directory if open and return True.
941       --  The library directory will be added to the path.
942
943       when others =>
944          if Is_Open (Direct) then
945             Close (Direct);
946          end if;
947
948          return True;
949    end Contains_ALI_Files;
950
951    --------------------------
952    -- Get_Object_Directory --
953    --------------------------
954
955    function Get_Object_Directory
956      (Project             : Project_Id;
957       Including_Libraries : Boolean;
958       Only_If_Ada         : Boolean := False) return Path_Name_Type
959    is
960    begin
961       if (Project.Library and Including_Libraries)
962         or else
963           (Project.Object_Directory /= No_Path_Information
964             and then (not Including_Libraries or else not Project.Library))
965       then
966          --  For a library project, add the library ALI directory if there is
967          --  no object directory or if the library ALI directory contains ALI
968          --  files; otherwise add the object directory.
969
970          if Project.Library then
971             if Project.Object_Directory = No_Path_Information
972               or else Contains_ALI_Files (Project.Library_ALI_Dir.Name)
973             then
974                return Project.Library_ALI_Dir.Name;
975             else
976                return Project.Object_Directory.Name;
977             end if;
978
979             --  For a non-library project, add object directory if it is not a
980             --  virtual project, and if there are Ada sources in the project or
981             --  one of the projects it extends. If there are no Ada sources,
982             --  adding the object directory could disrupt the order of the
983             --  object dirs in the path.
984
985          elsif not Project.Virtual then
986             declare
987                Add_Object_Dir : Boolean;
988                Prj            : Project_Id;
989
990             begin
991                Add_Object_Dir := not Only_If_Ada;
992                Prj := Project;
993                while not Add_Object_Dir and then Prj /= No_Project loop
994                   if Has_Ada_Sources (Prj) then
995                      Add_Object_Dir := True;
996                   else
997                      Prj := Prj.Extends;
998                   end if;
999                end loop;
1000
1001                if Add_Object_Dir then
1002                   return Project.Object_Directory.Name;
1003                end if;
1004             end;
1005          end if;
1006       end if;
1007
1008       return No_Path;
1009    end Get_Object_Directory;
1010
1011    -----------------------------------
1012    -- Ultimate_Extending_Project_Of --
1013    -----------------------------------
1014
1015    function Ultimate_Extending_Project_Of
1016      (Proj : Project_Id) return Project_Id
1017    is
1018       Prj : Project_Id;
1019
1020    begin
1021       Prj := Proj;
1022       while Prj /= null and then Prj.Extended_By /= No_Project loop
1023          Prj := Prj.Extended_By;
1024       end loop;
1025
1026       return Prj;
1027    end Ultimate_Extending_Project_Of;
1028
1029    -----------------------------------
1030    -- Compute_All_Imported_Projects --
1031    -----------------------------------
1032
1033    procedure Compute_All_Imported_Projects (Project : Project_Id) is
1034       procedure Recursive_Add (Prj : Project_Id; Dummy : in out Boolean);
1035       --  Recursively add the projects imported by project Project, but not
1036       --  those that are extended.
1037
1038       -------------------
1039       -- Recursive_Add --
1040       -------------------
1041
1042       procedure Recursive_Add (Prj : Project_Id; Dummy : in out Boolean) is
1043          pragma Unreferenced (Dummy);
1044          List    : Project_List;
1045          Prj2    : Project_Id;
1046
1047       begin
1048          --  A project is not importing itself
1049
1050          if Project /= Prj then
1051             Prj2 := Ultimate_Extending_Project_Of (Prj);
1052
1053             --  Check that the project is not already in the list. We know the
1054             --  one passed to Recursive_Add have never been visited before, but
1055             --  the one passed it are the extended projects.
1056
1057             List := Project.All_Imported_Projects;
1058             while List /= null loop
1059                if List.Project = Prj2 then
1060                   return;
1061                end if;
1062                List := List.Next;
1063             end loop;
1064
1065             --  Add it to the list
1066
1067             Project.All_Imported_Projects :=
1068               new Project_List_Element'
1069                 (Project => Prj2,
1070                  Next    => Project.All_Imported_Projects);
1071          end if;
1072       end Recursive_Add;
1073
1074       procedure For_All_Projects is
1075         new For_Every_Project_Imported (Boolean, Recursive_Add);
1076       Dummy : Boolean := False;
1077
1078    begin
1079       Free_List (Project.All_Imported_Projects, Free_Project => False);
1080       For_All_Projects (Project, Dummy);
1081    end Compute_All_Imported_Projects;
1082
1083    -------------------
1084    -- Is_Compilable --
1085    -------------------
1086
1087    function Is_Compilable (Source : Source_Id) return Boolean is
1088    begin
1089       return Source.Language.Config.Compiler_Driver /= Empty_File_Name
1090         and then not Source.Locally_Removed;
1091    end Is_Compilable;
1092
1093    ------------------------------
1094    -- Object_To_Global_Archive --
1095    ------------------------------
1096
1097    function Object_To_Global_Archive (Source : Source_Id) return Boolean is
1098    begin
1099       return Source.Language.Config.Kind = File_Based
1100         and then Source.Kind = Impl
1101         and then Source.Language.Config.Objects_Linked
1102         and then Is_Compilable (Source)
1103         and then Source.Language.Config.Object_Generated;
1104    end Object_To_Global_Archive;
1105
1106    ----------------------------
1107    -- Get_Language_From_Name --
1108    ----------------------------
1109
1110    function Get_Language_From_Name
1111      (Project : Project_Id;
1112       Name    : String) return Language_Ptr
1113    is
1114       N      : Name_Id;
1115       Result : Language_Ptr;
1116
1117    begin
1118       Name_Len := Name'Length;
1119       Name_Buffer (1 .. Name_Len) := Name;
1120       To_Lower (Name_Buffer (1 .. Name_Len));
1121       N := Name_Find;
1122
1123       Result := Project.Languages;
1124       while Result /= No_Language_Index loop
1125          if Result.Name = N then
1126             return Result;
1127          end if;
1128
1129          Result := Result.Next;
1130       end loop;
1131
1132       return No_Language_Index;
1133    end Get_Language_From_Name;
1134
1135    ----------------
1136    -- Other_Part --
1137    ----------------
1138
1139    function Other_Part (Source : Source_Id) return Source_Id is
1140    begin
1141       if Source.Unit /= No_Unit_Index then
1142          case Source.Kind is
1143             when Impl =>
1144                return Source.Unit.File_Names (Spec);
1145             when Spec =>
1146                return Source.Unit.File_Names (Impl);
1147             when Sep =>
1148                return No_Source;
1149          end case;
1150       else
1151          return No_Source;
1152       end if;
1153    end Other_Part;
1154
1155 begin
1156    --  Make sure that the standard config and user project file extensions are
1157    --  compatible with canonical case file naming.
1158
1159    Canonical_Case_File_Name (Config_Project_File_Extension);
1160    Canonical_Case_File_Name (Project_File_Extension);
1161 end Prj;