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