OSDN Git Service

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