OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [gcc-4.5.1/] [gcc-4.5.1-or32-1.0rc2/] [gcc/] [ada/] [prj-nmsc.adb] - Blame information for rev 384

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 281 jeremybenn
------------------------------------------------------------------------------
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.Display_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_Run_Path_Origin then
2097
                  Get_Name_String (Attribute.Value.Value);
2098
 
2099
                  if Name_Len = 0 then
2100
                     Error_Msg
2101
                       (Data.Flags,
2102
                        "run path origin cannot be empty",
2103
                        Attribute.Value.Location, Project);
2104
                  end if;
2105
 
2106
                  Project.Config.Run_Path_Origin := Attribute.Value.Value;
2107
 
2108
               elsif Attribute.Name = Name_Library_Install_Name_Option then
2109
                  Project.Config.Library_Install_Name_Option :=
2110
                    Attribute.Value.Value;
2111
 
2112
               elsif Attribute.Name = Name_Separate_Run_Path_Options then
2113
                  declare
2114
                     pragma Unsuppress (All_Checks);
2115
                  begin
2116
                     Project.Config.Separate_Run_Path_Options :=
2117
                       Boolean'Value (Get_Name_String (Attribute.Value.Value));
2118
                  exception
2119
                     when Constraint_Error =>
2120
                        Error_Msg
2121
                          (Data.Flags,
2122
                           "invalid value """ &
2123
                           Get_Name_String (Attribute.Value.Value) &
2124
                           """ for Separate_Run_Path_Options",
2125
                           Attribute.Value.Location, Project);
2126
                  end;
2127
 
2128
               elsif Attribute.Name = Name_Library_Support then
2129
                  declare
2130
                     pragma Unsuppress (All_Checks);
2131
                  begin
2132
                     Project.Config.Lib_Support :=
2133
                       Library_Support'Value (Get_Name_String
2134
                                              (Attribute.Value.Value));
2135
                  exception
2136
                     when Constraint_Error =>
2137
                        Error_Msg
2138
                          (Data.Flags,
2139
                           "invalid value """ &
2140
                           Get_Name_String (Attribute.Value.Value) &
2141
                           """ for Library_Support",
2142
                           Attribute.Value.Location, Project);
2143
                  end;
2144
 
2145
               elsif Attribute.Name = Name_Shared_Library_Prefix then
2146
                  Project.Config.Shared_Lib_Prefix :=
2147
                    File_Name_Type (Attribute.Value.Value);
2148
 
2149
               elsif Attribute.Name = Name_Shared_Library_Suffix then
2150
                  Project.Config.Shared_Lib_Suffix :=
2151
                    File_Name_Type (Attribute.Value.Value);
2152
 
2153
               elsif Attribute.Name = Name_Symbolic_Link_Supported then
2154
                  declare
2155
                     pragma Unsuppress (All_Checks);
2156
                  begin
2157
                     Project.Config.Symbolic_Link_Supported :=
2158
                       Boolean'Value (Get_Name_String
2159
                                      (Attribute.Value.Value));
2160
                  exception
2161
                     when Constraint_Error =>
2162
                        Error_Msg
2163
                          (Data.Flags,
2164
                           "invalid value """
2165
                             & Get_Name_String (Attribute.Value.Value)
2166
                             & """ for Symbolic_Link_Supported",
2167
                           Attribute.Value.Location, Project);
2168
                  end;
2169
 
2170
               elsif
2171
                 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2172
               then
2173
                  declare
2174
                     pragma Unsuppress (All_Checks);
2175
                  begin
2176
                     Project.Config.Lib_Maj_Min_Id_Supported :=
2177
                       Boolean'Value (Get_Name_String
2178
                                      (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_Major_Minor_Id_Supported",
2186
                           Attribute.Value.Location, Project);
2187
                  end;
2188
 
2189
               elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2190
                  declare
2191
                     pragma Unsuppress (All_Checks);
2192
                  begin
2193
                     Project.Config.Auto_Init_Supported :=
2194
                       Boolean'Value (Get_Name_String (Attribute.Value.Value));
2195
                  exception
2196
                     when Constraint_Error =>
2197
                        Error_Msg
2198
                          (Data.Flags,
2199
                           "invalid value """
2200
                             & Get_Name_String (Attribute.Value.Value)
2201
                             & """ for Library_Auto_Init_Supported",
2202
                           Attribute.Value.Location, Project);
2203
                  end;
2204
 
2205
               elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2206
                  List := Attribute.Value.Values;
2207
 
2208
                  if List /= Nil_String then
2209
                     Put (Into_List => Project.Config.Shared_Lib_Min_Options,
2210
                          From_List => List,
2211
                          In_Tree   => Data.Tree);
2212
                  end if;
2213
 
2214
               elsif Attribute.Name = Name_Library_Version_Switches then
2215
                  List := Attribute.Value.Values;
2216
 
2217
                  if List /= Nil_String then
2218
                     Put (Into_List => Project.Config.Lib_Version_Options,
2219
                          From_List => List,
2220
                          In_Tree   => Data.Tree);
2221
                  end if;
2222
               end if;
2223
            end if;
2224
 
2225
            Attribute_Id := Attribute.Next;
2226
         end loop;
2227
      end Process_Project_Level_Simple_Attributes;
2228
 
2229
      --------------------------------------------
2230
      -- Process_Project_Level_Array_Attributes --
2231
      --------------------------------------------
2232
 
2233
      procedure Process_Project_Level_Array_Attributes is
2234
         Current_Array_Id : Array_Id;
2235
         Current_Array    : Array_Data;
2236
         Element_Id       : Array_Element_Id;
2237
         Element          : Array_Element;
2238
         List             : String_List_Id;
2239
 
2240
      begin
2241
         --  Process the associative array attributes at project level
2242
 
2243
         Current_Array_Id := Project.Decl.Arrays;
2244
         while Current_Array_Id /= No_Array loop
2245
            Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
2246
 
2247
            Element_Id := Current_Array.Value;
2248
            while Element_Id /= No_Array_Element loop
2249
               Element := Data.Tree.Array_Elements.Table (Element_Id);
2250
 
2251
               --  Get the name of the language
2252
 
2253
               Lang_Index :=
2254
                 Get_Language_From_Name
2255
                   (Project, Get_Name_String (Element.Index));
2256
 
2257
               if Lang_Index /= No_Language_Index then
2258
                  case Current_Array.Name is
2259
                     when Name_Inherit_Source_Path =>
2260
                        List := Element.Value.Values;
2261
 
2262
                        if List /= Nil_String then
2263
                           Put
2264
                             (Into_List  =>
2265
                                Lang_Index.Config.Include_Compatible_Languages,
2266
                              From_List  => List,
2267
                              In_Tree    => Data.Tree,
2268
                              Lower_Case => True);
2269
                        end if;
2270
 
2271
                     when Name_Toolchain_Description =>
2272
 
2273
                        --  Attribute Toolchain_Description (<language>)
2274
 
2275
                        Lang_Index.Config.Toolchain_Description :=
2276
                          Element.Value.Value;
2277
 
2278
                     when Name_Toolchain_Version =>
2279
 
2280
                        --  Attribute Toolchain_Version (<language>)
2281
 
2282
                        Lang_Index.Config.Toolchain_Version :=
2283
                          Element.Value.Value;
2284
 
2285
                     when Name_Runtime_Library_Dir =>
2286
 
2287
                        --  Attribute Runtime_Library_Dir (<language>)
2288
 
2289
                        Lang_Index.Config.Runtime_Library_Dir :=
2290
                          Element.Value.Value;
2291
 
2292
                     when Name_Runtime_Source_Dir =>
2293
 
2294
                        --  Attribute Runtime_Library_Dir (<language>)
2295
 
2296
                        Lang_Index.Config.Runtime_Source_Dir :=
2297
                          Element.Value.Value;
2298
 
2299
                     when Name_Object_Generated =>
2300
                        declare
2301
                           pragma Unsuppress (All_Checks);
2302
                           Value : Boolean;
2303
 
2304
                        begin
2305
                           Value :=
2306
                             Boolean'Value
2307
                               (Get_Name_String (Element.Value.Value));
2308
 
2309
                           Lang_Index.Config.Object_Generated := Value;
2310
 
2311
                           --  If no object is generated, no object may be
2312
                           --  linked.
2313
 
2314
                           if not Value then
2315
                              Lang_Index.Config.Objects_Linked := False;
2316
                           end if;
2317
 
2318
                        exception
2319
                           when Constraint_Error =>
2320
                              Error_Msg
2321
                                (Data.Flags,
2322
                                 "invalid value """
2323
                                 & Get_Name_String (Element.Value.Value)
2324
                                 & """ for Object_Generated",
2325
                                 Element.Value.Location, Project);
2326
                        end;
2327
 
2328
                     when Name_Objects_Linked =>
2329
                        declare
2330
                           pragma Unsuppress (All_Checks);
2331
                           Value : Boolean;
2332
 
2333
                        begin
2334
                           Value :=
2335
                             Boolean'Value
2336
                               (Get_Name_String (Element.Value.Value));
2337
 
2338
                           --  No change if Object_Generated is False, as this
2339
                           --  forces Objects_Linked to be False too.
2340
 
2341
                           if Lang_Index.Config.Object_Generated then
2342
                              Lang_Index.Config.Objects_Linked := Value;
2343
                           end if;
2344
 
2345
                        exception
2346
                           when Constraint_Error =>
2347
                              Error_Msg
2348
                                (Data.Flags,
2349
                                 "invalid value """
2350
                                 & Get_Name_String (Element.Value.Value)
2351
                                 & """ for Objects_Linked",
2352
                                 Element.Value.Location, Project);
2353
                        end;
2354
                     when others =>
2355
                        null;
2356
                  end case;
2357
               end if;
2358
 
2359
               Element_Id := Element.Next;
2360
            end loop;
2361
 
2362
            Current_Array_Id := Current_Array.Next;
2363
         end loop;
2364
      end Process_Project_Level_Array_Attributes;
2365
 
2366
   --  Start of processing for Check_Configuration
2367
 
2368
   begin
2369
      Process_Project_Level_Simple_Attributes;
2370
      Process_Project_Level_Array_Attributes;
2371
      Process_Packages;
2372
 
2373
      --  For unit based languages, set Casing, Dot_Replacement and
2374
      --  Separate_Suffix in Naming_Data.
2375
 
2376
      Lang_Index := Project.Languages;
2377
      while Lang_Index /= No_Language_Index loop
2378
         if Lang_Index.Name = Name_Ada then
2379
            Lang_Index.Config.Naming_Data.Casing := Casing;
2380
            Lang_Index.Config.Naming_Data.Dot_Replacement := Dot_Replacement;
2381
 
2382
            if Separate_Suffix /= No_File then
2383
               Lang_Index.Config.Naming_Data.Separate_Suffix :=
2384
                 Separate_Suffix;
2385
            end if;
2386
 
2387
            exit;
2388
         end if;
2389
 
2390
         Lang_Index := Lang_Index.Next;
2391
      end loop;
2392
 
2393
      --  Give empty names to various prefixes/suffixes, if they have not
2394
      --  been specified in the configuration.
2395
 
2396
      if Project.Config.Archive_Suffix = No_File then
2397
         Project.Config.Archive_Suffix := Empty_File;
2398
      end if;
2399
 
2400
      if Project.Config.Shared_Lib_Prefix = No_File then
2401
         Project.Config.Shared_Lib_Prefix := Empty_File;
2402
      end if;
2403
 
2404
      if Project.Config.Shared_Lib_Suffix = No_File then
2405
         Project.Config.Shared_Lib_Suffix := Empty_File;
2406
      end if;
2407
 
2408
      Lang_Index := Project.Languages;
2409
      while Lang_Index /= No_Language_Index loop
2410
 
2411
         --  For all languages, Compiler_Driver needs to be specified. This is
2412
         --  only needed if we do intend to compile (not in GPS for instance).
2413
 
2414
         if Data.Flags.Compiler_Driver_Mandatory
2415
           and then Lang_Index.Config.Compiler_Driver = No_File
2416
         then
2417
            Error_Msg_Name_1 := Lang_Index.Display_Name;
2418
            Error_Msg
2419
              (Data.Flags,
2420
               "?no compiler specified for language %%" &
2421
                 ", ignoring all its sources",
2422
               No_Location, Project);
2423
 
2424
            if Lang_Index = Project.Languages then
2425
               Project.Languages := Lang_Index.Next;
2426
            else
2427
               Prev_Index.Next := Lang_Index.Next;
2428
            end if;
2429
 
2430
         elsif Lang_Index.Name = Name_Ada then
2431
            Prev_Index := Lang_Index;
2432
 
2433
            --  For unit based languages, Dot_Replacement, Spec_Suffix and
2434
            --  Body_Suffix need to be specified.
2435
 
2436
            if Lang_Index.Config.Naming_Data.Dot_Replacement = No_File then
2437
               Error_Msg
2438
                 (Data.Flags,
2439
                  "Dot_Replacement not specified for Ada",
2440
                  No_Location, Project);
2441
            end if;
2442
 
2443
            if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File then
2444
               Error_Msg
2445
                 (Data.Flags,
2446
                  "Spec_Suffix not specified for Ada",
2447
                  No_Location, Project);
2448
            end if;
2449
 
2450
            if Lang_Index.Config.Naming_Data.Body_Suffix = No_File then
2451
               Error_Msg
2452
                 (Data.Flags,
2453
                  "Body_Suffix not specified for Ada",
2454
                  No_Location, Project);
2455
            end if;
2456
 
2457
         else
2458
            Prev_Index := Lang_Index;
2459
 
2460
            --  For file based languages, either Spec_Suffix or Body_Suffix
2461
            --  need to be specified.
2462
 
2463
            if Data.Flags.Require_Sources_Other_Lang
2464
              and then Lang_Index.Config.Naming_Data.Spec_Suffix = No_File
2465
              and then Lang_Index.Config.Naming_Data.Body_Suffix = No_File
2466
            then
2467
               Error_Msg_Name_1 := Lang_Index.Display_Name;
2468
               Error_Msg
2469
                 (Data.Flags,
2470
                  "no suffixes specified for %%",
2471
                  No_Location, Project);
2472
            end if;
2473
         end if;
2474
 
2475
         Lang_Index := Lang_Index.Next;
2476
      end loop;
2477
   end Check_Configuration;
2478
 
2479
   -------------------------------
2480
   -- Check_If_Externally_Built --
2481
   -------------------------------
2482
 
2483
   procedure Check_If_Externally_Built
2484
     (Project : Project_Id;
2485
      Data    : in out Tree_Processing_Data)
2486
   is
2487
      Externally_Built : constant Variable_Value :=
2488
                           Util.Value_Of
2489
                            (Name_Externally_Built,
2490
                             Project.Decl.Attributes, Data.Tree);
2491
 
2492
   begin
2493
      if not Externally_Built.Default then
2494
         Get_Name_String (Externally_Built.Value);
2495
         To_Lower (Name_Buffer (1 .. Name_Len));
2496
 
2497
         if Name_Buffer (1 .. Name_Len) = "true" then
2498
            Project.Externally_Built := True;
2499
 
2500
         elsif Name_Buffer (1 .. Name_Len) /= "false" then
2501
            Error_Msg (Data.Flags,
2502
                       "Externally_Built may only be true or false",
2503
                       Externally_Built.Location, Project);
2504
         end if;
2505
      end if;
2506
 
2507
      --  A virtual project extending an externally built project is itself
2508
      --  externally built.
2509
 
2510
      if Project.Virtual and then Project.Extends /= No_Project then
2511
         Project.Externally_Built := Project.Extends.Externally_Built;
2512
      end if;
2513
 
2514
      if Current_Verbosity = High then
2515
         Write_Str ("Project is ");
2516
 
2517
         if not Project.Externally_Built then
2518
            Write_Str ("not ");
2519
         end if;
2520
 
2521
         Write_Line ("externally built.");
2522
      end if;
2523
   end Check_If_Externally_Built;
2524
 
2525
   ----------------------
2526
   -- Check_Interfaces --
2527
   ----------------------
2528
 
2529
   procedure Check_Interfaces
2530
     (Project : Project_Id;
2531
      Data    : in out Tree_Processing_Data)
2532
   is
2533
      Interfaces : constant Prj.Variable_Value :=
2534
                     Prj.Util.Value_Of
2535
                       (Snames.Name_Interfaces,
2536
                        Project.Decl.Attributes,
2537
                        Data.Tree);
2538
 
2539
      Library_Interface : constant Prj.Variable_Value :=
2540
                            Prj.Util.Value_Of
2541
                              (Snames.Name_Library_Interface,
2542
                               Project.Decl.Attributes,
2543
                               Data.Tree);
2544
 
2545
      List      : String_List_Id;
2546
      Element   : String_Element;
2547
      Name      : File_Name_Type;
2548
      Iter      : Source_Iterator;
2549
      Source    : Source_Id;
2550
      Project_2 : Project_Id;
2551
      Other     : Source_Id;
2552
 
2553
   begin
2554
      if not Interfaces.Default then
2555
 
2556
         --  Set In_Interfaces to False for all sources. It will be set to True
2557
         --  later for the sources in the Interfaces list.
2558
 
2559
         Project_2 := Project;
2560
         while Project_2 /= No_Project loop
2561
            Iter := For_Each_Source (Data.Tree, Project_2);
2562
            loop
2563
               Source := Prj.Element (Iter);
2564
               exit when Source = No_Source;
2565
               Source.In_Interfaces := False;
2566
               Next (Iter);
2567
            end loop;
2568
 
2569
            Project_2 := Project_2.Extends;
2570
         end loop;
2571
 
2572
         List := Interfaces.Values;
2573
         while List /= Nil_String loop
2574
            Element := Data.Tree.String_Elements.Table (List);
2575
            Name := Canonical_Case_File_Name (Element.Value);
2576
 
2577
            Project_2 := Project;
2578
            Big_Loop :
2579
            while Project_2 /= No_Project loop
2580
               Iter := For_Each_Source (Data.Tree, Project_2);
2581
 
2582
               loop
2583
                  Source := Prj.Element (Iter);
2584
                  exit when Source = No_Source;
2585
 
2586
                  if Source.File = Name then
2587
                     if not Source.Locally_Removed then
2588
                        Source.In_Interfaces := True;
2589
                        Source.Declared_In_Interfaces := True;
2590
 
2591
                        Other := Other_Part (Source);
2592
 
2593
                        if Other /= No_Source then
2594
                           Other.In_Interfaces := True;
2595
                           Other.Declared_In_Interfaces := True;
2596
                        end if;
2597
 
2598
                        if Current_Verbosity = High then
2599
                           Write_Str ("   interface: ");
2600
                           Write_Line (Get_Name_String (Source.Path.Name));
2601
                        end if;
2602
                     end if;
2603
 
2604
                     exit Big_Loop;
2605
                  end if;
2606
 
2607
                  Next (Iter);
2608
               end loop;
2609
 
2610
               Project_2 := Project_2.Extends;
2611
            end loop Big_Loop;
2612
 
2613
            if Source = No_Source then
2614
               Error_Msg_File_1 := File_Name_Type (Element.Value);
2615
               Error_Msg_Name_1 := Project.Name;
2616
 
2617
               Error_Msg
2618
                 (Data.Flags,
2619
                  "{ cannot be an interface of project %% "
2620
                  & "as it is not one of its sources",
2621
                  Element.Location, Project);
2622
            end if;
2623
 
2624
            List := Element.Next;
2625
         end loop;
2626
 
2627
         Project.Interfaces_Defined := True;
2628
 
2629
      elsif Project.Library and then not Library_Interface.Default then
2630
 
2631
         --  Set In_Interfaces to False for all sources. It will be set to True
2632
         --  later for the sources in the Library_Interface list.
2633
 
2634
         Project_2 := Project;
2635
         while Project_2 /= No_Project loop
2636
            Iter := For_Each_Source (Data.Tree, Project_2);
2637
            loop
2638
               Source := Prj.Element (Iter);
2639
               exit when Source = No_Source;
2640
               Source.In_Interfaces := False;
2641
               Next (Iter);
2642
            end loop;
2643
 
2644
            Project_2 := Project_2.Extends;
2645
         end loop;
2646
 
2647
         List := Library_Interface.Values;
2648
         while List /= Nil_String loop
2649
            Element := Data.Tree.String_Elements.Table (List);
2650
            Get_Name_String (Element.Value);
2651
            To_Lower (Name_Buffer (1 .. Name_Len));
2652
            Name := Name_Find;
2653
 
2654
            Project_2 := Project;
2655
            Big_Loop_2 :
2656
            while Project_2 /= No_Project loop
2657
               Iter := For_Each_Source (Data.Tree, Project_2);
2658
 
2659
               loop
2660
                  Source := Prj.Element (Iter);
2661
                  exit when Source = No_Source;
2662
 
2663
                  if Source.Unit /= No_Unit_Index and then
2664
                     Source.Unit.Name = Name_Id (Name)
2665
                  then
2666
                     if not Source.Locally_Removed then
2667
                        Source.In_Interfaces := True;
2668
                        Source.Declared_In_Interfaces := True;
2669
 
2670
                        Other := Other_Part (Source);
2671
 
2672
                        if Other /= No_Source then
2673
                           Other.In_Interfaces := True;
2674
                           Other.Declared_In_Interfaces := True;
2675
                        end if;
2676
 
2677
                        if Current_Verbosity = High then
2678
                           Write_Str ("   interface: ");
2679
                           Write_Line (Get_Name_String (Source.Path.Name));
2680
                        end if;
2681
                     end if;
2682
 
2683
                     exit Big_Loop_2;
2684
                  end if;
2685
 
2686
                  Next (Iter);
2687
               end loop;
2688
 
2689
               Project_2 := Project_2.Extends;
2690
            end loop Big_Loop_2;
2691
 
2692
            List := Element.Next;
2693
         end loop;
2694
 
2695
         Project.Interfaces_Defined := True;
2696
 
2697
      elsif Project.Extends /= No_Project
2698
        and then Project.Extends.Interfaces_Defined
2699
      then
2700
         Project.Interfaces_Defined := True;
2701
 
2702
         Iter := For_Each_Source (Data.Tree, Project);
2703
         loop
2704
            Source := Prj.Element (Iter);
2705
            exit when Source = No_Source;
2706
 
2707
            if not Source.Declared_In_Interfaces then
2708
               Source.In_Interfaces := False;
2709
            end if;
2710
 
2711
            Next (Iter);
2712
         end loop;
2713
      end if;
2714
   end Check_Interfaces;
2715
 
2716
   --------------------------
2717
   -- Check_Package_Naming --
2718
   --------------------------
2719
 
2720
   procedure Check_Package_Naming
2721
     (Project : Project_Id;
2722
      Data    : in out Tree_Processing_Data;
2723
      Bodies  : out Array_Element_Id;
2724
      Specs   : out Array_Element_Id)
2725
   is
2726
      Naming_Id : constant Package_Id :=
2727
                    Util.Value_Of
2728
                      (Name_Naming, Project.Decl.Packages, Data.Tree);
2729
      Naming    : Package_Element;
2730
 
2731
      Ada_Body_Suffix_Loc : Source_Ptr := No_Location;
2732
 
2733
      procedure Check_Naming;
2734
      --  Check the validity of the Naming package (suffixes valid, ...)
2735
 
2736
      procedure Check_Common
2737
        (Dot_Replacement : in out File_Name_Type;
2738
         Casing          : in out Casing_Type;
2739
         Casing_Defined  : out Boolean;
2740
         Separate_Suffix : in out File_Name_Type;
2741
         Sep_Suffix_Loc  : out Source_Ptr);
2742
      --  Check attributes common
2743
 
2744
      procedure Process_Exceptions_File_Based
2745
        (Lang_Id : Language_Ptr;
2746
         Kind    : Source_Kind);
2747
      procedure Process_Exceptions_Unit_Based
2748
        (Lang_Id : Language_Ptr;
2749
         Kind    : Source_Kind);
2750
      --  Process the naming exceptions for the two types of languages
2751
 
2752
      procedure Initialize_Naming_Data;
2753
      --  Initialize internal naming data for the various languages
2754
 
2755
      ------------------
2756
      -- Check_Common --
2757
      ------------------
2758
 
2759
      procedure Check_Common
2760
        (Dot_Replacement : in out File_Name_Type;
2761
         Casing          : in out Casing_Type;
2762
         Casing_Defined  : out Boolean;
2763
         Separate_Suffix : in out File_Name_Type;
2764
         Sep_Suffix_Loc  : out Source_Ptr)
2765
      is
2766
         Dot_Repl      : constant Variable_Value :=
2767
                           Util.Value_Of
2768
                             (Name_Dot_Replacement,
2769
                              Naming.Decl.Attributes,
2770
                              Data.Tree);
2771
         Casing_String : constant Variable_Value :=
2772
                           Util.Value_Of
2773
                             (Name_Casing,
2774
                              Naming.Decl.Attributes,
2775
                              Data.Tree);
2776
         Sep_Suffix    : constant Variable_Value :=
2777
                           Util.Value_Of
2778
                             (Name_Separate_Suffix,
2779
                              Naming.Decl.Attributes,
2780
                              Data.Tree);
2781
         Dot_Repl_Loc  : Source_Ptr;
2782
 
2783
      begin
2784
         Sep_Suffix_Loc := No_Location;
2785
 
2786
         if not Dot_Repl.Default then
2787
            pragma Assert
2788
              (Dot_Repl.Kind = Single, "Dot_Replacement is not a string");
2789
 
2790
            if Length_Of_Name (Dot_Repl.Value) = 0 then
2791
               Error_Msg
2792
                 (Data.Flags, "Dot_Replacement cannot be empty",
2793
                  Dot_Repl.Location, Project);
2794
            end if;
2795
 
2796
            Dot_Replacement := Canonical_Case_File_Name (Dot_Repl.Value);
2797
            Dot_Repl_Loc    := Dot_Repl.Location;
2798
 
2799
            declare
2800
               Repl : constant String := Get_Name_String (Dot_Replacement);
2801
 
2802
            begin
2803
               --  Dot_Replacement cannot
2804
               --   - be empty
2805
               --   - start or end with an alphanumeric
2806
               --   - be a single '_'
2807
               --   - start with an '_' followed by an alphanumeric
2808
               --   - contain a '.' except if it is "."
2809
 
2810
               if Repl'Length = 0
2811
                 or else Is_Alphanumeric (Repl (Repl'First))
2812
                 or else Is_Alphanumeric (Repl (Repl'Last))
2813
                 or else (Repl (Repl'First) = '_'
2814
                           and then
2815
                             (Repl'Length = 1
2816
                               or else
2817
                                 Is_Alphanumeric (Repl (Repl'First + 1))))
2818
                 or else (Repl'Length > 1
2819
                           and then
2820
                             Index (Source => Repl, Pattern => ".") /= 0)
2821
               then
2822
                  Error_Msg
2823
                    (Data.Flags,
2824
                     '"' & Repl &
2825
                     """ is illegal for Dot_Replacement.",
2826
                     Dot_Repl_Loc, Project);
2827
               end if;
2828
            end;
2829
         end if;
2830
 
2831
         if Dot_Replacement /= No_File then
2832
            Write_Attr
2833
              ("Dot_Replacement", Get_Name_String (Dot_Replacement));
2834
         end if;
2835
 
2836
         Casing_Defined := False;
2837
 
2838
         if not Casing_String.Default then
2839
            pragma Assert
2840
              (Casing_String.Kind = Single, "Casing is not a string");
2841
 
2842
            declare
2843
               Casing_Image : constant String :=
2844
                                Get_Name_String (Casing_String.Value);
2845
 
2846
            begin
2847
               if Casing_Image'Length = 0 then
2848
                  Error_Msg
2849
                    (Data.Flags,
2850
                     "Casing cannot be an empty string",
2851
                     Casing_String.Location, Project);
2852
               end if;
2853
 
2854
               Casing := Value (Casing_Image);
2855
               Casing_Defined := True;
2856
 
2857
            exception
2858
               when Constraint_Error =>
2859
                  Name_Len := Casing_Image'Length;
2860
                  Name_Buffer (1 .. Name_Len) := Casing_Image;
2861
                  Err_Vars.Error_Msg_Name_1 := Name_Find;
2862
                  Error_Msg
2863
                    (Data.Flags,
2864
                     "%% is not a correct Casing",
2865
                     Casing_String.Location, Project);
2866
            end;
2867
         end if;
2868
 
2869
         Write_Attr ("Casing", Image (Casing));
2870
 
2871
         if not Sep_Suffix.Default then
2872
            if Length_Of_Name (Sep_Suffix.Value) = 0 then
2873
               Error_Msg
2874
                 (Data.Flags,
2875
                  "Separate_Suffix cannot be empty",
2876
                  Sep_Suffix.Location, Project);
2877
 
2878
            else
2879
               Separate_Suffix := Canonical_Case_File_Name (Sep_Suffix.Value);
2880
               Sep_Suffix_Loc  := Sep_Suffix.Location;
2881
 
2882
               Check_Illegal_Suffix
2883
                 (Project, Separate_Suffix,
2884
                  Dot_Replacement, "Separate_Suffix", Sep_Suffix.Location,
2885
                  Data);
2886
            end if;
2887
         end if;
2888
 
2889
         if Separate_Suffix /= No_File then
2890
            Write_Attr
2891
              ("Separate_Suffix", Get_Name_String (Separate_Suffix));
2892
         end if;
2893
      end Check_Common;
2894
 
2895
      -----------------------------------
2896
      -- Process_Exceptions_File_Based --
2897
      -----------------------------------
2898
 
2899
      procedure Process_Exceptions_File_Based
2900
        (Lang_Id : Language_Ptr;
2901
         Kind    : Source_Kind)
2902
      is
2903
         Lang           : constant Name_Id := Lang_Id.Name;
2904
         Exceptions     : Array_Element_Id;
2905
         Exception_List : Variable_Value;
2906
         Element_Id     : String_List_Id;
2907
         Element        : String_Element;
2908
         File_Name      : File_Name_Type;
2909
         Source         : Source_Id;
2910
         Iter           : Source_Iterator;
2911
 
2912
      begin
2913
         case Kind is
2914
            when Impl | Sep =>
2915
               Exceptions :=
2916
                 Value_Of
2917
                   (Name_Implementation_Exceptions,
2918
                    In_Arrays => Naming.Decl.Arrays,
2919
                    In_Tree   => Data.Tree);
2920
 
2921
            when Spec =>
2922
               Exceptions :=
2923
                 Value_Of
2924
                   (Name_Specification_Exceptions,
2925
                    In_Arrays => Naming.Decl.Arrays,
2926
                    In_Tree   => Data.Tree);
2927
         end case;
2928
 
2929
         Exception_List := Value_Of
2930
           (Index    => Lang,
2931
            In_Array => Exceptions,
2932
            In_Tree  => Data.Tree);
2933
 
2934
         if Exception_List /= Nil_Variable_Value then
2935
            Element_Id := Exception_List.Values;
2936
            while Element_Id /= Nil_String loop
2937
               Element   := Data.Tree.String_Elements.Table (Element_Id);
2938
               File_Name := Canonical_Case_File_Name (Element.Value);
2939
 
2940
               Iter := For_Each_Source (Data.Tree, Project);
2941
               loop
2942
                  Source := Prj.Element (Iter);
2943
                  exit when Source = No_Source or else Source.File = File_Name;
2944
                  Next (Iter);
2945
               end loop;
2946
 
2947
               if Source = No_Source then
2948
                  Add_Source
2949
                    (Id               => Source,
2950
                     Data             => Data,
2951
                     Project          => Project,
2952
                     Source_Dir_Rank  => 0,
2953
                     Lang_Id          => Lang_Id,
2954
                     Kind             => Kind,
2955
                     File_Name        => File_Name,
2956
                     Display_File     => File_Name_Type (Element.Value),
2957
                     Naming_Exception => True);
2958
 
2959
               else
2960
                  --  Check if the file name is already recorded for another
2961
                  --  language or another kind.
2962
 
2963
                  if Source.Language /= Lang_Id then
2964
                     Error_Msg
2965
                       (Data.Flags,
2966
                        "the same file cannot be a source of two languages",
2967
                        Element.Location, Project);
2968
 
2969
                  elsif Source.Kind /= Kind then
2970
                     Error_Msg
2971
                       (Data.Flags,
2972
                        "the same file cannot be a source and a template",
2973
                        Element.Location, Project);
2974
                  end if;
2975
 
2976
                  --  If the file is already recorded for the same
2977
                  --  language and the same kind, it means that the file
2978
                  --  name appears several times in the *_Exceptions
2979
                  --  attribute; so there is nothing to do.
2980
               end if;
2981
 
2982
               Element_Id := Element.Next;
2983
            end loop;
2984
         end if;
2985
      end Process_Exceptions_File_Based;
2986
 
2987
      -----------------------------------
2988
      -- Process_Exceptions_Unit_Based --
2989
      -----------------------------------
2990
 
2991
      procedure Process_Exceptions_Unit_Based
2992
        (Lang_Id : Language_Ptr;
2993
         Kind    : Source_Kind)
2994
      is
2995
         Lang       : constant Name_Id := Lang_Id.Name;
2996
         Exceptions : Array_Element_Id;
2997
         Element    : Array_Element;
2998
         Unit       : Name_Id;
2999
         Index      : Int;
3000
         File_Name  : File_Name_Type;
3001
         Source     : Source_Id;
3002
 
3003
      begin
3004
         case Kind is
3005
            when Impl | Sep =>
3006
               Exceptions :=
3007
                 Value_Of
3008
                   (Name_Body,
3009
                    In_Arrays => Naming.Decl.Arrays,
3010
                    In_Tree   => Data.Tree);
3011
 
3012
               if Exceptions = No_Array_Element then
3013
                  Exceptions :=
3014
                    Value_Of
3015
                      (Name_Implementation,
3016
                       In_Arrays => Naming.Decl.Arrays,
3017
                       In_Tree   => Data.Tree);
3018
               end if;
3019
 
3020
            when Spec =>
3021
               Exceptions :=
3022
                 Value_Of
3023
                   (Name_Spec,
3024
                    In_Arrays => Naming.Decl.Arrays,
3025
                    In_Tree   => Data.Tree);
3026
 
3027
               if Exceptions = No_Array_Element then
3028
                  Exceptions :=
3029
                    Value_Of
3030
                      (Name_Spec,
3031
                       In_Arrays => Naming.Decl.Arrays,
3032
                       In_Tree   => Data.Tree);
3033
               end if;
3034
         end case;
3035
 
3036
         while Exceptions /= No_Array_Element loop
3037
            Element   := Data.Tree.Array_Elements.Table (Exceptions);
3038
            File_Name := Canonical_Case_File_Name (Element.Value.Value);
3039
 
3040
            Get_Name_String (Element.Index);
3041
            To_Lower (Name_Buffer (1 .. Name_Len));
3042
            Unit  := Name_Find;
3043
            Index := Element.Value.Index;
3044
 
3045
            --  For Ada, check if it is a valid unit name
3046
 
3047
            if Lang = Name_Ada then
3048
               Get_Name_String (Element.Index);
3049
               Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
3050
 
3051
               if Unit = No_Name then
3052
                  Err_Vars.Error_Msg_Name_1 := Element.Index;
3053
                  Error_Msg
3054
                    (Data.Flags,
3055
                     "%% is not a valid unit name.",
3056
                     Element.Value.Location, Project);
3057
               end if;
3058
            end if;
3059
 
3060
            if Unit /= No_Name then
3061
               Add_Source
3062
                 (Id               => Source,
3063
                  Data             => Data,
3064
                  Project          => Project,
3065
                  Source_Dir_Rank  => 0,
3066
                  Lang_Id          => Lang_Id,
3067
                  Kind             => Kind,
3068
                  File_Name        => File_Name,
3069
                  Display_File     => File_Name_Type (Element.Value.Value),
3070
                  Unit             => Unit,
3071
                  Index            => Index,
3072
                  Location         => Element.Value.Location,
3073
                  Naming_Exception => True);
3074
            end if;
3075
 
3076
            Exceptions := Element.Next;
3077
         end loop;
3078
      end Process_Exceptions_Unit_Based;
3079
 
3080
      ------------------
3081
      -- Check_Naming --
3082
      ------------------
3083
 
3084
      procedure Check_Naming is
3085
         Dot_Replacement : File_Name_Type :=
3086
                             File_Name_Type
3087
                               (First_Name_Id + Character'Pos ('-'));
3088
         Separate_Suffix : File_Name_Type := No_File;
3089
         Casing          : Casing_Type    := All_Lower_Case;
3090
         Casing_Defined  : Boolean;
3091
         Lang_Id         : Language_Ptr;
3092
         Sep_Suffix_Loc  : Source_Ptr;
3093
         Suffix          : Variable_Value;
3094
         Lang            : Name_Id;
3095
 
3096
      begin
3097
         Check_Common
3098
           (Dot_Replacement => Dot_Replacement,
3099
            Casing          => Casing,
3100
            Casing_Defined  => Casing_Defined,
3101
            Separate_Suffix => Separate_Suffix,
3102
            Sep_Suffix_Loc  => Sep_Suffix_Loc);
3103
 
3104
         --  For all unit based languages, if any, set the specified value
3105
         --  of Dot_Replacement, Casing and/or Separate_Suffix. Do not
3106
         --  systematically overwrite, since the defaults come from the
3107
         --  configuration file.
3108
 
3109
         if Dot_Replacement /= No_File
3110
           or else Casing_Defined
3111
           or else Separate_Suffix /= No_File
3112
         then
3113
            Lang_Id := Project.Languages;
3114
            while Lang_Id /= No_Language_Index loop
3115
               if Lang_Id.Config.Kind = Unit_Based then
3116
                  if Dot_Replacement /= No_File then
3117
                     Lang_Id.Config.Naming_Data.Dot_Replacement :=
3118
                         Dot_Replacement;
3119
                  end if;
3120
 
3121
                  if Casing_Defined then
3122
                     Lang_Id.Config.Naming_Data.Casing := Casing;
3123
                  end if;
3124
               end if;
3125
 
3126
               Lang_Id := Lang_Id.Next;
3127
            end loop;
3128
         end if;
3129
 
3130
         --  Next, get the spec and body suffixes
3131
 
3132
         Lang_Id := Project.Languages;
3133
         while Lang_Id /= No_Language_Index loop
3134
            Lang := Lang_Id.Name;
3135
 
3136
            --  Spec_Suffix
3137
 
3138
            Suffix := Value_Of
3139
              (Name                    => Lang,
3140
               Attribute_Or_Array_Name => Name_Spec_Suffix,
3141
               In_Package              => Naming_Id,
3142
               In_Tree                 => Data.Tree);
3143
 
3144
            if Suffix = Nil_Variable_Value then
3145
               Suffix := Value_Of
3146
                 (Name                    => Lang,
3147
                  Attribute_Or_Array_Name => Name_Specification_Suffix,
3148
                  In_Package              => Naming_Id,
3149
                  In_Tree                 => Data.Tree);
3150
            end if;
3151
 
3152
            if Suffix /= Nil_Variable_Value then
3153
               Lang_Id.Config.Naming_Data.Spec_Suffix :=
3154
                   File_Name_Type (Suffix.Value);
3155
 
3156
               Check_Illegal_Suffix
3157
                 (Project,
3158
                  Lang_Id.Config.Naming_Data.Spec_Suffix,
3159
                  Lang_Id.Config.Naming_Data.Dot_Replacement,
3160
                  "Spec_Suffix", Suffix.Location, Data);
3161
 
3162
               Write_Attr
3163
                 ("Spec_Suffix",
3164
                  Get_Name_String (Lang_Id.Config.Naming_Data.Spec_Suffix));
3165
            end if;
3166
 
3167
            --  Body_Suffix
3168
 
3169
            Suffix :=
3170
              Value_Of
3171
                (Name                    => Lang,
3172
                 Attribute_Or_Array_Name => Name_Body_Suffix,
3173
                 In_Package              => Naming_Id,
3174
                 In_Tree                 => Data.Tree);
3175
 
3176
            if Suffix = Nil_Variable_Value then
3177
               Suffix :=
3178
                 Value_Of
3179
                   (Name                    => Lang,
3180
                    Attribute_Or_Array_Name => Name_Implementation_Suffix,
3181
                    In_Package              => Naming_Id,
3182
                    In_Tree                 => Data.Tree);
3183
            end if;
3184
 
3185
            if Suffix /= Nil_Variable_Value then
3186
               Lang_Id.Config.Naming_Data.Body_Suffix :=
3187
                 File_Name_Type (Suffix.Value);
3188
 
3189
               --  The default value of separate suffix should be the same as
3190
               --  the body suffix, so we need to compute that first.
3191
 
3192
               if Separate_Suffix = No_File then
3193
                  Lang_Id.Config.Naming_Data.Separate_Suffix :=
3194
                    Lang_Id.Config.Naming_Data.Body_Suffix;
3195
                  Write_Attr
3196
                    ("Sep_Suffix",
3197
                     Get_Name_String
3198
                       (Lang_Id.Config.Naming_Data.Separate_Suffix));
3199
               else
3200
                  Lang_Id.Config.Naming_Data.Separate_Suffix :=
3201
                    Separate_Suffix;
3202
               end if;
3203
 
3204
               Check_Illegal_Suffix
3205
                 (Project,
3206
                  Lang_Id.Config.Naming_Data.Body_Suffix,
3207
                  Lang_Id.Config.Naming_Data.Dot_Replacement,
3208
                  "Body_Suffix", Suffix.Location, Data);
3209
 
3210
               Write_Attr
3211
                 ("Body_Suffix",
3212
                  Get_Name_String (Lang_Id.Config.Naming_Data.Body_Suffix));
3213
 
3214
            elsif Separate_Suffix /= No_File then
3215
               Lang_Id.Config.Naming_Data.Separate_Suffix := Separate_Suffix;
3216
            end if;
3217
 
3218
            --  Spec_Suffix cannot be equal to Body_Suffix or Separate_Suffix,
3219
            --  since that would cause a clear ambiguity. Note that we do allow
3220
            --  a Spec_Suffix to have the same termination as one of these,
3221
            --  which causes a potential ambiguity, but we resolve that my
3222
            --  matching the longest possible suffix.
3223
 
3224
            if Lang_Id.Config.Naming_Data.Spec_Suffix /= No_File
3225
              and then Lang_Id.Config.Naming_Data.Spec_Suffix =
3226
                       Lang_Id.Config.Naming_Data.Body_Suffix
3227
            then
3228
               Error_Msg
3229
                 (Data.Flags,
3230
                  "Body_Suffix ("""
3231
                  & Get_Name_String (Lang_Id.Config.Naming_Data.Body_Suffix)
3232
                  & """) cannot be the same as Spec_Suffix.",
3233
                  Ada_Body_Suffix_Loc, Project);
3234
            end if;
3235
 
3236
            if Lang_Id.Config.Naming_Data.Body_Suffix /=
3237
               Lang_Id.Config.Naming_Data.Separate_Suffix
3238
              and then Lang_Id.Config.Naming_Data.Spec_Suffix =
3239
                       Lang_Id.Config.Naming_Data.Separate_Suffix
3240
            then
3241
               Error_Msg
3242
                 (Data.Flags,
3243
                  "Separate_Suffix ("""
3244
                  & Get_Name_String
3245
                    (Lang_Id.Config.Naming_Data.Separate_Suffix)
3246
                  & """) cannot be the same as Spec_Suffix.",
3247
                  Sep_Suffix_Loc, Project);
3248
            end if;
3249
 
3250
            Lang_Id := Lang_Id.Next;
3251
         end loop;
3252
 
3253
         --  Get the naming exceptions for all languages
3254
 
3255
         for Kind in Spec .. Impl loop
3256
            Lang_Id := Project.Languages;
3257
            while Lang_Id /= No_Language_Index loop
3258
               case Lang_Id.Config.Kind is
3259
                  when File_Based =>
3260
                     Process_Exceptions_File_Based (Lang_Id, Kind);
3261
 
3262
                  when Unit_Based =>
3263
                     Process_Exceptions_Unit_Based (Lang_Id, Kind);
3264
               end case;
3265
 
3266
               Lang_Id := Lang_Id.Next;
3267
            end loop;
3268
         end loop;
3269
      end Check_Naming;
3270
 
3271
      ----------------------------
3272
      -- Initialize_Naming_Data --
3273
      ----------------------------
3274
 
3275
      procedure Initialize_Naming_Data is
3276
         Specs : Array_Element_Id :=
3277
                   Util.Value_Of
3278
                     (Name_Spec_Suffix,
3279
                      Naming.Decl.Arrays,
3280
                      Data.Tree);
3281
 
3282
         Impls : Array_Element_Id :=
3283
                   Util.Value_Of
3284
                     (Name_Body_Suffix,
3285
                      Naming.Decl.Arrays,
3286
                      Data.Tree);
3287
 
3288
         Lang      : Language_Ptr;
3289
         Lang_Name : Name_Id;
3290
         Value     : Variable_Value;
3291
         Extended  : Project_Id;
3292
 
3293
      begin
3294
         --  At this stage, the project already contains the default extensions
3295
         --  for the various languages. We now merge those suffixes read in the
3296
         --  user project, and they override the default.
3297
 
3298
         while Specs /= No_Array_Element loop
3299
            Lang_Name := Data.Tree.Array_Elements.Table (Specs).Index;
3300
            Lang :=
3301
              Get_Language_From_Name
3302
                (Project, Name => Get_Name_String (Lang_Name));
3303
 
3304
            --  An extending project inherits its parent projects' languages
3305
            --  so if needed we should create entries for those languages
3306
 
3307
            if Lang = null  then
3308
               Extended := Project.Extends;
3309
               while Extended /= null loop
3310
                  Lang := Get_Language_From_Name
3311
                    (Extended, Name => Get_Name_String (Lang_Name));
3312
                  exit when Lang /= null;
3313
 
3314
                  Extended := Extended.Extends;
3315
               end loop;
3316
 
3317
               if Lang /= null then
3318
                  Lang := new Language_Data'(Lang.all);
3319
                  Lang.First_Source := null;
3320
                  Lang.Next := Project.Languages;
3321
                  Project.Languages := Lang;
3322
               end if;
3323
            end if;
3324
 
3325
            --  If language was not found in project or the projects it extends
3326
 
3327
            if Lang = null then
3328
               if Current_Verbosity = High then
3329
                  Write_Line
3330
                    ("Ignoring spec naming data for "
3331
                     & Get_Name_String (Lang_Name)
3332
                     & " since language is not defined for this project");
3333
               end if;
3334
 
3335
            else
3336
               Value := Data.Tree.Array_Elements.Table (Specs).Value;
3337
 
3338
               if Value.Kind = Single then
3339
                  Lang.Config.Naming_Data.Spec_Suffix :=
3340
                    Canonical_Case_File_Name (Value.Value);
3341
               end if;
3342
            end if;
3343
 
3344
            Specs := Data.Tree.Array_Elements.Table (Specs).Next;
3345
         end loop;
3346
 
3347
         while Impls /= No_Array_Element loop
3348
            Lang_Name := Data.Tree.Array_Elements.Table (Impls).Index;
3349
            Lang :=
3350
              Get_Language_From_Name
3351
                (Project, Name => Get_Name_String (Lang_Name));
3352
 
3353
            if Lang = null then
3354
               if Current_Verbosity = High then
3355
                  Write_Line
3356
                    ("Ignoring impl naming data for "
3357
                     & Get_Name_String (Lang_Name)
3358
                     & " since language is not defined for this project");
3359
               end if;
3360
            else
3361
               Value := Data.Tree.Array_Elements.Table (Impls).Value;
3362
 
3363
               if Lang.Name = Name_Ada then
3364
                  Ada_Body_Suffix_Loc := Value.Location;
3365
               end if;
3366
 
3367
               if Value.Kind = Single then
3368
                  Lang.Config.Naming_Data.Body_Suffix :=
3369
                    Canonical_Case_File_Name (Value.Value);
3370
               end if;
3371
            end if;
3372
 
3373
            Impls := Data.Tree.Array_Elements.Table (Impls).Next;
3374
         end loop;
3375
      end Initialize_Naming_Data;
3376
 
3377
   --  Start of processing for Check_Naming_Schemes
3378
 
3379
   begin
3380
      Specs  := No_Array_Element;
3381
      Bodies := No_Array_Element;
3382
 
3383
      --  No Naming package or parsing a configuration file? nothing to do
3384
 
3385
      if Naming_Id /= No_Package
3386
        and then Project.Qualifier /= Configuration
3387
      then
3388
         Naming := Data.Tree.Packages.Table (Naming_Id);
3389
 
3390
         if Current_Verbosity = High then
3391
            Write_Line ("Checking package Naming for project "
3392
                        & Get_Name_String (Project.Name));
3393
         end if;
3394
 
3395
         Initialize_Naming_Data;
3396
         Check_Naming;
3397
      end if;
3398
   end Check_Package_Naming;
3399
 
3400
   ------------------------------
3401
   -- Check_Library_Attributes --
3402
   ------------------------------
3403
 
3404
   procedure Check_Library_Attributes
3405
     (Project : Project_Id;
3406
      Data    : in out Tree_Processing_Data)
3407
   is
3408
      Attributes   : constant Prj.Variable_Id := Project.Decl.Attributes;
3409
 
3410
      Lib_Dir      : constant Prj.Variable_Value :=
3411
                       Prj.Util.Value_Of
3412
                         (Snames.Name_Library_Dir, Attributes, Data.Tree);
3413
 
3414
      Lib_Name     : constant Prj.Variable_Value :=
3415
                       Prj.Util.Value_Of
3416
                         (Snames.Name_Library_Name, Attributes, Data.Tree);
3417
 
3418
      Lib_Version  : constant Prj.Variable_Value :=
3419
                       Prj.Util.Value_Of
3420
                         (Snames.Name_Library_Version, Attributes, Data.Tree);
3421
 
3422
      Lib_ALI_Dir  : constant Prj.Variable_Value :=
3423
                       Prj.Util.Value_Of
3424
                         (Snames.Name_Library_Ali_Dir, Attributes, Data.Tree);
3425
 
3426
      Lib_GCC      : constant Prj.Variable_Value :=
3427
                       Prj.Util.Value_Of
3428
                         (Snames.Name_Library_GCC, Attributes, Data.Tree);
3429
 
3430
      The_Lib_Kind : constant Prj.Variable_Value :=
3431
                       Prj.Util.Value_Of
3432
                         (Snames.Name_Library_Kind, Attributes, Data.Tree);
3433
 
3434
      Imported_Project_List : Project_List;
3435
 
3436
      Continuation : String_Access := No_Continuation_String'Access;
3437
 
3438
      Support_For_Libraries : Library_Support;
3439
 
3440
      Library_Directory_Present : Boolean;
3441
 
3442
      procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3443
      --  Check if an imported or extended project if also a library project
3444
 
3445
      -------------------
3446
      -- Check_Library --
3447
      -------------------
3448
 
3449
      procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3450
         Src_Id : Source_Id;
3451
         Iter   : Source_Iterator;
3452
 
3453
      begin
3454
         if Proj /= No_Project then
3455
            if not Proj.Library then
3456
 
3457
               --  The only not library projects that are OK are those that
3458
               --  have no sources. However, header files from non-Ada
3459
               --  languages are OK, as there is nothing to compile.
3460
 
3461
               Iter := For_Each_Source (Data.Tree, Proj);
3462
               loop
3463
                  Src_Id := Prj.Element (Iter);
3464
                  exit when Src_Id = No_Source
3465
                    or else Src_Id.Language.Config.Kind /= File_Based
3466
                    or else Src_Id.Kind /= Spec;
3467
                  Next (Iter);
3468
               end loop;
3469
 
3470
               if Src_Id /= No_Source then
3471
                  Error_Msg_Name_1 := Project.Name;
3472
                  Error_Msg_Name_2 := Proj.Name;
3473
 
3474
                  if Extends then
3475
                     if Project.Library_Kind /= Static then
3476
                        Error_Msg
3477
                          (Data.Flags,
3478
                           Continuation.all &
3479
                           "shared library project %% cannot extend " &
3480
                           "project %% that is not a library project",
3481
                           Project.Location, Project);
3482
                        Continuation := Continuation_String'Access;
3483
                     end if;
3484
 
3485
                  elsif (not Unchecked_Shared_Lib_Imports)
3486
                        and then Project.Library_Kind /= Static
3487
                  then
3488
                     Error_Msg
3489
                       (Data.Flags,
3490
                        Continuation.all &
3491
                        "shared library project %% cannot import project %% " &
3492
                        "that is not a shared library project",
3493
                        Project.Location, Project);
3494
                     Continuation := Continuation_String'Access;
3495
                  end if;
3496
               end if;
3497
 
3498
            elsif Project.Library_Kind /= Static and then
3499
                  Proj.Library_Kind = Static
3500
            then
3501
               Error_Msg_Name_1 := Project.Name;
3502
               Error_Msg_Name_2 := Proj.Name;
3503
 
3504
               if Extends then
3505
                  Error_Msg
3506
                    (Data.Flags,
3507
                     Continuation.all &
3508
                     "shared library project %% cannot extend static " &
3509
                     "library project %%",
3510
                     Project.Location, Project);
3511
                  Continuation := Continuation_String'Access;
3512
 
3513
               elsif not Unchecked_Shared_Lib_Imports then
3514
                  Error_Msg
3515
                    (Data.Flags,
3516
                     Continuation.all &
3517
                     "shared library project %% cannot import static " &
3518
                     "library project %%",
3519
                     Project.Location, Project);
3520
                  Continuation := Continuation_String'Access;
3521
               end if;
3522
 
3523
            end if;
3524
         end if;
3525
      end Check_Library;
3526
 
3527
      Dir_Exists : Boolean;
3528
 
3529
   --  Start of processing for Check_Library_Attributes
3530
 
3531
   begin
3532
      Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3533
 
3534
      --  Special case of extending project
3535
 
3536
      if Project.Extends /= No_Project then
3537
 
3538
         --  If the project extended is a library project, we inherit the
3539
         --  library name, if it is not redefined; we check that the library
3540
         --  directory is specified.
3541
 
3542
         if Project.Extends.Library then
3543
            if Project.Qualifier = Standard then
3544
               Error_Msg
3545
                 (Data.Flags,
3546
                  "a standard project cannot extend a library project",
3547
                  Project.Location, Project);
3548
 
3549
            else
3550
               if Lib_Name.Default then
3551
                  Project.Library_Name := Project.Extends.Library_Name;
3552
               end if;
3553
 
3554
               if Lib_Dir.Default then
3555
                  if not Project.Virtual then
3556
                     Error_Msg
3557
                       (Data.Flags,
3558
                        "a project extending a library project must " &
3559
                        "specify an attribute Library_Dir",
3560
                        Project.Location, Project);
3561
 
3562
                  else
3563
                     --  For a virtual project extending a library project,
3564
                     --  inherit library directory.
3565
 
3566
                     Project.Library_Dir := Project.Extends.Library_Dir;
3567
                     Library_Directory_Present := True;
3568
                  end if;
3569
               end if;
3570
            end if;
3571
         end if;
3572
      end if;
3573
 
3574
      pragma Assert (Lib_Name.Kind = Single);
3575
 
3576
      if Lib_Name.Value = Empty_String then
3577
         if Current_Verbosity = High
3578
           and then Project.Library_Name = No_Name
3579
         then
3580
            Write_Line ("No library name");
3581
         end if;
3582
 
3583
      else
3584
         --  There is no restriction on the syntax of library names
3585
 
3586
         Project.Library_Name := Lib_Name.Value;
3587
      end if;
3588
 
3589
      if Project.Library_Name /= No_Name then
3590
         if Current_Verbosity = High then
3591
            Write_Attr
3592
              ("Library name", Get_Name_String (Project.Library_Name));
3593
         end if;
3594
 
3595
         pragma Assert (Lib_Dir.Kind = Single);
3596
 
3597
         if not Library_Directory_Present then
3598
            if Current_Verbosity = High then
3599
               Write_Line ("No library directory");
3600
            end if;
3601
 
3602
         else
3603
            --  Find path name (unless inherited), check that it is a directory
3604
 
3605
            if Project.Library_Dir = No_Path_Information then
3606
               Locate_Directory
3607
                 (Project,
3608
                  File_Name_Type (Lib_Dir.Value),
3609
                  Path             => Project.Library_Dir,
3610
                  Dir_Exists       => Dir_Exists,
3611
                  Data             => Data,
3612
                  Create           => "library",
3613
                  Must_Exist       => False,
3614
                  Location         => Lib_Dir.Location,
3615
                  Externally_Built => Project.Externally_Built);
3616
 
3617
            else
3618
               Dir_Exists :=
3619
                 Is_Directory
3620
                   (Get_Name_String
3621
                        (Project.Library_Dir.Display_Name));
3622
            end if;
3623
 
3624
            if not Dir_Exists then
3625
 
3626
               --  Get the absolute name of the library directory that
3627
               --  does not exist, to report an error.
3628
 
3629
               Err_Vars.Error_Msg_File_1 :=
3630
                 File_Name_Type (Project.Library_Dir.Display_Name);
3631
               Error_Msg
3632
                 (Data.Flags,
3633
                  "library directory { does not exist",
3634
                  Lib_Dir.Location, Project);
3635
 
3636
               --  The library directory cannot be the same as the Object
3637
               --  directory.
3638
 
3639
            elsif Project.Library_Dir.Name = Project.Object_Directory.Name then
3640
               Error_Msg
3641
                 (Data.Flags,
3642
                  "library directory cannot be the same " &
3643
                  "as object directory",
3644
                  Lib_Dir.Location, Project);
3645
               Project.Library_Dir := No_Path_Information;
3646
 
3647
            else
3648
               declare
3649
                  OK       : Boolean := True;
3650
                  Dirs_Id  : String_List_Id;
3651
                  Dir_Elem : String_Element;
3652
                  Pid      : Project_List;
3653
 
3654
               begin
3655
                  --  The library directory cannot be the same as a source
3656
                  --  directory of the current project.
3657
 
3658
                  Dirs_Id := Project.Source_Dirs;
3659
                  while Dirs_Id /= Nil_String loop
3660
                     Dir_Elem := Data.Tree.String_Elements.Table (Dirs_Id);
3661
                     Dirs_Id  := Dir_Elem.Next;
3662
 
3663
                     if Project.Library_Dir.Name =
3664
                       Path_Name_Type (Dir_Elem.Value)
3665
                     then
3666
                        Err_Vars.Error_Msg_File_1 :=
3667
                          File_Name_Type (Dir_Elem.Value);
3668
                        Error_Msg
3669
                          (Data.Flags,
3670
                           "library directory cannot be the same " &
3671
                           "as source directory {",
3672
                           Lib_Dir.Location, Project);
3673
                        OK := False;
3674
                        exit;
3675
                     end if;
3676
                  end loop;
3677
 
3678
                  if OK then
3679
 
3680
                     --  The library directory cannot be the same as a source
3681
                     --  directory of another project either.
3682
 
3683
                     Pid := Data.Tree.Projects;
3684
                     Project_Loop : loop
3685
                        exit Project_Loop when Pid = null;
3686
 
3687
                        if Pid.Project /= Project then
3688
                           Dirs_Id := Pid.Project.Source_Dirs;
3689
 
3690
                           Dir_Loop : while Dirs_Id /= Nil_String loop
3691
                              Dir_Elem :=
3692
                                Data.Tree.String_Elements.Table (Dirs_Id);
3693
                              Dirs_Id  := Dir_Elem.Next;
3694
 
3695
                              if Project.Library_Dir.Name =
3696
                                Path_Name_Type (Dir_Elem.Value)
3697
                              then
3698
                                 Err_Vars.Error_Msg_File_1 :=
3699
                                   File_Name_Type (Dir_Elem.Value);
3700
                                 Err_Vars.Error_Msg_Name_1 := Pid.Project.Name;
3701
 
3702
                                 Error_Msg
3703
                                   (Data.Flags,
3704
                                    "library directory cannot be the same " &
3705
                                    "as source directory { of project %%",
3706
                                    Lib_Dir.Location, Project);
3707
                                 OK := False;
3708
                                 exit Project_Loop;
3709
                              end if;
3710
                           end loop Dir_Loop;
3711
                        end if;
3712
 
3713
                        Pid := Pid.Next;
3714
                     end loop Project_Loop;
3715
                  end if;
3716
 
3717
                  if not OK then
3718
                     Project.Library_Dir := No_Path_Information;
3719
 
3720
                  elsif Current_Verbosity = High then
3721
 
3722
                     --  Display the Library directory in high verbosity
3723
 
3724
                     Write_Attr
3725
                       ("Library directory",
3726
                        Get_Name_String (Project.Library_Dir.Display_Name));
3727
                  end if;
3728
               end;
3729
            end if;
3730
         end if;
3731
 
3732
      end if;
3733
 
3734
      Project.Library :=
3735
        Project.Library_Dir /= No_Path_Information
3736
          and then Project.Library_Name /= No_Name;
3737
 
3738
      if Project.Extends = No_Project then
3739
         case Project.Qualifier is
3740
            when Standard =>
3741
               if Project.Library then
3742
                  Error_Msg
3743
                    (Data.Flags,
3744
                     "a standard project cannot be a library project",
3745
                     Lib_Name.Location, Project);
3746
               end if;
3747
 
3748
            when Library =>
3749
               if not Project.Library then
3750
                  if Project.Library_Dir = No_Path_Information then
3751
                     Error_Msg
3752
                       (Data.Flags,
3753
                        "\attribute Library_Dir not declared",
3754
                        Project.Location, Project);
3755
                  end if;
3756
 
3757
                  if Project.Library_Name = No_Name then
3758
                     Error_Msg
3759
                       (Data.Flags,
3760
                        "\attribute Library_Name not declared",
3761
                        Project.Location, Project);
3762
                  end if;
3763
               end if;
3764
 
3765
            when others =>
3766
               null;
3767
 
3768
         end case;
3769
      end if;
3770
 
3771
      if Project.Library then
3772
         Support_For_Libraries := Project.Config.Lib_Support;
3773
 
3774
         if Support_For_Libraries = Prj.None then
3775
            Error_Msg
3776
              (Data.Flags,
3777
               "?libraries are not supported on this platform",
3778
               Lib_Name.Location, Project);
3779
            Project.Library := False;
3780
 
3781
         else
3782
            if Lib_ALI_Dir.Value = Empty_String then
3783
               if Current_Verbosity = High then
3784
                  Write_Line ("No library ALI directory specified");
3785
               end if;
3786
 
3787
               Project.Library_ALI_Dir := Project.Library_Dir;
3788
 
3789
            else
3790
               --  Find path name, check that it is a directory
3791
 
3792
               Locate_Directory
3793
                 (Project,
3794
                  File_Name_Type (Lib_ALI_Dir.Value),
3795
                  Path             => Project.Library_ALI_Dir,
3796
                  Create           => "library ALI",
3797
                  Dir_Exists       => Dir_Exists,
3798
                  Data             => Data,
3799
                  Must_Exist       => False,
3800
                  Location         => Lib_ALI_Dir.Location,
3801
                  Externally_Built => Project.Externally_Built);
3802
 
3803
               if not Dir_Exists then
3804
 
3805
                  --  Get the absolute name of the library ALI directory that
3806
                  --  does not exist, to report an error.
3807
 
3808
                  Err_Vars.Error_Msg_File_1 :=
3809
                    File_Name_Type (Project.Library_ALI_Dir.Display_Name);
3810
                  Error_Msg
3811
                    (Data.Flags,
3812
                     "library 'A'L'I directory { does not exist",
3813
                     Lib_ALI_Dir.Location, Project);
3814
               end if;
3815
 
3816
               if Project.Library_ALI_Dir /= Project.Library_Dir then
3817
 
3818
                  --  The library ALI directory cannot be the same as the
3819
                  --  Object directory.
3820
 
3821
                  if Project.Library_ALI_Dir = Project.Object_Directory then
3822
                     Error_Msg
3823
                       (Data.Flags,
3824
                        "library 'A'L'I directory cannot be the same " &
3825
                        "as object directory",
3826
                        Lib_ALI_Dir.Location, Project);
3827
                     Project.Library_ALI_Dir := No_Path_Information;
3828
 
3829
                  else
3830
                     declare
3831
                        OK       : Boolean := True;
3832
                        Dirs_Id  : String_List_Id;
3833
                        Dir_Elem : String_Element;
3834
                        Pid      : Project_List;
3835
 
3836
                     begin
3837
                        --  The library ALI directory cannot be the same as
3838
                        --  a source directory of the current project.
3839
 
3840
                        Dirs_Id := Project.Source_Dirs;
3841
                        while Dirs_Id /= Nil_String loop
3842
                           Dir_Elem :=
3843
                             Data.Tree.String_Elements.Table (Dirs_Id);
3844
                           Dirs_Id  := Dir_Elem.Next;
3845
 
3846
                           if Project.Library_ALI_Dir.Name =
3847
                             Path_Name_Type (Dir_Elem.Value)
3848
                           then
3849
                              Err_Vars.Error_Msg_File_1 :=
3850
                                File_Name_Type (Dir_Elem.Value);
3851
                              Error_Msg
3852
                                (Data.Flags,
3853
                                 "library 'A'L'I directory cannot be " &
3854
                                 "the same as source directory {",
3855
                                 Lib_ALI_Dir.Location, Project);
3856
                              OK := False;
3857
                              exit;
3858
                           end if;
3859
                        end loop;
3860
 
3861
                        if OK then
3862
 
3863
                           --  The library ALI directory cannot be the same as
3864
                           --  a source directory of another project either.
3865
 
3866
                           Pid := Data.Tree.Projects;
3867
                           ALI_Project_Loop : loop
3868
                              exit ALI_Project_Loop when Pid = null;
3869
 
3870
                              if Pid.Project /= Project then
3871
                                 Dirs_Id := Pid.Project.Source_Dirs;
3872
 
3873
                                 ALI_Dir_Loop :
3874
                                 while Dirs_Id /= Nil_String loop
3875
                                    Dir_Elem :=
3876
                                      Data.Tree.String_Elements.Table
3877
                                        (Dirs_Id);
3878
                                    Dirs_Id  := Dir_Elem.Next;
3879
 
3880
                                    if Project.Library_ALI_Dir.Name =
3881
                                        Path_Name_Type (Dir_Elem.Value)
3882
                                    then
3883
                                       Err_Vars.Error_Msg_File_1 :=
3884
                                         File_Name_Type (Dir_Elem.Value);
3885
                                       Err_Vars.Error_Msg_Name_1 :=
3886
                                         Pid.Project.Name;
3887
 
3888
                                       Error_Msg
3889
                                         (Data.Flags,
3890
                                          "library 'A'L'I directory cannot " &
3891
                                          "be the same as source directory " &
3892
                                          "{ of project %%",
3893
                                          Lib_ALI_Dir.Location, Project);
3894
                                       OK := False;
3895
                                       exit ALI_Project_Loop;
3896
                                    end if;
3897
                                 end loop ALI_Dir_Loop;
3898
                              end if;
3899
                              Pid := Pid.Next;
3900
                           end loop ALI_Project_Loop;
3901
                        end if;
3902
 
3903
                        if not OK then
3904
                           Project.Library_ALI_Dir := No_Path_Information;
3905
 
3906
                        elsif Current_Verbosity = High then
3907
 
3908
                           --  Display Library ALI directory in high verbosity
3909
 
3910
                           Write_Attr
3911
                             ("Library ALI dir",
3912
                              Get_Name_String
3913
                                (Project.Library_ALI_Dir.Display_Name));
3914
                        end if;
3915
                     end;
3916
                  end if;
3917
               end if;
3918
            end if;
3919
 
3920
            pragma Assert (Lib_Version.Kind = Single);
3921
 
3922
            if Lib_Version.Value = Empty_String then
3923
               if Current_Verbosity = High then
3924
                  Write_Line ("No library version specified");
3925
               end if;
3926
 
3927
            else
3928
               Project.Lib_Internal_Name := Lib_Version.Value;
3929
            end if;
3930
 
3931
            pragma Assert (The_Lib_Kind.Kind = Single);
3932
 
3933
            if The_Lib_Kind.Value = Empty_String then
3934
               if Current_Verbosity = High then
3935
                  Write_Line ("No library kind specified");
3936
               end if;
3937
 
3938
            else
3939
               Get_Name_String (The_Lib_Kind.Value);
3940
 
3941
               declare
3942
                  Kind_Name : constant String :=
3943
                                To_Lower (Name_Buffer (1 .. Name_Len));
3944
 
3945
                  OK : Boolean := True;
3946
 
3947
               begin
3948
                  if Kind_Name = "static" then
3949
                     Project.Library_Kind := Static;
3950
 
3951
                  elsif Kind_Name = "dynamic" then
3952
                     Project.Library_Kind := Dynamic;
3953
 
3954
                  elsif Kind_Name = "relocatable" then
3955
                     Project.Library_Kind := Relocatable;
3956
 
3957
                  else
3958
                     Error_Msg
3959
                       (Data.Flags,
3960
                        "illegal value for Library_Kind",
3961
                        The_Lib_Kind.Location, Project);
3962
                     OK := False;
3963
                  end if;
3964
 
3965
                  if Current_Verbosity = High and then OK then
3966
                     Write_Attr ("Library kind", Kind_Name);
3967
                  end if;
3968
 
3969
                  if Project.Library_Kind /= Static then
3970
                     if Support_For_Libraries = Prj.Static_Only then
3971
                        Error_Msg
3972
                          (Data.Flags,
3973
                           "only static libraries are supported " &
3974
                           "on this platform",
3975
                           The_Lib_Kind.Location, Project);
3976
                        Project.Library := False;
3977
 
3978
                     else
3979
                        --  Check if (obsolescent) attribute Library_GCC or
3980
                        --  Linker'Driver is declared.
3981
 
3982
                        if Lib_GCC.Value /= Empty_String then
3983
                           Error_Msg
3984
                             (Data.Flags,
3985
                              "?Library_'G'C'C is an obsolescent attribute, " &
3986
                              "use Linker''Driver instead",
3987
                              Lib_GCC.Location, Project);
3988
                           Project.Config.Shared_Lib_Driver :=
3989
                             File_Name_Type (Lib_GCC.Value);
3990
 
3991
                        else
3992
                           declare
3993
                              Linker : constant Package_Id :=
3994
                                         Value_Of
3995
                                           (Name_Linker,
3996
                                            Project.Decl.Packages,
3997
                                            Data.Tree);
3998
                              Driver : constant Variable_Value :=
3999
                                         Value_Of
4000
                                           (Name                 => No_Name,
4001
                                            Attribute_Or_Array_Name =>
4002
                                              Name_Driver,
4003
                                            In_Package           => Linker,
4004
                                            In_Tree              => Data.Tree);
4005
 
4006
                           begin
4007
                              if Driver /= Nil_Variable_Value
4008
                                 and then Driver.Value /= Empty_String
4009
                              then
4010
                                 Project.Config.Shared_Lib_Driver :=
4011
                                   File_Name_Type (Driver.Value);
4012
                              end if;
4013
                           end;
4014
                        end if;
4015
                     end if;
4016
                  end if;
4017
               end;
4018
            end if;
4019
 
4020
            if Project.Library then
4021
               if Current_Verbosity = High then
4022
                  Write_Line ("This is a library project file");
4023
               end if;
4024
 
4025
               Check_Library (Project.Extends, Extends => True);
4026
 
4027
               Imported_Project_List := Project.Imported_Projects;
4028
               while Imported_Project_List /= null loop
4029
                  Check_Library
4030
                    (Imported_Project_List.Project,
4031
                     Extends => False);
4032
                  Imported_Project_List := Imported_Project_List.Next;
4033
               end loop;
4034
            end if;
4035
 
4036
         end if;
4037
      end if;
4038
 
4039
      --  Check if Linker'Switches or Linker'Default_Switches are declared.
4040
      --  Warn if they are declared, as it is a common error to think that
4041
      --  library are "linked" with Linker switches.
4042
 
4043
      if Project.Library then
4044
         declare
4045
            Linker_Package_Id : constant Package_Id :=
4046
                                  Util.Value_Of
4047
                                    (Name_Linker,
4048
                                     Project.Decl.Packages, Data.Tree);
4049
            Linker_Package    : Package_Element;
4050
            Switches          : Array_Element_Id := No_Array_Element;
4051
 
4052
         begin
4053
            if Linker_Package_Id /= No_Package then
4054
               Linker_Package := Data.Tree.Packages.Table (Linker_Package_Id);
4055
 
4056
               Switches :=
4057
                 Value_Of
4058
                   (Name      => Name_Switches,
4059
                    In_Arrays => Linker_Package.Decl.Arrays,
4060
                    In_Tree   => Data.Tree);
4061
 
4062
               if Switches = No_Array_Element then
4063
                  Switches :=
4064
                    Value_Of
4065
                      (Name      => Name_Default_Switches,
4066
                       In_Arrays => Linker_Package.Decl.Arrays,
4067
                       In_Tree   => Data.Tree);
4068
               end if;
4069
 
4070
               if Switches /= No_Array_Element then
4071
                  Error_Msg
4072
                    (Data.Flags,
4073
                     "?Linker switches not taken into account in library " &
4074
                     "projects",
4075
                     No_Location, Project);
4076
               end if;
4077
            end if;
4078
         end;
4079
      end if;
4080
 
4081
      if Project.Extends /= No_Project then
4082
         Project.Extends.Library := False;
4083
      end if;
4084
   end Check_Library_Attributes;
4085
 
4086
   ---------------------------------
4087
   -- Check_Programming_Languages --
4088
   ---------------------------------
4089
 
4090
   procedure Check_Programming_Languages
4091
     (Project : Project_Id;
4092
      Data    : in out Tree_Processing_Data)
4093
   is
4094
      Languages   : Variable_Value := Nil_Variable_Value;
4095
      Def_Lang    : Variable_Value := Nil_Variable_Value;
4096
      Def_Lang_Id : Name_Id;
4097
 
4098
      procedure Add_Language (Name, Display_Name : Name_Id);
4099
      --  Add a new language to the list of languages for the project.
4100
      --  Nothing is done if the language has already been defined
4101
 
4102
      ------------------
4103
      -- Add_Language --
4104
      ------------------
4105
 
4106
      procedure Add_Language (Name, Display_Name : Name_Id) is
4107
         Lang : Language_Ptr;
4108
 
4109
      begin
4110
         Lang := Project.Languages;
4111
         while Lang /= No_Language_Index loop
4112
            if Name = Lang.Name then
4113
               return;
4114
            end if;
4115
 
4116
            Lang := Lang.Next;
4117
         end loop;
4118
 
4119
         Lang              := new Language_Data'(No_Language_Data);
4120
         Lang.Next         := Project.Languages;
4121
         Project.Languages := Lang;
4122
         Lang.Name         := Name;
4123
         Lang.Display_Name := Display_Name;
4124
 
4125
         if Name = Name_Ada then
4126
            Lang.Config.Kind            := Unit_Based;
4127
            Lang.Config.Dependency_Kind := ALI_File;
4128
         else
4129
            Lang.Config.Kind := File_Based;
4130
         end if;
4131
      end Add_Language;
4132
 
4133
   --  Start of processing for Check_Programming_Languages
4134
 
4135
   begin
4136
      Project.Languages := null;
4137
      Languages :=
4138
        Prj.Util.Value_Of (Name_Languages, Project.Decl.Attributes, Data.Tree);
4139
      Def_Lang :=
4140
        Prj.Util.Value_Of
4141
          (Name_Default_Language, Project.Decl.Attributes, Data.Tree);
4142
 
4143
      if Project.Source_Dirs /= Nil_String then
4144
 
4145
         --  Check if languages are specified in this project
4146
 
4147
         if Languages.Default then
4148
 
4149
            --  Fail if there is no default language defined
4150
 
4151
            if Def_Lang.Default then
4152
               Error_Msg
4153
                 (Data.Flags,
4154
                  "no languages defined for this project",
4155
                  Project.Location, Project);
4156
               Def_Lang_Id := No_Name;
4157
 
4158
            else
4159
               Get_Name_String (Def_Lang.Value);
4160
               To_Lower (Name_Buffer (1 .. Name_Len));
4161
               Def_Lang_Id := Name_Find;
4162
            end if;
4163
 
4164
            if Def_Lang_Id /= No_Name then
4165
               Get_Name_String (Def_Lang_Id);
4166
               Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4167
               Add_Language
4168
                 (Name         => Def_Lang_Id,
4169
                  Display_Name => Name_Find);
4170
            end if;
4171
 
4172
         else
4173
            declare
4174
               Current : String_List_Id := Languages.Values;
4175
               Element : String_Element;
4176
 
4177
            begin
4178
               --  If there are no languages declared, there are no sources
4179
 
4180
               if Current = Nil_String then
4181
                  Project.Source_Dirs := Nil_String;
4182
 
4183
                  if Project.Qualifier = Standard then
4184
                     Error_Msg
4185
                       (Data.Flags,
4186
                        "a standard project must have at least one language",
4187
                        Languages.Location, Project);
4188
                  end if;
4189
 
4190
               else
4191
                  --  Look through all the languages specified in attribute
4192
                  --  Languages.
4193
 
4194
                  while Current /= Nil_String loop
4195
                     Element := Data.Tree.String_Elements.Table (Current);
4196
                     Get_Name_String (Element.Value);
4197
                     To_Lower (Name_Buffer (1 .. Name_Len));
4198
 
4199
                     Add_Language
4200
                       (Name         => Name_Find,
4201
                        Display_Name => Element.Value);
4202
 
4203
                     Current := Element.Next;
4204
                  end loop;
4205
               end if;
4206
            end;
4207
         end if;
4208
      end if;
4209
   end Check_Programming_Languages;
4210
 
4211
   -------------------------------
4212
   -- Check_Stand_Alone_Library --
4213
   -------------------------------
4214
 
4215
   procedure Check_Stand_Alone_Library
4216
     (Project : Project_Id;
4217
      Data    : in out Tree_Processing_Data)
4218
   is
4219
      Lib_Interfaces      : constant Prj.Variable_Value :=
4220
                              Prj.Util.Value_Of
4221
                                (Snames.Name_Library_Interface,
4222
                                 Project.Decl.Attributes,
4223
                                 Data.Tree);
4224
 
4225
      Lib_Auto_Init       : constant Prj.Variable_Value :=
4226
                              Prj.Util.Value_Of
4227
                                (Snames.Name_Library_Auto_Init,
4228
                                 Project.Decl.Attributes,
4229
                                 Data.Tree);
4230
 
4231
      Lib_Src_Dir         : constant Prj.Variable_Value :=
4232
                              Prj.Util.Value_Of
4233
                                (Snames.Name_Library_Src_Dir,
4234
                                 Project.Decl.Attributes,
4235
                                 Data.Tree);
4236
 
4237
      Lib_Symbol_File     : constant Prj.Variable_Value :=
4238
                              Prj.Util.Value_Of
4239
                                (Snames.Name_Library_Symbol_File,
4240
                                 Project.Decl.Attributes,
4241
                                 Data.Tree);
4242
 
4243
      Lib_Symbol_Policy   : constant Prj.Variable_Value :=
4244
                              Prj.Util.Value_Of
4245
                                (Snames.Name_Library_Symbol_Policy,
4246
                                 Project.Decl.Attributes,
4247
                                 Data.Tree);
4248
 
4249
      Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4250
                              Prj.Util.Value_Of
4251
                                (Snames.Name_Library_Reference_Symbol_File,
4252
                                 Project.Decl.Attributes,
4253
                                 Data.Tree);
4254
 
4255
      Auto_Init_Supported : Boolean;
4256
      OK                  : Boolean := True;
4257
      Source              : Source_Id;
4258
      Next_Proj           : Project_Id;
4259
      Iter                : Source_Iterator;
4260
 
4261
   begin
4262
      Auto_Init_Supported := Project.Config.Auto_Init_Supported;
4263
 
4264
      pragma Assert (Lib_Interfaces.Kind = List);
4265
 
4266
      --  It is a stand-alone library project file if attribute
4267
      --  Library_Interface is defined.
4268
 
4269
      if not Lib_Interfaces.Default then
4270
         declare
4271
            Interfaces     : String_List_Id := Lib_Interfaces.Values;
4272
            Interface_ALIs : String_List_Id := Nil_String;
4273
            Unit           : Name_Id;
4274
 
4275
         begin
4276
            Project.Standalone_Library := True;
4277
 
4278
            --  Library_Interface cannot be an empty list
4279
 
4280
            if Interfaces = Nil_String then
4281
               Error_Msg
4282
                 (Data.Flags,
4283
                  "Library_Interface cannot be an empty list",
4284
                  Lib_Interfaces.Location, Project);
4285
            end if;
4286
 
4287
            --  Process each unit name specified in the attribute
4288
            --  Library_Interface.
4289
 
4290
            while Interfaces /= Nil_String loop
4291
               Get_Name_String
4292
                 (Data.Tree.String_Elements.Table (Interfaces).Value);
4293
               To_Lower (Name_Buffer (1 .. Name_Len));
4294
 
4295
               if Name_Len = 0 then
4296
                  Error_Msg
4297
                    (Data.Flags,
4298
                     "an interface cannot be an empty string",
4299
                     Data.Tree.String_Elements.Table (Interfaces).Location,
4300
                     Project);
4301
 
4302
               else
4303
                  Unit := Name_Find;
4304
                  Error_Msg_Name_1 := Unit;
4305
 
4306
                  Next_Proj := Project.Extends;
4307
                  Iter := For_Each_Source (Data.Tree, Project);
4308
                  loop
4309
                     while Prj.Element (Iter) /= No_Source
4310
                       and then
4311
                         (Prj.Element (Iter).Unit = null
4312
                           or else Prj.Element (Iter).Unit.Name /= Unit)
4313
                     loop
4314
                        Next (Iter);
4315
                     end loop;
4316
 
4317
                     Source := Prj.Element (Iter);
4318
                     exit when Source /= No_Source
4319
                       or else Next_Proj = No_Project;
4320
 
4321
                     Iter := For_Each_Source (Data.Tree, Next_Proj);
4322
                     Next_Proj := Next_Proj.Extends;
4323
                  end loop;
4324
 
4325
                  if Source /= No_Source then
4326
                     if Source.Kind = Sep then
4327
                        Source := No_Source;
4328
 
4329
                     elsif Source.Kind = Spec
4330
                       and then Other_Part (Source) /= No_Source
4331
                     then
4332
                        Source := Other_Part (Source);
4333
                     end if;
4334
                  end if;
4335
 
4336
                  if Source /= No_Source then
4337
                     if Source.Project /= Project
4338
                       and then not Is_Extending (Project, Source.Project)
4339
                     then
4340
                        Source := No_Source;
4341
                     end if;
4342
                  end if;
4343
 
4344
                  if Source = No_Source then
4345
                     Error_Msg
4346
                       (Data.Flags,
4347
                        "%% is not a unit of this project",
4348
                        Data.Tree.String_Elements.Table
4349
                          (Interfaces).Location, Project);
4350
 
4351
                  else
4352
                     if Source.Kind = Spec
4353
                       and then Other_Part (Source) /= No_Source
4354
                     then
4355
                        Source := Other_Part (Source);
4356
                     end if;
4357
 
4358
                     String_Element_Table.Increment_Last
4359
                       (Data.Tree.String_Elements);
4360
 
4361
                     Data.Tree.String_Elements.Table
4362
                       (String_Element_Table.Last
4363
                          (Data.Tree.String_Elements)) :=
4364
                       (Value         => Name_Id (Source.Dep_Name),
4365
                        Index         => 0,
4366
                        Display_Value => Name_Id (Source.Dep_Name),
4367
                        Location      =>
4368
                          Data.Tree.String_Elements.Table
4369
                            (Interfaces).Location,
4370
                        Flag          => False,
4371
                        Next          => Interface_ALIs);
4372
 
4373
                     Interface_ALIs :=
4374
                       String_Element_Table.Last
4375
                         (Data.Tree.String_Elements);
4376
                  end if;
4377
               end if;
4378
 
4379
               Interfaces := Data.Tree.String_Elements.Table (Interfaces).Next;
4380
            end loop;
4381
 
4382
            --  Put the list of Interface ALIs in the project data
4383
 
4384
            Project.Lib_Interface_ALIs := Interface_ALIs;
4385
 
4386
            --  Check value of attribute Library_Auto_Init and set
4387
            --  Lib_Auto_Init accordingly.
4388
 
4389
            if Lib_Auto_Init.Default then
4390
 
4391
               --  If no attribute Library_Auto_Init is declared, then set auto
4392
               --  init only if it is supported.
4393
 
4394
               Project.Lib_Auto_Init := Auto_Init_Supported;
4395
 
4396
            else
4397
               Get_Name_String (Lib_Auto_Init.Value);
4398
               To_Lower (Name_Buffer (1 .. Name_Len));
4399
 
4400
               if Name_Buffer (1 .. Name_Len) = "false" then
4401
                  Project.Lib_Auto_Init := False;
4402
 
4403
               elsif Name_Buffer (1 .. Name_Len) = "true" then
4404
                  if Auto_Init_Supported then
4405
                     Project.Lib_Auto_Init := True;
4406
 
4407
                  else
4408
                     --  Library_Auto_Init cannot be "true" if auto init is not
4409
                     --  supported.
4410
 
4411
                     Error_Msg
4412
                       (Data.Flags,
4413
                        "library auto init not supported " &
4414
                        "on this platform",
4415
                        Lib_Auto_Init.Location, Project);
4416
                  end if;
4417
 
4418
               else
4419
                  Error_Msg
4420
                    (Data.Flags,
4421
                     "invalid value for attribute Library_Auto_Init",
4422
                     Lib_Auto_Init.Location, Project);
4423
               end if;
4424
            end if;
4425
         end;
4426
 
4427
         --  If attribute Library_Src_Dir is defined and not the empty string,
4428
         --  check if the directory exist and is not the object directory or
4429
         --  one of the source directories. This is the directory where copies
4430
         --  of the interface sources will be copied. Note that this directory
4431
         --  may be the library directory.
4432
 
4433
         if Lib_Src_Dir.Value /= Empty_String then
4434
            declare
4435
               Dir_Id     : constant File_Name_Type :=
4436
                              File_Name_Type (Lib_Src_Dir.Value);
4437
               Dir_Exists : Boolean;
4438
 
4439
            begin
4440
               Locate_Directory
4441
                 (Project,
4442
                  Dir_Id,
4443
                  Path             => Project.Library_Src_Dir,
4444
                  Dir_Exists       => Dir_Exists,
4445
                  Data             => Data,
4446
                  Must_Exist       => False,
4447
                  Create           => "library source copy",
4448
                  Location         => Lib_Src_Dir.Location,
4449
                  Externally_Built => Project.Externally_Built);
4450
 
4451
               --  If directory does not exist, report an error
4452
 
4453
               if not Dir_Exists then
4454
 
4455
                  --  Get the absolute name of the library directory that does
4456
                  --  not exist, to report an error.
4457
 
4458
                  Err_Vars.Error_Msg_File_1 :=
4459
                    File_Name_Type (Project.Library_Src_Dir.Display_Name);
4460
                  Error_Msg
4461
                    (Data.Flags,
4462
                     "Directory { does not exist",
4463
                     Lib_Src_Dir.Location, Project);
4464
 
4465
                  --  Report error if it is the same as the object directory
4466
 
4467
               elsif Project.Library_Src_Dir = Project.Object_Directory then
4468
                  Error_Msg
4469
                    (Data.Flags,
4470
                     "directory to copy interfaces cannot be " &
4471
                     "the object directory",
4472
                     Lib_Src_Dir.Location, Project);
4473
                  Project.Library_Src_Dir := No_Path_Information;
4474
 
4475
               else
4476
                  declare
4477
                     Src_Dirs : String_List_Id;
4478
                     Src_Dir  : String_Element;
4479
                     Pid      : Project_List;
4480
 
4481
                  begin
4482
                     --  Interface copy directory cannot be one of the source
4483
                     --  directory of the current project.
4484
 
4485
                     Src_Dirs := Project.Source_Dirs;
4486
                     while Src_Dirs /= Nil_String loop
4487
                        Src_Dir := Data.Tree.String_Elements.Table (Src_Dirs);
4488
 
4489
                        --  Report error if it is one of the source directories
4490
 
4491
                        if Project.Library_Src_Dir.Name =
4492
                             Path_Name_Type (Src_Dir.Value)
4493
                        then
4494
                           Error_Msg
4495
                             (Data.Flags,
4496
                              "directory to copy interfaces cannot " &
4497
                              "be one of the source directories",
4498
                              Lib_Src_Dir.Location, Project);
4499
                           Project.Library_Src_Dir := No_Path_Information;
4500
                           exit;
4501
                        end if;
4502
 
4503
                        Src_Dirs := Src_Dir.Next;
4504
                     end loop;
4505
 
4506
                     if Project.Library_Src_Dir /= No_Path_Information then
4507
 
4508
                        --  It cannot be a source directory of any other
4509
                        --  project either.
4510
 
4511
                        Pid := Data.Tree.Projects;
4512
                        Project_Loop : loop
4513
                           exit Project_Loop when Pid = null;
4514
 
4515
                           Src_Dirs := Pid.Project.Source_Dirs;
4516
                           Dir_Loop : while Src_Dirs /= Nil_String loop
4517
                              Src_Dir :=
4518
                                Data.Tree.String_Elements.Table (Src_Dirs);
4519
 
4520
                              --  Report error if it is one of the source
4521
                              --  directories.
4522
 
4523
                              if Project.Library_Src_Dir.Name =
4524
                                Path_Name_Type (Src_Dir.Value)
4525
                              then
4526
                                 Error_Msg_File_1 :=
4527
                                   File_Name_Type (Src_Dir.Value);
4528
                                 Error_Msg_Name_1 := Pid.Project.Name;
4529
                                 Error_Msg
4530
                                   (Data.Flags,
4531
                                    "directory to copy interfaces cannot " &
4532
                                    "be the same as source directory { of " &
4533
                                    "project %%",
4534
                                    Lib_Src_Dir.Location, Project);
4535
                                 Project.Library_Src_Dir :=
4536
                                   No_Path_Information;
4537
                                 exit Project_Loop;
4538
                              end if;
4539
 
4540
                              Src_Dirs := Src_Dir.Next;
4541
                           end loop Dir_Loop;
4542
 
4543
                           Pid := Pid.Next;
4544
                        end loop Project_Loop;
4545
                     end if;
4546
                  end;
4547
 
4548
                  --  In high verbosity, if there is a valid Library_Src_Dir,
4549
                  --  display its path name.
4550
 
4551
                  if Project.Library_Src_Dir /= No_Path_Information
4552
                    and then Current_Verbosity = High
4553
                  then
4554
                     Write_Attr
4555
                       ("Directory to copy interfaces",
4556
                        Get_Name_String (Project.Library_Src_Dir.Name));
4557
                  end if;
4558
               end if;
4559
            end;
4560
         end if;
4561
 
4562
         --  Check the symbol related attributes
4563
 
4564
         --  First, the symbol policy
4565
 
4566
         if not Lib_Symbol_Policy.Default then
4567
            declare
4568
               Value : constant String :=
4569
                         To_Lower
4570
                           (Get_Name_String (Lib_Symbol_Policy.Value));
4571
 
4572
            begin
4573
               --  Symbol policy must hove one of a limited number of values
4574
 
4575
               if Value = "autonomous" or else Value = "default" then
4576
                  Project.Symbol_Data.Symbol_Policy := Autonomous;
4577
 
4578
               elsif Value = "compliant" then
4579
                  Project.Symbol_Data.Symbol_Policy := Compliant;
4580
 
4581
               elsif Value = "controlled" then
4582
                  Project.Symbol_Data.Symbol_Policy := Controlled;
4583
 
4584
               elsif Value = "restricted" then
4585
                  Project.Symbol_Data.Symbol_Policy := Restricted;
4586
 
4587
               elsif Value = "direct" then
4588
                  Project.Symbol_Data.Symbol_Policy := Direct;
4589
 
4590
               else
4591
                  Error_Msg
4592
                    (Data.Flags,
4593
                     "illegal value for Library_Symbol_Policy",
4594
                     Lib_Symbol_Policy.Location, Project);
4595
               end if;
4596
            end;
4597
         end if;
4598
 
4599
         --  If attribute Library_Symbol_File is not specified, symbol policy
4600
         --  cannot be Restricted.
4601
 
4602
         if Lib_Symbol_File.Default then
4603
            if Project.Symbol_Data.Symbol_Policy = Restricted then
4604
               Error_Msg
4605
                 (Data.Flags,
4606
                  "Library_Symbol_File needs to be defined when " &
4607
                  "symbol policy is Restricted",
4608
                  Lib_Symbol_Policy.Location, Project);
4609
            end if;
4610
 
4611
         else
4612
            --  Library_Symbol_File is defined
4613
 
4614
            Project.Symbol_Data.Symbol_File :=
4615
              Path_Name_Type (Lib_Symbol_File.Value);
4616
 
4617
            Get_Name_String (Lib_Symbol_File.Value);
4618
 
4619
            if Name_Len = 0 then
4620
               Error_Msg
4621
                 (Data.Flags,
4622
                  "symbol file name cannot be an empty string",
4623
                  Lib_Symbol_File.Location, Project);
4624
 
4625
            else
4626
               OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
4627
 
4628
               if OK then
4629
                  for J in 1 .. Name_Len loop
4630
                     if Name_Buffer (J) = '/'
4631
                       or else Name_Buffer (J) = Directory_Separator
4632
                     then
4633
                        OK := False;
4634
                        exit;
4635
                     end if;
4636
                  end loop;
4637
               end if;
4638
 
4639
               if not OK then
4640
                  Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
4641
                  Error_Msg
4642
                    (Data.Flags,
4643
                     "symbol file name { is illegal. " &
4644
                     "Name cannot include directory info.",
4645
                     Lib_Symbol_File.Location, Project);
4646
               end if;
4647
            end if;
4648
         end if;
4649
 
4650
         --  If attribute Library_Reference_Symbol_File is not defined,
4651
         --  symbol policy cannot be Compliant or Controlled.
4652
 
4653
         if Lib_Ref_Symbol_File.Default then
4654
            if Project.Symbol_Data.Symbol_Policy = Compliant
4655
              or else Project.Symbol_Data.Symbol_Policy = Controlled
4656
            then
4657
               Error_Msg
4658
                 (Data.Flags,
4659
                  "a reference symbol file needs to be defined",
4660
                  Lib_Symbol_Policy.Location, Project);
4661
            end if;
4662
 
4663
         else
4664
            --  Library_Reference_Symbol_File is defined, check file exists
4665
 
4666
            Project.Symbol_Data.Reference :=
4667
              Path_Name_Type (Lib_Ref_Symbol_File.Value);
4668
 
4669
            Get_Name_String (Lib_Ref_Symbol_File.Value);
4670
 
4671
            if Name_Len = 0 then
4672
               Error_Msg
4673
                 (Data.Flags,
4674
                  "reference symbol file name cannot be an empty string",
4675
                  Lib_Symbol_File.Location, Project);
4676
 
4677
            else
4678
               if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
4679
                  Name_Len := 0;
4680
                  Add_Str_To_Name_Buffer
4681
                    (Get_Name_String (Project.Directory.Name));
4682
                  Add_Str_To_Name_Buffer
4683
                    (Get_Name_String (Lib_Ref_Symbol_File.Value));
4684
                  Project.Symbol_Data.Reference := Name_Find;
4685
               end if;
4686
 
4687
               if not Is_Regular_File
4688
                        (Get_Name_String (Project.Symbol_Data.Reference))
4689
               then
4690
                  Error_Msg_File_1 :=
4691
                    File_Name_Type (Lib_Ref_Symbol_File.Value);
4692
 
4693
                  --  For controlled and direct symbol policies, it is an error
4694
                  --  if the reference symbol file does not exist. For other
4695
                  --  symbol policies, this is just a warning
4696
 
4697
                  Error_Msg_Warn :=
4698
                    Project.Symbol_Data.Symbol_Policy /= Controlled
4699
                    and then Project.Symbol_Data.Symbol_Policy /= Direct;
4700
 
4701
                  Error_Msg
4702
                    (Data.Flags,
4703
                     "<library reference symbol file { does not exist",
4704
                     Lib_Ref_Symbol_File.Location, Project);
4705
 
4706
                  --  In addition in the non-controlled case, if symbol policy
4707
                  --  is Compliant, it is changed to Autonomous, because there
4708
                  --  is no reference to check against, and we don't want to
4709
                  --  fail in this case.
4710
 
4711
                  if Project.Symbol_Data.Symbol_Policy /= Controlled then
4712
                     if Project.Symbol_Data.Symbol_Policy = Compliant then
4713
                        Project.Symbol_Data.Symbol_Policy := Autonomous;
4714
                     end if;
4715
                  end if;
4716
               end if;
4717
 
4718
               --  If both the reference symbol file and the symbol file are
4719
               --  defined, then check that they are not the same file.
4720
 
4721
               if Project.Symbol_Data.Symbol_File /= No_Path then
4722
                  Get_Name_String (Project.Symbol_Data.Symbol_File);
4723
 
4724
                  if Name_Len > 0 then
4725
                     declare
4726
                        --  We do not need to pass a Directory to
4727
                        --  Normalize_Pathname, since the path_information
4728
                        --  already contains absolute information.
4729
 
4730
                        Symb_Path : constant String :=
4731
                                      Normalize_Pathname
4732
                                        (Get_Name_String
4733
                                           (Project.Object_Directory.Name) &
4734
                                         Name_Buffer (1 .. Name_Len),
4735
                                         Directory     => "/",
4736
                                         Resolve_Links =>
4737
                                           Opt.Follow_Links_For_Files);
4738
                        Ref_Path  : constant String :=
4739
                                      Normalize_Pathname
4740
                                        (Get_Name_String
4741
                                           (Project.Symbol_Data.Reference),
4742
                                         Directory     => "/",
4743
                                         Resolve_Links =>
4744
                                           Opt.Follow_Links_For_Files);
4745
                     begin
4746
                        if Symb_Path = Ref_Path then
4747
                           Error_Msg
4748
                             (Data.Flags,
4749
                              "library reference symbol file and library" &
4750
                              " symbol file cannot be the same file",
4751
                              Lib_Ref_Symbol_File.Location, Project);
4752
                        end if;
4753
                     end;
4754
                  end if;
4755
               end if;
4756
            end if;
4757
         end if;
4758
      end if;
4759
   end Check_Stand_Alone_Library;
4760
 
4761
   ----------------------------
4762
   -- Compute_Directory_Last --
4763
   ----------------------------
4764
 
4765
   function Compute_Directory_Last (Dir : String) return Natural is
4766
   begin
4767
      if Dir'Length > 1
4768
        and then (Dir (Dir'Last - 1) = Directory_Separator
4769
                    or else
4770
                  Dir (Dir'Last - 1) = '/')
4771
      then
4772
         return Dir'Last - 1;
4773
      else
4774
         return Dir'Last;
4775
      end if;
4776
   end Compute_Directory_Last;
4777
 
4778
   ---------------------
4779
   -- Get_Directories --
4780
   ---------------------
4781
 
4782
   procedure Get_Directories
4783
     (Project     : Project_Id;
4784
      Data        : in out Tree_Processing_Data)
4785
   is
4786
      package Recursive_Dirs is new GNAT.Dynamic_HTables.Simple_HTable
4787
        (Header_Num => Header_Num,
4788
         Element    => Boolean,
4789
         No_Element => False,
4790
         Key        => Name_Id,
4791
         Hash       => Hash,
4792
         Equal      => "=");
4793
      --  Hash table stores recursive source directories, to avoid looking
4794
      --  several times, and to avoid cycles that may be introduced by symbolic
4795
      --  links.
4796
 
4797
      Visited : Recursive_Dirs.Instance;
4798
 
4799
      Object_Dir  : constant Variable_Value :=
4800
                      Util.Value_Of
4801
                        (Name_Object_Dir, Project.Decl.Attributes, Data.Tree);
4802
 
4803
      Exec_Dir : constant Variable_Value :=
4804
                   Util.Value_Of
4805
                     (Name_Exec_Dir, Project.Decl.Attributes, Data.Tree);
4806
 
4807
      Source_Dirs : constant Variable_Value :=
4808
                      Util.Value_Of
4809
                        (Name_Source_Dirs, Project.Decl.Attributes, Data.Tree);
4810
 
4811
      Excluded_Source_Dirs : constant Variable_Value :=
4812
                              Util.Value_Of
4813
                                (Name_Excluded_Source_Dirs,
4814
                                 Project.Decl.Attributes,
4815
                                 Data.Tree);
4816
 
4817
      Source_Files : constant Variable_Value :=
4818
                      Util.Value_Of
4819
                        (Name_Source_Files,
4820
                         Project.Decl.Attributes, Data.Tree);
4821
 
4822
      Last_Source_Dir   : String_List_Id    := Nil_String;
4823
      Last_Src_Dir_Rank : Number_List_Index := No_Number_List;
4824
 
4825
      Languages : constant Variable_Value :=
4826
                      Prj.Util.Value_Of
4827
                        (Name_Languages, Project.Decl.Attributes, Data.Tree);
4828
 
4829
      procedure Find_Source_Dirs
4830
        (From     : File_Name_Type;
4831
         Location : Source_Ptr;
4832
         Rank     : Natural;
4833
         Removed  : Boolean := False);
4834
      --  Find one or several source directories, and add (or remove, if
4835
      --  Removed is True) them to list of source directories of the project.
4836
 
4837
      ----------------------
4838
      -- Find_Source_Dirs --
4839
      ----------------------
4840
 
4841
      procedure Find_Source_Dirs
4842
        (From     : File_Name_Type;
4843
         Location : Source_Ptr;
4844
         Rank     : Natural;
4845
         Removed  : Boolean := False)
4846
      is
4847
         Directory : constant String := Get_Name_String (From);
4848
 
4849
         procedure Add_To_Or_Remove_From_List
4850
           (Path_Id         : Name_Id;
4851
            Display_Path_Id : Name_Id);
4852
         --  When Removed = False, the directory Path_Id to the list of
4853
         --  source_dirs if not already in the list. When Removed = True,
4854
         --  removed directory Path_Id if in the list.
4855
 
4856
         procedure Recursive_Find_Dirs (Path : Name_Id);
4857
         --  Find all the subdirectories (recursively) of Path and add them
4858
         --  to the list of source directories of the project.
4859
 
4860
         --------------------------------
4861
         -- Add_To_Or_Remove_From_List --
4862
         --------------------------------
4863
 
4864
         procedure Add_To_Or_Remove_From_List
4865
           (Path_Id         : Name_Id;
4866
            Display_Path_Id : Name_Id)
4867
         is
4868
            List       : String_List_Id;
4869
            Prev       : String_List_Id;
4870
            Rank_List  : Number_List_Index;
4871
            Prev_Rank  : Number_List_Index;
4872
            Element    : String_Element;
4873
 
4874
         begin
4875
            Prev      := Nil_String;
4876
            Prev_Rank := No_Number_List;
4877
            List      := Project.Source_Dirs;
4878
            Rank_List := Project.Source_Dir_Ranks;
4879
            while List /= Nil_String loop
4880
               Element := Data.Tree.String_Elements.Table (List);
4881
               exit when Element.Value = Path_Id;
4882
               Prev := List;
4883
               List := Element.Next;
4884
               Prev_Rank := Rank_List;
4885
               Rank_List := Data.Tree.Number_Lists.Table (Prev_Rank).Next;
4886
            end loop;
4887
 
4888
            --  The directory is in the list if List is not Nil_String
4889
 
4890
            if not Removed and then List = Nil_String then
4891
               if Current_Verbosity = High then
4892
                  Write_Str  ("   Adding Source Dir=");
4893
                  Write_Line (Get_Name_String (Path_Id));
4894
               end if;
4895
 
4896
               String_Element_Table.Increment_Last (Data.Tree.String_Elements);
4897
               Element :=
4898
                 (Value         => Path_Id,
4899
                  Index         => 0,
4900
                  Display_Value => Display_Path_Id,
4901
                  Location      => No_Location,
4902
                  Flag          => False,
4903
                  Next          => Nil_String);
4904
 
4905
               Number_List_Table.Increment_Last (Data.Tree.Number_Lists);
4906
 
4907
               if Last_Source_Dir = Nil_String then
4908
 
4909
                  --  This is the first source directory
4910
 
4911
                  Project.Source_Dirs :=
4912
                    String_Element_Table.Last (Data.Tree.String_Elements);
4913
                  Project.Source_Dir_Ranks :=
4914
                    Number_List_Table.Last (Data.Tree.Number_Lists);
4915
 
4916
               else
4917
                  --  We already have source directories, link the previous
4918
                  --  last to the new one.
4919
 
4920
                  Data.Tree.String_Elements.Table (Last_Source_Dir).Next :=
4921
                    String_Element_Table.Last (Data.Tree.String_Elements);
4922
                  Data.Tree.Number_Lists.Table (Last_Src_Dir_Rank).Next :=
4923
                    Number_List_Table.Last (Data.Tree.Number_Lists);
4924
               end if;
4925
 
4926
               --  And register this source directory as the new last
4927
 
4928
               Last_Source_Dir :=
4929
                 String_Element_Table.Last (Data.Tree.String_Elements);
4930
               Data.Tree.String_Elements.Table (Last_Source_Dir) := Element;
4931
               Last_Src_Dir_Rank :=
4932
                 Number_List_Table.Last (Data.Tree.Number_Lists);
4933
               Data.Tree.Number_Lists.Table (Last_Src_Dir_Rank) :=
4934
                 (Number => Rank, Next => No_Number_List);
4935
 
4936
            elsif Removed and then List /= Nil_String then
4937
 
4938
               --  Remove source dir, if present
4939
 
4940
               if Prev = Nil_String then
4941
                  Project.Source_Dirs :=
4942
                    Data.Tree.String_Elements.Table (List).Next;
4943
                  Project.Source_Dir_Ranks :=
4944
                    Data.Tree.Number_Lists.Table (Rank_List).Next;
4945
 
4946
               else
4947
                  Data.Tree.String_Elements.Table (Prev).Next :=
4948
                    Data.Tree.String_Elements.Table (List).Next;
4949
                  Data.Tree.Number_Lists.Table (Prev_Rank).Next :=
4950
                    Data.Tree.Number_Lists.Table (Rank_List).Next;
4951
               end if;
4952
            end if;
4953
         end Add_To_Or_Remove_From_List;
4954
 
4955
         -------------------------
4956
         -- Recursive_Find_Dirs --
4957
         -------------------------
4958
 
4959
         procedure Recursive_Find_Dirs (Path : Name_Id) is
4960
            Dir  : Dir_Type;
4961
            Name : String (1 .. 250);
4962
            Last : Natural;
4963
 
4964
            Non_Canonical_Path : Name_Id := No_Name;
4965
            Canonical_Path     : Name_Id := No_Name;
4966
 
4967
            The_Path : constant String :=
4968
                         Normalize_Pathname
4969
                           (Get_Name_String (Path),
4970
                            Directory     =>
4971
                              Get_Name_String (Project.Directory.Display_Name),
4972
                            Resolve_Links => Opt.Follow_Links_For_Dirs) &
4973
                         Directory_Separator;
4974
 
4975
            The_Path_Last : constant Natural :=
4976
                              Compute_Directory_Last (The_Path);
4977
 
4978
         begin
4979
            Name_Len := The_Path_Last - The_Path'First + 1;
4980
            Name_Buffer (1 .. Name_Len) :=
4981
              The_Path (The_Path'First .. The_Path_Last);
4982
            Non_Canonical_Path := Name_Find;
4983
            Canonical_Path :=
4984
              Name_Id (Canonical_Case_File_Name (Non_Canonical_Path));
4985
 
4986
            --  To avoid processing the same directory several times, check
4987
            --  if the directory is already in Recursive_Dirs. If it is, then
4988
            --  there is nothing to do, just return. If it is not, put it there
4989
            --  and continue recursive processing.
4990
 
4991
            if not Removed then
4992
               if Recursive_Dirs.Get (Visited, Canonical_Path) then
4993
                  return;
4994
               else
4995
                  Recursive_Dirs.Set (Visited, Canonical_Path, True);
4996
               end if;
4997
            end if;
4998
 
4999
            Add_To_Or_Remove_From_List
5000
              (Path_Id         => Canonical_Path,
5001
               Display_Path_Id => Non_Canonical_Path);
5002
 
5003
            --  Now look for subdirectories. Do that even when this directory
5004
            --  is already in the list, because some of its subdirectories may
5005
            --  not be in the list yet.
5006
 
5007
            Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5008
 
5009
            loop
5010
               Read (Dir, Name, Last);
5011
               exit when Last = 0;
5012
 
5013
               if Name (1 .. Last) /= "."
5014
                 and then Name (1 .. Last) /= ".."
5015
               then
5016
                  --  Avoid . and .. directories
5017
 
5018
                  if Current_Verbosity = High then
5019
                     Write_Str  ("   Checking ");
5020
                     Write_Line (Name (1 .. Last));
5021
                  end if;
5022
 
5023
                  declare
5024
                     Path_Name : constant String :=
5025
                                   Normalize_Pathname
5026
                                     (Name           => Name (1 .. Last),
5027
                                      Directory      =>
5028
                                        The_Path
5029
                                          (The_Path'First .. The_Path_Last),
5030
                                      Resolve_Links  =>
5031
                                        Opt.Follow_Links_For_Dirs,
5032
                                      Case_Sensitive => True);
5033
 
5034
                  begin
5035
                     if Is_Directory (Path_Name) then
5036
 
5037
                        --  We have found a new subdirectory, call self
5038
 
5039
                        Name_Len := Path_Name'Length;
5040
                        Name_Buffer (1 .. Name_Len) := Path_Name;
5041
                        Recursive_Find_Dirs (Name_Find);
5042
                     end if;
5043
                  end;
5044
               end if;
5045
            end loop;
5046
 
5047
            Close (Dir);
5048
 
5049
         exception
5050
            when Directory_Error =>
5051
               null;
5052
         end Recursive_Find_Dirs;
5053
 
5054
      --  Start of processing for Find_Source_Dirs
5055
 
5056
      begin
5057
         if Current_Verbosity = High and then not Removed then
5058
            Write_Str ("Find_Source_Dirs (""");
5059
            Write_Str (Directory);
5060
            Write_Str (",");
5061
            Write_Str (Rank'Img);
5062
            Write_Line (""")");
5063
         end if;
5064
 
5065
         --  First, check if we are looking for a directory tree, indicated
5066
         --  by "/**" at the end.
5067
 
5068
         if Directory'Length >= 3
5069
           and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5070
           and then (Directory (Directory'Last - 2) = '/'
5071
                       or else
5072
                     Directory (Directory'Last - 2) = Directory_Separator)
5073
         then
5074
            Name_Len := Directory'Length - 3;
5075
 
5076
            if Name_Len = 0 then
5077
 
5078
               --  Case of "/**": all directories in file system
5079
 
5080
               Name_Len := 1;
5081
               Name_Buffer (1) := Directory (Directory'First);
5082
 
5083
            else
5084
               Name_Buffer (1 .. Name_Len) :=
5085
                 Directory (Directory'First .. Directory'Last - 3);
5086
            end if;
5087
 
5088
            if Current_Verbosity = High then
5089
               Write_Str ("Looking for all subdirectories of """);
5090
               Write_Str (Name_Buffer (1 .. Name_Len));
5091
               Write_Line ("""");
5092
            end if;
5093
 
5094
            declare
5095
               Base_Dir : constant File_Name_Type := Name_Find;
5096
               Root_Dir : constant String :=
5097
                            Normalize_Pathname
5098
                              (Name      => Get_Name_String (Base_Dir),
5099
                               Directory =>
5100
                                 Get_Name_String
5101
                                   (Project.Directory.Display_Name),
5102
                               Resolve_Links  =>
5103
                                 Opt.Follow_Links_For_Dirs,
5104
                               Case_Sensitive => True);
5105
 
5106
            begin
5107
               if Root_Dir'Length = 0 then
5108
                  Err_Vars.Error_Msg_File_1 := Base_Dir;
5109
 
5110
                  if Location = No_Location then
5111
                     Error_Msg
5112
                       (Data.Flags,
5113
                        "{ is not a valid directory.",
5114
                        Project.Location, Project);
5115
                  else
5116
                     Error_Msg
5117
                       (Data.Flags,
5118
                        "{ is not a valid directory.",
5119
                        Location, Project);
5120
                  end if;
5121
 
5122
               else
5123
                  --  We have an existing directory, we register it and all of
5124
                  --  its subdirectories.
5125
 
5126
                  if Current_Verbosity = High then
5127
                     Write_Line ("Looking for source directories:");
5128
                  end if;
5129
 
5130
                  Name_Len := Root_Dir'Length;
5131
                  Name_Buffer (1 .. Name_Len) := Root_Dir;
5132
                  Recursive_Find_Dirs (Name_Find);
5133
 
5134
                  if Current_Verbosity = High then
5135
                     Write_Line ("End of looking for source directories.");
5136
                  end if;
5137
               end if;
5138
            end;
5139
 
5140
         --  We have a single directory
5141
 
5142
         else
5143
            declare
5144
               Path_Name  : Path_Information;
5145
               Dir_Exists : Boolean;
5146
 
5147
            begin
5148
               Locate_Directory
5149
                 (Project     => Project,
5150
                  Name        => From,
5151
                  Path        => Path_Name,
5152
                  Dir_Exists  => Dir_Exists,
5153
                  Data        => Data,
5154
                  Must_Exist  => False);
5155
 
5156
               if not Dir_Exists then
5157
                  Err_Vars.Error_Msg_File_1 := From;
5158
 
5159
                  if Location = No_Location then
5160
                     Error_Msg
5161
                       (Data.Flags,
5162
                        "{ is not a valid directory",
5163
                        Project.Location, Project);
5164
                  else
5165
                     Error_Msg
5166
                       (Data.Flags,
5167
                        "{ is not a valid directory",
5168
                        Location, Project);
5169
                  end if;
5170
 
5171
               else
5172
                  declare
5173
                     Path : constant String :=
5174
                              Normalize_Pathname
5175
                                (Name           =>
5176
                                   Get_Name_String (Path_Name.Name),
5177
                                 Directory      =>
5178
                                   Get_Name_String (Project.Directory.Name),
5179
                                 Resolve_Links  => Opt.Follow_Links_For_Dirs,
5180
                                 Case_Sensitive => True) &
5181
                              Directory_Separator;
5182
 
5183
                     Last_Path         : constant Natural :=
5184
                                           Compute_Directory_Last (Path);
5185
                     Path_Id           : Name_Id;
5186
                     Display_Path      : constant String :=
5187
                                           Get_Name_String
5188
                                             (Path_Name.Display_Name);
5189
                     Last_Display_Path : constant Natural :=
5190
                                           Compute_Directory_Last
5191
                                             (Display_Path);
5192
                     Display_Path_Id   : Name_Id;
5193
 
5194
                  begin
5195
                     Name_Len := 0;
5196
                     Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
5197
                     Path_Id := Name_Find;
5198
 
5199
                     Name_Len := 0;
5200
                     Add_Str_To_Name_Buffer
5201
                       (Display_Path
5202
                          (Display_Path'First .. Last_Display_Path));
5203
                     Display_Path_Id := Name_Find;
5204
 
5205
                     Add_To_Or_Remove_From_List
5206
                       (Path_Id         => Path_Id,
5207
                        Display_Path_Id => Display_Path_Id);
5208
                  end;
5209
               end if;
5210
            end;
5211
         end if;
5212
 
5213
         Recursive_Dirs.Reset (Visited);
5214
      end Find_Source_Dirs;
5215
 
5216
   --  Start of processing for Get_Directories
5217
 
5218
      Dir_Exists : Boolean;
5219
 
5220
   begin
5221
      if Current_Verbosity = High then
5222
         Write_Line ("Starting to look for directories");
5223
      end if;
5224
 
5225
      --  Set the object directory to its default which may be nil, if there
5226
      --  is no sources in the project.
5227
 
5228
      if (((not Source_Files.Default)
5229
             and then Source_Files.Values = Nil_String)
5230
          or else
5231
           ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
5232
              or else
5233
           ((not Languages.Default) and then Languages.Values = Nil_String))
5234
        and then Project.Extends = No_Project
5235
      then
5236
         Project.Object_Directory := No_Path_Information;
5237
      else
5238
         Project.Object_Directory := Project.Directory;
5239
      end if;
5240
 
5241
      --  Check the object directory
5242
 
5243
      if Object_Dir.Value /= Empty_String then
5244
         Get_Name_String (Object_Dir.Value);
5245
 
5246
         if Name_Len = 0 then
5247
            Error_Msg
5248
              (Data.Flags,
5249
               "Object_Dir cannot be empty",
5250
               Object_Dir.Location, Project);
5251
 
5252
         else
5253
            --  We check that the specified object directory does exist.
5254
            --  However, even when it doesn't exist, we set it to a default
5255
            --  value. This is for the benefit of tools that recover from
5256
            --  errors; for example, these tools could create the non existent
5257
            --  directory. We always return an absolute directory name though.
5258
 
5259
            Locate_Directory
5260
              (Project,
5261
               File_Name_Type (Object_Dir.Value),
5262
               Path             => Project.Object_Directory,
5263
               Create           => "object",
5264
               Dir_Exists       => Dir_Exists,
5265
               Data             => Data,
5266
               Location         => Object_Dir.Location,
5267
               Must_Exist       => False,
5268
               Externally_Built => Project.Externally_Built);
5269
 
5270
            if not Dir_Exists
5271
              and then not Project.Externally_Built
5272
            then
5273
               --  The object directory does not exist, report an error if
5274
               --  the project is not externally built.
5275
 
5276
               Err_Vars.Error_Msg_File_1 :=
5277
                 File_Name_Type (Object_Dir.Value);
5278
 
5279
               case Data.Flags.Require_Obj_Dirs is
5280
                  when Error =>
5281
                     Error_Msg
5282
                       (Data.Flags,
5283
                        "object directory { not found",
5284
                        Project.Location, Project);
5285
                  when Warning =>
5286
                     Error_Msg
5287
                       (Data.Flags,
5288
                        "?object directory { not found",
5289
                        Project.Location, Project);
5290
                  when Silent =>
5291
                     null;
5292
               end case;
5293
            end if;
5294
         end if;
5295
 
5296
      elsif Project.Object_Directory /= No_Path_Information
5297
        and then Subdirs /= null
5298
      then
5299
         Name_Len := 1;
5300
         Name_Buffer (1) := '.';
5301
         Locate_Directory
5302
           (Project,
5303
            Name_Find,
5304
            Path             => Project.Object_Directory,
5305
            Create           => "object",
5306
            Dir_Exists       => Dir_Exists,
5307
            Data             => Data,
5308
            Location         => Object_Dir.Location,
5309
            Externally_Built => Project.Externally_Built);
5310
      end if;
5311
 
5312
      if Current_Verbosity = High then
5313
         if Project.Object_Directory = No_Path_Information then
5314
            Write_Line ("No object directory");
5315
         else
5316
            Write_Attr
5317
              ("Object directory",
5318
               Get_Name_String (Project.Object_Directory.Display_Name));
5319
         end if;
5320
      end if;
5321
 
5322
      --  Check the exec directory
5323
 
5324
      --  We set the object directory to its default
5325
 
5326
      Project.Exec_Directory   := Project.Object_Directory;
5327
 
5328
      if Exec_Dir.Value /= Empty_String then
5329
         Get_Name_String (Exec_Dir.Value);
5330
 
5331
         if Name_Len = 0 then
5332
            Error_Msg
5333
              (Data.Flags,
5334
               "Exec_Dir cannot be empty",
5335
               Exec_Dir.Location, Project);
5336
 
5337
         else
5338
            --  We check that the specified exec directory does exist
5339
 
5340
            Locate_Directory
5341
              (Project,
5342
               File_Name_Type (Exec_Dir.Value),
5343
               Path             => Project.Exec_Directory,
5344
               Dir_Exists       => Dir_Exists,
5345
               Data             => Data,
5346
               Create           => "exec",
5347
               Location         => Exec_Dir.Location,
5348
               Externally_Built => Project.Externally_Built);
5349
 
5350
            if not Dir_Exists then
5351
               Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
5352
               Error_Msg
5353
                 (Data.Flags,
5354
                  "exec directory { not found",
5355
                  Project.Location, Project);
5356
            end if;
5357
         end if;
5358
      end if;
5359
 
5360
      if Current_Verbosity = High then
5361
         if Project.Exec_Directory = No_Path_Information then
5362
            Write_Line ("No exec directory");
5363
         else
5364
            Write_Str ("Exec directory: """);
5365
            Write_Str (Get_Name_String (Project.Exec_Directory.Display_Name));
5366
            Write_Line ("""");
5367
         end if;
5368
      end if;
5369
 
5370
      --  Look for the source directories
5371
 
5372
      if Current_Verbosity = High then
5373
         Write_Line ("Starting to look for source directories");
5374
      end if;
5375
 
5376
      pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
5377
 
5378
      if (not Source_Files.Default)
5379
        and then Source_Files.Values = Nil_String
5380
      then
5381
         Project.Source_Dirs := Nil_String;
5382
 
5383
         if Project.Qualifier = Standard then
5384
            Error_Msg
5385
              (Data.Flags,
5386
               "a standard project cannot have no sources",
5387
               Source_Files.Location, Project);
5388
         end if;
5389
 
5390
      elsif Source_Dirs.Default then
5391
 
5392
         --  No Source_Dirs specified: the single source directory is the one
5393
         --  containing the project file.
5394
 
5395
         String_Element_Table.Append (Data.Tree.String_Elements,
5396
           (Value         => Name_Id (Project.Directory.Name),
5397
            Display_Value => Name_Id (Project.Directory.Display_Name),
5398
            Location      => No_Location,
5399
            Flag          => False,
5400
            Next          => Nil_String,
5401
            Index         => 0));
5402
 
5403
         Project.Source_Dirs :=
5404
           String_Element_Table.Last (Data.Tree.String_Elements);
5405
 
5406
         Number_List_Table.Append
5407
           (Data.Tree.Number_Lists,
5408
            (Number => 1, Next => No_Number_List));
5409
 
5410
         Project.Source_Dir_Ranks :=
5411
           Number_List_Table.Last (Data.Tree.Number_Lists);
5412
 
5413
         if Current_Verbosity = High then
5414
            Write_Attr
5415
              ("Default source directory",
5416
               Get_Name_String (Project.Directory.Display_Name));
5417
         end if;
5418
 
5419
      elsif Source_Dirs.Values = Nil_String then
5420
         if Project.Qualifier = Standard then
5421
            Error_Msg
5422
              (Data.Flags,
5423
               "a standard project cannot have no source directories",
5424
               Source_Dirs.Location, Project);
5425
         end if;
5426
 
5427
         Project.Source_Dirs := Nil_String;
5428
 
5429
      else
5430
         declare
5431
            Source_Dir : String_List_Id;
5432
            Element    : String_Element;
5433
            Rank       : Natural;
5434
         begin
5435
            --  Process the source directories for each element of the list
5436
 
5437
            Source_Dir := Source_Dirs.Values;
5438
            Rank := 0;
5439
            while Source_Dir /= Nil_String loop
5440
               Element := Data.Tree.String_Elements.Table (Source_Dir);
5441
               Rank := Rank + 1;
5442
               Find_Source_Dirs
5443
                 (File_Name_Type (Element.Value), Element.Location, Rank);
5444
               Source_Dir := Element.Next;
5445
            end loop;
5446
         end;
5447
      end if;
5448
 
5449
      if not Excluded_Source_Dirs.Default
5450
        and then Excluded_Source_Dirs.Values /= Nil_String
5451
      then
5452
         declare
5453
            Source_Dir : String_List_Id;
5454
            Element    : String_Element;
5455
 
5456
         begin
5457
            --  Process the source directories for each element of the list
5458
 
5459
            Source_Dir := Excluded_Source_Dirs.Values;
5460
            while Source_Dir /= Nil_String loop
5461
               Element := Data.Tree.String_Elements.Table (Source_Dir);
5462
               Find_Source_Dirs
5463
                 (File_Name_Type (Element.Value),
5464
                  Element.Location,
5465
                  0,
5466
                  Removed => True);
5467
               Source_Dir := Element.Next;
5468
            end loop;
5469
         end;
5470
      end if;
5471
 
5472
      if Current_Verbosity = High then
5473
         Write_Line ("Putting source directories in canonical cases");
5474
      end if;
5475
 
5476
      declare
5477
         Current : String_List_Id := Project.Source_Dirs;
5478
         Element : String_Element;
5479
 
5480
      begin
5481
         while Current /= Nil_String loop
5482
            Element := Data.Tree.String_Elements.Table (Current);
5483
            if Element.Value /= No_Name then
5484
               Element.Value :=
5485
                 Name_Id (Canonical_Case_File_Name (Name_Id (Element.Value)));
5486
               Data.Tree.String_Elements.Table (Current) := Element;
5487
            end if;
5488
 
5489
            Current := Element.Next;
5490
         end loop;
5491
      end;
5492
   end Get_Directories;
5493
 
5494
   ---------------
5495
   -- Get_Mains --
5496
   ---------------
5497
 
5498
   procedure Get_Mains
5499
     (Project : Project_Id;
5500
      Data    : in out Tree_Processing_Data)
5501
   is
5502
      Mains : constant Variable_Value :=
5503
               Prj.Util.Value_Of
5504
                 (Name_Main, Project.Decl.Attributes, Data.Tree);
5505
      List  : String_List_Id;
5506
      Elem  : String_Element;
5507
 
5508
   begin
5509
      Project.Mains := Mains.Values;
5510
 
5511
      --  If no Mains were specified, and if we are an extending project,
5512
      --  inherit the Mains from the project we are extending.
5513
 
5514
      if Mains.Default then
5515
         if not Project.Library and then Project.Extends /= No_Project then
5516
            Project.Mains := Project.Extends.Mains;
5517
         end if;
5518
 
5519
      --  In a library project file, Main cannot be specified
5520
 
5521
      elsif Project.Library then
5522
         Error_Msg
5523
           (Data.Flags,
5524
            "a library project file cannot have Main specified",
5525
            Mains.Location, Project);
5526
 
5527
      else
5528
         List := Mains.Values;
5529
         while List /= Nil_String loop
5530
            Elem := Data.Tree.String_Elements.Table (List);
5531
 
5532
            if Length_Of_Name (Elem.Value) = 0 then
5533
               Error_Msg
5534
                 (Data.Flags,
5535
                  "?a main cannot have an empty name",
5536
                  Elem.Location, Project);
5537
               exit;
5538
            end if;
5539
 
5540
            List := Elem.Next;
5541
         end loop;
5542
      end if;
5543
   end Get_Mains;
5544
 
5545
   ---------------------------
5546
   -- Get_Sources_From_File --
5547
   ---------------------------
5548
 
5549
   procedure Get_Sources_From_File
5550
     (Path     : String;
5551
      Location : Source_Ptr;
5552
      Project  : in out Project_Processing_Data;
5553
      Data     : in out Tree_Processing_Data)
5554
   is
5555
      File        : Prj.Util.Text_File;
5556
      Line        : String (1 .. 250);
5557
      Last        : Natural;
5558
      Source_Name : File_Name_Type;
5559
      Name_Loc    : Name_Location;
5560
 
5561
   begin
5562
      if Current_Verbosity = High then
5563
         Write_Str  ("Opening """);
5564
         Write_Str  (Path);
5565
         Write_Line (""".");
5566
      end if;
5567
 
5568
      --  Open the file
5569
 
5570
      Prj.Util.Open (File, Path);
5571
 
5572
      if not Prj.Util.Is_Valid (File) then
5573
         Error_Msg
5574
           (Data.Flags, "file does not exist", Location, Project.Project);
5575
 
5576
      else
5577
         --  Read the lines one by one
5578
 
5579
         while not Prj.Util.End_Of_File (File) loop
5580
            Prj.Util.Get_Line (File, Line, Last);
5581
 
5582
            --  A non empty, non comment line should contain a file name
5583
 
5584
            if Last /= 0
5585
              and then (Last = 1 or else Line (1 .. 2) /= "--")
5586
            then
5587
               Name_Len := Last;
5588
               Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
5589
               Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5590
               Source_Name := Name_Find;
5591
 
5592
               --  Check that there is no directory information
5593
 
5594
               for J in 1 .. Last loop
5595
                  if Line (J) = '/' or else Line (J) = Directory_Separator then
5596
                     Error_Msg_File_1 := Source_Name;
5597
                     Error_Msg
5598
                       (Data.Flags,
5599
                        "file name cannot include directory information ({)",
5600
                        Location, Project.Project);
5601
                     exit;
5602
                  end if;
5603
               end loop;
5604
 
5605
               Name_Loc := Source_Names_Htable.Get
5606
                 (Project.Source_Names, Source_Name);
5607
 
5608
               if Name_Loc = No_Name_Location then
5609
                  Name_Loc :=
5610
                    (Name     => Source_Name,
5611
                     Location => Location,
5612
                     Source   => No_Source,
5613
                     Found    => False);
5614
               end if;
5615
 
5616
               Source_Names_Htable.Set
5617
                 (Project.Source_Names, Source_Name, Name_Loc);
5618
            end if;
5619
         end loop;
5620
 
5621
         Prj.Util.Close (File);
5622
 
5623
      end if;
5624
   end Get_Sources_From_File;
5625
 
5626
   -----------------------
5627
   -- Compute_Unit_Name --
5628
   -----------------------
5629
 
5630
   procedure Compute_Unit_Name
5631
     (File_Name : File_Name_Type;
5632
      Naming    : Lang_Naming_Data;
5633
      Kind      : out Source_Kind;
5634
      Unit      : out Name_Id;
5635
      Project   : Project_Processing_Data;
5636
      In_Tree   : Project_Tree_Ref)
5637
   is
5638
      Filename : constant String  := Get_Name_String (File_Name);
5639
      Last     : Integer          := Filename'Last;
5640
      Sep_Len  : Integer;
5641
      Body_Len : Integer;
5642
      Spec_Len : Integer;
5643
 
5644
      Unit_Except : Unit_Exception;
5645
      Masked      : Boolean  := False;
5646
 
5647
   begin
5648
      Unit := No_Name;
5649
      Kind := Spec;
5650
 
5651
      if Naming.Separate_Suffix = No_File
5652
        or else Naming.Body_Suffix = No_File
5653
        or else Naming.Spec_Suffix = No_File
5654
      then
5655
         return;
5656
      end if;
5657
 
5658
      if Naming.Dot_Replacement = No_File then
5659
         if Current_Verbosity = High then
5660
            Write_Line ("  No dot_replacement specified");
5661
         end if;
5662
 
5663
         return;
5664
      end if;
5665
 
5666
      Sep_Len  := Integer (Length_Of_Name (Naming.Separate_Suffix));
5667
      Spec_Len := Integer (Length_Of_Name (Naming.Spec_Suffix));
5668
      Body_Len := Integer (Length_Of_Name (Naming.Body_Suffix));
5669
 
5670
      --  Choose the longest suffix that matches. If there are several matches,
5671
      --  give priority to specs, then bodies, then separates.
5672
 
5673
      if Naming.Separate_Suffix /= Naming.Body_Suffix
5674
        and then Suffix_Matches (Filename, Naming.Separate_Suffix)
5675
      then
5676
         Last := Filename'Last - Sep_Len;
5677
         Kind := Sep;
5678
      end if;
5679
 
5680
      if Filename'Last - Body_Len <= Last
5681
        and then Suffix_Matches (Filename, Naming.Body_Suffix)
5682
      then
5683
         Last := Natural'Min (Last, Filename'Last - Body_Len);
5684
         Kind := Impl;
5685
      end if;
5686
 
5687
      if Filename'Last - Spec_Len <= Last
5688
        and then Suffix_Matches (Filename, Naming.Spec_Suffix)
5689
      then
5690
         Last := Natural'Min (Last, Filename'Last - Spec_Len);
5691
         Kind := Spec;
5692
      end if;
5693
 
5694
      if Last = Filename'Last then
5695
         if Current_Verbosity = High then
5696
            Write_Line ("     no matching suffix");
5697
         end if;
5698
 
5699
         return;
5700
      end if;
5701
 
5702
      --  Check that the casing matches
5703
 
5704
      if File_Names_Case_Sensitive then
5705
         case Naming.Casing is
5706
            when All_Lower_Case =>
5707
               for J in Filename'First .. Last loop
5708
                  if Is_Letter (Filename (J))
5709
                    and then not Is_Lower (Filename (J))
5710
                  then
5711
                     if Current_Verbosity = High then
5712
                        Write_Line ("  Invalid casing");
5713
                     end if;
5714
 
5715
                     return;
5716
                  end if;
5717
               end loop;
5718
 
5719
            when All_Upper_Case =>
5720
               for J in Filename'First .. Last loop
5721
                  if Is_Letter (Filename (J))
5722
                    and then not Is_Upper (Filename (J))
5723
                  then
5724
                     if Current_Verbosity = High then
5725
                        Write_Line ("  Invalid casing");
5726
                     end if;
5727
 
5728
                     return;
5729
                  end if;
5730
               end loop;
5731
 
5732
            when Mixed_Case | Unknown =>
5733
               null;
5734
         end case;
5735
      end if;
5736
 
5737
      --  If Dot_Replacement is not a single dot, then there should not
5738
      --  be any dot in the name.
5739
 
5740
      declare
5741
         Dot_Repl : constant String :=
5742
                      Get_Name_String (Naming.Dot_Replacement);
5743
 
5744
      begin
5745
         if Dot_Repl /= "." then
5746
            for Index in Filename'First .. Last loop
5747
               if Filename (Index) = '.' then
5748
                  if Current_Verbosity = High then
5749
                     Write_Line ("   Invalid name, contains dot");
5750
                  end if;
5751
 
5752
                  return;
5753
               end if;
5754
            end loop;
5755
 
5756
            Replace_Into_Name_Buffer
5757
              (Filename (Filename'First .. Last), Dot_Repl, '.');
5758
 
5759
         else
5760
            Name_Len := Last - Filename'First + 1;
5761
            Name_Buffer (1 .. Name_Len) := Filename (Filename'First .. Last);
5762
            Fixed.Translate
5763
              (Source  => Name_Buffer (1 .. Name_Len),
5764
               Mapping => Lower_Case_Map);
5765
         end if;
5766
      end;
5767
 
5768
      --  In the standard GNAT naming scheme, check for special cases: children
5769
      --  or separates of A, G, I or S, and run time sources.
5770
 
5771
      if Is_Standard_GNAT_Naming (Naming)
5772
        and then Name_Len >= 3
5773
      then
5774
         declare
5775
            S1 : constant Character := Name_Buffer (1);
5776
            S2 : constant Character := Name_Buffer (2);
5777
            S3 : constant Character := Name_Buffer (3);
5778
 
5779
         begin
5780
            if        S1 = 'a'
5781
              or else S1 = 'g'
5782
              or else S1 = 'i'
5783
              or else S1 = 's'
5784
            then
5785
               --  Children or separates of packages A, G, I or S. These names
5786
               --  are x__ ... or x~... (where x is a, g, i, or s). Both
5787
               --  versions (x__... and x~...) are allowed in all platforms,
5788
               --  because it is not possible to know the platform before
5789
               --  processing of the project files.
5790
 
5791
               if S2 = '_' and then S3 = '_' then
5792
                  Name_Buffer (2) := '.';
5793
                  Name_Buffer (3 .. Name_Len - 1) :=
5794
                    Name_Buffer (4 .. Name_Len);
5795
                  Name_Len := Name_Len - 1;
5796
 
5797
               elsif S2 = '~' then
5798
                  Name_Buffer (2) := '.';
5799
 
5800
               elsif S2 = '.' then
5801
 
5802
                  --  If it is potentially a run time source
5803
 
5804
                  null;
5805
               end if;
5806
            end if;
5807
         end;
5808
      end if;
5809
 
5810
      --  Name_Buffer contains the name of the the unit in lower-cases. Check
5811
      --  that this is a valid unit name
5812
 
5813
      Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
5814
 
5815
      --  If there is a naming exception for the same unit, the file is not
5816
      --  a source for the unit.
5817
 
5818
      if Unit /= No_Name then
5819
         Unit_Except :=
5820
           Unit_Exceptions_Htable.Get (Project.Unit_Exceptions, Unit);
5821
 
5822
         if Kind = Spec then
5823
            Masked := Unit_Except.Spec /= No_File
5824
                        and then
5825
                      Unit_Except.Spec /= File_Name;
5826
         else
5827
            Masked := Unit_Except.Impl /= No_File
5828
                        and then
5829
                      Unit_Except.Impl /= File_Name;
5830
         end if;
5831
 
5832
         if Masked then
5833
            if Current_Verbosity = High then
5834
               Write_Str ("   """ & Filename & """ contains the ");
5835
 
5836
               if Kind = Spec then
5837
                  Write_Str ("spec of a unit found in """);
5838
                  Write_Str (Get_Name_String (Unit_Except.Spec));
5839
               else
5840
                  Write_Str ("body of a unit found in """);
5841
                  Write_Str (Get_Name_String (Unit_Except.Impl));
5842
               end if;
5843
 
5844
               Write_Line (""" (ignored)");
5845
            end if;
5846
 
5847
            Unit := No_Name;
5848
         end if;
5849
      end if;
5850
 
5851
      if Unit /= No_Name
5852
        and then Current_Verbosity = High
5853
      then
5854
         case Kind is
5855
            when Spec => Write_Str ("   spec of ");
5856
            when Impl => Write_Str ("   body of ");
5857
            when Sep  => Write_Str ("   sep of ");
5858
         end case;
5859
 
5860
         Write_Line (Get_Name_String (Unit));
5861
      end if;
5862
   end Compute_Unit_Name;
5863
 
5864
   --------------------------
5865
   -- Check_Illegal_Suffix --
5866
   --------------------------
5867
 
5868
   procedure Check_Illegal_Suffix
5869
     (Project         : Project_Id;
5870
      Suffix          : File_Name_Type;
5871
      Dot_Replacement : File_Name_Type;
5872
      Attribute_Name  : String;
5873
      Location        : Source_Ptr;
5874
      Data            : in out Tree_Processing_Data)
5875
   is
5876
      Suffix_Str : constant String := Get_Name_String (Suffix);
5877
 
5878
   begin
5879
      if Suffix_Str'Length = 0 then
5880
 
5881
         --  Always valid
5882
 
5883
         return;
5884
 
5885
      elsif Index (Suffix_Str, ".") = 0 then
5886
         Err_Vars.Error_Msg_File_1 := Suffix;
5887
         Error_Msg
5888
           (Data.Flags,
5889
            "{ is illegal for " & Attribute_Name & ": must have a dot",
5890
            Location, Project);
5891
         return;
5892
      end if;
5893
 
5894
      --  Case of dot replacement is a single dot, and first character of
5895
      --  suffix is also a dot.
5896
 
5897
      if Dot_Replacement /= No_File
5898
        and then Get_Name_String (Dot_Replacement) = "."
5899
        and then Suffix_Str (Suffix_Str'First) = '.'
5900
      then
5901
         for Index in Suffix_Str'First + 1 .. Suffix_Str'Last loop
5902
 
5903
            --  If there are multiple dots in the name
5904
 
5905
            if Suffix_Str (Index) = '.' then
5906
 
5907
               --  It is illegal to have a letter following the initial dot
5908
 
5909
               if Is_Letter (Suffix_Str (Suffix_Str'First + 1)) then
5910
                  Err_Vars.Error_Msg_File_1 := Suffix;
5911
                  Error_Msg
5912
                    (Data.Flags,
5913
                     "{ is illegal for " & Attribute_Name
5914
                     & ": ambiguous prefix when Dot_Replacement is a dot",
5915
                     Location, Project);
5916
               end if;
5917
               return;
5918
            end if;
5919
         end loop;
5920
      end if;
5921
   end Check_Illegal_Suffix;
5922
 
5923
   ----------------------
5924
   -- Locate_Directory --
5925
   ----------------------
5926
 
5927
   procedure Locate_Directory
5928
     (Project          : Project_Id;
5929
      Name             : File_Name_Type;
5930
      Path             : out Path_Information;
5931
      Dir_Exists       : out Boolean;
5932
      Data             : in out Tree_Processing_Data;
5933
      Create           : String := "";
5934
      Location         : Source_Ptr := No_Location;
5935
      Must_Exist       : Boolean := True;
5936
      Externally_Built : Boolean := False)
5937
   is
5938
      Parent          : constant Path_Name_Type :=
5939
                          Project.Directory.Display_Name;
5940
      The_Parent      : constant String :=
5941
                          Get_Name_String (Parent);
5942
      The_Parent_Last : constant Natural :=
5943
                          Compute_Directory_Last (The_Parent);
5944
      Full_Name       : File_Name_Type;
5945
      The_Name        : File_Name_Type;
5946
 
5947
   begin
5948
      Get_Name_String (Name);
5949
 
5950
      --  Add Subdirs.all if it is a directory that may be created and
5951
      --  Subdirs is not null;
5952
 
5953
      if Create /= "" and then Subdirs /= null then
5954
         if Name_Buffer (Name_Len) /= Directory_Separator then
5955
            Add_Char_To_Name_Buffer (Directory_Separator);
5956
         end if;
5957
 
5958
         Add_Str_To_Name_Buffer (Subdirs.all);
5959
      end if;
5960
 
5961
      --  Convert '/' to directory separator (for Windows)
5962
 
5963
      for J in 1 .. Name_Len loop
5964
         if Name_Buffer (J) = '/' then
5965
            Name_Buffer (J) := Directory_Separator;
5966
         end if;
5967
      end loop;
5968
 
5969
      The_Name := Name_Find;
5970
 
5971
      if Current_Verbosity = High then
5972
         Write_Str ("Locate_Directory (""");
5973
         Write_Str (Get_Name_String (The_Name));
5974
         Write_Str (""", """);
5975
         Write_Str (The_Parent);
5976
         Write_Line (""")");
5977
      end if;
5978
 
5979
      Path := No_Path_Information;
5980
      Dir_Exists := False;
5981
 
5982
      if Is_Absolute_Path (Get_Name_String (The_Name)) then
5983
         Full_Name := The_Name;
5984
 
5985
      else
5986
         Name_Len := 0;
5987
         Add_Str_To_Name_Buffer
5988
           (The_Parent (The_Parent'First .. The_Parent_Last));
5989
         Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
5990
         Full_Name := Name_Find;
5991
      end if;
5992
 
5993
      declare
5994
         Full_Path_Name : String_Access :=
5995
                            new String'(Get_Name_String (Full_Name));
5996
 
5997
      begin
5998
         if (Setup_Projects or else Subdirs /= null)
5999
           and then Create'Length > 0
6000
         then
6001
            if not Is_Directory (Full_Path_Name.all) then
6002
 
6003
               --  If project is externally built, do not create a subdir,
6004
               --  use the specified directory, without the subdir.
6005
 
6006
               if Externally_Built then
6007
                  if Is_Absolute_Path (Get_Name_String (Name)) then
6008
                     Get_Name_String (Name);
6009
 
6010
                  else
6011
                     Name_Len := 0;
6012
                     Add_Str_To_Name_Buffer
6013
                       (The_Parent (The_Parent'First .. The_Parent_Last));
6014
                     Add_Str_To_Name_Buffer (Get_Name_String (Name));
6015
                  end if;
6016
 
6017
                  Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
6018
 
6019
               else
6020
                  begin
6021
                     Create_Path (Full_Path_Name.all);
6022
 
6023
                     if not Quiet_Output then
6024
                        Write_Str (Create);
6025
                        Write_Str (" directory """);
6026
                        Write_Str (Full_Path_Name.all);
6027
                        Write_Str (""" created for project ");
6028
                        Write_Line (Get_Name_String (Project.Name));
6029
                     end if;
6030
 
6031
                  exception
6032
                     when Use_Error =>
6033
                        Error_Msg
6034
                          (Data.Flags,
6035
                           "could not create " & Create &
6036
                           " directory " & Full_Path_Name.all,
6037
                           Location, Project);
6038
                  end;
6039
               end if;
6040
            end if;
6041
         end if;
6042
 
6043
         Dir_Exists := Is_Directory (Full_Path_Name.all);
6044
 
6045
         if not Must_Exist or else Dir_Exists then
6046
            declare
6047
               Normed : constant String :=
6048
                          Normalize_Pathname
6049
                            (Full_Path_Name.all,
6050
                             Directory      =>
6051
                              The_Parent (The_Parent'First .. The_Parent_Last),
6052
                             Resolve_Links  => False,
6053
                             Case_Sensitive => True);
6054
 
6055
               Canonical_Path : constant String :=
6056
                                  Normalize_Pathname
6057
                                    (Normed,
6058
                                     Directory      =>
6059
                                       The_Parent
6060
                                         (The_Parent'First .. The_Parent_Last),
6061
                                     Resolve_Links  =>
6062
                                        Opt.Follow_Links_For_Dirs,
6063
                                     Case_Sensitive => False);
6064
 
6065
            begin
6066
               Name_Len := Normed'Length;
6067
               Name_Buffer (1 .. Name_Len) := Normed;
6068
 
6069
               --  Directories should always end with a directory separator
6070
 
6071
               if Name_Buffer (Name_Len) /= Directory_Separator then
6072
                  Add_Char_To_Name_Buffer (Directory_Separator);
6073
               end if;
6074
 
6075
               Path.Display_Name := Name_Find;
6076
 
6077
               Name_Len := Canonical_Path'Length;
6078
               Name_Buffer (1 .. Name_Len) := Canonical_Path;
6079
 
6080
               if Name_Buffer (Name_Len) /= Directory_Separator then
6081
                  Add_Char_To_Name_Buffer (Directory_Separator);
6082
               end if;
6083
 
6084
               Path.Name := Name_Find;
6085
            end;
6086
         end if;
6087
 
6088
         Free (Full_Path_Name);
6089
      end;
6090
   end Locate_Directory;
6091
 
6092
   ---------------------------
6093
   -- Find_Excluded_Sources --
6094
   ---------------------------
6095
 
6096
   procedure Find_Excluded_Sources
6097
     (Project : in out Project_Processing_Data;
6098
      Data    : in out Tree_Processing_Data)
6099
   is
6100
      Excluded_Source_List_File : constant Variable_Value :=
6101
                                    Util.Value_Of
6102
                                      (Name_Excluded_Source_List_File,
6103
                                       Project.Project.Decl.Attributes,
6104
                                       Data.Tree);
6105
      Excluded_Sources          : Variable_Value := Util.Value_Of
6106
                                    (Name_Excluded_Source_Files,
6107
                                     Project.Project.Decl.Attributes,
6108
                                     Data.Tree);
6109
 
6110
      Current         : String_List_Id;
6111
      Element         : String_Element;
6112
      Location        : Source_Ptr;
6113
      Name            : File_Name_Type;
6114
      File            : Prj.Util.Text_File;
6115
      Line            : String (1 .. 300);
6116
      Last            : Natural;
6117
      Locally_Removed : Boolean := False;
6118
 
6119
   begin
6120
      --  If Excluded_Source_Files is not declared, check Locally_Removed_Files
6121
 
6122
      if Excluded_Sources.Default then
6123
         Locally_Removed := True;
6124
         Excluded_Sources :=
6125
           Util.Value_Of
6126
             (Name_Locally_Removed_Files,
6127
              Project.Project.Decl.Attributes, Data.Tree);
6128
      end if;
6129
 
6130
      --  If there are excluded sources, put them in the table
6131
 
6132
      if not Excluded_Sources.Default then
6133
         if not Excluded_Source_List_File.Default then
6134
            if Locally_Removed then
6135
               Error_Msg
6136
                 (Data.Flags,
6137
                  "?both attributes Locally_Removed_Files and " &
6138
                  "Excluded_Source_List_File are present",
6139
                  Excluded_Source_List_File.Location, Project.Project);
6140
            else
6141
               Error_Msg
6142
                 (Data.Flags,
6143
                  "?both attributes Excluded_Source_Files and " &
6144
                  "Excluded_Source_List_File are present",
6145
                  Excluded_Source_List_File.Location, Project.Project);
6146
            end if;
6147
         end if;
6148
 
6149
         Current := Excluded_Sources.Values;
6150
         while Current /= Nil_String loop
6151
            Element := Data.Tree.String_Elements.Table (Current);
6152
            Name := Canonical_Case_File_Name (Element.Value);
6153
 
6154
            --  If the element has no location, then use the location of
6155
            --  Excluded_Sources to report possible errors.
6156
 
6157
            if Element.Location = No_Location then
6158
               Location := Excluded_Sources.Location;
6159
            else
6160
               Location := Element.Location;
6161
            end if;
6162
 
6163
            Excluded_Sources_Htable.Set
6164
              (Project.Excluded, Name, (Name, False, Location));
6165
            Current := Element.Next;
6166
         end loop;
6167
 
6168
      elsif not Excluded_Source_List_File.Default then
6169
         Location := Excluded_Source_List_File.Location;
6170
 
6171
         declare
6172
            Source_File_Path_Name : constant String :=
6173
                                      Path_Name_Of
6174
                                        (File_Name_Type
6175
                                           (Excluded_Source_List_File.Value),
6176
                                         Project.Project.Directory.Name);
6177
 
6178
         begin
6179
            if Source_File_Path_Name'Length = 0 then
6180
               Err_Vars.Error_Msg_File_1 :=
6181
                 File_Name_Type (Excluded_Source_List_File.Value);
6182
               Error_Msg
6183
                 (Data.Flags,
6184
                  "file with excluded sources { does not exist",
6185
                  Excluded_Source_List_File.Location, Project.Project);
6186
 
6187
            else
6188
               --  Open the file
6189
 
6190
               Prj.Util.Open (File, Source_File_Path_Name);
6191
 
6192
               if not Prj.Util.Is_Valid (File) then
6193
                  Error_Msg
6194
                    (Data.Flags, "file does not exist",
6195
                     Location, Project.Project);
6196
               else
6197
                  --  Read the lines one by one
6198
 
6199
                  while not Prj.Util.End_Of_File (File) loop
6200
                     Prj.Util.Get_Line (File, Line, Last);
6201
 
6202
                     --  Non empty, non comment line should contain a file name
6203
 
6204
                     if Last /= 0
6205
                       and then (Last = 1 or else Line (1 .. 2) /= "--")
6206
                     then
6207
                        Name_Len := Last;
6208
                        Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6209
                        Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6210
                        Name := Name_Find;
6211
 
6212
                        --  Check that there is no directory information
6213
 
6214
                        for J in 1 .. Last loop
6215
                           if Line (J) = '/'
6216
                             or else Line (J) = Directory_Separator
6217
                           then
6218
                              Error_Msg_File_1 := Name;
6219
                              Error_Msg
6220
                                (Data.Flags,
6221
                                 "file name cannot include " &
6222
                                 "directory information ({)",
6223
                                 Location, Project.Project);
6224
                              exit;
6225
                           end if;
6226
                        end loop;
6227
 
6228
                        Excluded_Sources_Htable.Set
6229
                          (Project.Excluded, Name, (Name, False, Location));
6230
                     end if;
6231
                  end loop;
6232
 
6233
                  Prj.Util.Close (File);
6234
               end if;
6235
            end if;
6236
         end;
6237
      end if;
6238
   end Find_Excluded_Sources;
6239
 
6240
   ------------------
6241
   -- Find_Sources --
6242
   ------------------
6243
 
6244
   procedure Find_Sources
6245
     (Project   : in out Project_Processing_Data;
6246
      Data      : in out Tree_Processing_Data)
6247
   is
6248
      Sources : constant Variable_Value :=
6249
                  Util.Value_Of
6250
                    (Name_Source_Files,
6251
                    Project.Project.Decl.Attributes,
6252
                    Data.Tree);
6253
 
6254
      Source_List_File : constant Variable_Value :=
6255
                           Util.Value_Of
6256
                             (Name_Source_List_File,
6257
                              Project.Project.Decl.Attributes,
6258
                              Data.Tree);
6259
 
6260
      Name_Loc             : Name_Location;
6261
      Has_Explicit_Sources : Boolean;
6262
 
6263
   begin
6264
      pragma Assert (Sources.Kind = List, "Source_Files is not a list");
6265
      pragma Assert
6266
        (Source_List_File.Kind = Single,
6267
         "Source_List_File is not a single string");
6268
 
6269
      Project.Source_List_File_Location := Source_List_File.Location;
6270
 
6271
      --  If the user has specified a Source_Files attribute
6272
 
6273
      if not Sources.Default then
6274
         if not Source_List_File.Default then
6275
            Error_Msg
6276
              (Data.Flags,
6277
               "?both attributes source_files and " &
6278
               "source_list_file are present",
6279
               Source_List_File.Location, Project.Project);
6280
         end if;
6281
 
6282
         --  Sources is a list of file names
6283
 
6284
         declare
6285
            Current  : String_List_Id := Sources.Values;
6286
            Element  : String_Element;
6287
            Location : Source_Ptr;
6288
            Name     : File_Name_Type;
6289
 
6290
         begin
6291
            if Current = Nil_String then
6292
               Project.Project.Languages := No_Language_Index;
6293
 
6294
               --  This project contains no source. For projects that don't
6295
               --  extend other projects, this also means that there is no
6296
               --  need for an object directory, if not specified.
6297
 
6298
               if Project.Project.Extends = No_Project
6299
                 and then Project.Project.Object_Directory =
6300
                   Project.Project.Directory
6301
               then
6302
                  Project.Project.Object_Directory := No_Path_Information;
6303
               end if;
6304
            end if;
6305
 
6306
            while Current /= Nil_String loop
6307
               Element := Data.Tree.String_Elements.Table (Current);
6308
               Name := Canonical_Case_File_Name (Element.Value);
6309
               Get_Name_String (Element.Value);
6310
 
6311
               --  If the element has no location, then use the location of
6312
               --  Sources to report possible errors.
6313
 
6314
               if Element.Location = No_Location then
6315
                  Location := Sources.Location;
6316
               else
6317
                  Location := Element.Location;
6318
               end if;
6319
 
6320
               --  Check that there is no directory information
6321
 
6322
               for J in 1 .. Name_Len loop
6323
                  if Name_Buffer (J) = '/'
6324
                    or else Name_Buffer (J) = Directory_Separator
6325
                  then
6326
                     Error_Msg_File_1 := Name;
6327
                     Error_Msg
6328
                       (Data.Flags,
6329
                        "file name cannot include directory " &
6330
                        "information ({)",
6331
                        Location, Project.Project);
6332
                     exit;
6333
                  end if;
6334
               end loop;
6335
 
6336
               --  Check whether the file is already there: the same file name
6337
               --  may be in the list. If the source is missing, the error will
6338
               --  be on the first mention of the source file name.
6339
 
6340
               Name_Loc := Source_Names_Htable.Get
6341
                 (Project.Source_Names, Name);
6342
 
6343
               if Name_Loc = No_Name_Location then
6344
                  Name_Loc :=
6345
                    (Name     => Name,
6346
                     Location => Location,
6347
                     Source   => No_Source,
6348
                     Found    => False);
6349
                  Source_Names_Htable.Set
6350
                    (Project.Source_Names, Name, Name_Loc);
6351
               end if;
6352
 
6353
               Current := Element.Next;
6354
            end loop;
6355
 
6356
            Has_Explicit_Sources := True;
6357
         end;
6358
 
6359
         --  If we have no Source_Files attribute, check the Source_List_File
6360
         --  attribute.
6361
 
6362
      elsif not Source_List_File.Default then
6363
 
6364
         --  Source_List_File is the name of the file that contains the source
6365
         --  file names.
6366
 
6367
         declare
6368
            Source_File_Path_Name : constant String :=
6369
              Path_Name_Of
6370
                (File_Name_Type (Source_List_File.Value),
6371
                 Project.Project.Directory.Name);
6372
 
6373
         begin
6374
            Has_Explicit_Sources := True;
6375
 
6376
            if Source_File_Path_Name'Length = 0 then
6377
               Err_Vars.Error_Msg_File_1 :=
6378
                 File_Name_Type (Source_List_File.Value);
6379
               Error_Msg
6380
                 (Data.Flags,
6381
                  "file with sources { does not exist",
6382
                  Source_List_File.Location, Project.Project);
6383
 
6384
            else
6385
               Get_Sources_From_File
6386
                 (Source_File_Path_Name, Source_List_File.Location,
6387
                  Project, Data);
6388
            end if;
6389
         end;
6390
 
6391
      else
6392
         --  Neither Source_Files nor Source_List_File has been specified. Find
6393
         --  all the files that satisfy the naming scheme in all the source
6394
         --  directories.
6395
 
6396
         Has_Explicit_Sources := False;
6397
      end if;
6398
 
6399
      Search_Directories
6400
        (Project,
6401
         Data            => Data,
6402
         For_All_Sources => Sources.Default and then Source_List_File.Default);
6403
 
6404
      --  Check if all exceptions have been found
6405
 
6406
      declare
6407
         Source : Source_Id;
6408
         Iter   : Source_Iterator;
6409
 
6410
      begin
6411
         Iter := For_Each_Source (Data.Tree, Project.Project);
6412
         loop
6413
            Source := Prj.Element (Iter);
6414
            exit when Source = No_Source;
6415
 
6416
            if Source.Naming_Exception
6417
              and then Source.Path = No_Path_Information
6418
            then
6419
               if Source.Unit /= No_Unit_Index then
6420
 
6421
                  --  For multi-unit source files, source_id gets duplicated
6422
                  --  once for every unit. Only the first source_id got its
6423
                  --  full path set. So if it isn't set for that first one,
6424
                  --  the file wasn't found. Otherwise we need to update for
6425
                  --  units after the first one.
6426
 
6427
                  if Source.Index = 0
6428
                    or else Source.Index = 1
6429
                  then
6430
                     Error_Msg_Name_1 := Name_Id (Source.Display_File);
6431
                     Error_Msg_Name_2 := Name_Id (Source.Unit.Name);
6432
                     Error_Msg
6433
                       (Data.Flags,
6434
                        "source file %% for unit %% not found",
6435
                        No_Location, Project.Project);
6436
 
6437
                  else
6438
                     Source.Path := Files_Htable.Get
6439
                       (Data.File_To_Source, Source.File).Path;
6440
 
6441
                     if Current_Verbosity = High then
6442
                        if Source.Path /= No_Path_Information then
6443
                           Write_Line ("Setting full path for "
6444
                                       & Get_Name_String (Source.File)
6445
                                       & " at" & Source.Index'Img
6446
                                       & " to "
6447
                                       & Get_Name_String (Source.Path.Name));
6448
                        end if;
6449
                     end if;
6450
                  end if;
6451
               end if;
6452
 
6453
               if Source.Path = No_Path_Information then
6454
                  Remove_Source (Source, No_Source);
6455
               end if;
6456
            end if;
6457
 
6458
            Next (Iter);
6459
         end loop;
6460
      end;
6461
 
6462
      --  It is an error if a source file name in a source list or in a source
6463
      --  list file is not found.
6464
 
6465
      if Has_Explicit_Sources then
6466
         declare
6467
            NL          : Name_Location;
6468
            First_Error : Boolean;
6469
 
6470
         begin
6471
            NL := Source_Names_Htable.Get_First (Project.Source_Names);
6472
            First_Error := True;
6473
            while NL /= No_Name_Location loop
6474
               if not NL.Found then
6475
                  Err_Vars.Error_Msg_File_1 := NL.Name;
6476
 
6477
                  if First_Error then
6478
                     Error_Msg
6479
                       (Data.Flags,
6480
                        "source file { not found",
6481
                        NL.Location, Project.Project);
6482
                     First_Error := False;
6483
 
6484
                  else
6485
                     Error_Msg
6486
                       (Data.Flags,
6487
                        "\source file { not found",
6488
                        NL.Location, Project.Project);
6489
                  end if;
6490
               end if;
6491
 
6492
               NL := Source_Names_Htable.Get_Next (Project.Source_Names);
6493
            end loop;
6494
         end;
6495
      end if;
6496
   end Find_Sources;
6497
 
6498
   ----------------
6499
   -- Initialize --
6500
   ----------------
6501
 
6502
   procedure Initialize
6503
     (Data  : out Tree_Processing_Data;
6504
      Tree  : Project_Tree_Ref;
6505
      Flags : Prj.Processing_Flags)
6506
   is
6507
   begin
6508
      Files_Htable.Reset (Data.File_To_Source);
6509
      Data.Tree  := Tree;
6510
      Data.Flags := Flags;
6511
   end Initialize;
6512
 
6513
   ----------
6514
   -- Free --
6515
   ----------
6516
 
6517
   procedure Free (Data : in out Tree_Processing_Data) is
6518
   begin
6519
      Files_Htable.Reset (Data.File_To_Source);
6520
   end Free;
6521
 
6522
   ----------------
6523
   -- Initialize --
6524
   ----------------
6525
 
6526
   procedure Initialize
6527
     (Data    : in out Project_Processing_Data;
6528
      Project : Project_Id)
6529
   is
6530
   begin
6531
      Data.Project := Project;
6532
   end Initialize;
6533
 
6534
   ----------
6535
   -- Free --
6536
   ----------
6537
 
6538
   procedure Free (Data : in out Project_Processing_Data) is
6539
   begin
6540
      Source_Names_Htable.Reset      (Data.Source_Names);
6541
      Unit_Exceptions_Htable.Reset   (Data.Unit_Exceptions);
6542
      Excluded_Sources_Htable.Reset  (Data.Excluded);
6543
   end Free;
6544
 
6545
   -------------------------------
6546
   -- Check_File_Naming_Schemes --
6547
   -------------------------------
6548
 
6549
   procedure Check_File_Naming_Schemes
6550
     (In_Tree               : Project_Tree_Ref;
6551
      Project               : Project_Processing_Data;
6552
      File_Name             : File_Name_Type;
6553
      Alternate_Languages   : out Language_List;
6554
      Language              : out Language_Ptr;
6555
      Display_Language_Name : out Name_Id;
6556
      Unit                  : out Name_Id;
6557
      Lang_Kind             : out Language_Kind;
6558
      Kind                  : out Source_Kind)
6559
   is
6560
      Filename : constant String := Get_Name_String (File_Name);
6561
      Config   : Language_Config;
6562
      Tmp_Lang : Language_Ptr;
6563
 
6564
      Header_File : Boolean := False;
6565
      --  True if we found at least one language for which the file is a header
6566
      --  In such a case, we search for all possible languages where this is
6567
      --  also a header (C and C++ for instance), since the file might be used
6568
      --  for several such languages.
6569
 
6570
      procedure Check_File_Based_Lang;
6571
      --  Does the naming scheme test for file-based languages. For those,
6572
      --  there is no Unit. Just check if the file name has the implementation
6573
      --  or, if it is specified, the template suffix of the language.
6574
      --
6575
      --  Returns True if the file belongs to the current language and we
6576
      --  should stop searching for matching languages. Not that a given header
6577
      --  file could belong to several languages (C and C++ for instance). Thus
6578
      --  if we found a header we'll check whether it matches other languages.
6579
 
6580
      ---------------------------
6581
      -- Check_File_Based_Lang --
6582
      ---------------------------
6583
 
6584
      procedure Check_File_Based_Lang is
6585
      begin
6586
         if not Header_File
6587
           and then Suffix_Matches (Filename, Config.Naming_Data.Body_Suffix)
6588
         then
6589
            Unit     := No_Name;
6590
            Kind     := Impl;
6591
            Language := Tmp_Lang;
6592
 
6593
            if Current_Verbosity = High then
6594
               Write_Str ("     implementation of language ");
6595
               Write_Line (Get_Name_String (Display_Language_Name));
6596
            end if;
6597
 
6598
         elsif Suffix_Matches (Filename, Config.Naming_Data.Spec_Suffix) then
6599
            if Current_Verbosity = High then
6600
               Write_Str ("     header of language ");
6601
               Write_Line (Get_Name_String (Display_Language_Name));
6602
            end if;
6603
 
6604
            if Header_File then
6605
               Alternate_Languages := new Language_List_Element'
6606
                 (Language => Language,
6607
                  Next     => Alternate_Languages);
6608
 
6609
            else
6610
               Header_File := True;
6611
               Kind        := Spec;
6612
               Unit        := No_Name;
6613
               Language    := Tmp_Lang;
6614
            end if;
6615
         end if;
6616
      end Check_File_Based_Lang;
6617
 
6618
   --  Start of processing for Check_File_Naming_Schemes
6619
 
6620
   begin
6621
      Language              := No_Language_Index;
6622
      Alternate_Languages   := null;
6623
      Display_Language_Name := No_Name;
6624
      Unit                  := No_Name;
6625
      Lang_Kind             := File_Based;
6626
      Kind                  := Spec;
6627
 
6628
      Tmp_Lang := Project.Project.Languages;
6629
      while Tmp_Lang /= No_Language_Index loop
6630
         if Current_Verbosity = High then
6631
            Write_Line
6632
              ("     Testing language "
6633
               & Get_Name_String (Tmp_Lang.Name)
6634
               & " Header_File=" & Header_File'Img);
6635
         end if;
6636
 
6637
         Display_Language_Name := Tmp_Lang.Display_Name;
6638
         Config := Tmp_Lang.Config;
6639
         Lang_Kind := Config.Kind;
6640
 
6641
         case Config.Kind is
6642
            when File_Based =>
6643
               Check_File_Based_Lang;
6644
               exit when Kind = Impl;
6645
 
6646
            when Unit_Based =>
6647
 
6648
               --  We know it belongs to a least a file_based language, no
6649
               --  need to check unit-based ones.
6650
 
6651
               if not Header_File then
6652
                  Compute_Unit_Name
6653
                    (File_Name       => File_Name,
6654
                     Naming          => Config.Naming_Data,
6655
                     Kind            => Kind,
6656
                     Unit            => Unit,
6657
                     Project         => Project,
6658
                     In_Tree         => In_Tree);
6659
 
6660
                  if Unit /= No_Name then
6661
                     Language    := Tmp_Lang;
6662
                     exit;
6663
                  end if;
6664
               end if;
6665
         end case;
6666
 
6667
         Tmp_Lang := Tmp_Lang.Next;
6668
      end loop;
6669
 
6670
      if Language = No_Language_Index
6671
        and then Current_Verbosity = High
6672
      then
6673
         Write_Line ("     not a source of any language");
6674
      end if;
6675
   end Check_File_Naming_Schemes;
6676
 
6677
   -------------------
6678
   -- Override_Kind --
6679
   -------------------
6680
 
6681
   procedure Override_Kind (Source : Source_Id; Kind : Source_Kind) is
6682
   begin
6683
      --  If the file was previously already associated with a unit, change it
6684
 
6685
      if Source.Unit /= null
6686
        and then Source.Kind in Spec_Or_Body
6687
        and then Source.Unit.File_Names (Source.Kind) /= null
6688
      then
6689
         --  If we had another file referencing the same unit (for instance it
6690
         --  was in an extended project), that source file is in fact invisible
6691
         --  from now on, and in particular doesn't belong to the same unit.
6692
 
6693
         if Source.Unit.File_Names (Source.Kind) /= Source then
6694
            Source.Unit.File_Names (Source.Kind).Unit := No_Unit_Index;
6695
         end if;
6696
 
6697
         Source.Unit.File_Names (Source.Kind) := null;
6698
      end if;
6699
 
6700
      Source.Kind := Kind;
6701
 
6702
      if Current_Verbosity = High
6703
        and then Source.File /= No_File
6704
      then
6705
         Write_Line ("Override kind for "
6706
                     & Get_Name_String (Source.File)
6707
                     & " kind=" & Source.Kind'Img);
6708
      end if;
6709
 
6710
      if Source.Kind in Spec_Or_Body and then Source.Unit /= null then
6711
         Source.Unit.File_Names (Source.Kind) := Source;
6712
      end if;
6713
   end Override_Kind;
6714
 
6715
   ----------------
6716
   -- Check_File --
6717
   ----------------
6718
 
6719
   procedure Check_File
6720
     (Project           : in out Project_Processing_Data;
6721
      Data              : in out Tree_Processing_Data;
6722
      Source_Dir_Rank   : Natural;
6723
      Path              : Path_Name_Type;
6724
      File_Name         : File_Name_Type;
6725
      Display_File_Name : File_Name_Type;
6726
      Locally_Removed   : Boolean;
6727
      For_All_Sources   : Boolean)
6728
   is
6729
      Canonical_Path : constant Path_Name_Type :=
6730
                         Path_Name_Type
6731
                           (Canonical_Case_File_Name (Name_Id (Path)));
6732
 
6733
      Name_Loc              : Name_Location :=
6734
                                Source_Names_Htable.Get
6735
                                  (Project.Source_Names, File_Name);
6736
      Check_Name            : Boolean := False;
6737
      Alternate_Languages   : Language_List;
6738
      Language              : Language_Ptr;
6739
      Source                : Source_Id;
6740
      Src_Ind               : Source_File_Index;
6741
      Unit                  : Name_Id;
6742
      Display_Language_Name : Name_Id;
6743
      Lang_Kind             : Language_Kind;
6744
      Kind                  : Source_Kind := Spec;
6745
 
6746
   begin
6747
      if Current_Verbosity = High then
6748
         Write_Line ("Checking file:");
6749
         Write_Str ("   Path = ");
6750
         Write_Line (Get_Name_String (Path));
6751
         Write_Str ("   Rank =");
6752
         Write_Line (Source_Dir_Rank'Img);
6753
      end if;
6754
 
6755
      if Name_Loc = No_Name_Location then
6756
         Check_Name := For_All_Sources;
6757
 
6758
      else
6759
         if Name_Loc.Found then
6760
 
6761
            --  Check if it is OK to have the same file name in several
6762
            --  source directories.
6763
 
6764
            if Source_Dir_Rank = Name_Loc.Source.Source_Dir_Rank then
6765
               Error_Msg_File_1 := File_Name;
6766
               Error_Msg
6767
                 (Data.Flags,
6768
                  "{ is found in several source directories",
6769
                  Name_Loc.Location, Project.Project);
6770
            end if;
6771
 
6772
         else
6773
            Name_Loc.Found := True;
6774
 
6775
            Source_Names_Htable.Set
6776
              (Project.Source_Names, File_Name, Name_Loc);
6777
 
6778
            if Name_Loc.Source = No_Source then
6779
               Check_Name := True;
6780
 
6781
            else
6782
               Name_Loc.Source.Path := (Canonical_Path, Path);
6783
 
6784
               Source_Paths_Htable.Set
6785
                 (Data.Tree.Source_Paths_HT,
6786
                  Canonical_Path,
6787
                  Name_Loc.Source);
6788
 
6789
               --  Check if this is a subunit
6790
 
6791
               if Name_Loc.Source.Unit /= No_Unit_Index
6792
                 and then Name_Loc.Source.Kind = Impl
6793
               then
6794
                  Src_Ind := Sinput.P.Load_Project_File
6795
                    (Get_Name_String (Canonical_Path));
6796
 
6797
                  if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
6798
                     Override_Kind (Name_Loc.Source, Sep);
6799
                  end if;
6800
               end if;
6801
 
6802
               Files_Htable.Set
6803
                 (Data.File_To_Source, File_Name, Name_Loc.Source);
6804
            end if;
6805
         end if;
6806
      end if;
6807
 
6808
      if Check_Name then
6809
         Check_File_Naming_Schemes
6810
           (In_Tree               => Data.Tree,
6811
            Project               => Project,
6812
            File_Name             => File_Name,
6813
            Alternate_Languages   => Alternate_Languages,
6814
            Language              => Language,
6815
            Display_Language_Name => Display_Language_Name,
6816
            Unit                  => Unit,
6817
            Lang_Kind             => Lang_Kind,
6818
            Kind                  => Kind);
6819
 
6820
         if Language = No_Language_Index then
6821
 
6822
            --  A file name in a list must be a source of a language
6823
 
6824
            if Data.Flags.Error_On_Unknown_Language
6825
              and then Name_Loc.Found
6826
            then
6827
               Error_Msg_File_1 := File_Name;
6828
               Error_Msg
6829
                 (Data.Flags,
6830
                  "language unknown for {",
6831
                  Name_Loc.Location, Project.Project);
6832
            end if;
6833
 
6834
         else
6835
            Add_Source
6836
              (Id                  => Source,
6837
               Project             => Project.Project,
6838
               Source_Dir_Rank     => Source_Dir_Rank,
6839
               Lang_Id             => Language,
6840
               Kind                => Kind,
6841
               Data                => Data,
6842
               Alternate_Languages => Alternate_Languages,
6843
               File_Name           => File_Name,
6844
               Display_File        => Display_File_Name,
6845
               Unit                => Unit,
6846
               Locally_Removed     => Locally_Removed,
6847
               Path                => (Canonical_Path, Path));
6848
 
6849
            --  If it is a source specified in a list, update the entry in
6850
            --  the Source_Names table.
6851
 
6852
            if Name_Loc.Found and then Name_Loc.Source = No_Source then
6853
               Name_Loc.Source := Source;
6854
               Source_Names_Htable.Set
6855
                 (Project.Source_Names, File_Name, Name_Loc);
6856
            end if;
6857
         end if;
6858
      end if;
6859
   end Check_File;
6860
 
6861
   ------------------------
6862
   -- Search_Directories --
6863
   ------------------------
6864
 
6865
   procedure Search_Directories
6866
     (Project         : in out Project_Processing_Data;
6867
      Data            : in out Tree_Processing_Data;
6868
      For_All_Sources : Boolean)
6869
   is
6870
      Source_Dir        : String_List_Id;
6871
      Element           : String_Element;
6872
      Src_Dir_Rank      : Number_List_Index;
6873
      Num_Nod           : Number_Node;
6874
      Dir               : Dir_Type;
6875
      Name              : String (1 .. 1_000);
6876
      Last              : Natural;
6877
      File_Name         : File_Name_Type;
6878
      Display_File_Name : File_Name_Type;
6879
 
6880
   begin
6881
      if Current_Verbosity = High then
6882
         Write_Line ("Looking for sources:");
6883
      end if;
6884
 
6885
      --  Loop through subdirectories
6886
 
6887
      Source_Dir := Project.Project.Source_Dirs;
6888
      Src_Dir_Rank := Project.Project.Source_Dir_Ranks;
6889
      while Source_Dir /= Nil_String loop
6890
         begin
6891
            Num_Nod := Data.Tree.Number_Lists.Table (Src_Dir_Rank);
6892
            Element := Data.Tree.String_Elements.Table (Source_Dir);
6893
 
6894
            if Element.Value /= No_Name then
6895
               Get_Name_String (Element.Display_Value);
6896
 
6897
               if Current_Verbosity = High then
6898
                  Write_Str ("Directory: ");
6899
                  Write_Str (Name_Buffer (1 .. Name_Len));
6900
                  Write_Line (Num_Nod.Number'Img);
6901
               end if;
6902
 
6903
               declare
6904
                  Source_Directory : constant String :=
6905
                                       Name_Buffer (1 .. Name_Len) &
6906
                                         Directory_Separator;
6907
 
6908
                  Dir_Last : constant Natural :=
6909
                                       Compute_Directory_Last
6910
                                         (Source_Directory);
6911
 
6912
               begin
6913
                  if Current_Verbosity = High then
6914
                     Write_Attr ("Source_Dir", Source_Directory);
6915
                  end if;
6916
 
6917
                  --  We look to every entry in the source directory
6918
 
6919
                  Open (Dir, Source_Directory);
6920
 
6921
                  loop
6922
                     Read (Dir, Name, Last);
6923
 
6924
                     exit when Last = 0;
6925
 
6926
                     --  In fast project loading mode (without -eL), the user
6927
                     --  guarantees that no directory has a name which is a
6928
                     --  valid source name, so we can avoid doing a system call
6929
                     --  here. This provides a very significant speed up on
6930
                     --  slow file systems (remote files for instance).
6931
 
6932
                     if not Opt.Follow_Links_For_Files
6933
                       or else Is_Regular_File
6934
                                 (Source_Directory & Name (1 .. Last))
6935
                     then
6936
                        if Current_Verbosity = High then
6937
                           Write_Str  ("   Checking ");
6938
                           Write_Line (Name (1 .. Last));
6939
                        end if;
6940
 
6941
                        Name_Len := Last;
6942
                        Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
6943
                        Display_File_Name := Name_Find;
6944
 
6945
                        if Osint.File_Names_Case_Sensitive then
6946
                           File_Name := Display_File_Name;
6947
                        else
6948
                           Canonical_Case_File_Name
6949
                             (Name_Buffer (1 .. Name_Len));
6950
                           File_Name := Name_Find;
6951
                        end if;
6952
 
6953
                        declare
6954
                           Path_Name : constant String :=
6955
                                         Normalize_Pathname
6956
                                           (Name (1 .. Last),
6957
                                            Directory       =>
6958
                                              Source_Directory
6959
                                                (Source_Directory'First ..
6960
                                                 Dir_Last),
6961
                                            Resolve_Links   =>
6962
                                              Opt.Follow_Links_For_Files,
6963
                                            Case_Sensitive => True);
6964
                           --  Case_Sensitive set True (no folding)
6965
 
6966
                           Path : Path_Name_Type;
6967
                           FF   : File_Found := Excluded_Sources_Htable.Get
6968
                                                 (Project.Excluded, File_Name);
6969
                           To_Remove : Boolean := False;
6970
 
6971
                        begin
6972
                           Name_Len := Path_Name'Length;
6973
                           Name_Buffer (1 .. Name_Len) := Path_Name;
6974
                           Path := Name_Find;
6975
 
6976
                           if FF /= No_File_Found then
6977
                              if not FF.Found then
6978
                                 FF.Found := True;
6979
                                 Excluded_Sources_Htable.Set
6980
                                   (Project.Excluded, File_Name, FF);
6981
 
6982
                                 if Current_Verbosity = High then
6983
                                    Write_Str ("     excluded source """);
6984
                                    Write_Str (Get_Name_String (File_Name));
6985
                                    Write_Line ("""");
6986
                                 end if;
6987
 
6988
                                 --  Will mark the file as removed, but we
6989
                                 --  still need to add it to the list: if we
6990
                                 --  don't, the file will not appear in the
6991
                                 --  mapping file and will cause the compiler
6992
                                 --  to fail.
6993
 
6994
                                 To_Remove := True;
6995
                              end if;
6996
                           end if;
6997
 
6998
                           Check_File
6999
                             (Project           => Project,
7000
                              Source_Dir_Rank   => Num_Nod.Number,
7001
                              Data              => Data,
7002
                              Path              => Path,
7003
                              File_Name         => File_Name,
7004
                              Locally_Removed   => To_Remove,
7005
                              Display_File_Name => Display_File_Name,
7006
                              For_All_Sources   => For_All_Sources);
7007
                        end;
7008
                     end if;
7009
                  end loop;
7010
 
7011
                  Close (Dir);
7012
               end;
7013
            end if;
7014
 
7015
         exception
7016
            when Directory_Error =>
7017
               null;
7018
         end;
7019
 
7020
         Source_Dir := Element.Next;
7021
         Src_Dir_Rank := Num_Nod.Next;
7022
      end loop;
7023
 
7024
      if Current_Verbosity = High then
7025
         Write_Line ("end Looking for sources.");
7026
      end if;
7027
   end Search_Directories;
7028
 
7029
   ----------------------------
7030
   -- Load_Naming_Exceptions --
7031
   ----------------------------
7032
 
7033
   procedure Load_Naming_Exceptions
7034
     (Project : in out Project_Processing_Data;
7035
      Data    : in out Tree_Processing_Data)
7036
   is
7037
      Source : Source_Id;
7038
      Iter   : Source_Iterator;
7039
 
7040
   begin
7041
      Iter := For_Each_Source (Data.Tree, Project.Project);
7042
      loop
7043
         Source := Prj.Element (Iter);
7044
         exit when Source = No_Source;
7045
 
7046
         --  An excluded file cannot also be an exception file name
7047
 
7048
         if Excluded_Sources_Htable.Get (Project.Excluded, Source.File) /=
7049
                                                                 No_File_Found
7050
         then
7051
            Error_Msg_File_1 := Source.File;
7052
            Error_Msg
7053
              (Data.Flags,
7054
               "{ cannot be both excluded and an exception file name",
7055
               No_Location, Project.Project);
7056
         end if;
7057
 
7058
         if Current_Verbosity = High then
7059
            Write_Str ("Naming exception: Putting source file ");
7060
            Write_Str (Get_Name_String (Source.File));
7061
            Write_Line (" in Source_Names");
7062
         end if;
7063
 
7064
         Source_Names_Htable.Set
7065
           (Project.Source_Names,
7066
            K => Source.File,
7067
            E => Name_Location'
7068
                  (Name     => Source.File,
7069
                   Location => No_Location,
7070
                   Source   => Source,
7071
                   Found    => False));
7072
 
7073
         --  If this is an Ada exception, record in table Unit_Exceptions
7074
 
7075
         if Source.Unit /= No_Unit_Index then
7076
            declare
7077
               Unit_Except : Unit_Exception :=
7078
                 Unit_Exceptions_Htable.Get
7079
                   (Project.Unit_Exceptions, Source.Unit.Name);
7080
 
7081
            begin
7082
               Unit_Except.Name := Source.Unit.Name;
7083
 
7084
               if Source.Kind = Spec then
7085
                  Unit_Except.Spec := Source.File;
7086
               else
7087
                  Unit_Except.Impl := Source.File;
7088
               end if;
7089
 
7090
               Unit_Exceptions_Htable.Set
7091
                 (Project.Unit_Exceptions, Source.Unit.Name, Unit_Except);
7092
            end;
7093
         end if;
7094
 
7095
         Next (Iter);
7096
      end loop;
7097
   end Load_Naming_Exceptions;
7098
 
7099
   ----------------------
7100
   -- Look_For_Sources --
7101
   ----------------------
7102
 
7103
   procedure Look_For_Sources
7104
     (Project : in out Project_Processing_Data;
7105
      Data    : in out Tree_Processing_Data)
7106
   is
7107
      Object_Files : Object_File_Names_Htable.Instance;
7108
      Iter : Source_Iterator;
7109
      Src  : Source_Id;
7110
 
7111
      procedure Check_Object (Src : Source_Id);
7112
      --  Check if object file name of Src is already used in the project tree,
7113
      --  and report an error if so.
7114
 
7115
      procedure Check_Object_Files;
7116
      --  Check that no two sources of this project have the same object file
7117
 
7118
      procedure Mark_Excluded_Sources;
7119
      --  Mark as such the sources that are declared as excluded
7120
 
7121
      ------------------
7122
      -- Check_Object --
7123
      ------------------
7124
 
7125
      procedure Check_Object (Src : Source_Id) is
7126
         Source : Source_Id;
7127
 
7128
      begin
7129
         Source := Object_File_Names_Htable.Get (Object_Files, Src.Object);
7130
 
7131
         --  We cannot just check on "Source /= Src", since we might have
7132
         --  two different entries for the same file (and since that's
7133
         --  the same file it is expected that it has the same object)
7134
 
7135
         if Source /= No_Source
7136
           and then Source.Path /= Src.Path
7137
         then
7138
            Error_Msg_File_1 := Src.File;
7139
            Error_Msg_File_2 := Source.File;
7140
            Error_Msg
7141
              (Data.Flags,
7142
               "{ and { have the same object file name",
7143
               No_Location, Project.Project);
7144
 
7145
         else
7146
            Object_File_Names_Htable.Set (Object_Files, Src.Object, Src);
7147
         end if;
7148
      end Check_Object;
7149
 
7150
      ---------------------------
7151
      -- Mark_Excluded_Sources --
7152
      ---------------------------
7153
 
7154
      procedure Mark_Excluded_Sources is
7155
         Source   : Source_Id := No_Source;
7156
         Excluded : File_Found;
7157
         Proj     : Project_Id;
7158
 
7159
      begin
7160
         --  Minor optimization: if there are no excluded files, no need to
7161
         --  traverse the list of sources. We cannot however also check whether
7162
         --  the existing exceptions have ".Found" set to True (indicating we
7163
         --  found them before) because we need to do some final processing on
7164
         --  them in any case.
7165
 
7166
         if Excluded_Sources_Htable.Get_First (Project.Excluded) /=
7167
                                                             No_File_Found
7168
         then
7169
            Proj := Project.Project;
7170
            while Proj /= No_Project loop
7171
               Iter := For_Each_Source (Data.Tree, Proj);
7172
               while Prj.Element (Iter) /= No_Source loop
7173
                  Source   := Prj.Element (Iter);
7174
                  Excluded := Excluded_Sources_Htable.Get
7175
                    (Project.Excluded, Source.File);
7176
 
7177
                  if Excluded /= No_File_Found then
7178
                     Source.Locally_Removed := True;
7179
                     Source.In_Interfaces   := False;
7180
 
7181
                     if Current_Verbosity = High then
7182
                        Write_Str ("Removing file ");
7183
                        Write_Line
7184
                          (Get_Name_String (Excluded.File)
7185
                           & " " & Get_Name_String (Source.Project.Name));
7186
                     end if;
7187
 
7188
                     Excluded_Sources_Htable.Remove
7189
                       (Project.Excluded, Source.File);
7190
                  end if;
7191
 
7192
                  Next (Iter);
7193
               end loop;
7194
 
7195
               Proj := Proj.Extends;
7196
            end loop;
7197
         end if;
7198
 
7199
         --  If we have any excluded element left, that means we did not find
7200
         --  the source file
7201
 
7202
         Excluded := Excluded_Sources_Htable.Get_First (Project.Excluded);
7203
         while Excluded /= No_File_Found loop
7204
            if not Excluded.Found then
7205
 
7206
               --  Check if the file belongs to another imported project to
7207
               --  provide a better error message.
7208
 
7209
               Src := Find_Source
7210
                 (In_Tree          => Data.Tree,
7211
                  Project          => Project.Project,
7212
                  In_Imported_Only => True,
7213
                  Base_Name        => Excluded.File);
7214
 
7215
               Err_Vars.Error_Msg_File_1 := Excluded.File;
7216
 
7217
               if Src = No_Source then
7218
                  Error_Msg
7219
                    (Data.Flags,
7220
                     "unknown file {", Excluded.Location, Project.Project);
7221
               else
7222
                  Error_Msg
7223
                    (Data.Flags,
7224
                     "cannot remove a source from an imported project: {",
7225
                     Excluded.Location, Project.Project);
7226
               end if;
7227
            end if;
7228
 
7229
            Excluded := Excluded_Sources_Htable.Get_Next (Project.Excluded);
7230
         end loop;
7231
      end Mark_Excluded_Sources;
7232
 
7233
      ------------------------
7234
      -- Check_Object_Files --
7235
      ------------------------
7236
 
7237
      procedure Check_Object_Files is
7238
         Iter    : Source_Iterator;
7239
         Src_Id  : Source_Id;
7240
         Src_Ind : Source_File_Index;
7241
 
7242
      begin
7243
         Iter := For_Each_Source (Data.Tree);
7244
         loop
7245
            Src_Id := Prj.Element (Iter);
7246
            exit when Src_Id = No_Source;
7247
 
7248
            if Is_Compilable (Src_Id)
7249
              and then Src_Id.Language.Config.Object_Generated
7250
              and then Is_Extending (Project.Project, Src_Id.Project)
7251
            then
7252
               if Src_Id.Unit = No_Unit_Index then
7253
                  if Src_Id.Kind = Impl then
7254
                     Check_Object (Src_Id);
7255
                  end if;
7256
 
7257
               else
7258
                  case Src_Id.Kind is
7259
                     when Spec =>
7260
                        if Other_Part (Src_Id) = No_Source then
7261
                           Check_Object (Src_Id);
7262
                        end if;
7263
 
7264
                     when Sep =>
7265
                        null;
7266
 
7267
                     when Impl =>
7268
                        if Other_Part (Src_Id) /= No_Source then
7269
                           Check_Object (Src_Id);
7270
 
7271
                        else
7272
                           --  Check if it is a subunit
7273
 
7274
                           Src_Ind :=
7275
                             Sinput.P.Load_Project_File
7276
                               (Get_Name_String (Src_Id.Path.Name));
7277
 
7278
                           if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7279
                              Override_Kind (Src_Id, Sep);
7280
                           else
7281
                              Check_Object (Src_Id);
7282
                           end if;
7283
                        end if;
7284
                  end case;
7285
               end if;
7286
            end if;
7287
 
7288
            Next (Iter);
7289
         end loop;
7290
      end Check_Object_Files;
7291
 
7292
   --  Start of processing for Look_For_Sources
7293
 
7294
   begin
7295
      Find_Excluded_Sources (Project, Data);
7296
 
7297
      if Project.Project.Languages /= No_Language_Index then
7298
         Load_Naming_Exceptions (Project, Data);
7299
         Find_Sources (Project, Data);
7300
         Mark_Excluded_Sources;
7301
         Check_Object_Files;
7302
      end if;
7303
 
7304
      Object_File_Names_Htable.Reset (Object_Files);
7305
   end Look_For_Sources;
7306
 
7307
   ------------------
7308
   -- Path_Name_Of --
7309
   ------------------
7310
 
7311
   function Path_Name_Of
7312
     (File_Name : File_Name_Type;
7313
      Directory : Path_Name_Type) return String
7314
   is
7315
      Result        : String_Access;
7316
      The_Directory : constant String := Get_Name_String (Directory);
7317
 
7318
   begin
7319
      Get_Name_String (File_Name);
7320
      Result :=
7321
        Locate_Regular_File
7322
          (File_Name => Name_Buffer (1 .. Name_Len),
7323
           Path      => The_Directory);
7324
 
7325
      if Result = null then
7326
         return "";
7327
      else
7328
         declare
7329
            R : String := Result.all;
7330
         begin
7331
            Free (Result);
7332
            Canonical_Case_File_Name (R);
7333
            return R;
7334
         end;
7335
      end if;
7336
   end Path_Name_Of;
7337
 
7338
   -------------------
7339
   -- Remove_Source --
7340
   -------------------
7341
 
7342
   procedure Remove_Source
7343
     (Id          : Source_Id;
7344
      Replaced_By : Source_Id)
7345
   is
7346
      Source : Source_Id;
7347
 
7348
   begin
7349
      if Current_Verbosity = High then
7350
         Write_Str ("Removing source ");
7351
         Write_Str (Get_Name_String (Id.File));
7352
 
7353
         if Id.Index /= 0 then
7354
            Write_Str (" at" & Id.Index'Img);
7355
         end if;
7356
 
7357
         Write_Eol;
7358
      end if;
7359
 
7360
      if Replaced_By /= No_Source then
7361
         Id.Replaced_By := Replaced_By;
7362
         Replaced_By.Declared_In_Interfaces := Id.Declared_In_Interfaces;
7363
      end if;
7364
 
7365
      Id.In_Interfaces := False;
7366
      Id.Locally_Removed := True;
7367
 
7368
      --  ??? Should we remove the source from the unit ? The file is not used,
7369
      --  so probably should not be referenced from the unit. On the other hand
7370
      --  it might give useful additional info
7371
      --        if Id.Unit /= null then
7372
      --           Id.Unit.File_Names (Id.Kind) := null;
7373
      --        end if;
7374
 
7375
      Source := Id.Language.First_Source;
7376
 
7377
      if Source = Id then
7378
         Id.Language.First_Source := Id.Next_In_Lang;
7379
 
7380
      else
7381
         while Source.Next_In_Lang /= Id loop
7382
            Source := Source.Next_In_Lang;
7383
         end loop;
7384
 
7385
         Source.Next_In_Lang := Id.Next_In_Lang;
7386
      end if;
7387
   end Remove_Source;
7388
 
7389
   -----------------------
7390
   -- Report_No_Sources --
7391
   -----------------------
7392
 
7393
   procedure Report_No_Sources
7394
     (Project      : Project_Id;
7395
      Lang_Name    : String;
7396
      Data         : Tree_Processing_Data;
7397
      Location     : Source_Ptr;
7398
      Continuation : Boolean := False)
7399
   is
7400
   begin
7401
      case Data.Flags.When_No_Sources is
7402
         when Silent =>
7403
            null;
7404
 
7405
         when Warning | Error =>
7406
            declare
7407
               Msg : constant String :=
7408
                       "<there are no " &
7409
                       Lang_Name &
7410
                       " sources in this project";
7411
 
7412
            begin
7413
               Error_Msg_Warn := Data.Flags.When_No_Sources = Warning;
7414
 
7415
               if Continuation then
7416
                  Error_Msg (Data.Flags, "\" & Msg, Location, Project);
7417
               else
7418
                  Error_Msg (Data.Flags, Msg, Location, Project);
7419
               end if;
7420
            end;
7421
      end case;
7422
   end Report_No_Sources;
7423
 
7424
   ----------------------
7425
   -- Show_Source_Dirs --
7426
   ----------------------
7427
 
7428
   procedure Show_Source_Dirs
7429
     (Project : Project_Id;
7430
      In_Tree : Project_Tree_Ref)
7431
   is
7432
      Current : String_List_Id;
7433
      Element : String_Element;
7434
 
7435
   begin
7436
      Write_Line ("Source_Dirs:");
7437
 
7438
      Current := Project.Source_Dirs;
7439
      while Current /= Nil_String loop
7440
         Element := In_Tree.String_Elements.Table (Current);
7441
         Write_Str  ("   ");
7442
         Write_Line (Get_Name_String (Element.Value));
7443
         Current := Element.Next;
7444
      end loop;
7445
 
7446
      Write_Line ("end Source_Dirs.");
7447
   end Show_Source_Dirs;
7448
 
7449
   ---------------------------
7450
   -- Process_Naming_Scheme --
7451
   ---------------------------
7452
 
7453
   procedure Process_Naming_Scheme
7454
     (Tree         : Project_Tree_Ref;
7455
      Root_Project : Project_Id;
7456
      Flags        : Processing_Flags)
7457
   is
7458
      procedure Recursive_Check
7459
        (Project : Project_Id;
7460
         Data    : in out Tree_Processing_Data);
7461
      --  Check_Naming_Scheme for the project
7462
 
7463
      ---------------------
7464
      -- Recursive_Check --
7465
      ---------------------
7466
 
7467
      procedure Recursive_Check
7468
        (Project : Project_Id;
7469
         Data    : in out Tree_Processing_Data)
7470
      is
7471
      begin
7472
         if Verbose_Mode then
7473
            Write_Str ("Processing_Naming_Scheme for project """);
7474
            Write_Str (Get_Name_String (Project.Name));
7475
            Write_Line ("""");
7476
         end if;
7477
 
7478
         Prj.Nmsc.Check (Project, Data);
7479
      end Recursive_Check;
7480
 
7481
      procedure Check_All_Projects is new
7482
        For_Every_Project_Imported (Tree_Processing_Data, Recursive_Check);
7483
 
7484
      Data : Tree_Processing_Data;
7485
 
7486
   --  Start of processing for Process_Naming_Scheme
7487
   begin
7488
      Initialize (Data, Tree => Tree, Flags => Flags);
7489
      Check_All_Projects (Root_Project, Data, Imported_First => True);
7490
      Free (Data);
7491
   end Process_Naming_Scheme;
7492
 
7493
end Prj.Nmsc;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.