OSDN Git Service

5e76bce58ac138903603224436ff9fe75717ca59
[pf3gnuchains/gcc-fork.git] / gcc / ada / prj-nmsc.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                             P R J . N M S C                              --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 2000-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 GNAT.Case_Util;             use GNAT.Case_Util;
27 with GNAT.Directory_Operations;  use GNAT.Directory_Operations;
28 with GNAT.Dynamic_HTables;
29
30 with Err_Vars; use Err_Vars;
31 with Opt;      use Opt;
32 with Osint;    use Osint;
33 with Output;   use Output;
34 with Prj.Err;  use Prj.Err;
35 with Prj.Util; use Prj.Util;
36 with Sinput.P;
37 with Snames;   use Snames;
38 with Targparm; use Targparm;
39
40 with Ada.Characters.Handling;    use Ada.Characters.Handling;
41 with Ada.Directories;            use Ada.Directories;
42 with Ada.Strings;                use Ada.Strings;
43 with Ada.Strings.Fixed;          use Ada.Strings.Fixed;
44 with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
45
46 package body Prj.Nmsc is
47
48    No_Continuation_String : aliased String := "";
49    Continuation_String    : aliased String := "\";
50    --  Used in Check_Library for continuation error messages at the same
51    --  location.
52
53    type Name_Location is record
54       Name     : File_Name_Type;  --  ??? duplicates the key
55       Location : Source_Ptr;
56       Source   : Source_Id := No_Source;
57       Found    : Boolean := False;
58    end record;
59    No_Name_Location : constant Name_Location :=
60      (No_File, No_Location, No_Source, False);
61    package Source_Names_Htable is new GNAT.Dynamic_HTables.Simple_HTable
62      (Header_Num => Header_Num,
63       Element    => Name_Location,
64       No_Element => No_Name_Location,
65       Key        => File_Name_Type,
66       Hash       => Hash,
67       Equal      => "=");
68    --  Information about file names found in string list attribute
69    --  (Source_Files or Source_List_File).
70    --  Except is set to True if source is a naming exception in the project.
71    --  This is used to check that all referenced files were indeed found on the
72    --  disk.
73
74    type Unit_Exception is record
75       Name : Name_Id;  --  ??? duplicates the key
76       Spec : File_Name_Type;
77       Impl : File_Name_Type;
78    end record;
79
80    No_Unit_Exception : constant Unit_Exception := (No_Name, No_File, No_File);
81
82    package Unit_Exceptions_Htable is new GNAT.Dynamic_HTables.Simple_HTable
83      (Header_Num => Header_Num,
84       Element    => Unit_Exception,
85       No_Element => No_Unit_Exception,
86       Key        => Name_Id,
87       Hash       => Hash,
88       Equal      => "=");
89    --  Record special naming schemes for Ada units (name of spec file and name
90    --  of implementation file). The elements in this list come from the naming
91    --  exceptions specified in the project files.
92
93    type File_Found is record
94       File     : File_Name_Type  := No_File;
95       Found    : Boolean         := False;
96       Location : Source_Ptr      := No_Location;
97    end record;
98
99    No_File_Found : constant File_Found := (No_File, False, No_Location);
100
101    package Excluded_Sources_Htable is new GNAT.Dynamic_HTables.Simple_HTable
102      (Header_Num => Header_Num,
103       Element    => File_Found,
104       No_Element => No_File_Found,
105       Key        => File_Name_Type,
106       Hash       => Hash,
107       Equal      => "=");
108    --  A hash table to store the base names of excluded files, if any
109
110    package Object_File_Names_Htable is new GNAT.Dynamic_HTables.Simple_HTable
111      (Header_Num => Header_Num,
112       Element    => Source_Id,
113       No_Element => No_Source,
114       Key        => File_Name_Type,
115       Hash       => Hash,
116       Equal      => "=");
117    --  A hash table to store the object file names for a project, to check that
118    --  two different sources have different object file names.
119
120    type Project_Processing_Data is record
121       Project         : Project_Id;
122       Source_Names    : Source_Names_Htable.Instance;
123       Unit_Exceptions : Unit_Exceptions_Htable.Instance;
124       Excluded        : Excluded_Sources_Htable.Instance;
125
126       Source_List_File_Location : Source_Ptr;
127       --  Location of the Source_List_File attribute, for error messages
128    end record;
129    --  This is similar to Tree_Processing_Data, but contains project-specific
130    --  information which is only useful while processing the project, and can
131    --  be discarded as soon as we have finished processing the project
132
133    package Files_Htable is new GNAT.Dynamic_HTables.Simple_HTable
134      (Header_Num => Header_Num,
135       Element    => Source_Id,
136       No_Element => No_Source,
137       Key        => File_Name_Type,
138       Hash       => Hash,
139       Equal      => "=");
140    --  Mapping from base file names to Source_Id (containing full info about
141    --  the source).
142
143    type Tree_Processing_Data is record
144       Tree           : Project_Tree_Ref;
145       File_To_Source : Files_Htable.Instance;
146       Flags          : Prj.Processing_Flags;
147    end record;
148    --  Temporary data which is needed while parsing a project. It does not need
149    --  to be kept in memory once a project has been fully loaded, but is
150    --  necessary while performing consistency checks (duplicate sources,...)
151    --  This data must be initialized before processing any project, and the
152    --  same data is used for processing all projects in the tree.
153
154    procedure Initialize
155      (Data  : out Tree_Processing_Data;
156       Tree  : Project_Tree_Ref;
157       Flags : Prj.Processing_Flags);
158    --  Initialize Data
159
160    procedure Free (Data : in out Tree_Processing_Data);
161    --  Free the memory occupied by Data
162
163    procedure Check
164      (Project     : Project_Id;
165       Data        : in out Tree_Processing_Data);
166    --  Process the naming scheme for a single project
167
168    procedure Initialize
169      (Data    : in out Project_Processing_Data;
170       Project : Project_Id);
171    procedure Free (Data : in out Project_Processing_Data);
172    --  Initialize or free memory for a project-specific data
173
174    procedure Find_Excluded_Sources
175      (Project : in out Project_Processing_Data;
176       Data    : in out Tree_Processing_Data);
177    --  Find the list of files that should not be considered as source files
178    --  for this project. Sets the list in the Project.Excluded_Sources_Htable.
179
180    procedure Override_Kind (Source : Source_Id; Kind : Source_Kind);
181    --  Override the reference kind for a source file. This properly updates
182    --  the unit data if necessary.
183
184    procedure Load_Naming_Exceptions
185      (Project : in out Project_Processing_Data;
186       Data    : in out Tree_Processing_Data);
187    --  All source files in Data.First_Source are considered as naming
188    --  exceptions, and copied into the Source_Names and Unit_Exceptions tables
189    --  as appropriate.
190
191    procedure Add_Source
192      (Id                  : out Source_Id;
193       Data                : in out Tree_Processing_Data;
194       Project             : Project_Id;
195       Source_Dir_Rank     : Natural;
196       Lang_Id             : Language_Ptr;
197       Kind                : Source_Kind;
198       File_Name           : File_Name_Type;
199       Display_File        : File_Name_Type;
200       Naming_Exception    : Boolean          := False;
201       Path                : Path_Information := No_Path_Information;
202       Alternate_Languages : Language_List    := null;
203       Unit                : Name_Id          := No_Name;
204       Index               : Int              := 0;
205       Locally_Removed     : Boolean          := False;
206       Location            : Source_Ptr       := No_Location);
207    --  Add a new source to the different lists: list of all sources in the
208    --  project tree, list of source of a project and list of sources of a
209    --  language.
210    --
211    --  If Path is specified, the file is also added to Source_Paths_HT.
212    --
213    --  Location is used for error messages
214
215    function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type;
216    --  Same as Osint.Canonical_Case_File_Name but applies to Name_Id.
217    --  This alters Name_Buffer
218
219    function Suffix_Matches
220      (Filename : String;
221       Suffix   : File_Name_Type) return Boolean;
222    --  True if the file name ends with the given suffix. Always returns False
223    --  if Suffix is No_Name.
224
225    procedure Replace_Into_Name_Buffer
226      (Str         : String;
227       Pattern     : String;
228       Replacement : Character);
229    --  Copy Str into Name_Buffer, replacing Pattern with Replacement. Str is
230    --  converted to lower-case at the same time.
231
232    procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
233    --  Check that a name is a valid Ada unit name
234
235    procedure Check_Package_Naming
236      (Project : Project_Id;
237       Data    : in out Tree_Processing_Data;
238       Bodies  : out Array_Element_Id;
239       Specs   : out Array_Element_Id);
240    --  Check the naming scheme part of Data, and initialize the naming scheme
241    --  data in the config of the various languages. This also returns the
242    --  naming scheme exceptions for unit-based languages (Bodies and Specs are
243    --  associative arrays mapping individual unit names to source file names).
244
245    procedure Check_Configuration
246      (Project : Project_Id;
247       Data    : in out Tree_Processing_Data);
248    --  Check the configuration attributes for the project
249
250    procedure Check_If_Externally_Built
251      (Project : Project_Id;
252       Data    : in out Tree_Processing_Data);
253    --  Check attribute Externally_Built of project Project in project tree
254    --  Data.Tree and modify its data Data if it has the value "true".
255
256    procedure Check_Interfaces
257      (Project : Project_Id;
258       Data    : in out Tree_Processing_Data);
259    --  If a list of sources is specified in attribute Interfaces, set
260    --  In_Interfaces only for the sources specified in the list.
261
262    procedure Check_Library_Attributes
263      (Project : Project_Id;
264       Data    : in out Tree_Processing_Data);
265    --  Check the library attributes of project Project in project tree
266    --  and modify its data Data accordingly.
267
268    procedure Check_Programming_Languages
269      (Project : Project_Id;
270       Data    : in out Tree_Processing_Data);
271    --  Check attribute Languages for the project with data Data in project
272    --  tree Data.Tree and set the components of Data for all the programming
273    --  languages indicated in attribute Languages, if any.
274
275    procedure Check_Stand_Alone_Library
276      (Project : Project_Id;
277       Data    : in out Tree_Processing_Data);
278    --  Check if project Project in project tree Data.Tree is a Stand-Alone
279    --  Library project, and modify its data Data accordingly if it is one.
280
281    function Compute_Directory_Last (Dir : String) return Natural;
282    --  Return the index of the last significant character in Dir. This is used
283    --  to avoid duplicate '/' (slash) characters at the end of directory names.
284
285    procedure Search_Directories
286      (Project         : in out Project_Processing_Data;
287       Data            : in out Tree_Processing_Data;
288       For_All_Sources : Boolean);
289    --  Search the source directories to find the sources. If For_All_Sources is
290    --  True, check each regular file name against the naming schemes of the
291    --  various languages. Otherwise consider only the file names in hash table
292    --  Source_Names. If Allow_Duplicate_Basenames then files with identical
293    --  base names are permitted within a project for source-based languages
294    --  (never for unit based languages).
295
296    procedure Check_File
297      (Project           : in out Project_Processing_Data;
298       Data              : in out Tree_Processing_Data;
299       Source_Dir_Rank   : Natural;
300       Path              : Path_Name_Type;
301       File_Name         : File_Name_Type;
302       Display_File_Name : File_Name_Type;
303       Locally_Removed   : Boolean;
304       For_All_Sources   : Boolean);
305    --  Check if file File_Name is a valid source of the project. This is used
306    --  in multi-language mode only. When the file matches one of the naming
307    --  schemes, it is added to various htables through Add_Source and to
308    --  Source_Paths_Htable.
309    --
310    --  Name is the name of the candidate file. It hasn't been normalized yet
311    --  and is the direct result of readdir().
312    --
313    --  File_Name is the same as Name, but has been normalized.
314    --  Display_File_Name, however, has not been normalized.
315    --
316    --  Source_Directory is the directory in which the file was found. It is
317    --  neither normalized nor has had links resolved, and must not end with a
318    --  a directory separator, to avoid duplicates later on.
319    --
320    --  If For_All_Sources is True, then all possible file names are analyzed
321    --  otherwise only those currently set in the Source_Names hash table.
322
323    procedure Check_File_Naming_Schemes
324      (In_Tree               : Project_Tree_Ref;
325       Project               : Project_Processing_Data;
326       File_Name             : File_Name_Type;
327       Alternate_Languages   : out Language_List;
328       Language              : out Language_Ptr;
329       Display_Language_Name : out Name_Id;
330       Unit                  : out Name_Id;
331       Lang_Kind             : out Language_Kind;
332       Kind                  : out Source_Kind);
333    --  Check if the file name File_Name conforms to one of the naming schemes
334    --  of the project. If the file does not match one of the naming schemes,
335    --  set Language to No_Language_Index. Filename is the name of the file
336    --  being investigated. It has been normalized (case-folded). File_Name is
337    --  the same value.
338
339    procedure Get_Directories
340      (Project     : Project_Id;
341       Data        : in out Tree_Processing_Data);
342    --  Get the object directory, the exec directory and the source directories
343    --  of a project.
344
345    procedure Get_Mains
346      (Project : Project_Id;
347       Data    : in out Tree_Processing_Data);
348    --  Get the mains of a project from attribute Main, if it exists, and put
349    --  them in the project data.
350
351    procedure Get_Sources_From_File
352      (Path     : String;
353       Location : Source_Ptr;
354       Project  : in out Project_Processing_Data;
355       Data     : in out Tree_Processing_Data);
356    --  Get the list of sources from a text file and put them in hash table
357    --  Source_Names.
358
359    procedure Find_Sources
360      (Project : in out Project_Processing_Data;
361       Data    : in out Tree_Processing_Data);
362    --  Process the Source_Files and Source_List_File attributes, and store the
363    --  list of source files into the Source_Names htable. When these attributes
364    --  are not defined, find all files matching the naming schemes in the
365    --  source directories. If Allow_Duplicate_Basenames, then files with the
366    --  same base names are authorized within a project for source-based
367    --  languages (never for unit based languages)
368
369    procedure Compute_Unit_Name
370      (File_Name : File_Name_Type;
371       Naming    : Lang_Naming_Data;
372       Kind      : out Source_Kind;
373       Unit      : out Name_Id;
374       Project   : Project_Processing_Data;
375       In_Tree   : Project_Tree_Ref);
376    --  Check whether the file matches the naming scheme. If it does,
377    --  compute its unit name. If Unit is set to No_Name on exit, none of the
378    --  other out parameters are relevant.
379
380    procedure Check_Illegal_Suffix
381      (Project         : Project_Id;
382       Suffix          : File_Name_Type;
383       Dot_Replacement : File_Name_Type;
384       Attribute_Name  : String;
385       Location        : Source_Ptr;
386       Data            : in out Tree_Processing_Data);
387    --  Display an error message if the given suffix is illegal for some reason.
388    --  The name of the attribute we are testing is specified in Attribute_Name,
389    --  which is used in the error message. Location is the location where the
390    --  suffix is defined.
391
392    procedure Locate_Directory
393      (Project          : Project_Id;
394       Name             : File_Name_Type;
395       Path             : out Path_Information;
396       Dir_Exists       : out Boolean;
397       Data             : in out Tree_Processing_Data;
398       Create           : String := "";
399       Location         : Source_Ptr := No_Location;
400       Must_Exist       : Boolean := True;
401       Externally_Built : Boolean := False);
402    --  Locate a directory. Name is the directory name. Relative paths are
403    --  resolved relative to the project's directory. If the directory does not
404    --  exist and Setup_Projects is True and Create is a non null string, an
405    --  attempt is made to create the directory. If the directory does not
406    --  exist, it is either created if Setup_Projects is False (and then
407    --  returned), or simply returned without checking for its existence (if
408    --  Must_Exist is False) or No_Path_Information is returned. In all cases,
409    --  Dir_Exists indicates whether the directory now exists. Create is also
410    --  used for debugging traces to show which path we are computing.
411
412    procedure Look_For_Sources
413      (Project : in out Project_Processing_Data;
414       Data    : in out Tree_Processing_Data);
415    --  Find all the sources of project Project in project tree Data.Tree and
416    --  update its Data accordingly. This assumes that Data.First_Source has
417    --  been initialized with the list of excluded sources and special naming
418    --  exceptions.
419
420    function Path_Name_Of
421      (File_Name : File_Name_Type;
422       Directory : Path_Name_Type) return String;
423    --  Returns the path name of a (non project) file. Returns an empty string
424    --  if file cannot be found.
425
426    procedure Remove_Source
427      (Id          : Source_Id;
428       Replaced_By : Source_Id);
429    --  Remove a file from the list of sources of a project. This might be
430    --  because the file is replaced by another one in an extending project,
431    --  or because a file was added as a naming exception but was not found
432    --  in the end.
433
434    procedure Report_No_Sources
435      (Project      : Project_Id;
436       Lang_Name    : String;
437       Data         : Tree_Processing_Data;
438       Location     : Source_Ptr;
439       Continuation : Boolean := False);
440    --  Report an error or a warning depending on the value of When_No_Sources
441    --  when there are no sources for language Lang_Name.
442
443    procedure Show_Source_Dirs
444      (Project : Project_Id; In_Tree : Project_Tree_Ref);
445    --  List all the source directories of a project
446
447    procedure Write_Attr (Name, Value : String);
448    --  Debug print a value for a specific property. Does nothing when not in
449    --  debug mode
450
451    ------------------------------
452    -- Replace_Into_Name_Buffer --
453    ------------------------------
454
455    procedure Replace_Into_Name_Buffer
456      (Str         : String;
457       Pattern     : String;
458       Replacement : Character)
459    is
460       Max : constant Integer := Str'Last - Pattern'Length + 1;
461       J   : Positive;
462
463    begin
464       Name_Len := 0;
465
466       J := Str'First;
467       while J <= Str'Last loop
468          Name_Len := Name_Len + 1;
469
470          if J <= Max
471            and then Str (J .. J + Pattern'Length - 1) = Pattern
472          then
473             Name_Buffer (Name_Len) := Replacement;
474             J := J + Pattern'Length;
475
476          else
477             Name_Buffer (Name_Len) := GNAT.Case_Util.To_Lower (Str (J));
478             J := J + 1;
479          end if;
480       end loop;
481    end Replace_Into_Name_Buffer;
482
483    --------------------
484    -- Suffix_Matches --
485    --------------------
486
487    function Suffix_Matches
488      (Filename : String;
489       Suffix   : File_Name_Type) return Boolean
490    is
491       Min_Prefix_Length : Natural := 0;
492
493    begin
494       if Suffix = No_File or else Suffix = Empty_File then
495          return False;
496       end if;
497
498       declare
499          Suf : String := Get_Name_String (Suffix);
500
501       begin
502          --  On non case-sensitive systems, use proper suffix casing
503
504          Canonical_Case_File_Name (Suf);
505
506          --  The file name must end with the suffix (which is not an extension)
507          --  For instance a suffix "configure.in" must match a file with the
508          --  same name. To avoid dummy cases, though, a suffix starting with
509          --  '.' requires a file that is at least one character longer ('.cpp'
510          --  should not match a file with the same name)
511
512          if Suf (Suf'First) = '.' then
513             Min_Prefix_Length := 1;
514          end if;
515
516          return Filename'Length >= Suf'Length + Min_Prefix_Length
517            and then Filename
518              (Filename'Last - Suf'Length + 1 .. Filename'Last) = Suf;
519       end;
520    end Suffix_Matches;
521
522    ----------------
523    -- Write_Attr --
524    ----------------
525
526    procedure Write_Attr (Name, Value : String) is
527    begin
528       if Current_Verbosity = High then
529          Write_Str  ("  " & Name & " = """);
530          Write_Str  (Value);
531          Write_Char ('"');
532          Write_Eol;
533       end if;
534    end Write_Attr;
535
536    ----------------
537    -- Add_Source --
538    ----------------
539
540    procedure Add_Source
541      (Id                  : out Source_Id;
542       Data                : in out Tree_Processing_Data;
543       Project             : Project_Id;
544       Source_Dir_Rank     : Natural;
545       Lang_Id             : Language_Ptr;
546       Kind                : Source_Kind;
547       File_Name           : File_Name_Type;
548       Display_File        : File_Name_Type;
549       Naming_Exception    : Boolean          := False;
550       Path                : Path_Information := No_Path_Information;
551       Alternate_Languages : Language_List    := null;
552       Unit                : Name_Id          := No_Name;
553       Index               : Int              := 0;
554       Locally_Removed     : Boolean          := False;
555       Location            : Source_Ptr       := No_Location)
556    is
557       Config    : constant Language_Config := Lang_Id.Config;
558       UData     : Unit_Index;
559       Add_Src   : Boolean;
560       Source    : Source_Id;
561       Prev_Unit : Unit_Index := No_Unit_Index;
562
563       Source_To_Replace : Source_Id := No_Source;
564
565    begin
566       --  Check if the same file name or unit is used in the prj tree
567
568       Add_Src := True;
569
570       if Unit /= No_Name then
571          Prev_Unit := Units_Htable.Get (Data.Tree.Units_HT, Unit);
572       end if;
573
574       if Prev_Unit /= No_Unit_Index
575         and then (Kind = Impl or else Kind = Spec)
576         and then Prev_Unit.File_Names (Kind) /= null
577       then
578          --  Suspicious, we need to check later whether this is authorized
579
580          Add_Src := False;
581          Source := Prev_Unit.File_Names (Kind);
582
583       else
584          Source  := Files_Htable.Get (Data.File_To_Source, File_Name);
585
586          if Source /= No_Source
587            and then Source.Index = Index
588          then
589             Add_Src := False;
590          end if;
591       end if;
592
593       --  Duplication of file/unit in same project is allowed if order of
594       --  source directories is known.
595
596       if Add_Src = False then
597          Add_Src := True;
598
599          if Project = Source.Project then
600             if Prev_Unit = No_Unit_Index then
601                if Data.Flags.Allow_Duplicate_Basenames then
602                   Add_Src := True;
603
604                elsif Source_Dir_Rank /= Source.Source_Dir_Rank then
605                   Add_Src := False;
606
607                else
608                   Error_Msg_File_1 := File_Name;
609                   Error_Msg
610                     (Data.Flags, "duplicate source file name {",
611                      Location, Project);
612                   Add_Src := False;
613                end if;
614
615             else
616                if Source_Dir_Rank /= Source.Source_Dir_Rank then
617                   Add_Src := False;
618
619                --  We might be seeing the same file through a different path
620                --  (for instance because of symbolic links).
621
622                elsif Source.Path.Name /= Path.Name then
623                   Error_Msg_Name_1 := Unit;
624                   Error_Msg
625                     (Data.Flags, "duplicate unit %%", Location, Project);
626                   Add_Src := False;
627                end if;
628             end if;
629
630             --  Do not allow the same unit name in different projects, except
631             --  if one is extending the other.
632
633             --  For a file based language, the same file name replaces a file
634             --  in a project being extended, but it is allowed to have the same
635             --  file name in unrelated projects.
636
637          elsif Is_Extending (Project, Source.Project) then
638             if not Locally_Removed then
639                Source_To_Replace := Source;
640             end if;
641
642          elsif Prev_Unit /= No_Unit_Index
643            and then not Source.Locally_Removed
644          then
645             --  Path is set if this is a source we found on the disk, in which
646             --  case we can provide more explicit error message. Path is unset
647             --  when the source is added from one of the naming exceptions in
648             --  the project.
649
650             if Path /= No_Path_Information then
651                Error_Msg_Name_1 := Unit;
652                Error_Msg
653                  (Data.Flags,
654                   "unit %% cannot belong to several projects",
655                   Location, Project);
656
657                Error_Msg_Name_1 := Project.Name;
658                Error_Msg_Name_2 := Name_Id (Path.Name);
659                Error_Msg
660                  (Data.Flags, "\  project %%, %%", Location, Project);
661
662                Error_Msg_Name_1 := Source.Project.Name;
663                Error_Msg_Name_2 := Name_Id (Source.Path.Display_Name);
664                Error_Msg
665                  (Data.Flags, "\  project %%, %%", Location, Project);
666
667             else
668                Error_Msg_Name_1 := Unit;
669                Error_Msg_Name_2 := Source.Project.Name;
670                Error_Msg
671                  (Data.Flags, "unit %% already belongs to project %%",
672                   Location, Project);
673             end if;
674
675             Add_Src := False;
676
677          elsif not Source.Locally_Removed
678            and then not Data.Flags.Allow_Duplicate_Basenames
679            and then Lang_Id.Config.Kind = Unit_Based
680          then
681             Error_Msg_File_1 := File_Name;
682             Error_Msg_File_2 := File_Name_Type (Source.Project.Name);
683             Error_Msg
684               (Data.Flags,
685                "{ is already a source of project {", Location, Project);
686
687             --  Add the file anyway, to avoid further warnings like "language
688             --  unknown".
689
690             Add_Src := True;
691          end if;
692       end if;
693
694       if not Add_Src then
695          return;
696       end if;
697
698       --  Add the new file
699
700       Id := new Source_Data;
701
702       if Current_Verbosity = High then
703          Write_Str ("Adding source File: ");
704          Write_Str (Get_Name_String (File_Name));
705
706          if Index /= 0 then
707             Write_Str (" at" & Index'Img);
708          end if;
709
710          if Lang_Id.Config.Kind = Unit_Based then
711             Write_Str (" Unit: ");
712
713             --  ??? in gprclean, it seems we sometimes pass an empty Unit name
714             --  (see test extended_projects).
715
716             if Unit /= No_Name then
717                Write_Str (Get_Name_String (Unit));
718             end if;
719
720             Write_Str (" Kind: ");
721             Write_Str (Source_Kind'Image (Kind));
722          end if;
723
724          Write_Eol;
725       end if;
726
727       Id.Project             := Project;
728       Id.Source_Dir_Rank     := Source_Dir_Rank;
729       Id.Language            := Lang_Id;
730       Id.Kind                := Kind;
731       Id.Alternate_Languages := Alternate_Languages;
732       Id.Locally_Removed     := Locally_Removed;
733       Id.Index               := Index;
734       Id.File                := File_Name;
735       Id.Display_File        := Display_File;
736       Id.Dep_Name            := Dependency_Name
737                                   (File_Name, Lang_Id.Config.Dependency_Kind);
738       Id.Naming_Exception    := Naming_Exception;
739
740       --  Add the source id to the Unit_Sources_HT hash table, if the unit name
741       --  is not null.
742
743       if Unit /= No_Name then
744
745          --  Note: we might be creating a dummy unit here, when we in fact have
746          --  a separate. For instance, file file-bar.adb will initially be
747          --  assumed to be the IMPL of unit "file.bar". Only later on (in
748          --  Check_Object_Files) will we parse those units that only have an
749          --  impl and no spec to make sure whether we have a Separate in fact
750          --  (that significantly reduces the number of times we need to parse
751          --  the files, since we are then only interested in those with no
752          --  spec). We still need those dummy units in the table, since that's
753          --  the name we find in the ALI file
754
755          UData := Units_Htable.Get (Data.Tree.Units_HT, Unit);
756
757          if UData = No_Unit_Index then
758             UData := new Unit_Data;
759             UData.Name := Unit;
760             Units_Htable.Set (Data.Tree.Units_HT, Unit, UData);
761          end if;
762
763          Id.Unit := UData;
764
765          --  Note that this updates Unit information as well
766
767          Override_Kind (Id, Kind);
768       end if;
769
770       if Is_Compilable (Id) and then Config.Object_Generated then
771          Id.Object   := Object_Name (File_Name, Config.Object_File_Suffix);
772          Id.Switches := Switches_Name (File_Name);
773       end if;
774
775       if Path /= No_Path_Information then
776          Id.Path := Path;
777          Source_Paths_Htable.Set (Data.Tree.Source_Paths_HT, Path.Name, Id);
778       end if;
779
780       --  Add the source to the language list
781
782       Id.Next_In_Lang := Lang_Id.First_Source;
783       Lang_Id.First_Source := Id;
784
785       if Source_To_Replace /= No_Source then
786          Remove_Source (Source_To_Replace, Id);
787       end if;
788
789       Files_Htable.Set (Data.File_To_Source, File_Name, Id);
790    end Add_Source;
791
792    ------------------------------
793    -- Canonical_Case_File_Name --
794    ------------------------------
795
796    function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type is
797    begin
798       if Osint.File_Names_Case_Sensitive then
799          return File_Name_Type (Name);
800       else
801          Get_Name_String (Name);
802          Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
803          return Name_Find;
804       end if;
805    end Canonical_Case_File_Name;
806
807    -----------
808    -- Check --
809    -----------
810
811    procedure Check
812      (Project     : Project_Id;
813       Data        : in out Tree_Processing_Data)
814    is
815       Specs     : Array_Element_Id;
816       Bodies    : Array_Element_Id;
817       Extending : Boolean := False;
818       Prj_Data  : Project_Processing_Data;
819
820    begin
821       Initialize (Prj_Data, Project);
822
823       Check_If_Externally_Built (Project, Data);
824
825       --  Object, exec and source directories
826
827       Get_Directories (Project, Data);
828
829       --  Get the programming languages
830
831       Check_Programming_Languages (Project, Data);
832
833       if Project.Qualifier = Dry
834         and then Project.Source_Dirs /= Nil_String
835       then
836          declare
837             Source_Dirs      : constant Variable_Value :=
838                                  Util.Value_Of
839                                    (Name_Source_Dirs,
840                                     Project.Decl.Attributes, Data.Tree);
841             Source_Files     : constant Variable_Value :=
842                                  Util.Value_Of
843                                    (Name_Source_Files,
844                                     Project.Decl.Attributes, Data.Tree);
845             Source_List_File : constant Variable_Value :=
846                                  Util.Value_Of
847                                    (Name_Source_List_File,
848                                     Project.Decl.Attributes, Data.Tree);
849             Languages        : constant Variable_Value :=
850                                  Util.Value_Of
851                                    (Name_Languages,
852                                     Project.Decl.Attributes, Data.Tree);
853
854          begin
855             if Source_Dirs.Values  = Nil_String
856               and then Source_Files.Values = Nil_String
857               and then Languages.Values = Nil_String
858               and then Source_List_File.Default
859             then
860                Project.Source_Dirs := Nil_String;
861
862             else
863                Error_Msg
864                  (Data.Flags,
865                   "at least one of Source_Files, Source_Dirs or Languages "
866                     & "must be declared empty for an abstract project",
867                   Project.Location, Project);
868             end if;
869          end;
870       end if;
871
872       --  Check configuration. This must be done even for gnatmake (even though
873       --  no user configuration file was provided) since the default config we
874       --  generate indicates whether libraries are supported for instance.
875
876       Check_Configuration (Project, Data);
877
878       --  Library attributes
879
880       Check_Library_Attributes (Project, Data);
881
882       if Current_Verbosity = High then
883          Show_Source_Dirs (Project, Data.Tree);
884       end if;
885
886       Extending := Project.Extends /= No_Project;
887
888       Check_Package_Naming (Project, Data, Bodies => Bodies, Specs => Specs);
889
890       --  Find the sources
891
892       if Project.Source_Dirs /= Nil_String then
893          Look_For_Sources (Prj_Data, Data);
894
895          if not Project.Externally_Built
896            and then not Extending
897          then
898             declare
899                Language     : Language_Ptr;
900                Source       : Source_Id;
901                Alt_Lang     : Language_List;
902                Continuation : Boolean := False;
903                Iter         : Source_Iterator;
904
905             begin
906                Language := Project.Languages;
907                while Language /= No_Language_Index loop
908
909                   --  If there are no sources for this language, check if there
910                   --  are sources for which this is an alternate language.
911
912                   if Language.First_Source = No_Source
913                     and then (Data.Flags.Require_Sources_Other_Lang
914                                or else Language.Name = Name_Ada)
915                   then
916                      Iter := For_Each_Source (In_Tree => Data.Tree,
917                                               Project => Project);
918                      Source_Loop : loop
919                         Source := Element (Iter);
920                         exit Source_Loop when Source = No_Source
921                           or else Source.Language = Language;
922
923                         Alt_Lang := Source.Alternate_Languages;
924                         while Alt_Lang /= null loop
925                            exit Source_Loop when Alt_Lang.Language = Language;
926                            Alt_Lang := Alt_Lang.Next;
927                         end loop;
928
929                         Next (Iter);
930                      end loop Source_Loop;
931
932                      if Source = No_Source then
933
934                         Report_No_Sources
935                           (Project,
936                            Get_Name_String (Language.Display_Name),
937                            Data,
938                            Prj_Data.Source_List_File_Location,
939                            Continuation);
940                         Continuation := True;
941                      end if;
942                   end if;
943
944                   Language := Language.Next;
945                end loop;
946             end;
947          end if;
948       end if;
949
950       --  If a list of sources is specified in attribute Interfaces, set
951       --  In_Interfaces only for the sources specified in the list.
952
953       Check_Interfaces (Project, Data);
954
955       --  If it is a library project file, check if it is a standalone library
956
957       if Project.Library then
958          Check_Stand_Alone_Library (Project, Data);
959       end if;
960
961       --  Put the list of Mains, if any, in the project data
962
963       Get_Mains (Project, Data);
964
965       Free (Prj_Data);
966    end Check;
967
968    --------------------
969    -- Check_Ada_Name --
970    --------------------
971
972    procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
973       The_Name        : String := Name;
974       Real_Name       : Name_Id;
975       Need_Letter     : Boolean := True;
976       Last_Underscore : Boolean := False;
977       OK              : Boolean := The_Name'Length > 0;
978       First           : Positive;
979
980       function Is_Reserved (Name : Name_Id) return Boolean;
981       function Is_Reserved (S    : String)  return Boolean;
982       --  Check that the given name is not an Ada 95 reserved word. The reason
983       --  for the Ada 95 here is that we do not want to exclude the case of an
984       --  Ada 95 unit called Interface (for example). In Ada 2005, such a unit
985       --  name would be rejected anyway by the compiler. That means there is no
986       --  requirement that the project file parser reject this.
987
988       -----------------
989       -- Is_Reserved --
990       -----------------
991
992       function Is_Reserved (S : String) return Boolean is
993       begin
994          Name_Len := 0;
995          Add_Str_To_Name_Buffer (S);
996          return Is_Reserved (Name_Find);
997       end Is_Reserved;
998
999       -----------------
1000       -- Is_Reserved --
1001       -----------------
1002
1003       function Is_Reserved (Name : Name_Id) return Boolean is
1004       begin
1005          if Get_Name_Table_Byte (Name) /= 0
1006            and then Name /= Name_Project
1007            and then Name /= Name_Extends
1008            and then Name /= Name_External
1009            and then Name not in Ada_2005_Reserved_Words
1010          then
1011             Unit := No_Name;
1012
1013             if Current_Verbosity = High then
1014                Write_Str (The_Name);
1015                Write_Line (" is an Ada reserved word.");
1016             end if;
1017
1018             return True;
1019
1020          else
1021             return False;
1022          end if;
1023       end Is_Reserved;
1024
1025    --  Start of processing for Check_Ada_Name
1026
1027    begin
1028       To_Lower (The_Name);
1029
1030       Name_Len := The_Name'Length;
1031       Name_Buffer (1 .. Name_Len) := The_Name;
1032
1033       --  Special cases of children of packages A, G, I and S on VMS
1034
1035       if OpenVMS_On_Target
1036         and then Name_Len > 3
1037         and then Name_Buffer (2 .. 3) = "__"
1038         and then
1039           ((Name_Buffer (1) = 'a') or else
1040            (Name_Buffer (1) = 'g') or else
1041            (Name_Buffer (1) = 'i') or else
1042            (Name_Buffer (1) = 's'))
1043       then
1044          Name_Buffer (2) := '.';
1045          Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
1046          Name_Len := Name_Len - 1;
1047       end if;
1048
1049       Real_Name := Name_Find;
1050
1051       if Is_Reserved (Real_Name) then
1052          return;
1053       end if;
1054
1055       First := The_Name'First;
1056
1057       for Index in The_Name'Range loop
1058          if Need_Letter then
1059
1060             --  We need a letter (at the beginning, and following a dot),
1061             --  but we don't have one.
1062
1063             if Is_Letter (The_Name (Index)) then
1064                Need_Letter := False;
1065
1066             else
1067                OK := False;
1068
1069                if Current_Verbosity = High then
1070                   Write_Int  (Types.Int (Index));
1071                   Write_Str  (": '");
1072                   Write_Char (The_Name (Index));
1073                   Write_Line ("' is not a letter.");
1074                end if;
1075
1076                exit;
1077             end if;
1078
1079          elsif Last_Underscore
1080            and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
1081          then
1082             --  Two underscores are illegal, and a dot cannot follow
1083             --  an underscore.
1084
1085             OK := False;
1086
1087             if Current_Verbosity = High then
1088                Write_Int  (Types.Int (Index));
1089                Write_Str  (": '");
1090                Write_Char (The_Name (Index));
1091                Write_Line ("' is illegal here.");
1092             end if;
1093
1094             exit;
1095
1096          elsif The_Name (Index) = '.' then
1097
1098             --  First, check if the name before the dot is not a reserved word
1099
1100             if Is_Reserved (The_Name (First .. Index - 1)) then
1101                return;
1102             end if;
1103
1104             First := Index + 1;
1105
1106             --  We need a letter after a dot
1107
1108             Need_Letter := True;
1109
1110          elsif The_Name (Index) = '_' then
1111             Last_Underscore := True;
1112
1113          else
1114             --  We need an letter or a digit
1115
1116             Last_Underscore := False;
1117
1118             if not Is_Alphanumeric (The_Name (Index)) then
1119                OK := False;
1120
1121                if Current_Verbosity = High then
1122                   Write_Int  (Types.Int (Index));
1123                   Write_Str  (": '");
1124                   Write_Char (The_Name (Index));
1125                   Write_Line ("' is not alphanumeric.");
1126                end if;
1127
1128                exit;
1129             end if;
1130          end if;
1131       end loop;
1132
1133       --  Cannot end with an underscore or a dot
1134
1135       OK := OK and then not Need_Letter and then not Last_Underscore;
1136
1137       if OK then
1138          if First /= Name'First and then
1139            Is_Reserved (The_Name (First .. The_Name'Last))
1140          then
1141             return;
1142          end if;
1143
1144          Unit := Real_Name;
1145
1146       else
1147          --  Signal a problem with No_Name
1148
1149          Unit := No_Name;
1150       end if;
1151    end Check_Ada_Name;
1152
1153    -------------------------
1154    -- Check_Configuration --
1155    -------------------------
1156
1157    procedure Check_Configuration
1158      (Project : Project_Id;
1159       Data    : in out Tree_Processing_Data)
1160    is
1161       Dot_Replacement : File_Name_Type := No_File;
1162       Casing          : Casing_Type    := All_Lower_Case;
1163       Separate_Suffix : File_Name_Type := No_File;
1164
1165       Lang_Index : Language_Ptr := No_Language_Index;
1166       --  The index of the language data being checked
1167
1168       Prev_Index : Language_Ptr := No_Language_Index;
1169       --  The index of the previous language
1170
1171       procedure Process_Project_Level_Simple_Attributes;
1172       --  Process the simple attributes at the project level
1173
1174       procedure Process_Project_Level_Array_Attributes;
1175       --  Process the associate array attributes at the project level
1176
1177       procedure Process_Packages;
1178       --  Read the packages of the project
1179
1180       ----------------------
1181       -- Process_Packages --
1182       ----------------------
1183
1184       procedure Process_Packages is
1185          Packages : Package_Id;
1186          Element  : Package_Element;
1187
1188          procedure Process_Binder (Arrays : Array_Id);
1189          --  Process the associate array attributes of package Binder
1190
1191          procedure Process_Builder (Attributes : Variable_Id);
1192          --  Process the simple attributes of package Builder
1193
1194          procedure Process_Compiler (Arrays : Array_Id);
1195          --  Process the associate array attributes of package Compiler
1196
1197          procedure Process_Naming (Attributes : Variable_Id);
1198          --  Process the simple attributes of package Naming
1199
1200          procedure Process_Naming (Arrays : Array_Id);
1201          --  Process the associate array attributes of package Naming
1202
1203          procedure Process_Linker (Attributes : Variable_Id);
1204          --  Process the simple attributes of package Linker of a
1205          --  configuration project.
1206
1207          --------------------
1208          -- Process_Binder --
1209          --------------------
1210
1211          procedure Process_Binder (Arrays : Array_Id) is
1212             Current_Array_Id : Array_Id;
1213             Current_Array    : Array_Data;
1214             Element_Id       : Array_Element_Id;
1215             Element          : Array_Element;
1216
1217          begin
1218             --  Process the associative array attribute of package Binder
1219
1220             Current_Array_Id := Arrays;
1221             while Current_Array_Id /= No_Array loop
1222                Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
1223
1224                Element_Id := Current_Array.Value;
1225                while Element_Id /= No_Array_Element loop
1226                   Element := Data.Tree.Array_Elements.Table (Element_Id);
1227
1228                   if Element.Index /= All_Other_Names then
1229
1230                      --  Get the name of the language
1231
1232                      Lang_Index :=
1233                        Get_Language_From_Name
1234                          (Project, Get_Name_String (Element.Index));
1235
1236                      if Lang_Index /= No_Language_Index then
1237                         case Current_Array.Name is
1238                            when Name_Driver =>
1239
1240                               --  Attribute Driver (<language>)
1241
1242                               Lang_Index.Config.Binder_Driver :=
1243                                 File_Name_Type (Element.Value.Value);
1244
1245                            when Name_Required_Switches =>
1246                               Put
1247                                 (Into_List =>
1248                                    Lang_Index.Config.Binder_Required_Switches,
1249                                  From_List => Element.Value.Values,
1250                                  In_Tree   => Data.Tree);
1251
1252                            when Name_Prefix =>
1253
1254                               --  Attribute Prefix (<language>)
1255
1256                               Lang_Index.Config.Binder_Prefix :=
1257                                 Element.Value.Value;
1258
1259                            when Name_Objects_Path =>
1260
1261                               --  Attribute Objects_Path (<language>)
1262
1263                               Lang_Index.Config.Objects_Path :=
1264                                 Element.Value.Value;
1265
1266                            when Name_Objects_Path_File =>
1267
1268                               --  Attribute Objects_Path (<language>)
1269
1270                               Lang_Index.Config.Objects_Path_File :=
1271                                 Element.Value.Value;
1272
1273                            when others =>
1274                               null;
1275                         end case;
1276                      end if;
1277                   end if;
1278
1279                   Element_Id := Element.Next;
1280                end loop;
1281
1282                Current_Array_Id := Current_Array.Next;
1283             end loop;
1284          end Process_Binder;
1285
1286          ---------------------
1287          -- Process_Builder --
1288          ---------------------
1289
1290          procedure Process_Builder (Attributes : Variable_Id) is
1291             Attribute_Id : Variable_Id;
1292             Attribute    : Variable;
1293
1294          begin
1295             --  Process non associated array attribute from package Builder
1296
1297             Attribute_Id := Attributes;
1298             while Attribute_Id /= No_Variable loop
1299                Attribute :=
1300                  Data.Tree.Variable_Elements.Table (Attribute_Id);
1301
1302                if not Attribute.Value.Default then
1303                   if Attribute.Name = Name_Executable_Suffix then
1304
1305                      --  Attribute Executable_Suffix: the suffix of the
1306                      --  executables.
1307
1308                      Project.Config.Executable_Suffix :=
1309                        Attribute.Value.Value;
1310                   end if;
1311                end if;
1312
1313                Attribute_Id := Attribute.Next;
1314             end loop;
1315          end Process_Builder;
1316
1317          ----------------------
1318          -- Process_Compiler --
1319          ----------------------
1320
1321          procedure Process_Compiler (Arrays : Array_Id) is
1322             Current_Array_Id : Array_Id;
1323             Current_Array    : Array_Data;
1324             Element_Id       : Array_Element_Id;
1325             Element          : Array_Element;
1326             List             : String_List_Id;
1327
1328          begin
1329             --  Process the associative array attribute of package Compiler
1330
1331             Current_Array_Id := Arrays;
1332             while Current_Array_Id /= No_Array loop
1333                Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
1334
1335                Element_Id := Current_Array.Value;
1336                while Element_Id /= No_Array_Element loop
1337                   Element := Data.Tree.Array_Elements.Table (Element_Id);
1338
1339                   if Element.Index /= All_Other_Names then
1340
1341                      --  Get the name of the language
1342
1343                      Lang_Index := Get_Language_From_Name
1344                        (Project, Get_Name_String (Element.Index));
1345
1346                      if Lang_Index /= No_Language_Index then
1347                         case Current_Array.Name is
1348                         when Name_Dependency_Switches =>
1349
1350                            --  Attribute Dependency_Switches (<language>)
1351
1352                            if Lang_Index.Config.Dependency_Kind = None then
1353                               Lang_Index.Config.Dependency_Kind := Makefile;
1354                            end if;
1355
1356                            List := Element.Value.Values;
1357
1358                            if List /= Nil_String then
1359                               Put (Into_List =>
1360                                      Lang_Index.Config.Dependency_Option,
1361                                    From_List => List,
1362                                    In_Tree   => Data.Tree);
1363                            end if;
1364
1365                         when Name_Dependency_Driver =>
1366
1367                            --  Attribute Dependency_Driver (<language>)
1368
1369                            if Lang_Index.Config.Dependency_Kind = None then
1370                               Lang_Index.Config.Dependency_Kind := Makefile;
1371                            end if;
1372
1373                            List := Element.Value.Values;
1374
1375                            if List /= Nil_String then
1376                               Put (Into_List =>
1377                                      Lang_Index.Config.Compute_Dependency,
1378                                    From_List => List,
1379                                    In_Tree   => Data.Tree);
1380                            end if;
1381
1382                         when Name_Include_Switches =>
1383
1384                            --  Attribute Include_Switches (<language>)
1385
1386                            List := Element.Value.Values;
1387
1388                            if List = Nil_String then
1389                               Error_Msg
1390                                 (Data.Flags, "include option cannot be null",
1391                                  Element.Value.Location, Project);
1392                            end if;
1393
1394                            Put (Into_List => Lang_Index.Config.Include_Option,
1395                                 From_List => List,
1396                                 In_Tree   => Data.Tree);
1397
1398                         when Name_Include_Path =>
1399
1400                            --  Attribute Include_Path (<language>)
1401
1402                            Lang_Index.Config.Include_Path :=
1403                              Element.Value.Value;
1404
1405                         when Name_Include_Path_File =>
1406
1407                            --  Attribute Include_Path_File (<language>)
1408
1409                            Lang_Index.Config.Include_Path_File :=
1410                                Element.Value.Value;
1411
1412                         when Name_Driver =>
1413
1414                            --  Attribute Driver (<language>)
1415
1416                            Lang_Index.Config.Compiler_Driver :=
1417                              File_Name_Type (Element.Value.Value);
1418
1419                         when Name_Required_Switches |
1420                              Name_Leading_Required_Switches =>
1421                            Put (Into_List =>
1422                                   Lang_Index.Config.
1423                                     Compiler_Leading_Required_Switches,
1424                                 From_List => Element.Value.Values,
1425                                 In_Tree   => Data.Tree);
1426
1427                         when Name_Trailing_Required_Switches =>
1428                            Put (Into_List =>
1429                                   Lang_Index.Config.
1430                                     Compiler_Trailing_Required_Switches,
1431                                 From_List => Element.Value.Values,
1432                                 In_Tree   => Data.Tree);
1433
1434                         when Name_Path_Syntax =>
1435                            begin
1436                               Lang_Index.Config.Path_Syntax :=
1437                                   Path_Syntax_Kind'Value
1438                                     (Get_Name_String (Element.Value.Value));
1439
1440                            exception
1441                               when Constraint_Error =>
1442                                  Error_Msg
1443                                    (Data.Flags,
1444                                     "invalid value for Path_Syntax",
1445                                     Element.Value.Location, Project);
1446                            end;
1447
1448                         when Name_Object_File_Suffix =>
1449                            if Get_Name_String (Element.Value.Value) = "" then
1450                               Error_Msg
1451                                 (Data.Flags,
1452                                  "object file suffix cannot be empty",
1453                                  Element.Value.Location, Project);
1454
1455                            else
1456                               Lang_Index.Config.Object_File_Suffix :=
1457                                 Element.Value.Value;
1458                            end if;
1459
1460                         when Name_Object_File_Switches =>
1461                            Put (Into_List =>
1462                                   Lang_Index.Config.Object_File_Switches,
1463                                 From_List => Element.Value.Values,
1464                                 In_Tree   => Data.Tree);
1465
1466                         when Name_Pic_Option =>
1467
1468                            --  Attribute Compiler_Pic_Option (<language>)
1469
1470                            List := Element.Value.Values;
1471
1472                            if List = Nil_String then
1473                               Error_Msg
1474                                 (Data.Flags,
1475                                  "compiler PIC option cannot be null",
1476                                  Element.Value.Location, Project);
1477                            end if;
1478
1479                            Put (Into_List =>
1480                                   Lang_Index.Config.Compilation_PIC_Option,
1481                                 From_List => List,
1482                                 In_Tree   => Data.Tree);
1483
1484                         when Name_Mapping_File_Switches =>
1485
1486                            --  Attribute Mapping_File_Switches (<language>)
1487
1488                            List := Element.Value.Values;
1489
1490                            if List = Nil_String then
1491                               Error_Msg
1492                                 (Data.Flags,
1493                                  "mapping file switches cannot be null",
1494                                  Element.Value.Location, Project);
1495                            end if;
1496
1497                            Put (Into_List =>
1498                                 Lang_Index.Config.Mapping_File_Switches,
1499                                 From_List => List,
1500                                 In_Tree   => Data.Tree);
1501
1502                         when Name_Mapping_Spec_Suffix =>
1503
1504                            --  Attribute Mapping_Spec_Suffix (<language>)
1505
1506                            Lang_Index.Config.Mapping_Spec_Suffix :=
1507                              File_Name_Type (Element.Value.Value);
1508
1509                         when Name_Mapping_Body_Suffix =>
1510
1511                            --  Attribute Mapping_Body_Suffix (<language>)
1512
1513                            Lang_Index.Config.Mapping_Body_Suffix :=
1514                              File_Name_Type (Element.Value.Value);
1515
1516                         when Name_Config_File_Switches =>
1517
1518                            --  Attribute Config_File_Switches (<language>)
1519
1520                            List := Element.Value.Values;
1521
1522                            if List = Nil_String then
1523                               Error_Msg
1524                                 (Data.Flags,
1525                                  "config file switches cannot be null",
1526                                  Element.Value.Location, Project);
1527                            end if;
1528
1529                            Put (Into_List =>
1530                                   Lang_Index.Config.Config_File_Switches,
1531                                 From_List => List,
1532                                 In_Tree   => Data.Tree);
1533
1534                         when Name_Objects_Path =>
1535
1536                            --  Attribute Objects_Path (<language>)
1537
1538                            Lang_Index.Config.Objects_Path :=
1539                              Element.Value.Value;
1540
1541                         when Name_Objects_Path_File =>
1542
1543                            --  Attribute Objects_Path_File (<language>)
1544
1545                            Lang_Index.Config.Objects_Path_File :=
1546                              Element.Value.Value;
1547
1548                         when Name_Config_Body_File_Name =>
1549
1550                            --  Attribute Config_Body_File_Name (<language>)
1551
1552                            Lang_Index.Config.Config_Body :=
1553                              Element.Value.Value;
1554
1555                         when Name_Config_Body_File_Name_Pattern =>
1556
1557                            --  Attribute Config_Body_File_Name_Pattern
1558                            --  (<language>)
1559
1560                            Lang_Index.Config.Config_Body_Pattern :=
1561                              Element.Value.Value;
1562
1563                         when Name_Config_Spec_File_Name =>
1564
1565                            --  Attribute Config_Spec_File_Name (<language>)
1566
1567                            Lang_Index.Config.Config_Spec :=
1568                              Element.Value.Value;
1569
1570                         when Name_Config_Spec_File_Name_Pattern =>
1571
1572                            --  Attribute Config_Spec_File_Name_Pattern
1573                            --  (<language>)
1574
1575                            Lang_Index.Config.Config_Spec_Pattern :=
1576                              Element.Value.Value;
1577
1578                         when Name_Config_File_Unique =>
1579
1580                            --  Attribute Config_File_Unique (<language>)
1581
1582                            begin
1583                               Lang_Index.Config.Config_File_Unique :=
1584                                 Boolean'Value
1585                                   (Get_Name_String (Element.Value.Value));
1586                            exception
1587                               when Constraint_Error =>
1588                                  Error_Msg
1589                                    (Data.Flags,
1590                                     "illegal value for Config_File_Unique",
1591                                     Element.Value.Location, Project);
1592                            end;
1593
1594                         when others =>
1595                            null;
1596                         end case;
1597                      end if;
1598                   end if;
1599
1600                   Element_Id := Element.Next;
1601                end loop;
1602
1603                Current_Array_Id := Current_Array.Next;
1604             end loop;
1605          end Process_Compiler;
1606
1607          --------------------
1608          -- Process_Naming --
1609          --------------------
1610
1611          procedure Process_Naming (Attributes : Variable_Id) is
1612             Attribute_Id : Variable_Id;
1613             Attribute    : Variable;
1614
1615          begin
1616             --  Process non associated array attribute from package Naming
1617
1618             Attribute_Id := Attributes;
1619             while Attribute_Id /= No_Variable loop
1620                Attribute := Data.Tree.Variable_Elements.Table (Attribute_Id);
1621
1622                if not Attribute.Value.Default then
1623                   if Attribute.Name = Name_Separate_Suffix then
1624
1625                      --  Attribute Separate_Suffix
1626
1627                      Get_Name_String (Attribute.Value.Value);
1628                      Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
1629                      Separate_Suffix := Name_Find;
1630
1631                   elsif Attribute.Name = Name_Casing then
1632
1633                      --  Attribute Casing
1634
1635                      begin
1636                         Casing :=
1637                           Value (Get_Name_String (Attribute.Value.Value));
1638
1639                      exception
1640                         when Constraint_Error =>
1641                            Error_Msg
1642                              (Data.Flags,
1643                               "invalid value for Casing",
1644                               Attribute.Value.Location, Project);
1645                      end;
1646
1647                   elsif Attribute.Name = Name_Dot_Replacement then
1648
1649                      --  Attribute Dot_Replacement
1650
1651                      Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1652
1653                   end if;
1654                end if;
1655
1656                Attribute_Id := Attribute.Next;
1657             end loop;
1658          end Process_Naming;
1659
1660          procedure Process_Naming (Arrays : Array_Id) is
1661             Current_Array_Id : Array_Id;
1662             Current_Array    : Array_Data;
1663             Element_Id       : Array_Element_Id;
1664             Element          : Array_Element;
1665
1666          begin
1667             --  Process the associative array attribute of package Naming
1668
1669             Current_Array_Id := Arrays;
1670             while Current_Array_Id /= No_Array loop
1671                Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
1672
1673                Element_Id := Current_Array.Value;
1674                while Element_Id /= No_Array_Element loop
1675                   Element := Data.Tree.Array_Elements.Table (Element_Id);
1676
1677                   --  Get the name of the language
1678
1679                   Lang_Index := Get_Language_From_Name
1680                     (Project, Get_Name_String (Element.Index));
1681
1682                   if Lang_Index /= No_Language_Index then
1683                      case Current_Array.Name is
1684                         when Name_Spec_Suffix | Name_Specification_Suffix =>
1685
1686                            --  Attribute Spec_Suffix (<language>)
1687
1688                            Get_Name_String (Element.Value.Value);
1689                            Canonical_Case_File_Name
1690                              (Name_Buffer (1 .. Name_Len));
1691                            Lang_Index.Config.Naming_Data.Spec_Suffix :=
1692                              Name_Find;
1693
1694                         when Name_Implementation_Suffix | Name_Body_Suffix =>
1695
1696                            Get_Name_String (Element.Value.Value);
1697                            Canonical_Case_File_Name
1698                              (Name_Buffer (1 .. Name_Len));
1699
1700                            --  Attribute Body_Suffix (<language>)
1701
1702                            Lang_Index.Config.Naming_Data.Body_Suffix :=
1703                              Name_Find;
1704                            Lang_Index.Config.Naming_Data.Separate_Suffix :=
1705                              Lang_Index.Config.Naming_Data.Body_Suffix;
1706
1707                         when others =>
1708                            null;
1709                      end case;
1710                   end if;
1711
1712                   Element_Id := Element.Next;
1713                end loop;
1714
1715                Current_Array_Id := Current_Array.Next;
1716             end loop;
1717          end Process_Naming;
1718
1719          --------------------
1720          -- Process_Linker --
1721          --------------------
1722
1723          procedure Process_Linker (Attributes : Variable_Id) is
1724             Attribute_Id : Variable_Id;
1725             Attribute    : Variable;
1726
1727          begin
1728             --  Process non associated array attribute from package Linker
1729
1730             Attribute_Id := Attributes;
1731             while Attribute_Id /= No_Variable loop
1732                Attribute :=
1733                  Data.Tree.Variable_Elements.Table (Attribute_Id);
1734
1735                if not Attribute.Value.Default then
1736                   if Attribute.Name = Name_Driver then
1737
1738                      --  Attribute Linker'Driver: the default linker to use
1739
1740                      Project.Config.Linker :=
1741                        Path_Name_Type (Attribute.Value.Value);
1742
1743                      --  Linker'Driver is also used to link shared libraries
1744                      --  if the obsolescent attribute Library_GCC has not been
1745                      --  specified.
1746
1747                      if Project.Config.Shared_Lib_Driver = No_File then
1748                         Project.Config.Shared_Lib_Driver :=
1749                           File_Name_Type (Attribute.Value.Value);
1750                      end if;
1751
1752                   elsif Attribute.Name = Name_Required_Switches then
1753
1754                      --  Attribute Required_Switches: the minimum
1755                      --  options to use when invoking the linker
1756
1757                      Put (Into_List => Project.Config.Minimum_Linker_Options,
1758                           From_List => Attribute.Value.Values,
1759                           In_Tree   => Data.Tree);
1760
1761                   elsif Attribute.Name = Name_Map_File_Option then
1762                      Project.Config.Map_File_Option := Attribute.Value.Value;
1763
1764                   elsif Attribute.Name = Name_Max_Command_Line_Length then
1765                      begin
1766                         Project.Config.Max_Command_Line_Length :=
1767                           Natural'Value (Get_Name_String
1768                                          (Attribute.Value.Value));
1769
1770                      exception
1771                         when Constraint_Error =>
1772                            Error_Msg
1773                              (Data.Flags,
1774                               "value must be positive or equal to 0",
1775                               Attribute.Value.Location, Project);
1776                      end;
1777
1778                   elsif Attribute.Name = Name_Response_File_Format then
1779                      declare
1780                         Name  : Name_Id;
1781
1782                      begin
1783                         Get_Name_String (Attribute.Value.Value);
1784                         To_Lower (Name_Buffer (1 .. Name_Len));
1785                         Name := Name_Find;
1786
1787                         if Name = Name_None then
1788                            Project.Config.Resp_File_Format := None;
1789
1790                         elsif Name = Name_Gnu then
1791                            Project.Config.Resp_File_Format := GNU;
1792
1793                         elsif Name = Name_Object_List then
1794                            Project.Config.Resp_File_Format := Object_List;
1795
1796                         elsif Name = Name_Option_List then
1797                            Project.Config.Resp_File_Format := Option_List;
1798
1799                         else
1800                            Error_Msg
1801                              (Data.Flags,
1802                               "illegal response file format",
1803                               Attribute.Value.Location, Project);
1804                         end if;
1805                      end;
1806
1807                   elsif Attribute.Name = Name_Response_File_Switches then
1808                      Put (Into_List => Project.Config.Resp_File_Options,
1809                           From_List => Attribute.Value.Values,
1810                           In_Tree   => Data.Tree);
1811                   end if;
1812                end if;
1813
1814                Attribute_Id := Attribute.Next;
1815             end loop;
1816          end Process_Linker;
1817
1818       --  Start of processing for Process_Packages
1819
1820       begin
1821          Packages := Project.Decl.Packages;
1822          while Packages /= No_Package loop
1823             Element := Data.Tree.Packages.Table (Packages);
1824
1825             case Element.Name is
1826                when Name_Binder =>
1827
1828                   --  Process attributes of package Binder
1829
1830                   Process_Binder (Element.Decl.Arrays);
1831
1832                when Name_Builder =>
1833
1834                   --  Process attributes of package Builder
1835
1836                   Process_Builder (Element.Decl.Attributes);
1837
1838                when Name_Compiler =>
1839
1840                   --  Process attributes of package Compiler
1841
1842                   Process_Compiler (Element.Decl.Arrays);
1843
1844                when Name_Linker =>
1845
1846                   --  Process attributes of package Linker
1847
1848                   Process_Linker (Element.Decl.Attributes);
1849
1850                when Name_Naming =>
1851
1852                   --  Process attributes of package Naming
1853
1854                   Process_Naming (Element.Decl.Attributes);
1855                   Process_Naming (Element.Decl.Arrays);
1856
1857                when others =>
1858                   null;
1859             end case;
1860
1861             Packages := Element.Next;
1862          end loop;
1863       end Process_Packages;
1864
1865       ---------------------------------------------
1866       -- Process_Project_Level_Simple_Attributes --
1867       ---------------------------------------------
1868
1869       procedure Process_Project_Level_Simple_Attributes is
1870          Attribute_Id : Variable_Id;
1871          Attribute    : Variable;
1872          List         : String_List_Id;
1873
1874       begin
1875          --  Process non associated array attribute at project level
1876
1877          Attribute_Id := Project.Decl.Attributes;
1878          while Attribute_Id /= No_Variable loop
1879             Attribute :=
1880               Data.Tree.Variable_Elements.Table (Attribute_Id);
1881
1882             if not Attribute.Value.Default then
1883                if Attribute.Name = Name_Target then
1884
1885                   --  Attribute Target: the target specified
1886
1887                   Project.Config.Target := Attribute.Value.Value;
1888
1889                elsif Attribute.Name = Name_Library_Builder then
1890
1891                   --  Attribute Library_Builder: the application to invoke
1892                   --  to build libraries.
1893
1894                   Project.Config.Library_Builder :=
1895                     Path_Name_Type (Attribute.Value.Value);
1896
1897                elsif Attribute.Name = Name_Archive_Builder then
1898
1899                   --  Attribute Archive_Builder: the archive builder
1900                   --  (usually "ar") and its minimum options (usually "cr").
1901
1902                   List := Attribute.Value.Values;
1903
1904                   if List = Nil_String then
1905                      Error_Msg
1906                        (Data.Flags,
1907                         "archive builder cannot be null",
1908                         Attribute.Value.Location, Project);
1909                   end if;
1910
1911                   Put (Into_List => Project.Config.Archive_Builder,
1912                        From_List => List,
1913                        In_Tree   => Data.Tree);
1914
1915                elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1916
1917                   --  Attribute Archive_Builder: the archive builder
1918                   --  (usually "ar") and its minimum options (usually "cr").
1919
1920                   List := Attribute.Value.Values;
1921
1922                   if List /= Nil_String then
1923                      Put
1924                        (Into_List =>
1925                           Project.Config.Archive_Builder_Append_Option,
1926                         From_List => List,
1927                         In_Tree   => Data.Tree);
1928                   end if;
1929
1930                elsif Attribute.Name = Name_Archive_Indexer then
1931
1932                   --  Attribute Archive_Indexer: the optional archive
1933                   --  indexer (usually "ranlib") with its minimum options
1934                   --  (usually none).
1935
1936                   List := Attribute.Value.Values;
1937
1938                   if List = Nil_String then
1939                      Error_Msg
1940                        (Data.Flags,
1941                         "archive indexer cannot be null",
1942                         Attribute.Value.Location, Project);
1943                   end if;
1944
1945                   Put (Into_List => Project.Config.Archive_Indexer,
1946                        From_List => List,
1947                        In_Tree   => Data.Tree);
1948
1949                elsif Attribute.Name = Name_Library_Partial_Linker then
1950
1951                   --  Attribute Library_Partial_Linker: the optional linker
1952                   --  driver with its minimum options, to partially link
1953                   --  archives.
1954
1955                   List := Attribute.Value.Values;
1956
1957                   if List = Nil_String then
1958                      Error_Msg
1959                        (Data.Flags,
1960                         "partial linker cannot be null",
1961                         Attribute.Value.Location, Project);
1962                   end if;
1963
1964                   Put (Into_List => Project.Config.Lib_Partial_Linker,
1965                        From_List => List,
1966                        In_Tree   => Data.Tree);
1967
1968                elsif Attribute.Name = Name_Library_GCC then
1969                   Project.Config.Shared_Lib_Driver :=
1970                     File_Name_Type (Attribute.Value.Value);
1971                   Error_Msg
1972                     (Data.Flags,
1973                      "?Library_'G'C'C is an obsolescent attribute, " &
1974                      "use Linker''Driver instead",
1975                      Attribute.Value.Location, Project);
1976
1977                elsif Attribute.Name = Name_Archive_Suffix then
1978                   Project.Config.Archive_Suffix :=
1979                     File_Name_Type (Attribute.Value.Value);
1980
1981                elsif Attribute.Name = Name_Linker_Executable_Option then
1982
1983                   --  Attribute Linker_Executable_Option: optional options
1984                   --  to specify an executable name. Defaults to "-o".
1985
1986                   List := Attribute.Value.Values;
1987
1988                   if List = Nil_String then
1989                      Error_Msg
1990                        (Data.Flags,
1991                         "linker executable option cannot be null",
1992                         Attribute.Value.Location, Project);
1993                   end if;
1994
1995                   Put (Into_List => Project.Config.Linker_Executable_Option,
1996                        From_List => List,
1997                        In_Tree   => Data.Tree);
1998
1999                elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2000
2001                   --  Attribute Linker_Lib_Dir_Option: optional options
2002                   --  to specify a library search directory. Defaults to
2003                   --  "-L".
2004
2005                   Get_Name_String (Attribute.Value.Value);
2006
2007                   if Name_Len = 0 then
2008                      Error_Msg
2009                        (Data.Flags,
2010                         "linker library directory option cannot be empty",
2011                         Attribute.Value.Location, Project);
2012                   end if;
2013
2014                   Project.Config.Linker_Lib_Dir_Option :=
2015                     Attribute.Value.Value;
2016
2017                elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2018
2019                   --  Attribute Linker_Lib_Name_Option: optional options
2020                   --  to specify the name of a library to be linked in.
2021                   --  Defaults to "-l".
2022
2023                   Get_Name_String (Attribute.Value.Value);
2024
2025                   if Name_Len = 0 then
2026                      Error_Msg
2027                        (Data.Flags,
2028                         "linker library name option cannot be empty",
2029                         Attribute.Value.Location, Project);
2030                   end if;
2031
2032                   Project.Config.Linker_Lib_Name_Option :=
2033                     Attribute.Value.Value;
2034
2035                elsif Attribute.Name = Name_Run_Path_Option then
2036
2037                   --  Attribute Run_Path_Option: optional options to
2038                   --  specify a path for libraries.
2039
2040                   List := Attribute.Value.Values;
2041
2042                   if List /= Nil_String then
2043                      Put (Into_List => Project.Config.Run_Path_Option,
2044                           From_List => List,
2045                           In_Tree   => Data.Tree);
2046                   end if;
2047
2048                elsif Attribute.Name = Name_Separate_Run_Path_Options then
2049                   declare
2050                      pragma Unsuppress (All_Checks);
2051                   begin
2052                      Project.Config.Separate_Run_Path_Options :=
2053                        Boolean'Value (Get_Name_String (Attribute.Value.Value));
2054                   exception
2055                      when Constraint_Error =>
2056                         Error_Msg
2057                           (Data.Flags,
2058                            "invalid value """ &
2059                            Get_Name_String (Attribute.Value.Value) &
2060                            """ for Separate_Run_Path_Options",
2061                            Attribute.Value.Location, Project);
2062                   end;
2063
2064                elsif Attribute.Name = Name_Library_Support then
2065                   declare
2066                      pragma Unsuppress (All_Checks);
2067                   begin
2068                      Project.Config.Lib_Support :=
2069                        Library_Support'Value (Get_Name_String
2070                                               (Attribute.Value.Value));
2071                   exception
2072                      when Constraint_Error =>
2073                         Error_Msg
2074                           (Data.Flags,
2075                            "invalid value """ &
2076                            Get_Name_String (Attribute.Value.Value) &
2077                            """ for Library_Support",
2078                            Attribute.Value.Location, Project);
2079                   end;
2080
2081                elsif Attribute.Name = Name_Shared_Library_Prefix then
2082                   Project.Config.Shared_Lib_Prefix :=
2083                     File_Name_Type (Attribute.Value.Value);
2084
2085                elsif Attribute.Name = Name_Shared_Library_Suffix then
2086                   Project.Config.Shared_Lib_Suffix :=
2087                     File_Name_Type (Attribute.Value.Value);
2088
2089                elsif Attribute.Name = Name_Symbolic_Link_Supported then
2090                   declare
2091                      pragma Unsuppress (All_Checks);
2092                   begin
2093                      Project.Config.Symbolic_Link_Supported :=
2094                        Boolean'Value (Get_Name_String
2095                                       (Attribute.Value.Value));
2096                   exception
2097                      when Constraint_Error =>
2098                         Error_Msg
2099                           (Data.Flags,
2100                            "invalid value """
2101                              & Get_Name_String (Attribute.Value.Value)
2102                              & """ for Symbolic_Link_Supported",
2103                            Attribute.Value.Location, Project);
2104                   end;
2105
2106                elsif
2107                  Attribute.Name = Name_Library_Major_Minor_Id_Supported
2108                then
2109                   declare
2110                      pragma Unsuppress (All_Checks);
2111                   begin
2112                      Project.Config.Lib_Maj_Min_Id_Supported :=
2113                        Boolean'Value (Get_Name_String
2114                                       (Attribute.Value.Value));
2115                   exception
2116                      when Constraint_Error =>
2117                         Error_Msg
2118                           (Data.Flags,
2119                            "invalid value """ &
2120                            Get_Name_String (Attribute.Value.Value) &
2121                            """ for Library_Major_Minor_Id_Supported",
2122                            Attribute.Value.Location, Project);
2123                   end;
2124
2125                elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2126                   declare
2127                      pragma Unsuppress (All_Checks);
2128                   begin
2129                      Project.Config.Auto_Init_Supported :=
2130                        Boolean'Value (Get_Name_String (Attribute.Value.Value));
2131                   exception
2132                      when Constraint_Error =>
2133                         Error_Msg
2134                           (Data.Flags,
2135                            "invalid value """
2136                              & Get_Name_String (Attribute.Value.Value)
2137                              & """ for Library_Auto_Init_Supported",
2138                            Attribute.Value.Location, Project);
2139                   end;
2140
2141                elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2142                   List := Attribute.Value.Values;
2143
2144                   if List /= Nil_String then
2145                      Put (Into_List => Project.Config.Shared_Lib_Min_Options,
2146                           From_List => List,
2147                           In_Tree   => Data.Tree);
2148                   end if;
2149
2150                elsif Attribute.Name = Name_Library_Version_Switches then
2151                   List := Attribute.Value.Values;
2152
2153                   if List /= Nil_String then
2154                      Put (Into_List => Project.Config.Lib_Version_Options,
2155                           From_List => List,
2156                           In_Tree   => Data.Tree);
2157                   end if;
2158                end if;
2159             end if;
2160
2161             Attribute_Id := Attribute.Next;
2162          end loop;
2163       end Process_Project_Level_Simple_Attributes;
2164
2165       --------------------------------------------
2166       -- Process_Project_Level_Array_Attributes --
2167       --------------------------------------------
2168
2169       procedure Process_Project_Level_Array_Attributes is
2170          Current_Array_Id : Array_Id;
2171          Current_Array    : Array_Data;
2172          Element_Id       : Array_Element_Id;
2173          Element          : Array_Element;
2174          List             : String_List_Id;
2175
2176       begin
2177          --  Process the associative array attributes at project level
2178
2179          Current_Array_Id := Project.Decl.Arrays;
2180          while Current_Array_Id /= No_Array loop
2181             Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
2182
2183             Element_Id := Current_Array.Value;
2184             while Element_Id /= No_Array_Element loop
2185                Element := Data.Tree.Array_Elements.Table (Element_Id);
2186
2187                --  Get the name of the language
2188
2189                Lang_Index :=
2190                  Get_Language_From_Name
2191                    (Project, Get_Name_String (Element.Index));
2192
2193                if Lang_Index /= No_Language_Index then
2194                   case Current_Array.Name is
2195                      when Name_Inherit_Source_Path =>
2196                         List := Element.Value.Values;
2197
2198                         if List /= Nil_String then
2199                            Put
2200                              (Into_List  =>
2201                                 Lang_Index.Config.Include_Compatible_Languages,
2202                               From_List  => List,
2203                               In_Tree    => Data.Tree,
2204                               Lower_Case => True);
2205                         end if;
2206
2207                      when Name_Toolchain_Description =>
2208
2209                         --  Attribute Toolchain_Description (<language>)
2210
2211                         Lang_Index.Config.Toolchain_Description :=
2212                           Element.Value.Value;
2213
2214                      when Name_Toolchain_Version =>
2215
2216                         --  Attribute Toolchain_Version (<language>)
2217
2218                         Lang_Index.Config.Toolchain_Version :=
2219                           Element.Value.Value;
2220
2221                      when Name_Runtime_Library_Dir =>
2222
2223                         --  Attribute Runtime_Library_Dir (<language>)
2224
2225                         Lang_Index.Config.Runtime_Library_Dir :=
2226                           Element.Value.Value;
2227
2228                      when Name_Runtime_Source_Dir =>
2229
2230                         --  Attribute Runtime_Library_Dir (<language>)
2231
2232                         Lang_Index.Config.Runtime_Source_Dir :=
2233                           Element.Value.Value;
2234
2235                      when Name_Object_Generated =>
2236                         declare
2237                            pragma Unsuppress (All_Checks);
2238                            Value : Boolean;
2239
2240                         begin
2241                            Value :=
2242                              Boolean'Value
2243                                (Get_Name_String (Element.Value.Value));
2244
2245                            Lang_Index.Config.Object_Generated := Value;
2246
2247                            --  If no object is generated, no object may be
2248                            --  linked.
2249
2250                            if not Value then
2251                               Lang_Index.Config.Objects_Linked := False;
2252                            end if;
2253
2254                         exception
2255                            when Constraint_Error =>
2256                               Error_Msg
2257                                 (Data.Flags,
2258                                  "invalid value """
2259                                  & Get_Name_String (Element.Value.Value)
2260                                  & """ for Object_Generated",
2261                                  Element.Value.Location, Project);
2262                         end;
2263
2264                      when Name_Objects_Linked =>
2265                         declare
2266                            pragma Unsuppress (All_Checks);
2267                            Value : Boolean;
2268
2269                         begin
2270                            Value :=
2271                              Boolean'Value
2272                                (Get_Name_String (Element.Value.Value));
2273
2274                            --  No change if Object_Generated is False, as this
2275                            --  forces Objects_Linked to be False too.
2276
2277                            if Lang_Index.Config.Object_Generated then
2278                               Lang_Index.Config.Objects_Linked := Value;
2279                            end if;
2280
2281                         exception
2282                            when Constraint_Error =>
2283                               Error_Msg
2284                                 (Data.Flags,
2285                                  "invalid value """
2286                                  & Get_Name_String (Element.Value.Value)
2287                                  & """ for Objects_Linked",
2288                                  Element.Value.Location, Project);
2289                         end;
2290                      when others =>
2291                         null;
2292                   end case;
2293                end if;
2294
2295                Element_Id := Element.Next;
2296             end loop;
2297
2298             Current_Array_Id := Current_Array.Next;
2299          end loop;
2300       end Process_Project_Level_Array_Attributes;
2301
2302    --  Start of processing for Check_Configuration
2303
2304    begin
2305       Process_Project_Level_Simple_Attributes;
2306       Process_Project_Level_Array_Attributes;
2307       Process_Packages;
2308
2309       --  For unit based languages, set Casing, Dot_Replacement and
2310       --  Separate_Suffix in Naming_Data.
2311
2312       Lang_Index := Project.Languages;
2313       while Lang_Index /= No_Language_Index loop
2314          if Lang_Index.Name = Name_Ada then
2315             Lang_Index.Config.Naming_Data.Casing := Casing;
2316             Lang_Index.Config.Naming_Data.Dot_Replacement := Dot_Replacement;
2317
2318             if Separate_Suffix /= No_File then
2319                Lang_Index.Config.Naming_Data.Separate_Suffix :=
2320                  Separate_Suffix;
2321             end if;
2322
2323             exit;
2324          end if;
2325
2326          Lang_Index := Lang_Index.Next;
2327       end loop;
2328
2329       --  Give empty names to various prefixes/suffixes, if they have not
2330       --  been specified in the configuration.
2331
2332       if Project.Config.Archive_Suffix = No_File then
2333          Project.Config.Archive_Suffix := Empty_File;
2334       end if;
2335
2336       if Project.Config.Shared_Lib_Prefix = No_File then
2337          Project.Config.Shared_Lib_Prefix := Empty_File;
2338       end if;
2339
2340       if Project.Config.Shared_Lib_Suffix = No_File then
2341          Project.Config.Shared_Lib_Suffix := Empty_File;
2342       end if;
2343
2344       Lang_Index := Project.Languages;
2345       while Lang_Index /= No_Language_Index loop
2346
2347          --  For all languages, Compiler_Driver needs to be specified. This is
2348          --  only needed if we do intend to compile (not in GPS for instance).
2349
2350          if Data.Flags.Compiler_Driver_Mandatory
2351            and then Lang_Index.Config.Compiler_Driver = No_File
2352          then
2353             Error_Msg_Name_1 := Lang_Index.Display_Name;
2354             Error_Msg
2355               (Data.Flags,
2356                "?no compiler specified for language %%" &
2357                  ", ignoring all its sources",
2358                No_Location, Project);
2359
2360             if Lang_Index = Project.Languages then
2361                Project.Languages := Lang_Index.Next;
2362             else
2363                Prev_Index.Next := Lang_Index.Next;
2364             end if;
2365
2366          elsif Lang_Index.Name = Name_Ada then
2367             Prev_Index := Lang_Index;
2368
2369             --  For unit based languages, Dot_Replacement, Spec_Suffix and
2370             --  Body_Suffix need to be specified.
2371
2372             if Lang_Index.Config.Naming_Data.Dot_Replacement = No_File then
2373                Error_Msg
2374                  (Data.Flags,
2375                   "Dot_Replacement not specified for Ada",
2376                   No_Location, Project);
2377             end if;
2378
2379             if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File then
2380                Error_Msg
2381                  (Data.Flags,
2382                   "Spec_Suffix not specified for Ada",
2383                   No_Location, Project);
2384             end if;
2385
2386             if Lang_Index.Config.Naming_Data.Body_Suffix = No_File then
2387                Error_Msg
2388                  (Data.Flags,
2389                   "Body_Suffix not specified for Ada",
2390                   No_Location, Project);
2391             end if;
2392
2393          else
2394             Prev_Index := Lang_Index;
2395
2396             --  For file based languages, either Spec_Suffix or Body_Suffix
2397             --  need to be specified.
2398
2399             if Data.Flags.Require_Sources_Other_Lang
2400               and then Lang_Index.Config.Naming_Data.Spec_Suffix = No_File
2401               and then Lang_Index.Config.Naming_Data.Body_Suffix = No_File
2402             then
2403                Error_Msg_Name_1 := Lang_Index.Display_Name;
2404                Error_Msg
2405                  (Data.Flags,
2406                   "no suffixes specified for %%",
2407                   No_Location, Project);
2408             end if;
2409          end if;
2410
2411          Lang_Index := Lang_Index.Next;
2412       end loop;
2413    end Check_Configuration;
2414
2415    -------------------------------
2416    -- Check_If_Externally_Built --
2417    -------------------------------
2418
2419    procedure Check_If_Externally_Built
2420      (Project : Project_Id;
2421       Data    : in out Tree_Processing_Data)
2422    is
2423       Externally_Built : constant Variable_Value :=
2424                            Util.Value_Of
2425                             (Name_Externally_Built,
2426                              Project.Decl.Attributes, Data.Tree);
2427
2428    begin
2429       if not Externally_Built.Default then
2430          Get_Name_String (Externally_Built.Value);
2431          To_Lower (Name_Buffer (1 .. Name_Len));
2432
2433          if Name_Buffer (1 .. Name_Len) = "true" then
2434             Project.Externally_Built := True;
2435
2436          elsif Name_Buffer (1 .. Name_Len) /= "false" then
2437             Error_Msg (Data.Flags,
2438                        "Externally_Built may only be true or false",
2439                        Externally_Built.Location, Project);
2440          end if;
2441       end if;
2442
2443       --  A virtual project extending an externally built project is itself
2444       --  externally built.
2445
2446       if Project.Virtual and then Project.Extends /= No_Project then
2447          Project.Externally_Built := Project.Extends.Externally_Built;
2448       end if;
2449
2450       if Current_Verbosity = High then
2451          Write_Str ("Project is ");
2452
2453          if not Project.Externally_Built then
2454             Write_Str ("not ");
2455          end if;
2456
2457          Write_Line ("externally built.");
2458       end if;
2459    end Check_If_Externally_Built;
2460
2461    ----------------------
2462    -- Check_Interfaces --
2463    ----------------------
2464
2465    procedure Check_Interfaces
2466      (Project : Project_Id;
2467       Data    : in out Tree_Processing_Data)
2468    is
2469       Interfaces : constant Prj.Variable_Value :=
2470                      Prj.Util.Value_Of
2471                        (Snames.Name_Interfaces,
2472                         Project.Decl.Attributes,
2473                         Data.Tree);
2474
2475       List      : String_List_Id;
2476       Element   : String_Element;
2477       Name      : File_Name_Type;
2478       Iter      : Source_Iterator;
2479       Source    : Source_Id;
2480       Project_2 : Project_Id;
2481       Other     : Source_Id;
2482
2483    begin
2484       if not Interfaces.Default then
2485
2486          --  Set In_Interfaces to False for all sources. It will be set to True
2487          --  later for the sources in the Interfaces list.
2488
2489          Project_2 := Project;
2490          while Project_2 /= No_Project loop
2491             Iter := For_Each_Source (Data.Tree, Project_2);
2492             loop
2493                Source := Prj.Element (Iter);
2494                exit when Source = No_Source;
2495                Source.In_Interfaces := False;
2496                Next (Iter);
2497             end loop;
2498
2499             Project_2 := Project_2.Extends;
2500          end loop;
2501
2502          List := Interfaces.Values;
2503          while List /= Nil_String loop
2504             Element := Data.Tree.String_Elements.Table (List);
2505             Name := Canonical_Case_File_Name (Element.Value);
2506
2507             Project_2 := Project;
2508             Big_Loop :
2509             while Project_2 /= No_Project loop
2510                Iter := For_Each_Source (Data.Tree, Project_2);
2511
2512                loop
2513                   Source := Prj.Element (Iter);
2514                   exit when Source = No_Source;
2515
2516                   if Source.File = Name then
2517                      if not Source.Locally_Removed then
2518                         Source.In_Interfaces := True;
2519                         Source.Declared_In_Interfaces := True;
2520
2521                         Other := Other_Part (Source);
2522
2523                         if Other /= No_Source then
2524                            Other.In_Interfaces := True;
2525                            Other.Declared_In_Interfaces := True;
2526                         end if;
2527
2528                         if Current_Verbosity = High then
2529                            Write_Str ("   interface: ");
2530                            Write_Line (Get_Name_String (Source.Path.Name));
2531                         end if;
2532                      end if;
2533
2534                      exit Big_Loop;
2535                   end if;
2536
2537                   Next (Iter);
2538                end loop;
2539
2540                Project_2 := Project_2.Extends;
2541             end loop Big_Loop;
2542
2543             if Source = No_Source then
2544                Error_Msg_File_1 := File_Name_Type (Element.Value);
2545                Error_Msg_Name_1 := Project.Name;
2546
2547                Error_Msg
2548                  (Data.Flags,
2549                   "{ cannot be an interface of project %% "
2550                   & "as it is not one of its sources",
2551                   Element.Location, Project);
2552             end if;
2553
2554             List := Element.Next;
2555          end loop;
2556
2557          Project.Interfaces_Defined := True;
2558
2559       elsif Project.Extends /= No_Project then
2560          Project.Interfaces_Defined := Project.Extends.Interfaces_Defined;
2561
2562          if Project.Interfaces_Defined then
2563             Iter := For_Each_Source (Data.Tree, Project);
2564             loop
2565                Source := Prj.Element (Iter);
2566                exit when Source = No_Source;
2567
2568                if not Source.Declared_In_Interfaces then
2569                   Source.In_Interfaces := False;
2570                end if;
2571
2572                Next (Iter);
2573             end loop;
2574          end if;
2575       end if;
2576    end Check_Interfaces;
2577
2578    --------------------------
2579    -- Check_Package_Naming --
2580    --------------------------
2581
2582    procedure Check_Package_Naming
2583      (Project : Project_Id;
2584       Data    : in out Tree_Processing_Data;
2585       Bodies  : out Array_Element_Id;
2586       Specs   : out Array_Element_Id)
2587    is
2588       Naming_Id : constant Package_Id :=
2589                     Util.Value_Of
2590                       (Name_Naming, Project.Decl.Packages, Data.Tree);
2591       Naming    : Package_Element;
2592
2593       Ada_Body_Suffix_Loc : Source_Ptr := No_Location;
2594
2595       procedure Check_Naming;
2596       --  Check the validity of the Naming package (suffixes valid, ...)
2597
2598       procedure Check_Common
2599         (Dot_Replacement : in out File_Name_Type;
2600          Casing          : in out Casing_Type;
2601          Casing_Defined  : out Boolean;
2602          Separate_Suffix : in out File_Name_Type;
2603          Sep_Suffix_Loc  : out Source_Ptr);
2604       --  Check attributes common
2605
2606       procedure Process_Exceptions_File_Based
2607         (Lang_Id : Language_Ptr;
2608          Kind    : Source_Kind);
2609       procedure Process_Exceptions_Unit_Based
2610         (Lang_Id : Language_Ptr;
2611          Kind    : Source_Kind);
2612       --  Process the naming exceptions for the two types of languages
2613
2614       procedure Initialize_Naming_Data;
2615       --  Initialize internal naming data for the various languages
2616
2617       ------------------
2618       -- Check_Common --
2619       ------------------
2620
2621       procedure Check_Common
2622         (Dot_Replacement : in out File_Name_Type;
2623          Casing          : in out Casing_Type;
2624          Casing_Defined  : out Boolean;
2625          Separate_Suffix : in out File_Name_Type;
2626          Sep_Suffix_Loc  : out Source_Ptr)
2627       is
2628          Dot_Repl      : constant Variable_Value :=
2629                            Util.Value_Of
2630                              (Name_Dot_Replacement,
2631                               Naming.Decl.Attributes,
2632                               Data.Tree);
2633          Casing_String : constant Variable_Value :=
2634                            Util.Value_Of
2635                              (Name_Casing,
2636                               Naming.Decl.Attributes,
2637                               Data.Tree);
2638          Sep_Suffix    : constant Variable_Value :=
2639                            Util.Value_Of
2640                              (Name_Separate_Suffix,
2641                               Naming.Decl.Attributes,
2642                               Data.Tree);
2643          Dot_Repl_Loc  : Source_Ptr;
2644
2645       begin
2646          Sep_Suffix_Loc := No_Location;
2647
2648          if not Dot_Repl.Default then
2649             pragma Assert
2650               (Dot_Repl.Kind = Single, "Dot_Replacement is not a string");
2651
2652             if Length_Of_Name (Dot_Repl.Value) = 0 then
2653                Error_Msg
2654                  (Data.Flags, "Dot_Replacement cannot be empty",
2655                   Dot_Repl.Location, Project);
2656             end if;
2657
2658             Dot_Replacement := Canonical_Case_File_Name (Dot_Repl.Value);
2659             Dot_Repl_Loc    := Dot_Repl.Location;
2660
2661             declare
2662                Repl : constant String := Get_Name_String (Dot_Replacement);
2663
2664             begin
2665                --  Dot_Replacement cannot
2666                --   - be empty
2667                --   - start or end with an alphanumeric
2668                --   - be a single '_'
2669                --   - start with an '_' followed by an alphanumeric
2670                --   - contain a '.' except if it is "."
2671
2672                if Repl'Length = 0
2673                  or else Is_Alphanumeric (Repl (Repl'First))
2674                  or else Is_Alphanumeric (Repl (Repl'Last))
2675                  or else (Repl (Repl'First) = '_'
2676                            and then
2677                              (Repl'Length = 1
2678                                or else
2679                                  Is_Alphanumeric (Repl (Repl'First + 1))))
2680                  or else (Repl'Length > 1
2681                            and then
2682                              Index (Source => Repl, Pattern => ".") /= 0)
2683                then
2684                   Error_Msg
2685                     (Data.Flags,
2686                      '"' & Repl &
2687                      """ is illegal for Dot_Replacement.",
2688                      Dot_Repl_Loc, Project);
2689                end if;
2690             end;
2691          end if;
2692
2693          if Dot_Replacement /= No_File then
2694             Write_Attr
2695               ("Dot_Replacement", Get_Name_String (Dot_Replacement));
2696          end if;
2697
2698          Casing_Defined := False;
2699
2700          if not Casing_String.Default then
2701             pragma Assert
2702               (Casing_String.Kind = Single, "Casing is not a string");
2703
2704             declare
2705                Casing_Image : constant String :=
2706                                 Get_Name_String (Casing_String.Value);
2707
2708             begin
2709                if Casing_Image'Length = 0 then
2710                   Error_Msg
2711                     (Data.Flags,
2712                      "Casing cannot be an empty string",
2713                      Casing_String.Location, Project);
2714                end if;
2715
2716                Casing := Value (Casing_Image);
2717                Casing_Defined := True;
2718
2719             exception
2720                when Constraint_Error =>
2721                   Name_Len := Casing_Image'Length;
2722                   Name_Buffer (1 .. Name_Len) := Casing_Image;
2723                   Err_Vars.Error_Msg_Name_1 := Name_Find;
2724                   Error_Msg
2725                     (Data.Flags,
2726                      "%% is not a correct Casing",
2727                      Casing_String.Location, Project);
2728             end;
2729          end if;
2730
2731          Write_Attr ("Casing", Image (Casing));
2732
2733          if not Sep_Suffix.Default then
2734             if Length_Of_Name (Sep_Suffix.Value) = 0 then
2735                Error_Msg
2736                  (Data.Flags,
2737                   "Separate_Suffix cannot be empty",
2738                   Sep_Suffix.Location, Project);
2739
2740             else
2741                Separate_Suffix := Canonical_Case_File_Name (Sep_Suffix.Value);
2742                Sep_Suffix_Loc  := Sep_Suffix.Location;
2743
2744                Check_Illegal_Suffix
2745                  (Project, Separate_Suffix,
2746                   Dot_Replacement, "Separate_Suffix", Sep_Suffix.Location,
2747                   Data);
2748             end if;
2749          end if;
2750
2751          if Separate_Suffix /= No_File then
2752             Write_Attr
2753               ("Separate_Suffix", Get_Name_String (Separate_Suffix));
2754          end if;
2755       end Check_Common;
2756
2757       -----------------------------------
2758       -- Process_Exceptions_File_Based --
2759       -----------------------------------
2760
2761       procedure Process_Exceptions_File_Based
2762         (Lang_Id : Language_Ptr;
2763          Kind    : Source_Kind)
2764       is
2765          Lang           : constant Name_Id := Lang_Id.Name;
2766          Exceptions     : Array_Element_Id;
2767          Exception_List : Variable_Value;
2768          Element_Id     : String_List_Id;
2769          Element        : String_Element;
2770          File_Name      : File_Name_Type;
2771          Source         : Source_Id;
2772          Iter           : Source_Iterator;
2773
2774       begin
2775          case Kind is
2776             when Impl | Sep =>
2777                Exceptions :=
2778                  Value_Of
2779                    (Name_Implementation_Exceptions,
2780                     In_Arrays => Naming.Decl.Arrays,
2781                     In_Tree   => Data.Tree);
2782
2783             when Spec =>
2784                Exceptions :=
2785                  Value_Of
2786                    (Name_Specification_Exceptions,
2787                     In_Arrays => Naming.Decl.Arrays,
2788                     In_Tree   => Data.Tree);
2789          end case;
2790
2791          Exception_List := Value_Of
2792            (Index    => Lang,
2793             In_Array => Exceptions,
2794             In_Tree  => Data.Tree);
2795
2796          if Exception_List /= Nil_Variable_Value then
2797             Element_Id := Exception_List.Values;
2798             while Element_Id /= Nil_String loop
2799                Element   := Data.Tree.String_Elements.Table (Element_Id);
2800                File_Name := Canonical_Case_File_Name (Element.Value);
2801
2802                Iter := For_Each_Source (Data.Tree, Project);
2803                loop
2804                   Source := Prj.Element (Iter);
2805                   exit when Source = No_Source or else Source.File = File_Name;
2806                   Next (Iter);
2807                end loop;
2808
2809                if Source = No_Source then
2810                   Add_Source
2811                     (Id               => Source,
2812                      Data             => Data,
2813                      Project          => Project,
2814                      Source_Dir_Rank  => 0,
2815                      Lang_Id          => Lang_Id,
2816                      Kind             => Kind,
2817                      File_Name        => File_Name,
2818                      Display_File     => File_Name_Type (Element.Value),
2819                      Naming_Exception => True);
2820
2821                else
2822                   --  Check if the file name is already recorded for another
2823                   --  language or another kind.
2824
2825                   if Source.Language /= Lang_Id then
2826                      Error_Msg
2827                        (Data.Flags,
2828                         "the same file cannot be a source of two languages",
2829                         Element.Location, Project);
2830
2831                   elsif Source.Kind /= Kind then
2832                      Error_Msg
2833                        (Data.Flags,
2834                         "the same file cannot be a source and a template",
2835                         Element.Location, Project);
2836                   end if;
2837
2838                   --  If the file is already recorded for the same
2839                   --  language and the same kind, it means that the file
2840                   --  name appears several times in the *_Exceptions
2841                   --  attribute; so there is nothing to do.
2842                end if;
2843
2844                Element_Id := Element.Next;
2845             end loop;
2846          end if;
2847       end Process_Exceptions_File_Based;
2848
2849       -----------------------------------
2850       -- Process_Exceptions_Unit_Based --
2851       -----------------------------------
2852
2853       procedure Process_Exceptions_Unit_Based
2854         (Lang_Id : Language_Ptr;
2855          Kind    : Source_Kind)
2856       is
2857          Lang       : constant Name_Id := Lang_Id.Name;
2858          Exceptions : Array_Element_Id;
2859          Element    : Array_Element;
2860          Unit       : Name_Id;
2861          Index      : Int;
2862          File_Name  : File_Name_Type;
2863          Source     : Source_Id;
2864
2865       begin
2866          case Kind is
2867             when Impl | Sep =>
2868                Exceptions :=
2869                  Value_Of
2870                    (Name_Body,
2871                     In_Arrays => Naming.Decl.Arrays,
2872                     In_Tree   => Data.Tree);
2873
2874                if Exceptions = No_Array_Element then
2875                   Exceptions :=
2876                     Value_Of
2877                       (Name_Implementation,
2878                        In_Arrays => Naming.Decl.Arrays,
2879                        In_Tree   => Data.Tree);
2880                end if;
2881
2882             when Spec =>
2883                Exceptions :=
2884                  Value_Of
2885                    (Name_Spec,
2886                     In_Arrays => Naming.Decl.Arrays,
2887                     In_Tree   => Data.Tree);
2888
2889                if Exceptions = No_Array_Element then
2890                   Exceptions :=
2891                     Value_Of
2892                       (Name_Spec,
2893                        In_Arrays => Naming.Decl.Arrays,
2894                        In_Tree   => Data.Tree);
2895                end if;
2896          end case;
2897
2898          while Exceptions /= No_Array_Element loop
2899             Element   := Data.Tree.Array_Elements.Table (Exceptions);
2900             File_Name := Canonical_Case_File_Name (Element.Value.Value);
2901
2902             Get_Name_String (Element.Index);
2903             To_Lower (Name_Buffer (1 .. Name_Len));
2904             Unit  := Name_Find;
2905             Index := Element.Value.Index;
2906
2907             --  For Ada, check if it is a valid unit name
2908
2909             if Lang = Name_Ada then
2910                Get_Name_String (Element.Index);
2911                Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
2912
2913                if Unit = No_Name then
2914                   Err_Vars.Error_Msg_Name_1 := Element.Index;
2915                   Error_Msg
2916                     (Data.Flags,
2917                      "%% is not a valid unit name.",
2918                      Element.Value.Location, Project);
2919                end if;
2920             end if;
2921
2922             if Unit /= No_Name then
2923                Add_Source
2924                  (Id               => Source,
2925                   Data             => Data,
2926                   Project          => Project,
2927                   Source_Dir_Rank  => 0,
2928                   Lang_Id          => Lang_Id,
2929                   Kind             => Kind,
2930                   File_Name        => File_Name,
2931                   Display_File     => File_Name_Type (Element.Value.Value),
2932                   Unit             => Unit,
2933                   Index            => Index,
2934                   Location         => Element.Value.Location,
2935                   Naming_Exception => True);
2936             end if;
2937
2938             Exceptions := Element.Next;
2939          end loop;
2940       end Process_Exceptions_Unit_Based;
2941
2942       ------------------
2943       -- Check_Naming --
2944       ------------------
2945
2946       procedure Check_Naming is
2947          Dot_Replacement : File_Name_Type :=
2948                              File_Name_Type
2949                                (First_Name_Id + Character'Pos ('-'));
2950          Separate_Suffix : File_Name_Type := No_File;
2951          Casing          : Casing_Type    := All_Lower_Case;
2952          Casing_Defined  : Boolean;
2953          Lang_Id         : Language_Ptr;
2954          Sep_Suffix_Loc  : Source_Ptr;
2955          Suffix          : Variable_Value;
2956          Lang            : Name_Id;
2957
2958       begin
2959          Check_Common
2960            (Dot_Replacement => Dot_Replacement,
2961             Casing          => Casing,
2962             Casing_Defined  => Casing_Defined,
2963             Separate_Suffix => Separate_Suffix,
2964             Sep_Suffix_Loc  => Sep_Suffix_Loc);
2965
2966          --  For all unit based languages, if any, set the specified value
2967          --  of Dot_Replacement, Casing and/or Separate_Suffix. Do not
2968          --  systematically overwrite, since the defaults come from the
2969          --  configuration file.
2970
2971          if Dot_Replacement /= No_File
2972            or else Casing_Defined
2973            or else Separate_Suffix /= No_File
2974          then
2975             Lang_Id := Project.Languages;
2976             while Lang_Id /= No_Language_Index loop
2977                if Lang_Id.Config.Kind = Unit_Based then
2978                   if Dot_Replacement /= No_File then
2979                      Lang_Id.Config.Naming_Data.Dot_Replacement :=
2980                          Dot_Replacement;
2981                   end if;
2982
2983                   if Casing_Defined then
2984                      Lang_Id.Config.Naming_Data.Casing := Casing;
2985                   end if;
2986                end if;
2987
2988                Lang_Id := Lang_Id.Next;
2989             end loop;
2990          end if;
2991
2992          --  Next, get the spec and body suffixes
2993
2994          Lang_Id := Project.Languages;
2995          while Lang_Id /= No_Language_Index loop
2996             Lang := Lang_Id.Name;
2997
2998             --  Spec_Suffix
2999
3000             Suffix := Value_Of
3001               (Name                    => Lang,
3002                Attribute_Or_Array_Name => Name_Spec_Suffix,
3003                In_Package              => Naming_Id,
3004                In_Tree                 => Data.Tree);
3005
3006             if Suffix = Nil_Variable_Value then
3007                Suffix := Value_Of
3008                  (Name                    => Lang,
3009                   Attribute_Or_Array_Name => Name_Specification_Suffix,
3010                   In_Package              => Naming_Id,
3011                   In_Tree                 => Data.Tree);
3012             end if;
3013
3014             if Suffix /= Nil_Variable_Value then
3015                Lang_Id.Config.Naming_Data.Spec_Suffix :=
3016                    File_Name_Type (Suffix.Value);
3017
3018                Check_Illegal_Suffix
3019                  (Project,
3020                   Lang_Id.Config.Naming_Data.Spec_Suffix,
3021                   Lang_Id.Config.Naming_Data.Dot_Replacement,
3022                   "Spec_Suffix", Suffix.Location, Data);
3023
3024                Write_Attr
3025                  ("Spec_Suffix",
3026                   Get_Name_String (Lang_Id.Config.Naming_Data.Spec_Suffix));
3027             end if;
3028
3029             --  Body_Suffix
3030
3031             Suffix :=
3032               Value_Of
3033                 (Name                    => Lang,
3034                  Attribute_Or_Array_Name => Name_Body_Suffix,
3035                  In_Package              => Naming_Id,
3036                  In_Tree                 => Data.Tree);
3037
3038             if Suffix = Nil_Variable_Value then
3039                Suffix :=
3040                  Value_Of
3041                    (Name                    => Lang,
3042                     Attribute_Or_Array_Name => Name_Implementation_Suffix,
3043                     In_Package              => Naming_Id,
3044                     In_Tree                 => Data.Tree);
3045             end if;
3046
3047             if Suffix /= Nil_Variable_Value then
3048                Lang_Id.Config.Naming_Data.Body_Suffix :=
3049                  File_Name_Type (Suffix.Value);
3050
3051                --  The default value of separate suffix should be the same as
3052                --  the body suffix, so we need to compute that first.
3053
3054                if Separate_Suffix = No_File then
3055                   Lang_Id.Config.Naming_Data.Separate_Suffix :=
3056                     Lang_Id.Config.Naming_Data.Body_Suffix;
3057                   Write_Attr
3058                     ("Sep_Suffix",
3059                      Get_Name_String
3060                        (Lang_Id.Config.Naming_Data.Separate_Suffix));
3061                else
3062                   Lang_Id.Config.Naming_Data.Separate_Suffix :=
3063                     Separate_Suffix;
3064                end if;
3065
3066                Check_Illegal_Suffix
3067                  (Project,
3068                   Lang_Id.Config.Naming_Data.Body_Suffix,
3069                   Lang_Id.Config.Naming_Data.Dot_Replacement,
3070                   "Body_Suffix", Suffix.Location, Data);
3071
3072                Write_Attr
3073                  ("Body_Suffix",
3074                   Get_Name_String (Lang_Id.Config.Naming_Data.Body_Suffix));
3075
3076             elsif Separate_Suffix /= No_File then
3077                Lang_Id.Config.Naming_Data.Separate_Suffix := Separate_Suffix;
3078             end if;
3079
3080             --  Spec_Suffix cannot be equal to Body_Suffix or Separate_Suffix,
3081             --  since that would cause a clear ambiguity. Note that we do allow
3082             --  a Spec_Suffix to have the same termination as one of these,
3083             --  which causes a potential ambiguity, but we resolve that my
3084             --  matching the longest possible suffix.
3085
3086             if Lang_Id.Config.Naming_Data.Spec_Suffix /= No_File
3087               and then Lang_Id.Config.Naming_Data.Spec_Suffix =
3088                        Lang_Id.Config.Naming_Data.Body_Suffix
3089             then
3090                Error_Msg
3091                  (Data.Flags,
3092                   "Body_Suffix ("""
3093                   & Get_Name_String (Lang_Id.Config.Naming_Data.Body_Suffix)
3094                   & """) cannot be the same as Spec_Suffix.",
3095                   Ada_Body_Suffix_Loc, Project);
3096             end if;
3097
3098             if Lang_Id.Config.Naming_Data.Body_Suffix /=
3099                Lang_Id.Config.Naming_Data.Separate_Suffix
3100               and then Lang_Id.Config.Naming_Data.Spec_Suffix =
3101                        Lang_Id.Config.Naming_Data.Separate_Suffix
3102             then
3103                Error_Msg
3104                  (Data.Flags,
3105                   "Separate_Suffix ("""
3106                   & Get_Name_String
3107                     (Lang_Id.Config.Naming_Data.Separate_Suffix)
3108                   & """) cannot be the same as Spec_Suffix.",
3109                   Sep_Suffix_Loc, Project);
3110             end if;
3111
3112             Lang_Id := Lang_Id.Next;
3113          end loop;
3114
3115          --  Get the naming exceptions for all languages
3116
3117          for Kind in Spec .. Impl loop
3118             Lang_Id := Project.Languages;
3119             while Lang_Id /= No_Language_Index loop
3120                case Lang_Id.Config.Kind is
3121                   when File_Based =>
3122                      Process_Exceptions_File_Based (Lang_Id, Kind);
3123
3124                   when Unit_Based =>
3125                      Process_Exceptions_Unit_Based (Lang_Id, Kind);
3126                end case;
3127
3128                Lang_Id := Lang_Id.Next;
3129             end loop;
3130          end loop;
3131       end Check_Naming;
3132
3133       ----------------------------
3134       -- Initialize_Naming_Data --
3135       ----------------------------
3136
3137       procedure Initialize_Naming_Data is
3138          Specs : Array_Element_Id :=
3139                    Util.Value_Of
3140                      (Name_Spec_Suffix,
3141                       Naming.Decl.Arrays,
3142                       Data.Tree);
3143
3144          Impls : Array_Element_Id :=
3145                    Util.Value_Of
3146                      (Name_Body_Suffix,
3147                       Naming.Decl.Arrays,
3148                       Data.Tree);
3149
3150          Lang      : Language_Ptr;
3151          Lang_Name : Name_Id;
3152          Value     : Variable_Value;
3153          Extended  : Project_Id;
3154
3155       begin
3156          --  At this stage, the project already contains the default extensions
3157          --  for the various languages. We now merge those suffixes read in the
3158          --  user project, and they override the default.
3159
3160          while Specs /= No_Array_Element loop
3161             Lang_Name := Data.Tree.Array_Elements.Table (Specs).Index;
3162             Lang :=
3163               Get_Language_From_Name
3164                 (Project, Name => Get_Name_String (Lang_Name));
3165
3166             --  An extending project inherits its parent projects' languages
3167             --  so if needed we should create entries for those languages
3168
3169             if Lang = null  then
3170                Extended := Project.Extends;
3171                while Extended /= null loop
3172                   Lang := Get_Language_From_Name
3173                     (Extended, Name => Get_Name_String (Lang_Name));
3174                   exit when Lang /= null;
3175
3176                   Extended := Extended.Extends;
3177                end loop;
3178
3179                if Lang /= null then
3180                   Lang := new Language_Data'(Lang.all);
3181                   Lang.First_Source := null;
3182                   Lang.Next := Project.Languages;
3183                   Project.Languages := Lang;
3184                end if;
3185             end if;
3186
3187             --  If language was not found in project or the projects it extends
3188
3189             if Lang = null then
3190                if Current_Verbosity = High then
3191                   Write_Line
3192                     ("Ignoring spec naming data for "
3193                      & Get_Name_String (Lang_Name)
3194                      & " since language is not defined for this project");
3195                end if;
3196
3197             else
3198                Value := Data.Tree.Array_Elements.Table (Specs).Value;
3199
3200                if Value.Kind = Single then
3201                   Lang.Config.Naming_Data.Spec_Suffix :=
3202                     Canonical_Case_File_Name (Value.Value);
3203                end if;
3204             end if;
3205
3206             Specs := Data.Tree.Array_Elements.Table (Specs).Next;
3207          end loop;
3208
3209          while Impls /= No_Array_Element loop
3210             Lang_Name := Data.Tree.Array_Elements.Table (Impls).Index;
3211             Lang :=
3212               Get_Language_From_Name
3213                 (Project, Name => Get_Name_String (Lang_Name));
3214
3215             if Lang = null then
3216                if Current_Verbosity = High then
3217                   Write_Line
3218                     ("Ignoring impl naming data for "
3219                      & Get_Name_String (Lang_Name)
3220                      & " since language is not defined for this project");
3221                end if;
3222             else
3223                Value := Data.Tree.Array_Elements.Table (Impls).Value;
3224
3225                if Lang.Name = Name_Ada then
3226                   Ada_Body_Suffix_Loc := Value.Location;
3227                end if;
3228
3229                if Value.Kind = Single then
3230                   Lang.Config.Naming_Data.Body_Suffix :=
3231                     Canonical_Case_File_Name (Value.Value);
3232                end if;
3233             end if;
3234
3235             Impls := Data.Tree.Array_Elements.Table (Impls).Next;
3236          end loop;
3237       end Initialize_Naming_Data;
3238
3239    --  Start of processing for Check_Naming_Schemes
3240
3241    begin
3242       Specs  := No_Array_Element;
3243       Bodies := No_Array_Element;
3244
3245       --  No Naming package or parsing a configuration file? nothing to do
3246
3247       if Naming_Id /= No_Package
3248         and then Project.Qualifier /= Configuration
3249       then
3250          Naming := Data.Tree.Packages.Table (Naming_Id);
3251
3252          if Current_Verbosity = High then
3253             Write_Line ("Checking package Naming for project "
3254                         & Get_Name_String (Project.Name));
3255          end if;
3256
3257          Initialize_Naming_Data;
3258          Check_Naming;
3259       end if;
3260    end Check_Package_Naming;
3261
3262    ------------------------------
3263    -- Check_Library_Attributes --
3264    ------------------------------
3265
3266    procedure Check_Library_Attributes
3267      (Project : Project_Id;
3268       Data    : in out Tree_Processing_Data)
3269    is
3270       Attributes   : constant Prj.Variable_Id := Project.Decl.Attributes;
3271
3272       Lib_Dir      : constant Prj.Variable_Value :=
3273                        Prj.Util.Value_Of
3274                          (Snames.Name_Library_Dir, Attributes, Data.Tree);
3275
3276       Lib_Name     : constant Prj.Variable_Value :=
3277                        Prj.Util.Value_Of
3278                          (Snames.Name_Library_Name, Attributes, Data.Tree);
3279
3280       Lib_Version  : constant Prj.Variable_Value :=
3281                        Prj.Util.Value_Of
3282                          (Snames.Name_Library_Version, Attributes, Data.Tree);
3283
3284       Lib_ALI_Dir  : constant Prj.Variable_Value :=
3285                        Prj.Util.Value_Of
3286                          (Snames.Name_Library_Ali_Dir, Attributes, Data.Tree);
3287
3288       Lib_GCC      : constant Prj.Variable_Value :=
3289                        Prj.Util.Value_Of
3290                          (Snames.Name_Library_GCC, Attributes, Data.Tree);
3291
3292       The_Lib_Kind : constant Prj.Variable_Value :=
3293                        Prj.Util.Value_Of
3294                          (Snames.Name_Library_Kind, Attributes, Data.Tree);
3295
3296       Imported_Project_List : Project_List;
3297
3298       Continuation : String_Access := No_Continuation_String'Access;
3299
3300       Support_For_Libraries : Library_Support;
3301
3302       Library_Directory_Present : Boolean;
3303
3304       procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3305       --  Check if an imported or extended project if also a library project
3306
3307       -------------------
3308       -- Check_Library --
3309       -------------------
3310
3311       procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3312          Src_Id : Source_Id;
3313          Iter   : Source_Iterator;
3314
3315       begin
3316          if Proj /= No_Project then
3317             if not Proj.Library then
3318
3319                --  The only not library projects that are OK are those that
3320                --  have no sources. However, header files from non-Ada
3321                --  languages are OK, as there is nothing to compile.
3322
3323                Iter := For_Each_Source (Data.Tree, Proj);
3324                loop
3325                   Src_Id := Prj.Element (Iter);
3326                   exit when Src_Id = No_Source
3327                     or else Src_Id.Language.Config.Kind /= File_Based
3328                     or else Src_Id.Kind /= Spec;
3329                   Next (Iter);
3330                end loop;
3331
3332                if Src_Id /= No_Source then
3333                   Error_Msg_Name_1 := Project.Name;
3334                   Error_Msg_Name_2 := Proj.Name;
3335
3336                   if Extends then
3337                      if Project.Library_Kind /= Static then
3338                         Error_Msg
3339                           (Data.Flags,
3340                            Continuation.all &
3341                            "shared library project %% cannot extend " &
3342                            "project %% that is not a library project",
3343                            Project.Location, Project);
3344                         Continuation := Continuation_String'Access;
3345                      end if;
3346
3347                   elsif (not Unchecked_Shared_Lib_Imports)
3348                         and then Project.Library_Kind /= Static
3349                   then
3350                      Error_Msg
3351                        (Data.Flags,
3352                         Continuation.all &
3353                         "shared library project %% cannot import project %% " &
3354                         "that is not a shared library project",
3355                         Project.Location, Project);
3356                      Continuation := Continuation_String'Access;
3357                   end if;
3358                end if;
3359
3360             elsif Project.Library_Kind /= Static and then
3361                   Proj.Library_Kind = Static
3362             then
3363                Error_Msg_Name_1 := Project.Name;
3364                Error_Msg_Name_2 := Proj.Name;
3365
3366                if Extends then
3367                   Error_Msg
3368                     (Data.Flags,
3369                      Continuation.all &
3370                      "shared library project %% cannot extend static " &
3371                      "library project %%",
3372                      Project.Location, Project);
3373                   Continuation := Continuation_String'Access;
3374
3375                elsif not Unchecked_Shared_Lib_Imports then
3376                   Error_Msg
3377                     (Data.Flags,
3378                      Continuation.all &
3379                      "shared library project %% cannot import static " &
3380                      "library project %%",
3381                      Project.Location, Project);
3382                   Continuation := Continuation_String'Access;
3383                end if;
3384
3385             end if;
3386          end if;
3387       end Check_Library;
3388
3389       Dir_Exists : Boolean;
3390
3391    --  Start of processing for Check_Library_Attributes
3392
3393    begin
3394       Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3395
3396       --  Special case of extending project
3397
3398       if Project.Extends /= No_Project then
3399
3400          --  If the project extended is a library project, we inherit the
3401          --  library name, if it is not redefined; we check that the library
3402          --  directory is specified.
3403
3404          if Project.Extends.Library then
3405             if Project.Qualifier = Standard then
3406                Error_Msg
3407                  (Data.Flags,
3408                   "a standard project cannot extend a library project",
3409                   Project.Location, Project);
3410
3411             else
3412                if Lib_Name.Default then
3413                   Project.Library_Name := Project.Extends.Library_Name;
3414                end if;
3415
3416                if Lib_Dir.Default then
3417                   if not Project.Virtual then
3418                      Error_Msg
3419                        (Data.Flags,
3420                         "a project extending a library project must " &
3421                         "specify an attribute Library_Dir",
3422                         Project.Location, Project);
3423
3424                   else
3425                      --  For a virtual project extending a library project,
3426                      --  inherit library directory.
3427
3428                      Project.Library_Dir := Project.Extends.Library_Dir;
3429                      Library_Directory_Present := True;
3430                   end if;
3431                end if;
3432             end if;
3433          end if;
3434       end if;
3435
3436       pragma Assert (Lib_Name.Kind = Single);
3437
3438       if Lib_Name.Value = Empty_String then
3439          if Current_Verbosity = High
3440            and then Project.Library_Name = No_Name
3441          then
3442             Write_Line ("No library name");
3443          end if;
3444
3445       else
3446          --  There is no restriction on the syntax of library names
3447
3448          Project.Library_Name := Lib_Name.Value;
3449       end if;
3450
3451       if Project.Library_Name /= No_Name then
3452          if Current_Verbosity = High then
3453             Write_Attr
3454               ("Library name", Get_Name_String (Project.Library_Name));
3455          end if;
3456
3457          pragma Assert (Lib_Dir.Kind = Single);
3458
3459          if not Library_Directory_Present then
3460             if Current_Verbosity = High then
3461                Write_Line ("No library directory");
3462             end if;
3463
3464          else
3465             --  Find path name (unless inherited), check that it is a directory
3466
3467             if Project.Library_Dir = No_Path_Information then
3468                Locate_Directory
3469                  (Project,
3470                   File_Name_Type (Lib_Dir.Value),
3471                   Path             => Project.Library_Dir,
3472                   Dir_Exists       => Dir_Exists,
3473                   Data             => Data,
3474                   Create           => "library",
3475                   Must_Exist       => False,
3476                   Location         => Lib_Dir.Location,
3477                   Externally_Built => Project.Externally_Built);
3478
3479             else
3480                Dir_Exists :=
3481                  Is_Directory
3482                    (Get_Name_String
3483                         (Project.Library_Dir.Display_Name));
3484             end if;
3485
3486             if not Dir_Exists then
3487
3488                --  Get the absolute name of the library directory that
3489                --  does not exist, to report an error.
3490
3491                Err_Vars.Error_Msg_File_1 :=
3492                  File_Name_Type (Project.Library_Dir.Display_Name);
3493                Error_Msg
3494                  (Data.Flags,
3495                   "library directory { does not exist",
3496                   Lib_Dir.Location, Project);
3497
3498                --  The library directory cannot be the same as the Object
3499                --  directory.
3500
3501             elsif Project.Library_Dir.Name = Project.Object_Directory.Name then
3502                Error_Msg
3503                  (Data.Flags,
3504                   "library directory cannot be the same " &
3505                   "as object directory",
3506                   Lib_Dir.Location, Project);
3507                Project.Library_Dir := No_Path_Information;
3508
3509             else
3510                declare
3511                   OK       : Boolean := True;
3512                   Dirs_Id  : String_List_Id;
3513                   Dir_Elem : String_Element;
3514                   Pid      : Project_List;
3515
3516                begin
3517                   --  The library directory cannot be the same as a source
3518                   --  directory of the current project.
3519
3520                   Dirs_Id := Project.Source_Dirs;
3521                   while Dirs_Id /= Nil_String loop
3522                      Dir_Elem := Data.Tree.String_Elements.Table (Dirs_Id);
3523                      Dirs_Id  := Dir_Elem.Next;
3524
3525                      if Project.Library_Dir.Name =
3526                        Path_Name_Type (Dir_Elem.Value)
3527                      then
3528                         Err_Vars.Error_Msg_File_1 :=
3529                           File_Name_Type (Dir_Elem.Value);
3530                         Error_Msg
3531                           (Data.Flags,
3532                            "library directory cannot be the same " &
3533                            "as source directory {",
3534                            Lib_Dir.Location, Project);
3535                         OK := False;
3536                         exit;
3537                      end if;
3538                   end loop;
3539
3540                   if OK then
3541
3542                      --  The library directory cannot be the same as a source
3543                      --  directory of another project either.
3544
3545                      Pid := Data.Tree.Projects;
3546                      Project_Loop : loop
3547                         exit Project_Loop when Pid = null;
3548
3549                         if Pid.Project /= Project then
3550                            Dirs_Id := Pid.Project.Source_Dirs;
3551
3552                            Dir_Loop : while Dirs_Id /= Nil_String loop
3553                               Dir_Elem :=
3554                                 Data.Tree.String_Elements.Table (Dirs_Id);
3555                               Dirs_Id  := Dir_Elem.Next;
3556
3557                               if Project.Library_Dir.Name =
3558                                 Path_Name_Type (Dir_Elem.Value)
3559                               then
3560                                  Err_Vars.Error_Msg_File_1 :=
3561                                    File_Name_Type (Dir_Elem.Value);
3562                                  Err_Vars.Error_Msg_Name_1 := Pid.Project.Name;
3563
3564                                  Error_Msg
3565                                    (Data.Flags,
3566                                     "library directory cannot be the same " &
3567                                     "as source directory { of project %%",
3568                                     Lib_Dir.Location, Project);
3569                                  OK := False;
3570                                  exit Project_Loop;
3571                               end if;
3572                            end loop Dir_Loop;
3573                         end if;
3574
3575                         Pid := Pid.Next;
3576                      end loop Project_Loop;
3577                   end if;
3578
3579                   if not OK then
3580                      Project.Library_Dir := No_Path_Information;
3581
3582                   elsif Current_Verbosity = High then
3583
3584                      --  Display the Library directory in high verbosity
3585
3586                      Write_Attr
3587                        ("Library directory",
3588                         Get_Name_String (Project.Library_Dir.Display_Name));
3589                   end if;
3590                end;
3591             end if;
3592          end if;
3593
3594       end if;
3595
3596       Project.Library :=
3597         Project.Library_Dir /= No_Path_Information
3598           and then Project.Library_Name /= No_Name;
3599
3600       if Project.Extends = No_Project then
3601          case Project.Qualifier is
3602             when Standard =>
3603                if Project.Library then
3604                   Error_Msg
3605                     (Data.Flags,
3606                      "a standard project cannot be a library project",
3607                      Lib_Name.Location, Project);
3608                end if;
3609
3610             when Library =>
3611                if not Project.Library then
3612                   if Project.Library_Dir = No_Path_Information then
3613                      Error_Msg
3614                        (Data.Flags,
3615                         "\attribute Library_Dir not declared",
3616                         Project.Location, Project);
3617                   end if;
3618
3619                   if Project.Library_Name = No_Name then
3620                      Error_Msg
3621                        (Data.Flags,
3622                         "\attribute Library_Name not declared",
3623                         Project.Location, Project);
3624                   end if;
3625                end if;
3626
3627             when others =>
3628                null;
3629
3630          end case;
3631       end if;
3632
3633       if Project.Library then
3634          Support_For_Libraries := Project.Config.Lib_Support;
3635
3636          if Support_For_Libraries = Prj.None then
3637             Error_Msg
3638               (Data.Flags,
3639                "?libraries are not supported on this platform",
3640                Lib_Name.Location, Project);
3641             Project.Library := False;
3642
3643          else
3644             if Lib_ALI_Dir.Value = Empty_String then
3645                if Current_Verbosity = High then
3646                   Write_Line ("No library ALI directory specified");
3647                end if;
3648
3649                Project.Library_ALI_Dir := Project.Library_Dir;
3650
3651             else
3652                --  Find path name, check that it is a directory
3653
3654                Locate_Directory
3655                  (Project,
3656                   File_Name_Type (Lib_ALI_Dir.Value),
3657                   Path             => Project.Library_ALI_Dir,
3658                   Create           => "library ALI",
3659                   Dir_Exists       => Dir_Exists,
3660                   Data             => Data,
3661                   Must_Exist       => False,
3662                   Location         => Lib_ALI_Dir.Location,
3663                   Externally_Built => Project.Externally_Built);
3664
3665                if not Dir_Exists then
3666
3667                   --  Get the absolute name of the library ALI directory that
3668                   --  does not exist, to report an error.
3669
3670                   Err_Vars.Error_Msg_File_1 :=
3671                     File_Name_Type (Project.Library_ALI_Dir.Display_Name);
3672                   Error_Msg
3673                     (Data.Flags,
3674                      "library 'A'L'I directory { does not exist",
3675                      Lib_ALI_Dir.Location, Project);
3676                end if;
3677
3678                if Project.Library_ALI_Dir /= Project.Library_Dir then
3679
3680                   --  The library ALI directory cannot be the same as the
3681                   --  Object directory.
3682
3683                   if Project.Library_ALI_Dir = Project.Object_Directory then
3684                      Error_Msg
3685                        (Data.Flags,
3686                         "library 'A'L'I directory cannot be the same " &
3687                         "as object directory",
3688                         Lib_ALI_Dir.Location, Project);
3689                      Project.Library_ALI_Dir := No_Path_Information;
3690
3691                   else
3692                      declare
3693                         OK       : Boolean := True;
3694                         Dirs_Id  : String_List_Id;
3695                         Dir_Elem : String_Element;
3696                         Pid      : Project_List;
3697
3698                      begin
3699                         --  The library ALI directory cannot be the same as
3700                         --  a source directory of the current project.
3701
3702                         Dirs_Id := Project.Source_Dirs;
3703                         while Dirs_Id /= Nil_String loop
3704                            Dir_Elem :=
3705                              Data.Tree.String_Elements.Table (Dirs_Id);
3706                            Dirs_Id  := Dir_Elem.Next;
3707
3708                            if Project.Library_ALI_Dir.Name =
3709                              Path_Name_Type (Dir_Elem.Value)
3710                            then
3711                               Err_Vars.Error_Msg_File_1 :=
3712                                 File_Name_Type (Dir_Elem.Value);
3713                               Error_Msg
3714                                 (Data.Flags,
3715                                  "library 'A'L'I directory cannot be " &
3716                                  "the same as source directory {",
3717                                  Lib_ALI_Dir.Location, Project);
3718                               OK := False;
3719                               exit;
3720                            end if;
3721                         end loop;
3722
3723                         if OK then
3724
3725                            --  The library ALI directory cannot be the same as
3726                            --  a source directory of another project either.
3727
3728                            Pid := Data.Tree.Projects;
3729                            ALI_Project_Loop : loop
3730                               exit ALI_Project_Loop when Pid = null;
3731
3732                               if Pid.Project /= Project then
3733                                  Dirs_Id := Pid.Project.Source_Dirs;
3734
3735                                  ALI_Dir_Loop :
3736                                  while Dirs_Id /= Nil_String loop
3737                                     Dir_Elem :=
3738                                       Data.Tree.String_Elements.Table
3739                                         (Dirs_Id);
3740                                     Dirs_Id  := Dir_Elem.Next;
3741
3742                                     if Project.Library_ALI_Dir.Name =
3743                                         Path_Name_Type (Dir_Elem.Value)
3744                                     then
3745                                        Err_Vars.Error_Msg_File_1 :=
3746                                          File_Name_Type (Dir_Elem.Value);
3747                                        Err_Vars.Error_Msg_Name_1 :=
3748                                          Pid.Project.Name;
3749
3750                                        Error_Msg
3751                                          (Data.Flags,
3752                                           "library 'A'L'I directory cannot " &
3753                                           "be the same as source directory " &
3754                                           "{ of project %%",
3755                                           Lib_ALI_Dir.Location, Project);
3756                                        OK := False;
3757                                        exit ALI_Project_Loop;
3758                                     end if;
3759                                  end loop ALI_Dir_Loop;
3760                               end if;
3761                               Pid := Pid.Next;
3762                            end loop ALI_Project_Loop;
3763                         end if;
3764
3765                         if not OK then
3766                            Project.Library_ALI_Dir := No_Path_Information;
3767
3768                         elsif Current_Verbosity = High then
3769
3770                            --  Display Library ALI directory in high verbosity
3771
3772                            Write_Attr
3773                              ("Library ALI dir",
3774                               Get_Name_String
3775                                 (Project.Library_ALI_Dir.Display_Name));
3776                         end if;
3777                      end;
3778                   end if;
3779                end if;
3780             end if;
3781
3782             pragma Assert (Lib_Version.Kind = Single);
3783
3784             if Lib_Version.Value = Empty_String then
3785                if Current_Verbosity = High then
3786                   Write_Line ("No library version specified");
3787                end if;
3788
3789             else
3790                Project.Lib_Internal_Name := Lib_Version.Value;
3791             end if;
3792
3793             pragma Assert (The_Lib_Kind.Kind = Single);
3794
3795             if The_Lib_Kind.Value = Empty_String then
3796                if Current_Verbosity = High then
3797                   Write_Line ("No library kind specified");
3798                end if;
3799
3800             else
3801                Get_Name_String (The_Lib_Kind.Value);
3802
3803                declare
3804                   Kind_Name : constant String :=
3805                                 To_Lower (Name_Buffer (1 .. Name_Len));
3806
3807                   OK : Boolean := True;
3808
3809                begin
3810                   if Kind_Name = "static" then
3811                      Project.Library_Kind := Static;
3812
3813                   elsif Kind_Name = "dynamic" then
3814                      Project.Library_Kind := Dynamic;
3815
3816                   elsif Kind_Name = "relocatable" then
3817                      Project.Library_Kind := Relocatable;
3818
3819                   else
3820                      Error_Msg
3821                        (Data.Flags,
3822                         "illegal value for Library_Kind",
3823                         The_Lib_Kind.Location, Project);
3824                      OK := False;
3825                   end if;
3826
3827                   if Current_Verbosity = High and then OK then
3828                      Write_Attr ("Library kind", Kind_Name);
3829                   end if;
3830
3831                   if Project.Library_Kind /= Static then
3832                      if Support_For_Libraries = Prj.Static_Only then
3833                         Error_Msg
3834                           (Data.Flags,
3835                            "only static libraries are supported " &
3836                            "on this platform",
3837                            The_Lib_Kind.Location, Project);
3838                         Project.Library := False;
3839
3840                      else
3841                         --  Check if (obsolescent) attribute Library_GCC or
3842                         --  Linker'Driver is declared.
3843
3844                         if Lib_GCC.Value /= Empty_String then
3845                            Error_Msg
3846                              (Data.Flags,
3847                               "?Library_'G'C'C is an obsolescent attribute, " &
3848                               "use Linker''Driver instead",
3849                               Lib_GCC.Location, Project);
3850                            Project.Config.Shared_Lib_Driver :=
3851                              File_Name_Type (Lib_GCC.Value);
3852
3853                         else
3854                            declare
3855                               Linker : constant Package_Id :=
3856                                          Value_Of
3857                                            (Name_Linker,
3858                                             Project.Decl.Packages,
3859                                             Data.Tree);
3860                               Driver : constant Variable_Value :=
3861                                          Value_Of
3862                                            (Name                 => No_Name,
3863                                             Attribute_Or_Array_Name =>
3864                                               Name_Driver,
3865                                             In_Package           => Linker,
3866                                             In_Tree              => Data.Tree);
3867
3868                            begin
3869                               if Driver /= Nil_Variable_Value
3870                                  and then Driver.Value /= Empty_String
3871                               then
3872                                  Project.Config.Shared_Lib_Driver :=
3873                                    File_Name_Type (Driver.Value);
3874                               end if;
3875                            end;
3876                         end if;
3877                      end if;
3878                   end if;
3879                end;
3880             end if;
3881
3882             if Project.Library then
3883                if Current_Verbosity = High then
3884                   Write_Line ("This is a library project file");
3885                end if;
3886
3887                Check_Library (Project.Extends, Extends => True);
3888
3889                Imported_Project_List := Project.Imported_Projects;
3890                while Imported_Project_List /= null loop
3891                   Check_Library
3892                     (Imported_Project_List.Project,
3893                      Extends => False);
3894                   Imported_Project_List := Imported_Project_List.Next;
3895                end loop;
3896             end if;
3897
3898          end if;
3899       end if;
3900
3901       --  Check if Linker'Switches or Linker'Default_Switches are declared.
3902       --  Warn if they are declared, as it is a common error to think that
3903       --  library are "linked" with Linker switches.
3904
3905       if Project.Library then
3906          declare
3907             Linker_Package_Id : constant Package_Id :=
3908                                   Util.Value_Of
3909                                     (Name_Linker,
3910                                      Project.Decl.Packages, Data.Tree);
3911             Linker_Package    : Package_Element;
3912             Switches          : Array_Element_Id := No_Array_Element;
3913
3914          begin
3915             if Linker_Package_Id /= No_Package then
3916                Linker_Package := Data.Tree.Packages.Table (Linker_Package_Id);
3917
3918                Switches :=
3919                  Value_Of
3920                    (Name      => Name_Switches,
3921                     In_Arrays => Linker_Package.Decl.Arrays,
3922                     In_Tree   => Data.Tree);
3923
3924                if Switches = No_Array_Element then
3925                   Switches :=
3926                     Value_Of
3927                       (Name      => Name_Default_Switches,
3928                        In_Arrays => Linker_Package.Decl.Arrays,
3929                        In_Tree   => Data.Tree);
3930                end if;
3931
3932                if Switches /= No_Array_Element then
3933                   Error_Msg
3934                     (Data.Flags,
3935                      "?Linker switches not taken into account in library " &
3936                      "projects",
3937                      No_Location, Project);
3938                end if;
3939             end if;
3940          end;
3941       end if;
3942
3943       if Project.Extends /= No_Project then
3944          Project.Extends.Library := False;
3945       end if;
3946    end Check_Library_Attributes;
3947
3948    ---------------------------------
3949    -- Check_Programming_Languages --
3950    ---------------------------------
3951
3952    procedure Check_Programming_Languages
3953      (Project : Project_Id;
3954       Data    : in out Tree_Processing_Data)
3955    is
3956       Languages   : Variable_Value := Nil_Variable_Value;
3957       Def_Lang    : Variable_Value := Nil_Variable_Value;
3958       Def_Lang_Id : Name_Id;
3959
3960       procedure Add_Language (Name, Display_Name : Name_Id);
3961       --  Add a new language to the list of languages for the project.
3962       --  Nothing is done if the language has already been defined
3963
3964       ------------------
3965       -- Add_Language --
3966       ------------------
3967
3968       procedure Add_Language (Name, Display_Name : Name_Id) is
3969          Lang : Language_Ptr;
3970
3971       begin
3972          Lang := Project.Languages;
3973          while Lang /= No_Language_Index loop
3974             if Name = Lang.Name then
3975                return;
3976             end if;
3977
3978             Lang := Lang.Next;
3979          end loop;
3980
3981          Lang              := new Language_Data'(No_Language_Data);
3982          Lang.Next         := Project.Languages;
3983          Project.Languages := Lang;
3984          Lang.Name         := Name;
3985          Lang.Display_Name := Display_Name;
3986
3987          if Name = Name_Ada then
3988             Lang.Config.Kind            := Unit_Based;
3989             Lang.Config.Dependency_Kind := ALI_File;
3990          else
3991             Lang.Config.Kind := File_Based;
3992          end if;
3993       end Add_Language;
3994
3995    --  Start of processing for Check_Programming_Languages
3996
3997    begin
3998       Project.Languages := null;
3999       Languages :=
4000         Prj.Util.Value_Of (Name_Languages, Project.Decl.Attributes, Data.Tree);
4001       Def_Lang :=
4002         Prj.Util.Value_Of
4003           (Name_Default_Language, Project.Decl.Attributes, Data.Tree);
4004
4005       if Project.Source_Dirs /= Nil_String then
4006
4007          --  Check if languages are specified in this project
4008
4009          if Languages.Default then
4010
4011             --  Fail if there is no default language defined
4012
4013             if Def_Lang.Default then
4014                Error_Msg
4015                  (Data.Flags,
4016                   "no languages defined for this project",
4017                   Project.Location, Project);
4018                Def_Lang_Id := No_Name;
4019
4020             else
4021                Get_Name_String (Def_Lang.Value);
4022                To_Lower (Name_Buffer (1 .. Name_Len));
4023                Def_Lang_Id := Name_Find;
4024             end if;
4025
4026             if Def_Lang_Id /= No_Name then
4027                Get_Name_String (Def_Lang_Id);
4028                Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4029                Add_Language
4030                  (Name         => Def_Lang_Id,
4031                   Display_Name => Name_Find);
4032             end if;
4033
4034          else
4035             declare
4036                Current : String_List_Id := Languages.Values;
4037                Element : String_Element;
4038
4039             begin
4040                --  If there are no languages declared, there are no sources
4041
4042                if Current = Nil_String then
4043                   Project.Source_Dirs := Nil_String;
4044
4045                   if Project.Qualifier = Standard then
4046                      Error_Msg
4047                        (Data.Flags,
4048                         "a standard project must have at least one language",
4049                         Languages.Location, Project);
4050                   end if;
4051
4052                else
4053                   --  Look through all the languages specified in attribute
4054                   --  Languages.
4055
4056                   while Current /= Nil_String loop
4057                      Element := Data.Tree.String_Elements.Table (Current);
4058                      Get_Name_String (Element.Value);
4059                      To_Lower (Name_Buffer (1 .. Name_Len));
4060
4061                      Add_Language
4062                        (Name         => Name_Find,
4063                         Display_Name => Element.Value);
4064
4065                      Current := Element.Next;
4066                   end loop;
4067                end if;
4068             end;
4069          end if;
4070       end if;
4071    end Check_Programming_Languages;
4072
4073    -------------------------------
4074    -- Check_Stand_Alone_Library --
4075    -------------------------------
4076
4077    procedure Check_Stand_Alone_Library
4078      (Project : Project_Id;
4079       Data    : in out Tree_Processing_Data)
4080    is
4081       Lib_Interfaces      : constant Prj.Variable_Value :=
4082                               Prj.Util.Value_Of
4083                                 (Snames.Name_Library_Interface,
4084                                  Project.Decl.Attributes,
4085                                  Data.Tree);
4086
4087       Lib_Auto_Init       : constant Prj.Variable_Value :=
4088                               Prj.Util.Value_Of
4089                                 (Snames.Name_Library_Auto_Init,
4090                                  Project.Decl.Attributes,
4091                                  Data.Tree);
4092
4093       Lib_Src_Dir         : constant Prj.Variable_Value :=
4094                               Prj.Util.Value_Of
4095                                 (Snames.Name_Library_Src_Dir,
4096                                  Project.Decl.Attributes,
4097                                  Data.Tree);
4098
4099       Lib_Symbol_File     : constant Prj.Variable_Value :=
4100                               Prj.Util.Value_Of
4101                                 (Snames.Name_Library_Symbol_File,
4102                                  Project.Decl.Attributes,
4103                                  Data.Tree);
4104
4105       Lib_Symbol_Policy   : constant Prj.Variable_Value :=
4106                               Prj.Util.Value_Of
4107                                 (Snames.Name_Library_Symbol_Policy,
4108                                  Project.Decl.Attributes,
4109                                  Data.Tree);
4110
4111       Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4112                               Prj.Util.Value_Of
4113                                 (Snames.Name_Library_Reference_Symbol_File,
4114                                  Project.Decl.Attributes,
4115                                  Data.Tree);
4116
4117       Auto_Init_Supported : Boolean;
4118       OK                  : Boolean := True;
4119       Source              : Source_Id;
4120       Next_Proj           : Project_Id;
4121       Iter                : Source_Iterator;
4122
4123    begin
4124       Auto_Init_Supported := Project.Config.Auto_Init_Supported;
4125
4126       pragma Assert (Lib_Interfaces.Kind = List);
4127
4128       --  It is a stand-alone library project file if attribute
4129       --  Library_Interface is defined.
4130
4131       if not Lib_Interfaces.Default then
4132          declare
4133             Interfaces     : String_List_Id := Lib_Interfaces.Values;
4134             Interface_ALIs : String_List_Id := Nil_String;
4135             Unit           : Name_Id;
4136
4137          begin
4138             Project.Standalone_Library := True;
4139
4140             --  Library_Interface cannot be an empty list
4141
4142             if Interfaces = Nil_String then
4143                Error_Msg
4144                  (Data.Flags,
4145                   "Library_Interface cannot be an empty list",
4146                   Lib_Interfaces.Location, Project);
4147             end if;
4148
4149             --  Process each unit name specified in the attribute
4150             --  Library_Interface.
4151
4152             while Interfaces /= Nil_String loop
4153                Get_Name_String
4154                  (Data.Tree.String_Elements.Table (Interfaces).Value);
4155                To_Lower (Name_Buffer (1 .. Name_Len));
4156
4157                if Name_Len = 0 then
4158                   Error_Msg
4159                     (Data.Flags,
4160                      "an interface cannot be an empty string",
4161                      Data.Tree.String_Elements.Table (Interfaces).Location,
4162                      Project);
4163
4164                else
4165                   Unit := Name_Find;
4166                   Error_Msg_Name_1 := Unit;
4167
4168                   Next_Proj := Project.Extends;
4169                   Iter := For_Each_Source (Data.Tree, Project);
4170                   loop
4171                      while Prj.Element (Iter) /= No_Source
4172                        and then
4173                          (Prj.Element (Iter).Unit = null
4174                            or else Prj.Element (Iter).Unit.Name /= Unit)
4175                      loop
4176                         Next (Iter);
4177                      end loop;
4178
4179                      Source := Prj.Element (Iter);
4180                      exit when Source /= No_Source
4181                        or else Next_Proj = No_Project;
4182
4183                      Iter := For_Each_Source (Data.Tree, Next_Proj);
4184                      Next_Proj := Next_Proj.Extends;
4185                   end loop;
4186
4187                   if Source /= No_Source then
4188                      if Source.Kind = Sep then
4189                         Source := No_Source;
4190
4191                      elsif Source.Kind = Spec
4192                        and then Other_Part (Source) /= No_Source
4193                      then
4194                         Source := Other_Part (Source);
4195                      end if;
4196                   end if;
4197
4198                   if Source /= No_Source then
4199                      if Source.Project /= Project
4200                        and then not Is_Extending (Project, Source.Project)
4201                      then
4202                         Source := No_Source;
4203                      end if;
4204                   end if;
4205
4206                   if Source = No_Source then
4207                      Error_Msg
4208                        (Data.Flags,
4209                         "%% is not a unit of this project",
4210                         Data.Tree.String_Elements.Table
4211                           (Interfaces).Location, Project);
4212
4213                   else
4214                      if Source.Kind = Spec
4215                        and then Other_Part (Source) /= No_Source
4216                      then
4217                         Source := Other_Part (Source);
4218                      end if;
4219
4220                      String_Element_Table.Increment_Last
4221                        (Data.Tree.String_Elements);
4222
4223                      Data.Tree.String_Elements.Table
4224                        (String_Element_Table.Last
4225                           (Data.Tree.String_Elements)) :=
4226                        (Value         => Name_Id (Source.Dep_Name),
4227                         Index         => 0,
4228                         Display_Value => Name_Id (Source.Dep_Name),
4229                         Location      =>
4230                           Data.Tree.String_Elements.Table
4231                             (Interfaces).Location,
4232                         Flag          => False,
4233                         Next          => Interface_ALIs);
4234
4235                      Interface_ALIs :=
4236                        String_Element_Table.Last
4237                          (Data.Tree.String_Elements);
4238                   end if;
4239                end if;
4240
4241                Interfaces := Data.Tree.String_Elements.Table (Interfaces).Next;
4242             end loop;
4243
4244             --  Put the list of Interface ALIs in the project data
4245
4246             Project.Lib_Interface_ALIs := Interface_ALIs;
4247
4248             --  Check value of attribute Library_Auto_Init and set
4249             --  Lib_Auto_Init accordingly.
4250
4251             if Lib_Auto_Init.Default then
4252
4253                --  If no attribute Library_Auto_Init is declared, then set auto
4254                --  init only if it is supported.
4255
4256                Project.Lib_Auto_Init := Auto_Init_Supported;
4257
4258             else
4259                Get_Name_String (Lib_Auto_Init.Value);
4260                To_Lower (Name_Buffer (1 .. Name_Len));
4261
4262                if Name_Buffer (1 .. Name_Len) = "false" then
4263                   Project.Lib_Auto_Init := False;
4264
4265                elsif Name_Buffer (1 .. Name_Len) = "true" then
4266                   if Auto_Init_Supported then
4267                      Project.Lib_Auto_Init := True;
4268
4269                   else
4270                      --  Library_Auto_Init cannot be "true" if auto init is not
4271                      --  supported.
4272
4273                      Error_Msg
4274                        (Data.Flags,
4275                         "library auto init not supported " &
4276                         "on this platform",
4277                         Lib_Auto_Init.Location, Project);
4278                   end if;
4279
4280                else
4281                   Error_Msg
4282                     (Data.Flags,
4283                      "invalid value for attribute Library_Auto_Init",
4284                      Lib_Auto_Init.Location, Project);
4285                end if;
4286             end if;
4287          end;
4288
4289          --  If attribute Library_Src_Dir is defined and not the empty string,
4290          --  check if the directory exist and is not the object directory or
4291          --  one of the source directories. This is the directory where copies
4292          --  of the interface sources will be copied. Note that this directory
4293          --  may be the library directory.
4294
4295          if Lib_Src_Dir.Value /= Empty_String then
4296             declare
4297                Dir_Id     : constant File_Name_Type :=
4298                               File_Name_Type (Lib_Src_Dir.Value);
4299                Dir_Exists : Boolean;
4300
4301             begin
4302                Locate_Directory
4303                  (Project,
4304                   Dir_Id,
4305                   Path             => Project.Library_Src_Dir,
4306                   Dir_Exists       => Dir_Exists,
4307                   Data             => Data,
4308                   Must_Exist       => False,
4309                   Create           => "library source copy",
4310                   Location         => Lib_Src_Dir.Location,
4311                   Externally_Built => Project.Externally_Built);
4312
4313                --  If directory does not exist, report an error
4314
4315                if not Dir_Exists then
4316
4317                   --  Get the absolute name of the library directory that does
4318                   --  not exist, to report an error.
4319
4320                   Err_Vars.Error_Msg_File_1 :=
4321                     File_Name_Type (Project.Library_Src_Dir.Display_Name);
4322                   Error_Msg
4323                     (Data.Flags,
4324                      "Directory { does not exist",
4325                      Lib_Src_Dir.Location, Project);
4326
4327                   --  Report error if it is the same as the object directory
4328
4329                elsif Project.Library_Src_Dir = Project.Object_Directory then
4330                   Error_Msg
4331                     (Data.Flags,
4332                      "directory to copy interfaces cannot be " &
4333                      "the object directory",
4334                      Lib_Src_Dir.Location, Project);
4335                   Project.Library_Src_Dir := No_Path_Information;
4336
4337                else
4338                   declare
4339                      Src_Dirs : String_List_Id;
4340                      Src_Dir  : String_Element;
4341                      Pid      : Project_List;
4342
4343                   begin
4344                      --  Interface copy directory cannot be one of the source
4345                      --  directory of the current project.
4346
4347                      Src_Dirs := Project.Source_Dirs;
4348                      while Src_Dirs /= Nil_String loop
4349                         Src_Dir := Data.Tree.String_Elements.Table (Src_Dirs);
4350
4351                         --  Report error if it is one of the source directories
4352
4353                         if Project.Library_Src_Dir.Name =
4354                              Path_Name_Type (Src_Dir.Value)
4355                         then
4356                            Error_Msg
4357                              (Data.Flags,
4358                               "directory to copy interfaces cannot " &
4359                               "be one of the source directories",
4360                               Lib_Src_Dir.Location, Project);
4361                            Project.Library_Src_Dir := No_Path_Information;
4362                            exit;
4363                         end if;
4364
4365                         Src_Dirs := Src_Dir.Next;
4366                      end loop;
4367
4368                      if Project.Library_Src_Dir /= No_Path_Information then
4369
4370                         --  It cannot be a source directory of any other
4371                         --  project either.
4372
4373                         Pid := Data.Tree.Projects;
4374                         Project_Loop : loop
4375                            exit Project_Loop when Pid = null;
4376
4377                            Src_Dirs := Pid.Project.Source_Dirs;
4378                            Dir_Loop : while Src_Dirs /= Nil_String loop
4379                               Src_Dir :=
4380                                 Data.Tree.String_Elements.Table (Src_Dirs);
4381
4382                               --  Report error if it is one of the source
4383                               --  directories.
4384
4385                               if Project.Library_Src_Dir.Name =
4386                                 Path_Name_Type (Src_Dir.Value)
4387                               then
4388                                  Error_Msg_File_1 :=
4389                                    File_Name_Type (Src_Dir.Value);
4390                                  Error_Msg_Name_1 := Pid.Project.Name;
4391                                  Error_Msg
4392                                    (Data.Flags,
4393                                     "directory to copy interfaces cannot " &
4394                                     "be the same as source directory { of " &
4395                                     "project %%",
4396                                     Lib_Src_Dir.Location, Project);
4397                                  Project.Library_Src_Dir :=
4398                                    No_Path_Information;
4399                                  exit Project_Loop;
4400                               end if;
4401
4402                               Src_Dirs := Src_Dir.Next;
4403                            end loop Dir_Loop;
4404
4405                            Pid := Pid.Next;
4406                         end loop Project_Loop;
4407                      end if;
4408                   end;
4409
4410                   --  In high verbosity, if there is a valid Library_Src_Dir,
4411                   --  display its path name.
4412
4413                   if Project.Library_Src_Dir /= No_Path_Information
4414                     and then Current_Verbosity = High
4415                   then
4416                      Write_Attr
4417                        ("Directory to copy interfaces",
4418                         Get_Name_String (Project.Library_Src_Dir.Name));
4419                   end if;
4420                end if;
4421             end;
4422          end if;
4423
4424          --  Check the symbol related attributes
4425
4426          --  First, the symbol policy
4427
4428          if not Lib_Symbol_Policy.Default then
4429             declare
4430                Value : constant String :=
4431                          To_Lower
4432                            (Get_Name_String (Lib_Symbol_Policy.Value));
4433
4434             begin
4435                --  Symbol policy must hove one of a limited number of values
4436
4437                if Value = "autonomous" or else Value = "default" then
4438                   Project.Symbol_Data.Symbol_Policy := Autonomous;
4439
4440                elsif Value = "compliant" then
4441                   Project.Symbol_Data.Symbol_Policy := Compliant;
4442
4443                elsif Value = "controlled" then
4444                   Project.Symbol_Data.Symbol_Policy := Controlled;
4445
4446                elsif Value = "restricted" then
4447                   Project.Symbol_Data.Symbol_Policy := Restricted;
4448
4449                elsif Value = "direct" then
4450                   Project.Symbol_Data.Symbol_Policy := Direct;
4451
4452                else
4453                   Error_Msg
4454                     (Data.Flags,
4455                      "illegal value for Library_Symbol_Policy",
4456                      Lib_Symbol_Policy.Location, Project);
4457                end if;
4458             end;
4459          end if;
4460
4461          --  If attribute Library_Symbol_File is not specified, symbol policy
4462          --  cannot be Restricted.
4463
4464          if Lib_Symbol_File.Default then
4465             if Project.Symbol_Data.Symbol_Policy = Restricted then
4466                Error_Msg
4467                  (Data.Flags,
4468                   "Library_Symbol_File needs to be defined when " &
4469                   "symbol policy is Restricted",
4470                   Lib_Symbol_Policy.Location, Project);
4471             end if;
4472
4473          else
4474             --  Library_Symbol_File is defined
4475
4476             Project.Symbol_Data.Symbol_File :=
4477               Path_Name_Type (Lib_Symbol_File.Value);
4478
4479             Get_Name_String (Lib_Symbol_File.Value);
4480
4481             if Name_Len = 0 then
4482                Error_Msg
4483                  (Data.Flags,
4484                   "symbol file name cannot be an empty string",
4485                   Lib_Symbol_File.Location, Project);
4486
4487             else
4488                OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
4489
4490                if OK then
4491                   for J in 1 .. Name_Len loop
4492                      if Name_Buffer (J) = '/'
4493                        or else Name_Buffer (J) = Directory_Separator
4494                      then
4495                         OK := False;
4496                         exit;
4497                      end if;
4498                   end loop;
4499                end if;
4500
4501                if not OK then
4502                   Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
4503                   Error_Msg
4504                     (Data.Flags,
4505                      "symbol file name { is illegal. " &
4506                      "Name cannot include directory info.",
4507                      Lib_Symbol_File.Location, Project);
4508                end if;
4509             end if;
4510          end if;
4511
4512          --  If attribute Library_Reference_Symbol_File is not defined,
4513          --  symbol policy cannot be Compliant or Controlled.
4514
4515          if Lib_Ref_Symbol_File.Default then
4516             if Project.Symbol_Data.Symbol_Policy = Compliant
4517               or else Project.Symbol_Data.Symbol_Policy = Controlled
4518             then
4519                Error_Msg
4520                  (Data.Flags,
4521                   "a reference symbol file needs to be defined",
4522                   Lib_Symbol_Policy.Location, Project);
4523             end if;
4524
4525          else
4526             --  Library_Reference_Symbol_File is defined, check file exists
4527
4528             Project.Symbol_Data.Reference :=
4529               Path_Name_Type (Lib_Ref_Symbol_File.Value);
4530
4531             Get_Name_String (Lib_Ref_Symbol_File.Value);
4532
4533             if Name_Len = 0 then
4534                Error_Msg
4535                  (Data.Flags,
4536                   "reference symbol file name cannot be an empty string",
4537                   Lib_Symbol_File.Location, Project);
4538
4539             else
4540                if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
4541                   Name_Len := 0;
4542                   Add_Str_To_Name_Buffer
4543                     (Get_Name_String (Project.Directory.Name));
4544                   Add_Str_To_Name_Buffer
4545                     (Get_Name_String (Lib_Ref_Symbol_File.Value));
4546                   Project.Symbol_Data.Reference := Name_Find;
4547                end if;
4548
4549                if not Is_Regular_File
4550                         (Get_Name_String (Project.Symbol_Data.Reference))
4551                then
4552                   Error_Msg_File_1 :=
4553                     File_Name_Type (Lib_Ref_Symbol_File.Value);
4554
4555                   --  For controlled and direct symbol policies, it is an error
4556                   --  if the reference symbol file does not exist. For other
4557                   --  symbol policies, this is just a warning
4558
4559                   Error_Msg_Warn :=
4560                     Project.Symbol_Data.Symbol_Policy /= Controlled
4561                     and then Project.Symbol_Data.Symbol_Policy /= Direct;
4562
4563                   Error_Msg
4564                     (Data.Flags,
4565                      "<library reference symbol file { does not exist",
4566                      Lib_Ref_Symbol_File.Location, Project);
4567
4568                   --  In addition in the non-controlled case, if symbol policy
4569                   --  is Compliant, it is changed to Autonomous, because there
4570                   --  is no reference to check against, and we don't want to
4571                   --  fail in this case.
4572
4573                   if Project.Symbol_Data.Symbol_Policy /= Controlled then
4574                      if Project.Symbol_Data.Symbol_Policy = Compliant then
4575                         Project.Symbol_Data.Symbol_Policy := Autonomous;
4576                      end if;
4577                   end if;
4578                end if;
4579
4580                --  If both the reference symbol file and the symbol file are
4581                --  defined, then check that they are not the same file.
4582
4583                if Project.Symbol_Data.Symbol_File /= No_Path then
4584                   Get_Name_String (Project.Symbol_Data.Symbol_File);
4585
4586                   if Name_Len > 0 then
4587                      declare
4588                         --  We do not need to pass a Directory to
4589                         --  Normalize_Pathname, since the path_information
4590                         --  already contains absolute information.
4591
4592                         Symb_Path : constant String :=
4593                                       Normalize_Pathname
4594                                         (Get_Name_String
4595                                            (Project.Object_Directory.Name) &
4596                                          Name_Buffer (1 .. Name_Len),
4597                                          Directory     => "/",
4598                                          Resolve_Links =>
4599                                            Opt.Follow_Links_For_Files);
4600                         Ref_Path  : constant String :=
4601                                       Normalize_Pathname
4602                                         (Get_Name_String
4603                                            (Project.Symbol_Data.Reference),
4604                                          Directory     => "/",
4605                                          Resolve_Links =>
4606                                            Opt.Follow_Links_For_Files);
4607                      begin
4608                         if Symb_Path = Ref_Path then
4609                            Error_Msg
4610                              (Data.Flags,
4611                               "library reference symbol file and library" &
4612                               " symbol file cannot be the same file",
4613                               Lib_Ref_Symbol_File.Location, Project);
4614                         end if;
4615                      end;
4616                   end if;
4617                end if;
4618             end if;
4619          end if;
4620       end if;
4621    end Check_Stand_Alone_Library;
4622
4623    ----------------------------
4624    -- Compute_Directory_Last --
4625    ----------------------------
4626
4627    function Compute_Directory_Last (Dir : String) return Natural is
4628    begin
4629       if Dir'Length > 1
4630         and then (Dir (Dir'Last - 1) = Directory_Separator
4631                     or else
4632                   Dir (Dir'Last - 1) = '/')
4633       then
4634          return Dir'Last - 1;
4635       else
4636          return Dir'Last;
4637       end if;
4638    end Compute_Directory_Last;
4639
4640    ---------------------
4641    -- Get_Directories --
4642    ---------------------
4643
4644    procedure Get_Directories
4645      (Project     : Project_Id;
4646       Data        : in out Tree_Processing_Data)
4647    is
4648       package Recursive_Dirs is new GNAT.Dynamic_HTables.Simple_HTable
4649         (Header_Num => Header_Num,
4650          Element    => Boolean,
4651          No_Element => False,
4652          Key        => Name_Id,
4653          Hash       => Hash,
4654          Equal      => "=");
4655       --  Hash table stores recursive source directories, to avoid looking
4656       --  several times, and to avoid cycles that may be introduced by symbolic
4657       --  links.
4658
4659       Visited : Recursive_Dirs.Instance;
4660
4661       Object_Dir  : constant Variable_Value :=
4662                       Util.Value_Of
4663                         (Name_Object_Dir, Project.Decl.Attributes, Data.Tree);
4664
4665       Exec_Dir : constant Variable_Value :=
4666                    Util.Value_Of
4667                      (Name_Exec_Dir, Project.Decl.Attributes, Data.Tree);
4668
4669       Source_Dirs : constant Variable_Value :=
4670                       Util.Value_Of
4671                         (Name_Source_Dirs, Project.Decl.Attributes, Data.Tree);
4672
4673       Excluded_Source_Dirs : constant Variable_Value :=
4674                               Util.Value_Of
4675                                 (Name_Excluded_Source_Dirs,
4676                                  Project.Decl.Attributes,
4677                                  Data.Tree);
4678
4679       Source_Files : constant Variable_Value :=
4680                       Util.Value_Of
4681                         (Name_Source_Files,
4682                          Project.Decl.Attributes, Data.Tree);
4683
4684       Last_Source_Dir   : String_List_Id    := Nil_String;
4685       Last_Src_Dir_Rank : Number_List_Index := No_Number_List;
4686
4687       Languages : constant Variable_Value :=
4688                       Prj.Util.Value_Of
4689                         (Name_Languages, Project.Decl.Attributes, Data.Tree);
4690
4691       procedure Find_Source_Dirs
4692         (From     : File_Name_Type;
4693          Location : Source_Ptr;
4694          Rank     : Natural;
4695          Removed  : Boolean := False);
4696       --  Find one or several source directories, and add (or remove, if
4697       --  Removed is True) them to list of source directories of the project.
4698
4699       ----------------------
4700       -- Find_Source_Dirs --
4701       ----------------------
4702
4703       procedure Find_Source_Dirs
4704         (From     : File_Name_Type;
4705          Location : Source_Ptr;
4706          Rank     : Natural;
4707          Removed  : Boolean := False)
4708       is
4709          Directory : constant String := Get_Name_String (From);
4710
4711          procedure Add_To_Or_Remove_From_List
4712            (Path_Id         : Name_Id;
4713             Display_Path_Id : Name_Id);
4714          --  When Removed = False, the directory Path_Id to the list of
4715          --  source_dirs if not already in the list. When Removed = True,
4716          --  removed directory Path_Id if in the list.
4717
4718          procedure Recursive_Find_Dirs (Path : Name_Id);
4719          --  Find all the subdirectories (recursively) of Path and add them
4720          --  to the list of source directories of the project.
4721
4722          --------------------------------
4723          -- Add_To_Or_Remove_From_List --
4724          --------------------------------
4725
4726          procedure Add_To_Or_Remove_From_List
4727            (Path_Id         : Name_Id;
4728             Display_Path_Id : Name_Id)
4729          is
4730             List       : String_List_Id;
4731             Prev       : String_List_Id;
4732             Rank_List  : Number_List_Index;
4733             Prev_Rank  : Number_List_Index;
4734             Element    : String_Element;
4735
4736          begin
4737             Prev      := Nil_String;
4738             Prev_Rank := No_Number_List;
4739             List      := Project.Source_Dirs;
4740             Rank_List := Project.Source_Dir_Ranks;
4741             while List /= Nil_String loop
4742                Element := Data.Tree.String_Elements.Table (List);
4743                exit when Element.Value = Path_Id;
4744                Prev := List;
4745                List := Element.Next;
4746                Prev_Rank := Rank_List;
4747                Rank_List := Data.Tree.Number_Lists.Table (Prev_Rank).Next;
4748             end loop;
4749
4750             --  The directory is in the list if List is not Nil_String
4751
4752             if not Removed and then List = Nil_String then
4753                if Current_Verbosity = High then
4754                   Write_Str  ("   Adding Source Dir=");
4755                   Write_Line (Get_Name_String (Path_Id));
4756                end if;
4757
4758                String_Element_Table.Increment_Last (Data.Tree.String_Elements);
4759                Element :=
4760                  (Value         => Path_Id,
4761                   Index         => 0,
4762                   Display_Value => Display_Path_Id,
4763                   Location      => No_Location,
4764                   Flag          => False,
4765                   Next          => Nil_String);
4766
4767                Number_List_Table.Increment_Last (Data.Tree.Number_Lists);
4768
4769                if Last_Source_Dir = Nil_String then
4770
4771                   --  This is the first source directory
4772
4773                   Project.Source_Dirs :=
4774                     String_Element_Table.Last (Data.Tree.String_Elements);
4775                   Project.Source_Dir_Ranks :=
4776                     Number_List_Table.Last (Data.Tree.Number_Lists);
4777
4778                else
4779                   --  We already have source directories, link the previous
4780                   --  last to the new one.
4781
4782                   Data.Tree.String_Elements.Table (Last_Source_Dir).Next :=
4783                     String_Element_Table.Last (Data.Tree.String_Elements);
4784                   Data.Tree.Number_Lists.Table (Last_Src_Dir_Rank).Next :=
4785                     Number_List_Table.Last (Data.Tree.Number_Lists);
4786                end if;
4787
4788                --  And register this source directory as the new last
4789
4790                Last_Source_Dir :=
4791                  String_Element_Table.Last (Data.Tree.String_Elements);
4792                Data.Tree.String_Elements.Table (Last_Source_Dir) := Element;
4793                Last_Src_Dir_Rank :=
4794                  Number_List_Table.Last (Data.Tree.Number_Lists);
4795                Data.Tree.Number_Lists.Table (Last_Src_Dir_Rank) :=
4796                  (Number => Rank, Next => No_Number_List);
4797
4798             elsif Removed and then List /= Nil_String then
4799
4800                --  Remove source dir, if present
4801
4802                if Prev = Nil_String then
4803                   Project.Source_Dirs :=
4804                     Data.Tree.String_Elements.Table (List).Next;
4805                   Project.Source_Dir_Ranks :=
4806                     Data.Tree.Number_Lists.Table (Rank_List).Next;
4807
4808                else
4809                   Data.Tree.String_Elements.Table (Prev).Next :=
4810                     Data.Tree.String_Elements.Table (List).Next;
4811                   Data.Tree.Number_Lists.Table (Prev_Rank).Next :=
4812                     Data.Tree.Number_Lists.Table (Rank_List).Next;
4813                end if;
4814             end if;
4815          end Add_To_Or_Remove_From_List;
4816
4817          -------------------------
4818          -- Recursive_Find_Dirs --
4819          -------------------------
4820
4821          procedure Recursive_Find_Dirs (Path : Name_Id) is
4822             Dir  : Dir_Type;
4823             Name : String (1 .. 250);
4824             Last : Natural;
4825
4826             Non_Canonical_Path : Name_Id := No_Name;
4827             Canonical_Path     : Name_Id := No_Name;
4828
4829             The_Path : constant String :=
4830                          Normalize_Pathname
4831                            (Get_Name_String (Path),
4832                             Directory     =>
4833                               Get_Name_String (Project.Directory.Display_Name),
4834                             Resolve_Links => Opt.Follow_Links_For_Dirs) &
4835                          Directory_Separator;
4836
4837             The_Path_Last : constant Natural :=
4838                               Compute_Directory_Last (The_Path);
4839
4840          begin
4841             Name_Len := The_Path_Last - The_Path'First + 1;
4842             Name_Buffer (1 .. Name_Len) :=
4843               The_Path (The_Path'First .. The_Path_Last);
4844             Non_Canonical_Path := Name_Find;
4845             Canonical_Path :=
4846               Name_Id (Canonical_Case_File_Name (Non_Canonical_Path));
4847
4848             --  To avoid processing the same directory several times, check
4849             --  if the directory is already in Recursive_Dirs. If it is, then
4850             --  there is nothing to do, just return. If it is not, put it there
4851             --  and continue recursive processing.
4852
4853             if not Removed then
4854                if Recursive_Dirs.Get (Visited, Canonical_Path) then
4855                   return;
4856                else
4857                   Recursive_Dirs.Set (Visited, Canonical_Path, True);
4858                end if;
4859             end if;
4860
4861             Add_To_Or_Remove_From_List
4862               (Path_Id         => Canonical_Path,
4863                Display_Path_Id => Non_Canonical_Path);
4864
4865             --  Now look for subdirectories. Do that even when this directory
4866             --  is already in the list, because some of its subdirectories may
4867             --  not be in the list yet.
4868
4869             Open (Dir, The_Path (The_Path'First .. The_Path_Last));
4870
4871             loop
4872                Read (Dir, Name, Last);
4873                exit when Last = 0;
4874
4875                if Name (1 .. Last) /= "."
4876                  and then Name (1 .. Last) /= ".."
4877                then
4878                   --  Avoid . and .. directories
4879
4880                   if Current_Verbosity = High then
4881                      Write_Str  ("   Checking ");
4882                      Write_Line (Name (1 .. Last));
4883                   end if;
4884
4885                   declare
4886                      Path_Name : constant String :=
4887                                    Normalize_Pathname
4888                                      (Name           => Name (1 .. Last),
4889                                       Directory      =>
4890                                         The_Path
4891                                           (The_Path'First .. The_Path_Last),
4892                                       Resolve_Links  =>
4893                                         Opt.Follow_Links_For_Dirs,
4894                                       Case_Sensitive => True);
4895
4896                   begin
4897                      if Is_Directory (Path_Name) then
4898
4899                         --  We have found a new subdirectory, call self
4900
4901                         Name_Len := Path_Name'Length;
4902                         Name_Buffer (1 .. Name_Len) := Path_Name;
4903                         Recursive_Find_Dirs (Name_Find);
4904                      end if;
4905                   end;
4906                end if;
4907             end loop;
4908
4909             Close (Dir);
4910
4911          exception
4912             when Directory_Error =>
4913                null;
4914          end Recursive_Find_Dirs;
4915
4916       --  Start of processing for Find_Source_Dirs
4917
4918       begin
4919          if Current_Verbosity = High and then not Removed then
4920             Write_Str ("Find_Source_Dirs (""");
4921             Write_Str (Directory);
4922             Write_Str (",");
4923             Write_Str (Rank'Img);
4924             Write_Line (""")");
4925          end if;
4926
4927          --  First, check if we are looking for a directory tree, indicated
4928          --  by "/**" at the end.
4929
4930          if Directory'Length >= 3
4931            and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
4932            and then (Directory (Directory'Last - 2) = '/'
4933                        or else
4934                      Directory (Directory'Last - 2) = Directory_Separator)
4935          then
4936             Name_Len := Directory'Length - 3;
4937
4938             if Name_Len = 0 then
4939
4940                --  Case of "/**": all directories in file system
4941
4942                Name_Len := 1;
4943                Name_Buffer (1) := Directory (Directory'First);
4944
4945             else
4946                Name_Buffer (1 .. Name_Len) :=
4947                  Directory (Directory'First .. Directory'Last - 3);
4948             end if;
4949
4950             if Current_Verbosity = High then
4951                Write_Str ("Looking for all subdirectories of """);
4952                Write_Str (Name_Buffer (1 .. Name_Len));
4953                Write_Line ("""");
4954             end if;
4955
4956             declare
4957                Base_Dir : constant File_Name_Type := Name_Find;
4958                Root_Dir : constant String :=
4959                             Normalize_Pathname
4960                               (Name      => Get_Name_String (Base_Dir),
4961                                Directory =>
4962                                  Get_Name_String
4963                                    (Project.Directory.Display_Name),
4964                                Resolve_Links  =>
4965                                  Opt.Follow_Links_For_Dirs,
4966                                Case_Sensitive => True);
4967
4968             begin
4969                if Root_Dir'Length = 0 then
4970                   Err_Vars.Error_Msg_File_1 := Base_Dir;
4971
4972                   if Location = No_Location then
4973                      Error_Msg
4974                        (Data.Flags,
4975                         "{ is not a valid directory.",
4976                         Project.Location, Project);
4977                   else
4978                      Error_Msg
4979                        (Data.Flags,
4980                         "{ is not a valid directory.",
4981                         Location, Project);
4982                   end if;
4983
4984                else
4985                   --  We have an existing directory, we register it and all of
4986                   --  its subdirectories.
4987
4988                   if Current_Verbosity = High then
4989                      Write_Line ("Looking for source directories:");
4990                   end if;
4991
4992                   Name_Len := Root_Dir'Length;
4993                   Name_Buffer (1 .. Name_Len) := Root_Dir;
4994                   Recursive_Find_Dirs (Name_Find);
4995
4996                   if Current_Verbosity = High then
4997                      Write_Line ("End of looking for source directories.");
4998                   end if;
4999                end if;
5000             end;
5001
5002          --  We have a single directory
5003
5004          else
5005             declare
5006                Path_Name  : Path_Information;
5007                Dir_Exists : Boolean;
5008
5009             begin
5010                Locate_Directory
5011                  (Project     => Project,
5012                   Name        => From,
5013                   Path        => Path_Name,
5014                   Dir_Exists  => Dir_Exists,
5015                   Data        => Data,
5016                   Must_Exist  => False);
5017
5018                if not Dir_Exists then
5019                   Err_Vars.Error_Msg_File_1 := From;
5020
5021                   if Location = No_Location then
5022                      Error_Msg
5023                        (Data.Flags,
5024                         "{ is not a valid directory",
5025                         Project.Location, Project);
5026                   else
5027                      Error_Msg
5028                        (Data.Flags,
5029                         "{ is not a valid directory",
5030                         Location, Project);
5031                   end if;
5032
5033                else
5034                   declare
5035                      Path : constant String :=
5036                               Normalize_Pathname
5037                                 (Name           =>
5038                                    Get_Name_String (Path_Name.Name),
5039                                  Directory      =>
5040                                    Get_Name_String (Project.Directory.Name),
5041                                  Resolve_Links  => Opt.Follow_Links_For_Dirs,
5042                                  Case_Sensitive => True) &
5043                               Directory_Separator;
5044
5045                      Last_Path         : constant Natural :=
5046                                            Compute_Directory_Last (Path);
5047                      Path_Id           : Name_Id;
5048                      Display_Path      : constant String :=
5049                                            Get_Name_String
5050                                              (Path_Name.Display_Name);
5051                      Last_Display_Path : constant Natural :=
5052                                            Compute_Directory_Last
5053                                              (Display_Path);
5054                      Display_Path_Id   : Name_Id;
5055
5056                   begin
5057                      Name_Len := 0;
5058                      Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
5059                      Path_Id := Name_Find;
5060
5061                      Name_Len := 0;
5062                      Add_Str_To_Name_Buffer
5063                        (Display_Path
5064                           (Display_Path'First .. Last_Display_Path));
5065                      Display_Path_Id := Name_Find;
5066
5067                      Add_To_Or_Remove_From_List
5068                        (Path_Id         => Path_Id,
5069                         Display_Path_Id => Display_Path_Id);
5070                   end;
5071                end if;
5072             end;
5073          end if;
5074
5075          Recursive_Dirs.Reset (Visited);
5076       end Find_Source_Dirs;
5077
5078    --  Start of processing for Get_Directories
5079
5080       Dir_Exists : Boolean;
5081
5082    begin
5083       if Current_Verbosity = High then
5084          Write_Line ("Starting to look for directories");
5085       end if;
5086
5087       --  Set the object directory to its default which may be nil, if there
5088       --  is no sources in the project.
5089
5090       if (((not Source_Files.Default)
5091              and then Source_Files.Values = Nil_String)
5092           or else
5093            ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
5094               or else
5095            ((not Languages.Default) and then Languages.Values = Nil_String))
5096         and then Project.Extends = No_Project
5097       then
5098          Project.Object_Directory := No_Path_Information;
5099       else
5100          Project.Object_Directory := Project.Directory;
5101       end if;
5102
5103       --  Check the object directory
5104
5105       if Object_Dir.Value /= Empty_String then
5106          Get_Name_String (Object_Dir.Value);
5107
5108          if Name_Len = 0 then
5109             Error_Msg
5110               (Data.Flags,
5111                "Object_Dir cannot be empty",
5112                Object_Dir.Location, Project);
5113
5114          else
5115             --  We check that the specified object directory does exist.
5116             --  However, even when it doesn't exist, we set it to a default
5117             --  value. This is for the benefit of tools that recover from
5118             --  errors; for example, these tools could create the non existent
5119             --  directory. We always return an absolute directory name though.
5120
5121             Locate_Directory
5122               (Project,
5123                File_Name_Type (Object_Dir.Value),
5124                Path             => Project.Object_Directory,
5125                Create           => "object",
5126                Dir_Exists       => Dir_Exists,
5127                Data             => Data,
5128                Location         => Object_Dir.Location,
5129                Must_Exist       => False,
5130                Externally_Built => Project.Externally_Built);
5131
5132             if not Dir_Exists
5133               and then not Project.Externally_Built
5134             then
5135                --  The object directory does not exist, report an error if
5136                --  the project is not externally built.
5137
5138                Err_Vars.Error_Msg_File_1 :=
5139                  File_Name_Type (Object_Dir.Value);
5140
5141                case Data.Flags.Require_Obj_Dirs is
5142                   when Error =>
5143                      Error_Msg
5144                        (Data.Flags,
5145                         "object directory { not found",
5146                         Project.Location, Project);
5147                   when Warning =>
5148                      Error_Msg
5149                        (Data.Flags,
5150                         "?object directory { not found",
5151                         Project.Location, Project);
5152                   when Silent =>
5153                      null;
5154                end case;
5155             end if;
5156          end if;
5157
5158       elsif Project.Object_Directory /= No_Path_Information
5159         and then Subdirs /= null
5160       then
5161          Name_Len := 1;
5162          Name_Buffer (1) := '.';
5163          Locate_Directory
5164            (Project,
5165             Name_Find,
5166             Path             => Project.Object_Directory,
5167             Create           => "object",
5168             Dir_Exists       => Dir_Exists,
5169             Data             => Data,
5170             Location         => Object_Dir.Location,
5171             Externally_Built => Project.Externally_Built);
5172       end if;
5173
5174       if Current_Verbosity = High then
5175          if Project.Object_Directory = No_Path_Information then
5176             Write_Line ("No object directory");
5177          else
5178             Write_Attr
5179               ("Object directory",
5180                Get_Name_String (Project.Object_Directory.Display_Name));
5181          end if;
5182       end if;
5183
5184       --  Check the exec directory
5185
5186       --  We set the object directory to its default
5187
5188       Project.Exec_Directory   := Project.Object_Directory;
5189
5190       if Exec_Dir.Value /= Empty_String then
5191          Get_Name_String (Exec_Dir.Value);
5192
5193          if Name_Len = 0 then
5194             Error_Msg
5195               (Data.Flags,
5196                "Exec_Dir cannot be empty",
5197                Exec_Dir.Location, Project);
5198
5199          else
5200             --  We check that the specified exec directory does exist
5201
5202             Locate_Directory
5203               (Project,
5204                File_Name_Type (Exec_Dir.Value),
5205                Path             => Project.Exec_Directory,
5206                Dir_Exists       => Dir_Exists,
5207                Data             => Data,
5208                Create           => "exec",
5209                Location         => Exec_Dir.Location,
5210                Externally_Built => Project.Externally_Built);
5211
5212             if not Dir_Exists then
5213                Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
5214                Error_Msg
5215                  (Data.Flags,
5216                   "exec directory { not found",
5217                   Project.Location, Project);
5218             end if;
5219          end if;
5220       end if;
5221
5222       if Current_Verbosity = High then
5223          if Project.Exec_Directory = No_Path_Information then
5224             Write_Line ("No exec directory");
5225          else
5226             Write_Str ("Exec directory: """);
5227             Write_Str (Get_Name_String (Project.Exec_Directory.Display_Name));
5228             Write_Line ("""");
5229          end if;
5230       end if;
5231
5232       --  Look for the source directories
5233
5234       if Current_Verbosity = High then
5235          Write_Line ("Starting to look for source directories");
5236       end if;
5237
5238       pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
5239
5240       if (not Source_Files.Default)
5241         and then Source_Files.Values = Nil_String
5242       then
5243          Project.Source_Dirs := Nil_String;
5244
5245          if Project.Qualifier = Standard then
5246             Error_Msg
5247               (Data.Flags,
5248                "a standard project cannot have no sources",
5249                Source_Files.Location, Project);
5250          end if;
5251
5252       elsif Source_Dirs.Default then
5253
5254          --  No Source_Dirs specified: the single source directory is the one
5255          --  containing the project file.
5256
5257          String_Element_Table.Append (Data.Tree.String_Elements,
5258            (Value         => Name_Id (Project.Directory.Name),
5259             Display_Value => Name_Id (Project.Directory.Display_Name),
5260             Location      => No_Location,
5261             Flag          => False,
5262             Next          => Nil_String,
5263             Index         => 0));
5264
5265          Project.Source_Dirs :=
5266            String_Element_Table.Last (Data.Tree.String_Elements);
5267
5268          Number_List_Table.Append
5269            (Data.Tree.Number_Lists,
5270             (Number => 1, Next => No_Number_List));
5271
5272          Project.Source_Dir_Ranks :=
5273            Number_List_Table.Last (Data.Tree.Number_Lists);
5274
5275          if Current_Verbosity = High then
5276             Write_Attr
5277               ("Default source directory",
5278                Get_Name_String (Project.Directory.Display_Name));
5279          end if;
5280
5281       elsif Source_Dirs.Values = Nil_String then
5282          if Project.Qualifier = Standard then
5283             Error_Msg
5284               (Data.Flags,
5285                "a standard project cannot have no source directories",
5286                Source_Dirs.Location, Project);
5287          end if;
5288
5289          Project.Source_Dirs := Nil_String;
5290
5291       else
5292          declare
5293             Source_Dir : String_List_Id;
5294             Element    : String_Element;
5295             Rank       : Natural;
5296          begin
5297             --  Process the source directories for each element of the list
5298
5299             Source_Dir := Source_Dirs.Values;
5300             Rank := 0;
5301             while Source_Dir /= Nil_String loop
5302                Element := Data.Tree.String_Elements.Table (Source_Dir);
5303                Rank := Rank + 1;
5304                Find_Source_Dirs
5305                  (File_Name_Type (Element.Value), Element.Location, Rank);
5306                Source_Dir := Element.Next;
5307             end loop;
5308          end;
5309       end if;
5310
5311       if not Excluded_Source_Dirs.Default
5312         and then Excluded_Source_Dirs.Values /= Nil_String
5313       then
5314          declare
5315             Source_Dir : String_List_Id;
5316             Element    : String_Element;
5317
5318          begin
5319             --  Process the source directories for each element of the list
5320
5321             Source_Dir := Excluded_Source_Dirs.Values;
5322             while Source_Dir /= Nil_String loop
5323                Element := Data.Tree.String_Elements.Table (Source_Dir);
5324                Find_Source_Dirs
5325                  (File_Name_Type (Element.Value),
5326                   Element.Location,
5327                   0,
5328                   Removed => True);
5329                Source_Dir := Element.Next;
5330             end loop;
5331          end;
5332       end if;
5333
5334       if Current_Verbosity = High then
5335          Write_Line ("Putting source directories in canonical cases");
5336       end if;
5337
5338       declare
5339          Current : String_List_Id := Project.Source_Dirs;
5340          Element : String_Element;
5341
5342       begin
5343          while Current /= Nil_String loop
5344             Element := Data.Tree.String_Elements.Table (Current);
5345             if Element.Value /= No_Name then
5346                Element.Value :=
5347                  Name_Id (Canonical_Case_File_Name (Name_Id (Element.Value)));
5348                Data.Tree.String_Elements.Table (Current) := Element;
5349             end if;
5350
5351             Current := Element.Next;
5352          end loop;
5353       end;
5354    end Get_Directories;
5355
5356    ---------------
5357    -- Get_Mains --
5358    ---------------
5359
5360    procedure Get_Mains
5361      (Project : Project_Id;
5362       Data    : in out Tree_Processing_Data)
5363    is
5364       Mains : constant Variable_Value :=
5365                Prj.Util.Value_Of
5366                  (Name_Main, Project.Decl.Attributes, Data.Tree);
5367       List  : String_List_Id;
5368       Elem  : String_Element;
5369
5370    begin
5371       Project.Mains := Mains.Values;
5372
5373       --  If no Mains were specified, and if we are an extending project,
5374       --  inherit the Mains from the project we are extending.
5375
5376       if Mains.Default then
5377          if not Project.Library and then Project.Extends /= No_Project then
5378             Project.Mains := Project.Extends.Mains;
5379          end if;
5380
5381       --  In a library project file, Main cannot be specified
5382
5383       elsif Project.Library then
5384          Error_Msg
5385            (Data.Flags,
5386             "a library project file cannot have Main specified",
5387             Mains.Location, Project);
5388
5389       else
5390          List := Mains.Values;
5391          while List /= Nil_String loop
5392             Elem := Data.Tree.String_Elements.Table (List);
5393
5394             if Length_Of_Name (Elem.Value) = 0 then
5395                Error_Msg
5396                  (Data.Flags,
5397                   "?a main cannot have an empty name",
5398                   Elem.Location, Project);
5399                exit;
5400             end if;
5401
5402             List := Elem.Next;
5403          end loop;
5404       end if;
5405    end Get_Mains;
5406
5407    ---------------------------
5408    -- Get_Sources_From_File --
5409    ---------------------------
5410
5411    procedure Get_Sources_From_File
5412      (Path     : String;
5413       Location : Source_Ptr;
5414       Project  : in out Project_Processing_Data;
5415       Data     : in out Tree_Processing_Data)
5416    is
5417       File        : Prj.Util.Text_File;
5418       Line        : String (1 .. 250);
5419       Last        : Natural;
5420       Source_Name : File_Name_Type;
5421       Name_Loc    : Name_Location;
5422
5423    begin
5424       if Current_Verbosity = High then
5425          Write_Str  ("Opening """);
5426          Write_Str  (Path);
5427          Write_Line (""".");
5428       end if;
5429
5430       --  Open the file
5431
5432       Prj.Util.Open (File, Path);
5433
5434       if not Prj.Util.Is_Valid (File) then
5435          Error_Msg
5436            (Data.Flags, "file does not exist", Location, Project.Project);
5437
5438       else
5439          --  Read the lines one by one
5440
5441          while not Prj.Util.End_Of_File (File) loop
5442             Prj.Util.Get_Line (File, Line, Last);
5443
5444             --  A non empty, non comment line should contain a file name
5445
5446             if Last /= 0
5447               and then (Last = 1 or else Line (1 .. 2) /= "--")
5448             then
5449                Name_Len := Last;
5450                Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
5451                Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5452                Source_Name := Name_Find;
5453
5454                --  Check that there is no directory information
5455
5456                for J in 1 .. Last loop
5457                   if Line (J) = '/' or else Line (J) = Directory_Separator then
5458                      Error_Msg_File_1 := Source_Name;
5459                      Error_Msg
5460                        (Data.Flags,
5461                         "file name cannot include directory information ({)",
5462                         Location, Project.Project);
5463                      exit;
5464                   end if;
5465                end loop;
5466
5467                Name_Loc := Source_Names_Htable.Get
5468                  (Project.Source_Names, Source_Name);
5469
5470                if Name_Loc = No_Name_Location then
5471                   Name_Loc :=
5472                     (Name     => Source_Name,
5473                      Location => Location,
5474                      Source   => No_Source,
5475                      Found    => False);
5476                end if;
5477
5478                Source_Names_Htable.Set
5479                  (Project.Source_Names, Source_Name, Name_Loc);
5480             end if;
5481          end loop;
5482
5483          Prj.Util.Close (File);
5484
5485       end if;
5486    end Get_Sources_From_File;
5487
5488    -----------------------
5489    -- Compute_Unit_Name --
5490    -----------------------
5491
5492    procedure Compute_Unit_Name
5493      (File_Name : File_Name_Type;
5494       Naming    : Lang_Naming_Data;
5495       Kind      : out Source_Kind;
5496       Unit      : out Name_Id;
5497       Project   : Project_Processing_Data;
5498       In_Tree   : Project_Tree_Ref)
5499    is
5500       Filename : constant String  := Get_Name_String (File_Name);
5501       Last     : Integer          := Filename'Last;
5502       Sep_Len  : Integer;
5503       Body_Len : Integer;
5504       Spec_Len : Integer;
5505
5506       Unit_Except : Unit_Exception;
5507       Masked      : Boolean  := False;
5508
5509    begin
5510       Unit := No_Name;
5511       Kind := Spec;
5512
5513       if Naming.Separate_Suffix = No_File
5514         or else Naming.Body_Suffix = No_File
5515         or else Naming.Spec_Suffix = No_File
5516       then
5517          return;
5518       end if;
5519
5520       if Naming.Dot_Replacement = No_File then
5521          if Current_Verbosity = High then
5522             Write_Line ("  No dot_replacement specified");
5523          end if;
5524
5525          return;
5526       end if;
5527
5528       Sep_Len  := Integer (Length_Of_Name (Naming.Separate_Suffix));
5529       Spec_Len := Integer (Length_Of_Name (Naming.Spec_Suffix));
5530       Body_Len := Integer (Length_Of_Name (Naming.Body_Suffix));
5531
5532       --  Choose the longest suffix that matches. If there are several matches,
5533       --  give priority to specs, then bodies, then separates.
5534
5535       if Naming.Separate_Suffix /= Naming.Body_Suffix
5536         and then Suffix_Matches (Filename, Naming.Separate_Suffix)
5537       then
5538          Last := Filename'Last - Sep_Len;
5539          Kind := Sep;
5540       end if;
5541
5542       if Filename'Last - Body_Len <= Last
5543         and then Suffix_Matches (Filename, Naming.Body_Suffix)
5544       then
5545          Last := Natural'Min (Last, Filename'Last - Body_Len);
5546          Kind := Impl;
5547       end if;
5548
5549       if Filename'Last - Spec_Len <= Last
5550         and then Suffix_Matches (Filename, Naming.Spec_Suffix)
5551       then
5552          Last := Natural'Min (Last, Filename'Last - Spec_Len);
5553          Kind := Spec;
5554       end if;
5555
5556       if Last = Filename'Last then
5557          if Current_Verbosity = High then
5558             Write_Line ("     no matching suffix");
5559          end if;
5560
5561          return;
5562       end if;
5563
5564       --  Check that the casing matches
5565
5566       if File_Names_Case_Sensitive then
5567          case Naming.Casing is
5568             when All_Lower_Case =>
5569                for J in Filename'First .. Last loop
5570                   if Is_Letter (Filename (J))
5571                     and then not Is_Lower (Filename (J))
5572                   then
5573                      if Current_Verbosity = High then
5574                         Write_Line ("  Invalid casing");
5575                      end if;
5576
5577                      return;
5578                   end if;
5579                end loop;
5580
5581             when All_Upper_Case =>
5582                for J in Filename'First .. Last loop
5583                   if Is_Letter (Filename (J))
5584                     and then not Is_Upper (Filename (J))
5585                   then
5586                      if Current_Verbosity = High then
5587                         Write_Line ("  Invalid casing");
5588                      end if;
5589
5590                      return;
5591                   end if;
5592                end loop;
5593
5594             when Mixed_Case | Unknown =>
5595                null;
5596          end case;
5597       end if;
5598
5599       --  If Dot_Replacement is not a single dot, then there should not
5600       --  be any dot in the name.
5601
5602       declare
5603          Dot_Repl : constant String :=
5604                       Get_Name_String (Naming.Dot_Replacement);
5605
5606       begin
5607          if Dot_Repl /= "." then
5608             for Index in Filename'First .. Last loop
5609                if Filename (Index) = '.' then
5610                   if Current_Verbosity = High then
5611                      Write_Line ("   Invalid name, contains dot");
5612                   end if;
5613
5614                   return;
5615                end if;
5616             end loop;
5617
5618             Replace_Into_Name_Buffer
5619               (Filename (Filename'First .. Last), Dot_Repl, '.');
5620
5621          else
5622             Name_Len := Last - Filename'First + 1;
5623             Name_Buffer (1 .. Name_Len) := Filename (Filename'First .. Last);
5624             Fixed.Translate
5625               (Source  => Name_Buffer (1 .. Name_Len),
5626                Mapping => Lower_Case_Map);
5627          end if;
5628       end;
5629
5630       --  In the standard GNAT naming scheme, check for special cases: children
5631       --  or separates of A, G, I or S, and run time sources.
5632
5633       if Is_Standard_GNAT_Naming (Naming)
5634         and then Name_Len >= 3
5635       then
5636          declare
5637             S1 : constant Character := Name_Buffer (1);
5638             S2 : constant Character := Name_Buffer (2);
5639             S3 : constant Character := Name_Buffer (3);
5640
5641          begin
5642             if        S1 = 'a'
5643               or else S1 = 'g'
5644               or else S1 = 'i'
5645               or else S1 = 's'
5646             then
5647                --  Children or separates of packages A, G, I or S. These names
5648                --  are x__ ... or x~... (where x is a, g, i, or s). Both
5649                --  versions (x__... and x~...) are allowed in all platforms,
5650                --  because it is not possible to know the platform before
5651                --  processing of the project files.
5652
5653                if S2 = '_' and then S3 = '_' then
5654                   Name_Buffer (2) := '.';
5655                   Name_Buffer (3 .. Name_Len - 1) :=
5656                     Name_Buffer (4 .. Name_Len);
5657                   Name_Len := Name_Len - 1;
5658
5659                elsif S2 = '~' then
5660                   Name_Buffer (2) := '.';
5661
5662                elsif S2 = '.' then
5663
5664                   --  If it is potentially a run time source
5665
5666                   null;
5667                end if;
5668             end if;
5669          end;
5670       end if;
5671
5672       --  Name_Buffer contains the name of the the unit in lower-cases. Check
5673       --  that this is a valid unit name
5674
5675       Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
5676
5677       --  If there is a naming exception for the same unit, the file is not
5678       --  a source for the unit.
5679
5680       if Unit /= No_Name then
5681          Unit_Except :=
5682            Unit_Exceptions_Htable.Get (Project.Unit_Exceptions, Unit);
5683
5684          if Kind = Spec then
5685             Masked := Unit_Except.Spec /= No_File
5686                         and then
5687                       Unit_Except.Spec /= File_Name;
5688          else
5689             Masked := Unit_Except.Impl /= No_File
5690                         and then
5691                       Unit_Except.Impl /= File_Name;
5692          end if;
5693
5694          if Masked then
5695             if Current_Verbosity = High then
5696                Write_Str ("   """ & Filename & """ contains the ");
5697
5698                if Kind = Spec then
5699                   Write_Str ("spec of a unit found in """);
5700                   Write_Str (Get_Name_String (Unit_Except.Spec));
5701                else
5702                   Write_Str ("body of a unit found in """);
5703                   Write_Str (Get_Name_String (Unit_Except.Impl));
5704                end if;
5705
5706                Write_Line (""" (ignored)");
5707             end if;
5708
5709             Unit := No_Name;
5710          end if;
5711       end if;
5712
5713       if Unit /= No_Name
5714         and then Current_Verbosity = High
5715       then
5716          case Kind is
5717             when Spec => Write_Str ("   spec of ");
5718             when Impl => Write_Str ("   body of ");
5719             when Sep  => Write_Str ("   sep of ");
5720          end case;
5721
5722          Write_Line (Get_Name_String (Unit));
5723       end if;
5724    end Compute_Unit_Name;
5725
5726    --------------------------
5727    -- Check_Illegal_Suffix --
5728    --------------------------
5729
5730    procedure Check_Illegal_Suffix
5731      (Project         : Project_Id;
5732       Suffix          : File_Name_Type;
5733       Dot_Replacement : File_Name_Type;
5734       Attribute_Name  : String;
5735       Location        : Source_Ptr;
5736       Data            : in out Tree_Processing_Data)
5737    is
5738       Suffix_Str : constant String := Get_Name_String (Suffix);
5739
5740    begin
5741       if Suffix_Str'Length = 0 then
5742
5743          --  Always valid
5744
5745          return;
5746
5747       elsif Index (Suffix_Str, ".") = 0 then
5748          Err_Vars.Error_Msg_File_1 := Suffix;
5749          Error_Msg
5750            (Data.Flags,
5751             "{ is illegal for " & Attribute_Name & ": must have a dot",
5752             Location, Project);
5753          return;
5754       end if;
5755
5756       --  Case of dot replacement is a single dot, and first character of
5757       --  suffix is also a dot.
5758
5759       if Dot_Replacement /= No_File
5760         and then Get_Name_String (Dot_Replacement) = "."
5761         and then Suffix_Str (Suffix_Str'First) = '.'
5762       then
5763          for Index in Suffix_Str'First + 1 .. Suffix_Str'Last loop
5764
5765             --  If there are multiple dots in the name
5766
5767             if Suffix_Str (Index) = '.' then
5768
5769                --  It is illegal to have a letter following the initial dot
5770
5771                if Is_Letter (Suffix_Str (Suffix_Str'First + 1)) then
5772                   Err_Vars.Error_Msg_File_1 := Suffix;
5773                   Error_Msg
5774                     (Data.Flags,
5775                      "{ is illegal for " & Attribute_Name
5776                      & ": ambiguous prefix when Dot_Replacement is a dot",
5777                      Location, Project);
5778                end if;
5779                return;
5780             end if;
5781          end loop;
5782       end if;
5783    end Check_Illegal_Suffix;
5784
5785    ----------------------
5786    -- Locate_Directory --
5787    ----------------------
5788
5789    procedure Locate_Directory
5790      (Project          : Project_Id;
5791       Name             : File_Name_Type;
5792       Path             : out Path_Information;
5793       Dir_Exists       : out Boolean;
5794       Data             : in out Tree_Processing_Data;
5795       Create           : String := "";
5796       Location         : Source_Ptr := No_Location;
5797       Must_Exist       : Boolean := True;
5798       Externally_Built : Boolean := False)
5799    is
5800       Parent          : constant Path_Name_Type :=
5801                           Project.Directory.Display_Name;
5802       The_Parent      : constant String :=
5803                           Get_Name_String (Parent);
5804       The_Parent_Last : constant Natural :=
5805                           Compute_Directory_Last (The_Parent);
5806       Full_Name       : File_Name_Type;
5807       The_Name        : File_Name_Type;
5808
5809    begin
5810       Get_Name_String (Name);
5811
5812       --  Add Subdirs.all if it is a directory that may be created and
5813       --  Subdirs is not null;
5814
5815       if Create /= "" and then Subdirs /= null then
5816          if Name_Buffer (Name_Len) /= Directory_Separator then
5817             Add_Char_To_Name_Buffer (Directory_Separator);
5818          end if;
5819
5820          Add_Str_To_Name_Buffer (Subdirs.all);
5821       end if;
5822
5823       --  Convert '/' to directory separator (for Windows)
5824
5825       for J in 1 .. Name_Len loop
5826          if Name_Buffer (J) = '/' then
5827             Name_Buffer (J) := Directory_Separator;
5828          end if;
5829       end loop;
5830
5831       The_Name := Name_Find;
5832
5833       if Current_Verbosity = High then
5834          Write_Str ("Locate_Directory (""");
5835          Write_Str (Get_Name_String (The_Name));
5836          Write_Str (""", """);
5837          Write_Str (The_Parent);
5838          Write_Line (""")");
5839       end if;
5840
5841       Path := No_Path_Information;
5842       Dir_Exists := False;
5843
5844       if Is_Absolute_Path (Get_Name_String (The_Name)) then
5845          Full_Name := The_Name;
5846
5847       else
5848          Name_Len := 0;
5849          Add_Str_To_Name_Buffer
5850            (The_Parent (The_Parent'First .. The_Parent_Last));
5851          Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
5852          Full_Name := Name_Find;
5853       end if;
5854
5855       declare
5856          Full_Path_Name : String_Access :=
5857                             new String'(Get_Name_String (Full_Name));
5858
5859       begin
5860          if (Setup_Projects or else Subdirs /= null)
5861            and then Create'Length > 0
5862          then
5863             if not Is_Directory (Full_Path_Name.all) then
5864
5865                --  If project is externally built, do not create a subdir,
5866                --  use the specified directory, without the subdir.
5867
5868                if Externally_Built then
5869                   if Is_Absolute_Path (Get_Name_String (Name)) then
5870                      Get_Name_String (Name);
5871
5872                   else
5873                      Name_Len := 0;
5874                      Add_Str_To_Name_Buffer
5875                        (The_Parent (The_Parent'First .. The_Parent_Last));
5876                      Add_Str_To_Name_Buffer (Get_Name_String (Name));
5877                   end if;
5878
5879                   Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
5880
5881                else
5882                   begin
5883                      Create_Path (Full_Path_Name.all);
5884
5885                      if not Quiet_Output then
5886                         Write_Str (Create);
5887                         Write_Str (" directory """);
5888                         Write_Str (Full_Path_Name.all);
5889                         Write_Str (""" created for project ");
5890                         Write_Line (Get_Name_String (Project.Name));
5891                      end if;
5892
5893                   exception
5894                      when Use_Error =>
5895                         Error_Msg
5896                           (Data.Flags,
5897                            "could not create " & Create &
5898                            " directory " & Full_Path_Name.all,
5899                            Location, Project);
5900                   end;
5901                end if;
5902             end if;
5903          end if;
5904
5905          Dir_Exists := Is_Directory (Full_Path_Name.all);
5906
5907          if not Must_Exist or else Dir_Exists then
5908             declare
5909                Normed : constant String :=
5910                           Normalize_Pathname
5911                             (Full_Path_Name.all,
5912                              Directory      =>
5913                               The_Parent (The_Parent'First .. The_Parent_Last),
5914                              Resolve_Links  => False,
5915                              Case_Sensitive => True);
5916
5917                Canonical_Path : constant String :=
5918                                   Normalize_Pathname
5919                                     (Normed,
5920                                      Directory      =>
5921                                        The_Parent
5922                                          (The_Parent'First .. The_Parent_Last),
5923                                      Resolve_Links  =>
5924                                         Opt.Follow_Links_For_Dirs,
5925                                      Case_Sensitive => False);
5926
5927             begin
5928                Name_Len := Normed'Length;
5929                Name_Buffer (1 .. Name_Len) := Normed;
5930
5931                --  Directories should always end with a directory separator
5932
5933                if Name_Buffer (Name_Len) /= Directory_Separator then
5934                   Add_Char_To_Name_Buffer (Directory_Separator);
5935                end if;
5936
5937                Path.Display_Name := Name_Find;
5938
5939                Name_Len := Canonical_Path'Length;
5940                Name_Buffer (1 .. Name_Len) := Canonical_Path;
5941
5942                if Name_Buffer (Name_Len) /= Directory_Separator then
5943                   Add_Char_To_Name_Buffer (Directory_Separator);
5944                end if;
5945
5946                Path.Name := Name_Find;
5947             end;
5948          end if;
5949
5950          Free (Full_Path_Name);
5951       end;
5952    end Locate_Directory;
5953
5954    ---------------------------
5955    -- Find_Excluded_Sources --
5956    ---------------------------
5957
5958    procedure Find_Excluded_Sources
5959      (Project : in out Project_Processing_Data;
5960       Data    : in out Tree_Processing_Data)
5961    is
5962       Excluded_Source_List_File : constant Variable_Value :=
5963                                     Util.Value_Of
5964                                       (Name_Excluded_Source_List_File,
5965                                        Project.Project.Decl.Attributes,
5966                                        Data.Tree);
5967       Excluded_Sources          : Variable_Value := Util.Value_Of
5968                                     (Name_Excluded_Source_Files,
5969                                      Project.Project.Decl.Attributes,
5970                                      Data.Tree);
5971
5972       Current         : String_List_Id;
5973       Element         : String_Element;
5974       Location        : Source_Ptr;
5975       Name            : File_Name_Type;
5976       File            : Prj.Util.Text_File;
5977       Line            : String (1 .. 300);
5978       Last            : Natural;
5979       Locally_Removed : Boolean := False;
5980
5981    begin
5982       --  If Excluded_Source_Files is not declared, check Locally_Removed_Files
5983
5984       if Excluded_Sources.Default then
5985          Locally_Removed := True;
5986          Excluded_Sources :=
5987            Util.Value_Of
5988              (Name_Locally_Removed_Files,
5989               Project.Project.Decl.Attributes, Data.Tree);
5990       end if;
5991
5992       --  If there are excluded sources, put them in the table
5993
5994       if not Excluded_Sources.Default then
5995          if not Excluded_Source_List_File.Default then
5996             if Locally_Removed then
5997                Error_Msg
5998                  (Data.Flags,
5999                   "?both attributes Locally_Removed_Files and " &
6000                   "Excluded_Source_List_File are present",
6001                   Excluded_Source_List_File.Location, Project.Project);
6002             else
6003                Error_Msg
6004                  (Data.Flags,
6005                   "?both attributes Excluded_Source_Files and " &
6006                   "Excluded_Source_List_File are present",
6007                   Excluded_Source_List_File.Location, Project.Project);
6008             end if;
6009          end if;
6010
6011          Current := Excluded_Sources.Values;
6012          while Current /= Nil_String loop
6013             Element := Data.Tree.String_Elements.Table (Current);
6014             Name := Canonical_Case_File_Name (Element.Value);
6015
6016             --  If the element has no location, then use the location of
6017             --  Excluded_Sources to report possible errors.
6018
6019             if Element.Location = No_Location then
6020                Location := Excluded_Sources.Location;
6021             else
6022                Location := Element.Location;
6023             end if;
6024
6025             Excluded_Sources_Htable.Set
6026               (Project.Excluded, Name, (Name, False, Location));
6027             Current := Element.Next;
6028          end loop;
6029
6030       elsif not Excluded_Source_List_File.Default then
6031          Location := Excluded_Source_List_File.Location;
6032
6033          declare
6034             Source_File_Path_Name : constant String :=
6035                                       Path_Name_Of
6036                                         (File_Name_Type
6037                                            (Excluded_Source_List_File.Value),
6038                                          Project.Project.Directory.Name);
6039
6040          begin
6041             if Source_File_Path_Name'Length = 0 then
6042                Err_Vars.Error_Msg_File_1 :=
6043                  File_Name_Type (Excluded_Source_List_File.Value);
6044                Error_Msg
6045                  (Data.Flags,
6046                   "file with excluded sources { does not exist",
6047                   Excluded_Source_List_File.Location, Project.Project);
6048
6049             else
6050                --  Open the file
6051
6052                Prj.Util.Open (File, Source_File_Path_Name);
6053
6054                if not Prj.Util.Is_Valid (File) then
6055                   Error_Msg
6056                     (Data.Flags, "file does not exist",
6057                      Location, Project.Project);
6058                else
6059                   --  Read the lines one by one
6060
6061                   while not Prj.Util.End_Of_File (File) loop
6062                      Prj.Util.Get_Line (File, Line, Last);
6063
6064                      --  Non empty, non comment line should contain a file name
6065
6066                      if Last /= 0
6067                        and then (Last = 1 or else Line (1 .. 2) /= "--")
6068                      then
6069                         Name_Len := Last;
6070                         Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6071                         Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6072                         Name := Name_Find;
6073
6074                         --  Check that there is no directory information
6075
6076                         for J in 1 .. Last loop
6077                            if Line (J) = '/'
6078                              or else Line (J) = Directory_Separator
6079                            then
6080                               Error_Msg_File_1 := Name;
6081                               Error_Msg
6082                                 (Data.Flags,
6083                                  "file name cannot include " &
6084                                  "directory information ({)",
6085                                  Location, Project.Project);
6086                               exit;
6087                            end if;
6088                         end loop;
6089
6090                         Excluded_Sources_Htable.Set
6091                           (Project.Excluded, Name, (Name, False, Location));
6092                      end if;
6093                   end loop;
6094
6095                   Prj.Util.Close (File);
6096                end if;
6097             end if;
6098          end;
6099       end if;
6100    end Find_Excluded_Sources;
6101
6102    ------------------
6103    -- Find_Sources --
6104    ------------------
6105
6106    procedure Find_Sources
6107      (Project   : in out Project_Processing_Data;
6108       Data      : in out Tree_Processing_Data)
6109    is
6110       Sources : constant Variable_Value :=
6111                   Util.Value_Of
6112                     (Name_Source_Files,
6113                     Project.Project.Decl.Attributes,
6114                     Data.Tree);
6115
6116       Source_List_File : constant Variable_Value :=
6117                            Util.Value_Of
6118                              (Name_Source_List_File,
6119                               Project.Project.Decl.Attributes,
6120                               Data.Tree);
6121
6122       Name_Loc             : Name_Location;
6123       Has_Explicit_Sources : Boolean;
6124
6125    begin
6126       pragma Assert (Sources.Kind = List, "Source_Files is not a list");
6127       pragma Assert
6128         (Source_List_File.Kind = Single,
6129          "Source_List_File is not a single string");
6130
6131       Project.Source_List_File_Location := Source_List_File.Location;
6132
6133       --  If the user has specified a Source_Files attribute
6134
6135       if not Sources.Default then
6136          if not Source_List_File.Default then
6137             Error_Msg
6138               (Data.Flags,
6139                "?both attributes source_files and " &
6140                "source_list_file are present",
6141                Source_List_File.Location, Project.Project);
6142          end if;
6143
6144          --  Sources is a list of file names
6145
6146          declare
6147             Current  : String_List_Id := Sources.Values;
6148             Element  : String_Element;
6149             Location : Source_Ptr;
6150             Name     : File_Name_Type;
6151
6152          begin
6153             if Current = Nil_String then
6154                Project.Project.Languages := No_Language_Index;
6155
6156                --  This project contains no source. For projects that don't
6157                --  extend other projects, this also means that there is no
6158                --  need for an object directory, if not specified.
6159
6160                if Project.Project.Extends = No_Project
6161                  and then Project.Project.Object_Directory =
6162                    Project.Project.Directory
6163                then
6164                   Project.Project.Object_Directory := No_Path_Information;
6165                end if;
6166             end if;
6167
6168             while Current /= Nil_String loop
6169                Element := Data.Tree.String_Elements.Table (Current);
6170                Name := Canonical_Case_File_Name (Element.Value);
6171                Get_Name_String (Element.Value);
6172
6173                --  If the element has no location, then use the location of
6174                --  Sources to report possible errors.
6175
6176                if Element.Location = No_Location then
6177                   Location := Sources.Location;
6178                else
6179                   Location := Element.Location;
6180                end if;
6181
6182                --  Check that there is no directory information
6183
6184                for J in 1 .. Name_Len loop
6185                   if Name_Buffer (J) = '/'
6186                     or else Name_Buffer (J) = Directory_Separator
6187                   then
6188                      Error_Msg_File_1 := Name;
6189                      Error_Msg
6190                        (Data.Flags,
6191                         "file name cannot include directory " &
6192                         "information ({)",
6193                         Location, Project.Project);
6194                      exit;
6195                   end if;
6196                end loop;
6197
6198                --  Check whether the file is already there: the same file name
6199                --  may be in the list. If the source is missing, the error will
6200                --  be on the first mention of the source file name.
6201
6202                Name_Loc := Source_Names_Htable.Get
6203                  (Project.Source_Names, Name);
6204
6205                if Name_Loc = No_Name_Location then
6206                   Name_Loc :=
6207                     (Name     => Name,
6208                      Location => Location,
6209                      Source   => No_Source,
6210                      Found    => False);
6211                   Source_Names_Htable.Set
6212                     (Project.Source_Names, Name, Name_Loc);
6213                end if;
6214
6215                Current := Element.Next;
6216             end loop;
6217
6218             Has_Explicit_Sources := True;
6219          end;
6220
6221          --  If we have no Source_Files attribute, check the Source_List_File
6222          --  attribute.
6223
6224       elsif not Source_List_File.Default then
6225
6226          --  Source_List_File is the name of the file that contains the source
6227          --  file names.
6228
6229          declare
6230             Source_File_Path_Name : constant String :=
6231               Path_Name_Of
6232                 (File_Name_Type (Source_List_File.Value),
6233                  Project.Project.Directory.Name);
6234
6235          begin
6236             Has_Explicit_Sources := True;
6237
6238             if Source_File_Path_Name'Length = 0 then
6239                Err_Vars.Error_Msg_File_1 :=
6240                  File_Name_Type (Source_List_File.Value);
6241                Error_Msg
6242                  (Data.Flags,
6243                   "file with sources { does not exist",
6244                   Source_List_File.Location, Project.Project);
6245
6246             else
6247                Get_Sources_From_File
6248                  (Source_File_Path_Name, Source_List_File.Location,
6249                   Project, Data);
6250             end if;
6251          end;
6252
6253       else
6254          --  Neither Source_Files nor Source_List_File has been specified. Find
6255          --  all the files that satisfy the naming scheme in all the source
6256          --  directories.
6257
6258          Has_Explicit_Sources := False;
6259       end if;
6260
6261       Search_Directories
6262         (Project,
6263          Data            => Data,
6264          For_All_Sources => Sources.Default and then Source_List_File.Default);
6265
6266       --  Check if all exceptions have been found
6267
6268       declare
6269          Source : Source_Id;
6270          Iter   : Source_Iterator;
6271
6272       begin
6273          Iter := For_Each_Source (Data.Tree, Project.Project);
6274          loop
6275             Source := Prj.Element (Iter);
6276             exit when Source = No_Source;
6277
6278             if Source.Naming_Exception
6279               and then Source.Path = No_Path_Information
6280             then
6281                if Source.Unit /= No_Unit_Index then
6282
6283                   --  For multi-unit source files, source_id gets duplicated
6284                   --  once for every unit. Only the first source_id got its
6285                   --  full path set. So if it isn't set for that first one,
6286                   --  the file wasn't found. Otherwise we need to update for
6287                   --  units after the first one.
6288
6289                   if Source.Index = 0
6290                     or else Source.Index = 1
6291                   then
6292                      Error_Msg_Name_1 := Name_Id (Source.Display_File);
6293                      Error_Msg_Name_2 := Name_Id (Source.Unit.Name);
6294                      Error_Msg
6295                        (Data.Flags,
6296                         "source file %% for unit %% not found",
6297                         No_Location, Project.Project);
6298
6299                   else
6300                      Source.Path := Files_Htable.Get
6301                        (Data.File_To_Source, Source.File).Path;
6302
6303                      if Current_Verbosity = High then
6304                         if Source.Path /= No_Path_Information then
6305                            Write_Line ("Setting full path for "
6306                                        & Get_Name_String (Source.File)
6307                                        & " at" & Source.Index'Img
6308                                        & " to "
6309                                        & Get_Name_String (Source.Path.Name));
6310                         end if;
6311                      end if;
6312                   end if;
6313                end if;
6314
6315                if Source.Path = No_Path_Information then
6316                   Remove_Source (Source, No_Source);
6317                end if;
6318             end if;
6319
6320             Next (Iter);
6321          end loop;
6322       end;
6323
6324       --  It is an error if a source file name in a source list or in a source
6325       --  list file is not found.
6326
6327       if Has_Explicit_Sources then
6328          declare
6329             NL          : Name_Location;
6330             First_Error : Boolean;
6331
6332          begin
6333             NL := Source_Names_Htable.Get_First (Project.Source_Names);
6334             First_Error := True;
6335             while NL /= No_Name_Location loop
6336                if not NL.Found then
6337                   Err_Vars.Error_Msg_File_1 := NL.Name;
6338
6339                   if First_Error then
6340                      Error_Msg
6341                        (Data.Flags,
6342                         "source file { not found",
6343                         NL.Location, Project.Project);
6344                      First_Error := False;
6345
6346                   else
6347                      Error_Msg
6348                        (Data.Flags,
6349                         "\source file { not found",
6350                         NL.Location, Project.Project);
6351                   end if;
6352                end if;
6353
6354                NL := Source_Names_Htable.Get_Next (Project.Source_Names);
6355             end loop;
6356          end;
6357       end if;
6358    end Find_Sources;
6359
6360    ----------------
6361    -- Initialize --
6362    ----------------
6363
6364    procedure Initialize
6365      (Data  : out Tree_Processing_Data;
6366       Tree  : Project_Tree_Ref;
6367       Flags : Prj.Processing_Flags)
6368    is
6369    begin
6370       Files_Htable.Reset (Data.File_To_Source);
6371       Data.Tree  := Tree;
6372       Data.Flags := Flags;
6373    end Initialize;
6374
6375    ----------
6376    -- Free --
6377    ----------
6378
6379    procedure Free (Data : in out Tree_Processing_Data) is
6380    begin
6381       Files_Htable.Reset (Data.File_To_Source);
6382    end Free;
6383
6384    ----------------
6385    -- Initialize --
6386    ----------------
6387
6388    procedure Initialize
6389      (Data    : in out Project_Processing_Data;
6390       Project : Project_Id)
6391    is
6392    begin
6393       Data.Project := Project;
6394    end Initialize;
6395
6396    ----------
6397    -- Free --
6398    ----------
6399
6400    procedure Free (Data : in out Project_Processing_Data) is
6401    begin
6402       Source_Names_Htable.Reset      (Data.Source_Names);
6403       Unit_Exceptions_Htable.Reset   (Data.Unit_Exceptions);
6404       Excluded_Sources_Htable.Reset  (Data.Excluded);
6405    end Free;
6406
6407    -------------------------------
6408    -- Check_File_Naming_Schemes --
6409    -------------------------------
6410
6411    procedure Check_File_Naming_Schemes
6412      (In_Tree               : Project_Tree_Ref;
6413       Project               : Project_Processing_Data;
6414       File_Name             : File_Name_Type;
6415       Alternate_Languages   : out Language_List;
6416       Language              : out Language_Ptr;
6417       Display_Language_Name : out Name_Id;
6418       Unit                  : out Name_Id;
6419       Lang_Kind             : out Language_Kind;
6420       Kind                  : out Source_Kind)
6421    is
6422       Filename : constant String := Get_Name_String (File_Name);
6423       Config   : Language_Config;
6424       Tmp_Lang : Language_Ptr;
6425
6426       Header_File : Boolean := False;
6427       --  True if we found at least one language for which the file is a header
6428       --  In such a case, we search for all possible languages where this is
6429       --  also a header (C and C++ for instance), since the file might be used
6430       --  for several such languages.
6431
6432       procedure Check_File_Based_Lang;
6433       --  Does the naming scheme test for file-based languages. For those,
6434       --  there is no Unit. Just check if the file name has the implementation
6435       --  or, if it is specified, the template suffix of the language.
6436       --
6437       --  Returns True if the file belongs to the current language and we
6438       --  should stop searching for matching languages. Not that a given header
6439       --  file could belong to several languages (C and C++ for instance). Thus
6440       --  if we found a header we'll check whether it matches other languages.
6441
6442       ---------------------------
6443       -- Check_File_Based_Lang --
6444       ---------------------------
6445
6446       procedure Check_File_Based_Lang is
6447       begin
6448          if not Header_File
6449            and then Suffix_Matches (Filename, Config.Naming_Data.Body_Suffix)
6450          then
6451             Unit     := No_Name;
6452             Kind     := Impl;
6453             Language := Tmp_Lang;
6454
6455             if Current_Verbosity = High then
6456                Write_Str ("     implementation of language ");
6457                Write_Line (Get_Name_String (Display_Language_Name));
6458             end if;
6459
6460          elsif Suffix_Matches (Filename, Config.Naming_Data.Spec_Suffix) then
6461             if Current_Verbosity = High then
6462                Write_Str ("     header of language ");
6463                Write_Line (Get_Name_String (Display_Language_Name));
6464             end if;
6465
6466             if Header_File then
6467                Alternate_Languages := new Language_List_Element'
6468                  (Language => Language,
6469                   Next     => Alternate_Languages);
6470
6471             else
6472                Header_File := True;
6473                Kind        := Spec;
6474                Unit        := No_Name;
6475                Language    := Tmp_Lang;
6476             end if;
6477          end if;
6478       end Check_File_Based_Lang;
6479
6480    --  Start of processing for Check_File_Naming_Schemes
6481
6482    begin
6483       Language              := No_Language_Index;
6484       Alternate_Languages   := null;
6485       Display_Language_Name := No_Name;
6486       Unit                  := No_Name;
6487       Lang_Kind             := File_Based;
6488       Kind                  := Spec;
6489
6490       Tmp_Lang := Project.Project.Languages;
6491       while Tmp_Lang /= No_Language_Index loop
6492          if Current_Verbosity = High then
6493             Write_Line
6494               ("     Testing language "
6495                & Get_Name_String (Tmp_Lang.Name)
6496                & " Header_File=" & Header_File'Img);
6497          end if;
6498
6499          Display_Language_Name := Tmp_Lang.Display_Name;
6500          Config := Tmp_Lang.Config;
6501          Lang_Kind := Config.Kind;
6502
6503          case Config.Kind is
6504             when File_Based =>
6505                Check_File_Based_Lang;
6506                exit when Kind = Impl;
6507
6508             when Unit_Based =>
6509
6510                --  We know it belongs to a least a file_based language, no
6511                --  need to check unit-based ones.
6512
6513                if not Header_File then
6514                   Compute_Unit_Name
6515                     (File_Name       => File_Name,
6516                      Naming          => Config.Naming_Data,
6517                      Kind            => Kind,
6518                      Unit            => Unit,
6519                      Project         => Project,
6520                      In_Tree         => In_Tree);
6521
6522                   if Unit /= No_Name then
6523                      Language    := Tmp_Lang;
6524                      exit;
6525                   end if;
6526                end if;
6527          end case;
6528
6529          Tmp_Lang := Tmp_Lang.Next;
6530       end loop;
6531
6532       if Language = No_Language_Index
6533         and then Current_Verbosity = High
6534       then
6535          Write_Line ("     not a source of any language");
6536       end if;
6537    end Check_File_Naming_Schemes;
6538
6539    -------------------
6540    -- Override_Kind --
6541    -------------------
6542
6543    procedure Override_Kind (Source : Source_Id; Kind : Source_Kind) is
6544    begin
6545       --  If the file was previously already associated with a unit, change it
6546
6547       if Source.Unit /= null
6548         and then Source.Kind in Spec_Or_Body
6549         and then Source.Unit.File_Names (Source.Kind) /= null
6550       then
6551          --  If we had another file referencing the same unit (for instance it
6552          --  was in an extended project), that source file is in fact invisible
6553          --  from now on, and in particular doesn't belong to the same unit.
6554
6555          if Source.Unit.File_Names (Source.Kind) /= Source then
6556             Source.Unit.File_Names (Source.Kind).Unit := No_Unit_Index;
6557          end if;
6558
6559          Source.Unit.File_Names (Source.Kind) := null;
6560       end if;
6561
6562       Source.Kind := Kind;
6563
6564       if Current_Verbosity = High
6565         and then Source.File /= No_File
6566       then
6567          Write_Line ("Override kind for "
6568                      & Get_Name_String (Source.File)
6569                      & " kind=" & Source.Kind'Img);
6570       end if;
6571
6572       if Source.Kind in Spec_Or_Body and then Source.Unit /= null then
6573          Source.Unit.File_Names (Source.Kind) := Source;
6574       end if;
6575    end Override_Kind;
6576
6577    ----------------
6578    -- Check_File --
6579    ----------------
6580
6581    procedure Check_File
6582      (Project           : in out Project_Processing_Data;
6583       Data              : in out Tree_Processing_Data;
6584       Source_Dir_Rank   : Natural;
6585       Path              : Path_Name_Type;
6586       File_Name         : File_Name_Type;
6587       Display_File_Name : File_Name_Type;
6588       Locally_Removed   : Boolean;
6589       For_All_Sources   : Boolean)
6590    is
6591       Canonical_Path : constant Path_Name_Type :=
6592                          Path_Name_Type
6593                            (Canonical_Case_File_Name (Name_Id (Path)));
6594
6595       Name_Loc              : Name_Location :=
6596                                 Source_Names_Htable.Get
6597                                   (Project.Source_Names, File_Name);
6598       Check_Name            : Boolean := False;
6599       Alternate_Languages   : Language_List;
6600       Language              : Language_Ptr;
6601       Source                : Source_Id;
6602       Src_Ind               : Source_File_Index;
6603       Unit                  : Name_Id;
6604       Display_Language_Name : Name_Id;
6605       Lang_Kind             : Language_Kind;
6606       Kind                  : Source_Kind := Spec;
6607
6608    begin
6609       if Current_Verbosity = High then
6610          Write_Line ("Checking file:");
6611          Write_Str ("   Path = ");
6612          Write_Line (Get_Name_String (Path));
6613          Write_Str ("   Rank =");
6614          Write_Line (Source_Dir_Rank'Img);
6615       end if;
6616
6617       if Name_Loc = No_Name_Location then
6618          Check_Name := For_All_Sources;
6619
6620       else
6621          if Name_Loc.Found then
6622
6623             --  Check if it is OK to have the same file name in several
6624             --  source directories.
6625
6626             if Source_Dir_Rank = Name_Loc.Source.Source_Dir_Rank then
6627                Error_Msg_File_1 := File_Name;
6628                Error_Msg
6629                  (Data.Flags,
6630                   "{ is found in several source directories",
6631                   Name_Loc.Location, Project.Project);
6632             end if;
6633
6634          else
6635             Name_Loc.Found := True;
6636
6637             Source_Names_Htable.Set
6638               (Project.Source_Names, File_Name, Name_Loc);
6639
6640             if Name_Loc.Source = No_Source then
6641                Check_Name := True;
6642
6643             else
6644                Name_Loc.Source.Path := (Canonical_Path, Path);
6645
6646                Source_Paths_Htable.Set
6647                  (Data.Tree.Source_Paths_HT,
6648                   Canonical_Path,
6649                   Name_Loc.Source);
6650
6651                --  Check if this is a subunit
6652
6653                if Name_Loc.Source.Unit /= No_Unit_Index
6654                  and then Name_Loc.Source.Kind = Impl
6655                then
6656                   Src_Ind := Sinput.P.Load_Project_File
6657                     (Get_Name_String (Canonical_Path));
6658
6659                   if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
6660                      Override_Kind (Name_Loc.Source, Sep);
6661                   end if;
6662                end if;
6663
6664                Files_Htable.Set
6665                  (Data.File_To_Source, File_Name, Name_Loc.Source);
6666             end if;
6667          end if;
6668       end if;
6669
6670       if Check_Name then
6671          Check_File_Naming_Schemes
6672            (In_Tree               => Data.Tree,
6673             Project               => Project,
6674             File_Name             => File_Name,
6675             Alternate_Languages   => Alternate_Languages,
6676             Language              => Language,
6677             Display_Language_Name => Display_Language_Name,
6678             Unit                  => Unit,
6679             Lang_Kind             => Lang_Kind,
6680             Kind                  => Kind);
6681
6682          if Language = No_Language_Index then
6683
6684             --  A file name in a list must be a source of a language
6685
6686             if Data.Flags.Error_On_Unknown_Language
6687               and then Name_Loc.Found
6688             then
6689                Error_Msg_File_1 := File_Name;
6690                Error_Msg
6691                  (Data.Flags,
6692                   "language unknown for {",
6693                   Name_Loc.Location, Project.Project);
6694             end if;
6695
6696          else
6697             Add_Source
6698               (Id                  => Source,
6699                Project             => Project.Project,
6700                Source_Dir_Rank     => Source_Dir_Rank,
6701                Lang_Id             => Language,
6702                Kind                => Kind,
6703                Data                => Data,
6704                Alternate_Languages => Alternate_Languages,
6705                File_Name           => File_Name,
6706                Display_File        => Display_File_Name,
6707                Unit                => Unit,
6708                Locally_Removed     => Locally_Removed,
6709                Path                => (Canonical_Path, Path));
6710
6711             --  If it is a source specified in a list, update the entry in
6712             --  the Source_Names table.
6713
6714             if Name_Loc.Found and then Name_Loc.Source = No_Source then
6715                Name_Loc.Source := Source;
6716                Source_Names_Htable.Set
6717                  (Project.Source_Names, File_Name, Name_Loc);
6718             end if;
6719          end if;
6720       end if;
6721    end Check_File;
6722
6723    ------------------------
6724    -- Search_Directories --
6725    ------------------------
6726
6727    procedure Search_Directories
6728      (Project         : in out Project_Processing_Data;
6729       Data            : in out Tree_Processing_Data;
6730       For_All_Sources : Boolean)
6731    is
6732       Source_Dir        : String_List_Id;
6733       Element           : String_Element;
6734       Src_Dir_Rank      : Number_List_Index;
6735       Num_Nod           : Number_Node;
6736       Dir               : Dir_Type;
6737       Name              : String (1 .. 1_000);
6738       Last              : Natural;
6739       File_Name         : File_Name_Type;
6740       Display_File_Name : File_Name_Type;
6741
6742    begin
6743       if Current_Verbosity = High then
6744          Write_Line ("Looking for sources:");
6745       end if;
6746
6747       --  Loop through subdirectories
6748
6749       Source_Dir := Project.Project.Source_Dirs;
6750       Src_Dir_Rank := Project.Project.Source_Dir_Ranks;
6751       while Source_Dir /= Nil_String loop
6752          begin
6753             Num_Nod := Data.Tree.Number_Lists.Table (Src_Dir_Rank);
6754             Element := Data.Tree.String_Elements.Table (Source_Dir);
6755
6756             if Element.Value /= No_Name then
6757                Get_Name_String (Element.Display_Value);
6758
6759                if Current_Verbosity = High then
6760                   Write_Str ("Directory: ");
6761                   Write_Str (Name_Buffer (1 .. Name_Len));
6762                   Write_Line (Num_Nod.Number'Img);
6763                end if;
6764
6765                declare
6766                   Source_Directory : constant String :=
6767                                        Name_Buffer (1 .. Name_Len) &
6768                                          Directory_Separator;
6769
6770                   Dir_Last : constant Natural :=
6771                                        Compute_Directory_Last
6772                                          (Source_Directory);
6773
6774                begin
6775                   if Current_Verbosity = High then
6776                      Write_Attr ("Source_Dir", Source_Directory);
6777                   end if;
6778
6779                   --  We look to every entry in the source directory
6780
6781                   Open (Dir, Source_Directory);
6782
6783                   loop
6784                      Read (Dir, Name, Last);
6785
6786                      exit when Last = 0;
6787
6788                      --  ??? Duplicate system call here, we just did a a
6789                      --  similar one. Maybe Ada.Directories would be more
6790                      --  appropriate here.
6791
6792                      if Is_Regular_File
6793                           (Source_Directory & Name (1 .. Last))
6794                      then
6795                         if Current_Verbosity = High then
6796                            Write_Str  ("   Checking ");
6797                            Write_Line (Name (1 .. Last));
6798                         end if;
6799
6800                         Name_Len := Last;
6801                         Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
6802                         Display_File_Name := Name_Find;
6803
6804                         if Osint.File_Names_Case_Sensitive then
6805                            File_Name := Display_File_Name;
6806                         else
6807                            Canonical_Case_File_Name
6808                              (Name_Buffer (1 .. Name_Len));
6809                            File_Name := Name_Find;
6810                         end if;
6811
6812                         declare
6813                            Path_Name : constant String :=
6814                                          Normalize_Pathname
6815                                            (Name (1 .. Last),
6816                                             Directory       =>
6817                                               Source_Directory
6818                                                 (Source_Directory'First ..
6819                                                  Dir_Last),
6820                                             Resolve_Links   =>
6821                                               Opt.Follow_Links_For_Files,
6822                                             Case_Sensitive => True);
6823                            --  Case_Sensitive set True (no folding)
6824
6825                            Path : Path_Name_Type;
6826                            FF   : File_Found := Excluded_Sources_Htable.Get
6827                                                  (Project.Excluded, File_Name);
6828                            To_Remove : Boolean := False;
6829
6830                         begin
6831                            Name_Len := Path_Name'Length;
6832                            Name_Buffer (1 .. Name_Len) := Path_Name;
6833                            Path := Name_Find;
6834
6835                            if FF /= No_File_Found then
6836                               if not FF.Found then
6837                                  FF.Found := True;
6838                                  Excluded_Sources_Htable.Set
6839                                    (Project.Excluded, File_Name, FF);
6840
6841                                  if Current_Verbosity = High then
6842                                     Write_Str ("     excluded source """);
6843                                     Write_Str (Get_Name_String (File_Name));
6844                                     Write_Line ("""");
6845                                  end if;
6846
6847                                  --  Will mark the file as removed, but we
6848                                  --  still need to add it to the list: if we
6849                                  --  don't, the file will not appear in the
6850                                  --  mapping file and will cause the compiler
6851                                  --  to fail.
6852
6853                                  To_Remove := True;
6854                               end if;
6855                            end if;
6856
6857                            Check_File
6858                              (Project           => Project,
6859                               Source_Dir_Rank   => Num_Nod.Number,
6860                               Data              => Data,
6861                               Path              => Path,
6862                               File_Name         => File_Name,
6863                               Locally_Removed   => To_Remove,
6864                               Display_File_Name => Display_File_Name,
6865                               For_All_Sources   => For_All_Sources);
6866                         end;
6867                      end if;
6868                   end loop;
6869
6870                   Close (Dir);
6871                end;
6872             end if;
6873
6874          exception
6875             when Directory_Error =>
6876                null;
6877          end;
6878
6879          Source_Dir := Element.Next;
6880          Src_Dir_Rank := Num_Nod.Next;
6881       end loop;
6882
6883       if Current_Verbosity = High then
6884          Write_Line ("end Looking for sources.");
6885       end if;
6886    end Search_Directories;
6887
6888    ----------------------------
6889    -- Load_Naming_Exceptions --
6890    ----------------------------
6891
6892    procedure Load_Naming_Exceptions
6893      (Project : in out Project_Processing_Data;
6894       Data    : in out Tree_Processing_Data)
6895    is
6896       Source : Source_Id;
6897       Iter   : Source_Iterator;
6898
6899    begin
6900       Iter := For_Each_Source (Data.Tree, Project.Project);
6901       loop
6902          Source := Prj.Element (Iter);
6903          exit when Source = No_Source;
6904
6905          --  An excluded file cannot also be an exception file name
6906
6907          if Excluded_Sources_Htable.Get (Project.Excluded, Source.File) /=
6908                                                                  No_File_Found
6909          then
6910             Error_Msg_File_1 := Source.File;
6911             Error_Msg
6912               (Data.Flags,
6913                "{ cannot be both excluded and an exception file name",
6914                No_Location, Project.Project);
6915          end if;
6916
6917          if Current_Verbosity = High then
6918             Write_Str ("Naming exception: Putting source file ");
6919             Write_Str (Get_Name_String (Source.File));
6920             Write_Line (" in Source_Names");
6921          end if;
6922
6923          Source_Names_Htable.Set
6924            (Project.Source_Names,
6925             K => Source.File,
6926             E => Name_Location'
6927                   (Name     => Source.File,
6928                    Location => No_Location,
6929                    Source   => Source,
6930                    Found    => False));
6931
6932          --  If this is an Ada exception, record in table Unit_Exceptions
6933
6934          if Source.Unit /= No_Unit_Index then
6935             declare
6936                Unit_Except : Unit_Exception :=
6937                  Unit_Exceptions_Htable.Get
6938                    (Project.Unit_Exceptions, Source.Unit.Name);
6939
6940             begin
6941                Unit_Except.Name := Source.Unit.Name;
6942
6943                if Source.Kind = Spec then
6944                   Unit_Except.Spec := Source.File;
6945                else
6946                   Unit_Except.Impl := Source.File;
6947                end if;
6948
6949                Unit_Exceptions_Htable.Set
6950                  (Project.Unit_Exceptions, Source.Unit.Name, Unit_Except);
6951             end;
6952          end if;
6953
6954          Next (Iter);
6955       end loop;
6956    end Load_Naming_Exceptions;
6957
6958    ----------------------
6959    -- Look_For_Sources --
6960    ----------------------
6961
6962    procedure Look_For_Sources
6963      (Project : in out Project_Processing_Data;
6964       Data    : in out Tree_Processing_Data)
6965    is
6966       Object_Files : Object_File_Names_Htable.Instance;
6967       Iter : Source_Iterator;
6968       Src  : Source_Id;
6969
6970       procedure Check_Object (Src : Source_Id);
6971       --  Check if object file name of Src is already used in the project tree,
6972       --  and report an error if so.
6973
6974       procedure Check_Object_Files;
6975       --  Check that no two sources of this project have the same object file
6976
6977       procedure Mark_Excluded_Sources;
6978       --  Mark as such the sources that are declared as excluded
6979
6980       ------------------
6981       -- Check_Object --
6982       ------------------
6983
6984       procedure Check_Object (Src : Source_Id) is
6985          Source : Source_Id;
6986
6987       begin
6988          Source := Object_File_Names_Htable.Get (Object_Files, Src.Object);
6989
6990          --  We cannot just check on "Source /= Src", since we might have
6991          --  two different entries for the same file (and since that's
6992          --  the same file it is expected that it has the same object)
6993
6994          if Source /= No_Source
6995            and then Source.Path /= Src.Path
6996          then
6997             Error_Msg_File_1 := Src.File;
6998             Error_Msg_File_2 := Source.File;
6999             Error_Msg
7000               (Data.Flags,
7001                "{ and { have the same object file name",
7002                No_Location, Project.Project);
7003
7004          else
7005             Object_File_Names_Htable.Set (Object_Files, Src.Object, Src);
7006          end if;
7007       end Check_Object;
7008
7009       ---------------------------
7010       -- Mark_Excluded_Sources --
7011       ---------------------------
7012
7013       procedure Mark_Excluded_Sources is
7014          Source   : Source_Id := No_Source;
7015          Excluded : File_Found;
7016          Proj     : Project_Id;
7017
7018       begin
7019          --  Minor optimization: if there are no excluded files, no need to
7020          --  traverse the list of sources. We cannot however also check whether
7021          --  the existing exceptions have ".Found" set to True (indicating we
7022          --  found them before) because we need to do some final processing on
7023          --  them in any case.
7024
7025          if Excluded_Sources_Htable.Get_First (Project.Excluded) /=
7026                                                              No_File_Found
7027          then
7028             Proj := Project.Project;
7029             while Proj /= No_Project loop
7030                Iter := For_Each_Source (Data.Tree, Proj);
7031                while Prj.Element (Iter) /= No_Source loop
7032                   Source   := Prj.Element (Iter);
7033                   Excluded := Excluded_Sources_Htable.Get
7034                     (Project.Excluded, Source.File);
7035
7036                   if Excluded /= No_File_Found then
7037                      Source.Locally_Removed := True;
7038                      Source.In_Interfaces   := False;
7039
7040                      if Current_Verbosity = High then
7041                         Write_Str ("Removing file ");
7042                         Write_Line
7043                           (Get_Name_String (Excluded.File)
7044                            & " " & Get_Name_String (Source.Project.Name));
7045                      end if;
7046
7047                      Excluded_Sources_Htable.Remove
7048                        (Project.Excluded, Source.File);
7049                   end if;
7050
7051                   Next (Iter);
7052                end loop;
7053
7054                Proj := Proj.Extends;
7055             end loop;
7056          end if;
7057
7058          --  If we have any excluded element left, that means we did not find
7059          --  the source file
7060
7061          Excluded := Excluded_Sources_Htable.Get_First (Project.Excluded);
7062          while Excluded /= No_File_Found loop
7063             if not Excluded.Found then
7064
7065                --  Check if the file belongs to another imported project to
7066                --  provide a better error message.
7067
7068                Src := Find_Source
7069                  (In_Tree          => Data.Tree,
7070                   Project          => Project.Project,
7071                   In_Imported_Only => True,
7072                   Base_Name        => Excluded.File);
7073
7074                Err_Vars.Error_Msg_File_1 := Excluded.File;
7075
7076                if Src = No_Source then
7077                   Error_Msg
7078                     (Data.Flags,
7079                      "unknown file {", Excluded.Location, Project.Project);
7080                else
7081                   Error_Msg
7082                     (Data.Flags,
7083                      "cannot remove a source from an imported project: {",
7084                      Excluded.Location, Project.Project);
7085                end if;
7086             end if;
7087
7088             Excluded := Excluded_Sources_Htable.Get_Next (Project.Excluded);
7089          end loop;
7090       end Mark_Excluded_Sources;
7091
7092       ------------------------
7093       -- Check_Object_Files --
7094       ------------------------
7095
7096       procedure Check_Object_Files is
7097          Iter    : Source_Iterator;
7098          Src_Id  : Source_Id;
7099          Src_Ind : Source_File_Index;
7100
7101       begin
7102          Iter := For_Each_Source (Data.Tree);
7103          loop
7104             Src_Id := Prj.Element (Iter);
7105             exit when Src_Id = No_Source;
7106
7107             if Is_Compilable (Src_Id)
7108               and then Src_Id.Language.Config.Object_Generated
7109               and then Is_Extending (Project.Project, Src_Id.Project)
7110             then
7111                if Src_Id.Unit = No_Unit_Index then
7112                   if Src_Id.Kind = Impl then
7113                      Check_Object (Src_Id);
7114                   end if;
7115
7116                else
7117                   case Src_Id.Kind is
7118                      when Spec =>
7119                         if Other_Part (Src_Id) = No_Source then
7120                            Check_Object (Src_Id);
7121                         end if;
7122
7123                      when Sep =>
7124                         null;
7125
7126                      when Impl =>
7127                         if Other_Part (Src_Id) /= No_Source then
7128                            Check_Object (Src_Id);
7129
7130                         else
7131                            --  Check if it is a subunit
7132
7133                            Src_Ind :=
7134                              Sinput.P.Load_Project_File
7135                                (Get_Name_String (Src_Id.Path.Name));
7136
7137                            if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7138                               Override_Kind (Src_Id, Sep);
7139                            else
7140                               Check_Object (Src_Id);
7141                            end if;
7142                         end if;
7143                   end case;
7144                end if;
7145             end if;
7146
7147             Next (Iter);
7148          end loop;
7149       end Check_Object_Files;
7150
7151    --  Start of processing for Look_For_Sources
7152
7153    begin
7154       Find_Excluded_Sources (Project, Data);
7155
7156       if Project.Project.Languages /= No_Language_Index then
7157          Load_Naming_Exceptions (Project, Data);
7158          Find_Sources (Project, Data);
7159          Mark_Excluded_Sources;
7160          Check_Object_Files;
7161       end if;
7162
7163       Object_File_Names_Htable.Reset (Object_Files);
7164    end Look_For_Sources;
7165
7166    ------------------
7167    -- Path_Name_Of --
7168    ------------------
7169
7170    function Path_Name_Of
7171      (File_Name : File_Name_Type;
7172       Directory : Path_Name_Type) return String
7173    is
7174       Result        : String_Access;
7175       The_Directory : constant String := Get_Name_String (Directory);
7176
7177    begin
7178       Get_Name_String (File_Name);
7179       Result :=
7180         Locate_Regular_File
7181           (File_Name => Name_Buffer (1 .. Name_Len),
7182            Path      => The_Directory);
7183
7184       if Result = null then
7185          return "";
7186       else
7187          declare
7188             R : String := Result.all;
7189          begin
7190             Free (Result);
7191             Canonical_Case_File_Name (R);
7192             return R;
7193          end;
7194       end if;
7195    end Path_Name_Of;
7196
7197    -------------------
7198    -- Remove_Source --
7199    -------------------
7200
7201    procedure Remove_Source
7202      (Id          : Source_Id;
7203       Replaced_By : Source_Id)
7204    is
7205       Source : Source_Id;
7206
7207    begin
7208       if Current_Verbosity = High then
7209          Write_Str ("Removing source ");
7210          Write_Str (Get_Name_String (Id.File));
7211
7212          if Id.Index /= 0 then
7213             Write_Str (" at" & Id.Index'Img);
7214          end if;
7215
7216          Write_Eol;
7217       end if;
7218
7219       if Replaced_By /= No_Source then
7220          Id.Replaced_By := Replaced_By;
7221          Replaced_By.Declared_In_Interfaces := Id.Declared_In_Interfaces;
7222       end if;
7223
7224       Id.In_Interfaces := False;
7225       Id.Locally_Removed := True;
7226
7227       --  ??? Should we remove the source from the unit ? The file is not used,
7228       --  so probably should not be referenced from the unit. On the other hand
7229       --  it might give useful additional info
7230       --        if Id.Unit /= null then
7231       --           Id.Unit.File_Names (Id.Kind) := null;
7232       --        end if;
7233
7234       Source := Id.Language.First_Source;
7235
7236       if Source = Id then
7237          Id.Language.First_Source := Id.Next_In_Lang;
7238
7239       else
7240          while Source.Next_In_Lang /= Id loop
7241             Source := Source.Next_In_Lang;
7242          end loop;
7243
7244          Source.Next_In_Lang := Id.Next_In_Lang;
7245       end if;
7246    end Remove_Source;
7247
7248    -----------------------
7249    -- Report_No_Sources --
7250    -----------------------
7251
7252    procedure Report_No_Sources
7253      (Project      : Project_Id;
7254       Lang_Name    : String;
7255       Data         : Tree_Processing_Data;
7256       Location     : Source_Ptr;
7257       Continuation : Boolean := False)
7258    is
7259    begin
7260       case Data.Flags.When_No_Sources is
7261          when Silent =>
7262             null;
7263
7264          when Warning | Error =>
7265             declare
7266                Msg : constant String :=
7267                        "<there are no " &
7268                        Lang_Name &
7269                        " sources in this project";
7270
7271             begin
7272                Error_Msg_Warn := Data.Flags.When_No_Sources = Warning;
7273
7274                if Continuation then
7275                   Error_Msg (Data.Flags, "\" & Msg, Location, Project);
7276                else
7277                   Error_Msg (Data.Flags, Msg, Location, Project);
7278                end if;
7279             end;
7280       end case;
7281    end Report_No_Sources;
7282
7283    ----------------------
7284    -- Show_Source_Dirs --
7285    ----------------------
7286
7287    procedure Show_Source_Dirs
7288      (Project : Project_Id;
7289       In_Tree : Project_Tree_Ref)
7290    is
7291       Current : String_List_Id;
7292       Element : String_Element;
7293
7294    begin
7295       Write_Line ("Source_Dirs:");
7296
7297       Current := Project.Source_Dirs;
7298       while Current /= Nil_String loop
7299          Element := In_Tree.String_Elements.Table (Current);
7300          Write_Str  ("   ");
7301          Write_Line (Get_Name_String (Element.Value));
7302          Current := Element.Next;
7303       end loop;
7304
7305       Write_Line ("end Source_Dirs.");
7306    end Show_Source_Dirs;
7307
7308    ---------------------------
7309    -- Process_Naming_Scheme --
7310    ---------------------------
7311
7312    procedure Process_Naming_Scheme
7313      (Tree         : Project_Tree_Ref;
7314       Root_Project : Project_Id;
7315       Flags        : Processing_Flags)
7316    is
7317       procedure Recursive_Check
7318         (Project : Project_Id;
7319          Data    : in out Tree_Processing_Data);
7320       --  Check_Naming_Scheme for the project
7321
7322       ---------------------
7323       -- Recursive_Check --
7324       ---------------------
7325
7326       procedure Recursive_Check
7327         (Project : Project_Id;
7328          Data    : in out Tree_Processing_Data)
7329       is
7330       begin
7331          if Verbose_Mode then
7332             Write_Str ("Processing_Naming_Scheme for project """);
7333             Write_Str (Get_Name_String (Project.Name));
7334             Write_Line ("""");
7335          end if;
7336
7337          Prj.Nmsc.Check (Project, Data);
7338       end Recursive_Check;
7339
7340       procedure Check_All_Projects is new
7341         For_Every_Project_Imported (Tree_Processing_Data, Recursive_Check);
7342
7343       Data : Tree_Processing_Data;
7344
7345    --  Start of processing for Process_Naming_Scheme
7346    begin
7347       Initialize (Data, Tree => Tree, Flags => Flags);
7348       Check_All_Projects (Root_Project, Data, Imported_First => True);
7349       Free (Data);
7350    end Process_Naming_Scheme;
7351
7352 end Prj.Nmsc;