OSDN Git Service

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