1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2000-2010, Free Software Foundation, Inc. --
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. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with GNAT.Case_Util; use GNAT.Case_Util;
27 with GNAT.Directory_Operations; use GNAT.Directory_Operations;
28 with GNAT.Dynamic_HTables;
31 with Err_Vars; use Err_Vars;
33 with Osint; use Osint;
34 with Output; use Output;
36 with Prj.Err; use Prj.Err;
37 with Prj.Util; use Prj.Util;
39 with Snames; use Snames;
40 with Targparm; use Targparm;
42 with Ada.Characters.Handling; use Ada.Characters.Handling;
43 with Ada.Directories; use Ada.Directories;
44 with Ada.Strings; use Ada.Strings;
45 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
46 with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
48 package body Prj.Nmsc is
50 No_Continuation_String : aliased String := "";
51 Continuation_String : aliased String := "\";
52 -- Used in Check_Library for continuation error messages at the same
55 type Name_Location is record
56 Name : File_Name_Type; -- ??? duplicates the key
57 Location : Source_Ptr;
58 Source : Source_Id := No_Source;
59 Listed : Boolean := False;
60 Found : Boolean := False;
63 No_Name_Location : constant Name_Location :=
65 Location => No_Location,
70 package Source_Names_Htable is new GNAT.Dynamic_HTables.Simple_HTable
71 (Header_Num => Header_Num,
72 Element => Name_Location,
73 No_Element => No_Name_Location,
74 Key => File_Name_Type,
77 -- File name information found in string list attribute (Source_Files or
78 -- Source_List_File). Except is set to True if source is a naming exception
79 -- in the project. Used to check that all referenced files were indeed
82 type Unit_Exception is record
83 Name : Name_Id; -- ??? duplicates the key
84 Spec : File_Name_Type;
85 Impl : File_Name_Type;
88 No_Unit_Exception : constant Unit_Exception := (No_Name, No_File, No_File);
90 package Unit_Exceptions_Htable is new GNAT.Dynamic_HTables.Simple_HTable
91 (Header_Num => Header_Num,
92 Element => Unit_Exception,
93 No_Element => No_Unit_Exception,
97 -- Record special naming schemes for Ada units (name of spec file and name
98 -- of implementation file). The elements in this list come from the naming
99 -- exceptions specified in the project files.
101 type File_Found is record
102 File : File_Name_Type := No_File;
103 Found : Boolean := False;
104 Location : Source_Ptr := No_Location;
107 No_File_Found : constant File_Found := (No_File, False, No_Location);
109 package Excluded_Sources_Htable is new GNAT.Dynamic_HTables.Simple_HTable
110 (Header_Num => Header_Num,
111 Element => File_Found,
112 No_Element => No_File_Found,
113 Key => File_Name_Type,
116 -- A hash table to store the base names of excluded files, if any
118 package Object_File_Names_Htable is new GNAT.Dynamic_HTables.Simple_HTable
119 (Header_Num => Header_Num,
120 Element => Source_Id,
121 No_Element => No_Source,
122 Key => File_Name_Type,
125 -- A hash table to store the object file names for a project, to check that
126 -- two different sources have different object file names.
128 type Project_Processing_Data is record
129 Project : Project_Id;
130 Source_Names : Source_Names_Htable.Instance;
131 Unit_Exceptions : Unit_Exceptions_Htable.Instance;
132 Excluded : Excluded_Sources_Htable.Instance;
134 Source_List_File_Location : Source_Ptr;
135 -- Location of the Source_List_File attribute, for error messages
137 -- This is similar to Tree_Processing_Data, but contains project-specific
138 -- information which is only useful while processing the project, and can
139 -- be discarded as soon as we have finished processing the project
141 package Files_Htable is new GNAT.Dynamic_HTables.Simple_HTable
142 (Header_Num => Header_Num,
143 Element => Source_Id,
144 No_Element => No_Source,
145 Key => File_Name_Type,
148 -- Mapping from base file names to Source_Id (containing full info about
151 type Tree_Processing_Data is record
152 Tree : Project_Tree_Ref;
153 Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
154 File_To_Source : Files_Htable.Instance;
155 Flags : Prj.Processing_Flags;
157 -- Temporary data which is needed while parsing a project. It does not need
158 -- to be kept in memory once a project has been fully loaded, but is
159 -- necessary while performing consistency checks (duplicate sources,...)
160 -- This data must be initialized before processing any project, and the
161 -- same data is used for processing all projects in the tree.
163 type Lib_Data is record
168 package Lib_Data_Table is new GNAT.Table
169 (Table_Component_Type => Lib_Data,
170 Table_Index_Type => Natural,
171 Table_Low_Bound => 1,
173 Table_Increment => 100);
174 -- A table to record library names in order to check that two library
175 -- projects do not have the same library names.
178 (Data : out Tree_Processing_Data;
179 Tree : Project_Tree_Ref;
180 Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
181 Flags : Prj.Processing_Flags);
184 procedure Free (Data : in out Tree_Processing_Data);
185 -- Free the memory occupied by Data
188 (Project : Project_Id;
189 Data : in out Tree_Processing_Data);
190 -- Process the naming scheme for a single project
193 (Data : in out Project_Processing_Data;
194 Project : Project_Id);
195 procedure Free (Data : in out Project_Processing_Data);
196 -- Initialize or free memory for a project-specific data
198 procedure Find_Excluded_Sources
199 (Project : in out Project_Processing_Data;
200 Data : in out Tree_Processing_Data);
201 -- Find the list of files that should not be considered as source files
202 -- for this project. Sets the list in the Project.Excluded_Sources_Htable.
204 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind);
205 -- Override the reference kind for a source file. This properly updates
206 -- the unit data if necessary.
208 procedure Load_Naming_Exceptions
209 (Project : in out Project_Processing_Data;
210 Data : in out Tree_Processing_Data);
211 -- All source files in Data.First_Source are considered as naming
212 -- exceptions, and copied into the Source_Names and Unit_Exceptions tables
215 type Search_Type is (Search_Files, Search_Directories);
216 pragma Unreferenced (Search_Files);
219 with procedure Callback
220 (Path_Id : Path_Name_Type;
221 Display_Path_Id : Path_Name_Type;
222 Pattern_Index : Natural);
223 procedure Expand_Subdirectory_Pattern
224 (Project : Project_Id;
225 Data : in out Tree_Processing_Data;
226 Patterns : String_List_Id;
227 Search_For : Search_Type;
228 Resolve_Links : Boolean);
229 -- Search the subdirectories of Project's directory for files or
230 -- directories that match the globbing patterns found in Patterns (for
231 -- instance "**/*.adb"). Typically, Patterns will be the value of the
232 -- Source_Dirs or Excluded_Source_Dirs attributes.
233 -- Every time such a file or directory is found, the callback is called.
234 -- Resolve_Links indicates whether we should resolve links while
235 -- normalizing names.
236 -- In the callback, Pattern_Index is the index within Patterns where the
237 -- expanded pattern was found (1 for the first element of Patterns and
238 -- all its matching directories, then 2,...).
239 -- We use a generic and not an access-to-subprogram because in some cases
240 -- this code is compiled with the restriction No_Implicit_Dynamic_Code
244 Data : in out Tree_Processing_Data;
245 Project : Project_Id;
246 Source_Dir_Rank : Natural;
247 Lang_Id : Language_Ptr;
249 File_Name : File_Name_Type;
250 Display_File : File_Name_Type;
251 Naming_Exception : Boolean := False;
252 Path : Path_Information := No_Path_Information;
253 Alternate_Languages : Language_List := null;
254 Unit : Name_Id := No_Name;
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
262 -- If Path is specified, the file is also added to Source_Paths_HT.
264 -- Location is used for error messages
266 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type;
267 -- Same as Osint.Canonical_Case_File_Name but applies to Name_Id.
268 -- This alters Name_Buffer
270 function Suffix_Matches
272 Suffix : File_Name_Type) return Boolean;
273 -- True if the file name ends with the given suffix. Always returns False
274 -- if Suffix is No_Name.
276 procedure Replace_Into_Name_Buffer
279 Replacement : Character);
280 -- Copy Str into Name_Buffer, replacing Pattern with Replacement. Str is
281 -- converted to lower-case at the same time.
283 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
284 -- Check that a name is a valid Ada unit name
286 procedure Check_Package_Naming
287 (Project : Project_Id;
288 Data : in out Tree_Processing_Data);
289 -- Check the naming scheme part of Data, and initialize the naming scheme
290 -- data in the config of the various languages.
292 procedure Check_Configuration
293 (Project : Project_Id;
294 Data : in out Tree_Processing_Data);
295 -- Check the configuration attributes for the project
297 procedure Check_If_Externally_Built
298 (Project : Project_Id;
299 Data : in out Tree_Processing_Data);
300 -- Check attribute Externally_Built of project Project in project tree
301 -- Data.Tree and modify its data Data if it has the value "true".
303 procedure Check_Interfaces
304 (Project : Project_Id;
305 Data : in out Tree_Processing_Data);
306 -- If a list of sources is specified in attribute Interfaces, set
307 -- In_Interfaces only for the sources specified in the list.
309 procedure Check_Library_Attributes
310 (Project : Project_Id;
311 Data : in out Tree_Processing_Data);
312 -- Check the library attributes of project Project in project tree
313 -- and modify its data Data accordingly.
315 procedure Check_Aggregate_Project
316 (Project : Project_Id;
317 Data : in out Tree_Processing_Data);
318 -- Check aggregate projects attributes
320 procedure Check_Abstract_Project
321 (Project : Project_Id;
322 Data : in out Tree_Processing_Data);
323 -- Check abstract projects attributes
325 procedure Check_Programming_Languages
326 (Project : Project_Id;
327 Data : in out Tree_Processing_Data);
328 -- Check attribute Languages for the project with data Data in project
329 -- tree Data.Tree and set the components of Data for all the programming
330 -- languages indicated in attribute Languages, if any.
332 procedure Check_Stand_Alone_Library
333 (Project : Project_Id;
334 Data : in out Tree_Processing_Data);
335 -- Check if project Project in project tree Data.Tree is a Stand-Alone
336 -- Library project, and modify its data Data accordingly if it is one.
338 function Compute_Directory_Last (Dir : String) return Natural;
339 -- Return the index of the last significant character in Dir. This is used
340 -- to avoid duplicate '/' (slash) characters at the end of directory names.
342 procedure Search_Directories
343 (Project : in out Project_Processing_Data;
344 Data : in out Tree_Processing_Data;
345 For_All_Sources : Boolean);
346 -- Search the source directories to find the sources. If For_All_Sources is
347 -- True, check each regular file name against the naming schemes of the
348 -- various languages. Otherwise consider only the file names in hash table
349 -- Source_Names. If Allow_Duplicate_Basenames then files with identical
350 -- base names are permitted within a project for source-based languages
351 -- (never for unit based languages).
354 (Project : in out Project_Processing_Data;
355 Data : in out Tree_Processing_Data;
356 Source_Dir_Rank : Natural;
357 Path : Path_Name_Type;
358 Display_Path : Path_Name_Type;
359 File_Name : File_Name_Type;
360 Display_File_Name : File_Name_Type;
361 Locally_Removed : Boolean;
362 For_All_Sources : Boolean);
363 -- Check if file File_Name is a valid source of the project. This is used
364 -- in multi-language mode only. When the file matches one of the naming
365 -- schemes, it is added to various htables through Add_Source and to
366 -- Source_Paths_Htable.
368 -- File_Name is the same as Display_File_Name, but has been normalized.
369 -- They do not include the directory information.
371 -- Path and Display_Path on the other hand are the full path to the file.
372 -- Path must have been normalized (canonical casing and possibly links
375 -- Source_Directory is the directory in which the file was found. It is
376 -- neither normalized nor has had links resolved, and must not end with a
377 -- a directory separator, to avoid duplicates later on.
379 -- If For_All_Sources is True, then all possible file names are analyzed
380 -- otherwise only those currently set in the Source_Names hash table.
382 procedure Check_File_Naming_Schemes
383 (In_Tree : Project_Tree_Ref;
384 Project : Project_Processing_Data;
385 File_Name : File_Name_Type;
386 Alternate_Languages : out Language_List;
387 Language : out Language_Ptr;
388 Display_Language_Name : out Name_Id;
390 Lang_Kind : out Language_Kind;
391 Kind : out Source_Kind);
392 -- Check if the file name File_Name conforms to one of the naming schemes
393 -- of the project. If the file does not match one of the naming schemes,
394 -- set Language to No_Language_Index. Filename is the name of the file
395 -- being investigated. It has been normalized (case-folded). File_Name is
398 procedure Get_Directories
399 (Project : Project_Id;
400 Data : in out Tree_Processing_Data);
401 -- Get the object directory, the exec directory and the source directories
405 (Project : Project_Id;
406 Data : in out Tree_Processing_Data);
407 -- Get the mains of a project from attribute Main, if it exists, and put
408 -- them in the project data.
410 procedure Get_Sources_From_File
412 Location : Source_Ptr;
413 Project : in out Project_Processing_Data;
414 Data : in out Tree_Processing_Data);
415 -- Get the list of sources from a text file and put them in hash table
418 procedure Find_Sources
419 (Project : in out Project_Processing_Data;
420 Data : in out Tree_Processing_Data);
421 -- Process the Source_Files and Source_List_File attributes, and store the
422 -- list of source files into the Source_Names htable. When these attributes
423 -- are not defined, find all files matching the naming schemes in the
424 -- source directories. If Allow_Duplicate_Basenames, then files with the
425 -- same base names are authorized within a project for source-based
426 -- languages (never for unit based languages)
428 procedure Compute_Unit_Name
429 (File_Name : File_Name_Type;
430 Naming : Lang_Naming_Data;
431 Kind : out Source_Kind;
433 Project : Project_Processing_Data;
434 In_Tree : Project_Tree_Ref);
435 -- Check whether the file matches the naming scheme. If it does,
436 -- compute its unit name. If Unit is set to No_Name on exit, none of the
437 -- other out parameters are relevant.
439 procedure Check_Illegal_Suffix
440 (Project : Project_Id;
441 Suffix : File_Name_Type;
442 Dot_Replacement : File_Name_Type;
443 Attribute_Name : String;
444 Location : Source_Ptr;
445 Data : in out Tree_Processing_Data);
446 -- Display an error message if the given suffix is illegal for some reason.
447 -- The name of the attribute we are testing is specified in Attribute_Name,
448 -- which is used in the error message. Location is the location where the
449 -- suffix is defined.
451 procedure Locate_Directory
452 (Project : Project_Id;
453 Name : File_Name_Type;
454 Path : out Path_Information;
455 Dir_Exists : out Boolean;
456 Data : in out Tree_Processing_Data;
457 Create : String := "";
458 Location : Source_Ptr := No_Location;
459 Must_Exist : Boolean := True;
460 Externally_Built : Boolean := False);
461 -- Locate a directory. Name is the directory name. Relative paths are
462 -- resolved relative to the project's directory. If the directory does not
463 -- exist and Setup_Projects is True and Create is a non null string, an
464 -- attempt is made to create the directory. If the directory does not
465 -- exist, it is either created if Setup_Projects is False (and then
466 -- returned), or simply returned without checking for its existence (if
467 -- Must_Exist is False) or No_Path_Information is returned. In all cases,
468 -- Dir_Exists indicates whether the directory now exists. Create is also
469 -- used for debugging traces to show which path we are computing.
471 procedure Look_For_Sources
472 (Project : in out Project_Processing_Data;
473 Data : in out Tree_Processing_Data);
474 -- Find all the sources of project Project in project tree Data.Tree and
475 -- update its Data accordingly. This assumes that the special naming
476 -- exceptions have already been processed.
478 function Path_Name_Of
479 (File_Name : File_Name_Type;
480 Directory : Path_Name_Type) return String;
481 -- Returns the path name of a (non project) file. Returns an empty string
482 -- if file cannot be found.
484 procedure Remove_Source
486 Replaced_By : Source_Id);
487 -- Remove a file from the list of sources of a project. This might be
488 -- because the file is replaced by another one in an extending project,
489 -- or because a file was added as a naming exception but was not found
492 procedure Report_No_Sources
493 (Project : Project_Id;
495 Data : Tree_Processing_Data;
496 Location : Source_Ptr;
497 Continuation : Boolean := False);
498 -- Report an error or a warning depending on the value of When_No_Sources
499 -- when there are no sources for language Lang_Name.
501 procedure Show_Source_Dirs
502 (Project : Project_Id; In_Tree : Project_Tree_Ref);
503 -- List all the source directories of a project
505 procedure Write_Attr (Name, Value : String);
506 -- Debug print a value for a specific property. Does nothing when not in
509 procedure Error_Or_Warning
510 (Flags : Processing_Flags;
511 Kind : Error_Warning;
513 Location : Source_Ptr;
514 Project : Project_Id);
515 -- Emits either an error or warning message (or nothing), depending on Kind
517 ----------------------
518 -- Error_Or_Warning --
519 ----------------------
521 procedure Error_Or_Warning
522 (Flags : Processing_Flags;
523 Kind : Error_Warning;
525 Location : Source_Ptr;
526 Project : Project_Id) is
529 when Error => Error_Msg (Flags, Msg, Location, Project);
530 when Warning => Error_Msg (Flags, "?" & Msg, Location, Project);
533 end Error_Or_Warning;
535 ------------------------------
536 -- Replace_Into_Name_Buffer --
537 ------------------------------
539 procedure Replace_Into_Name_Buffer
542 Replacement : Character)
544 Max : constant Integer := Str'Last - Pattern'Length + 1;
551 while J <= Str'Last loop
552 Name_Len := Name_Len + 1;
555 and then Str (J .. J + Pattern'Length - 1) = Pattern
557 Name_Buffer (Name_Len) := Replacement;
558 J := J + Pattern'Length;
561 Name_Buffer (Name_Len) := GNAT.Case_Util.To_Lower (Str (J));
565 end Replace_Into_Name_Buffer;
571 function Suffix_Matches
573 Suffix : File_Name_Type) return Boolean
575 Min_Prefix_Length : Natural := 0;
578 if Suffix = No_File or else Suffix = Empty_File then
583 Suf : String := Get_Name_String (Suffix);
586 -- On non case-sensitive systems, use proper suffix casing
588 Canonical_Case_File_Name (Suf);
590 -- The file name must end with the suffix (which is not an extension)
591 -- For instance a suffix "configure.in" must match a file with the
592 -- same name. To avoid dummy cases, though, a suffix starting with
593 -- '.' requires a file that is at least one character longer ('.cpp'
594 -- should not match a file with the same name)
596 if Suf (Suf'First) = '.' then
597 Min_Prefix_Length := 1;
600 return Filename'Length >= Suf'Length + Min_Prefix_Length
602 (Filename'Last - Suf'Length + 1 .. Filename'Last) = Suf;
610 procedure Write_Attr (Name, Value : String) is
612 if Current_Verbosity = High then
613 Write_Str (" " & Name & " = """);
626 Data : in out Tree_Processing_Data;
627 Project : Project_Id;
628 Source_Dir_Rank : Natural;
629 Lang_Id : Language_Ptr;
631 File_Name : File_Name_Type;
632 Display_File : File_Name_Type;
633 Naming_Exception : Boolean := False;
634 Path : Path_Information := No_Path_Information;
635 Alternate_Languages : Language_List := null;
636 Unit : Name_Id := No_Name;
638 Locally_Removed : Boolean := False;
639 Location : Source_Ptr := No_Location)
641 Config : constant Language_Config := Lang_Id.Config;
645 Prev_Unit : Unit_Index := No_Unit_Index;
647 Source_To_Replace : Source_Id := No_Source;
650 -- Check if the same file name or unit is used in the prj tree
654 if Unit /= No_Name then
655 Prev_Unit := Units_Htable.Get (Data.Tree.Units_HT, Unit);
658 if Prev_Unit /= No_Unit_Index
659 and then (Kind = Impl or else Kind = Spec)
660 and then Prev_Unit.File_Names (Kind) /= null
662 -- Suspicious, we need to check later whether this is authorized
665 Source := Prev_Unit.File_Names (Kind);
668 Source := Files_Htable.Get (Data.File_To_Source, File_Name);
670 if Source /= No_Source
671 and then Source.Index = Index
677 -- Duplication of file/unit in same project is allowed if order of
678 -- source directories is known.
680 if Add_Src = False then
683 if Project = Source.Project then
684 if Prev_Unit = No_Unit_Index then
685 if Data.Flags.Allow_Duplicate_Basenames then
688 elsif Source_Dir_Rank /= Source.Source_Dir_Rank then
692 Error_Msg_File_1 := File_Name;
694 (Data.Flags, "duplicate source file name {",
700 if Source_Dir_Rank /= Source.Source_Dir_Rank then
703 -- We might be seeing the same file through a different path
704 -- (for instance because of symbolic links).
706 elsif Source.Path.Name /= Path.Name then
707 Error_Msg_Name_1 := Unit;
709 (Data.Flags, "duplicate unit %%", Location, Project);
714 -- Do not allow the same unit name in different projects, except
715 -- if one is extending the other.
717 -- For a file based language, the same file name replaces a file
718 -- in a project being extended, but it is allowed to have the same
719 -- file name in unrelated projects.
721 elsif Is_Extending (Project, Source.Project) then
722 if not Locally_Removed then
723 Source_To_Replace := Source;
726 elsif Prev_Unit /= No_Unit_Index
727 and then Prev_Unit.File_Names (Kind) /= null
728 and then not Source.Locally_Removed
730 -- Path is set if this is a source we found on the disk, in which
731 -- case we can provide more explicit error message. Path is unset
732 -- when the source is added from one of the naming exceptions in
735 if Path /= No_Path_Information then
736 Error_Msg_Name_1 := Unit;
739 "unit %% cannot belong to several projects",
742 Error_Msg_Name_1 := Project.Name;
743 Error_Msg_Name_2 := Name_Id (Path.Display_Name);
745 (Data.Flags, "\ project %%, %%", Location, Project);
747 Error_Msg_Name_1 := Source.Project.Name;
748 Error_Msg_Name_2 := Name_Id (Source.Path.Display_Name);
750 (Data.Flags, "\ project %%, %%", Location, Project);
753 Error_Msg_Name_1 := Unit;
754 Error_Msg_Name_2 := Source.Project.Name;
756 (Data.Flags, "unit %% already belongs to project %%",
762 elsif not Source.Locally_Removed
763 and then not Data.Flags.Allow_Duplicate_Basenames
764 and then Lang_Id.Config.Kind = Unit_Based
765 and then Source.Language.Config.Kind = Unit_Based
767 Error_Msg_File_1 := File_Name;
768 Error_Msg_File_2 := File_Name_Type (Source.Project.Name);
771 "{ is already a source of project {", Location, Project);
773 -- Add the file anyway, to avoid further warnings like "language
786 Id := new Source_Data;
788 if Current_Verbosity = High then
789 Write_Str ("Adding source File: ");
790 Write_Str (Get_Name_String (Display_File));
793 Write_Str (" at" & Index'Img);
796 if Lang_Id.Config.Kind = Unit_Based then
797 Write_Str (" Unit: ");
799 -- ??? in gprclean, it seems we sometimes pass an empty Unit name
800 -- (see test extended_projects).
802 if Unit /= No_Name then
803 Write_Str (Get_Name_String (Unit));
806 Write_Str (" Kind: ");
807 Write_Str (Source_Kind'Image (Kind));
813 Id.Project := Project;
814 Id.Location := Location;
815 Id.Source_Dir_Rank := Source_Dir_Rank;
816 Id.Language := Lang_Id;
818 Id.Alternate_Languages := Alternate_Languages;
819 Id.Locally_Removed := Locally_Removed;
821 Id.File := File_Name;
822 Id.Display_File := Display_File;
823 Id.Dep_Name := Dependency_Name
824 (File_Name, Lang_Id.Config.Dependency_Kind);
825 Id.Naming_Exception := Naming_Exception;
826 Id.Object := Object_Name
827 (File_Name, Config.Object_File_Suffix);
828 Id.Switches := Switches_Name (File_Name);
830 -- Add the source id to the Unit_Sources_HT hash table, if the unit name
833 if Unit /= No_Name then
835 -- Note: we might be creating a dummy unit here, when we in fact have
836 -- a separate. For instance, file file-bar.adb will initially be
837 -- assumed to be the IMPL of unit "file.bar". Only later on (in
838 -- Check_Object_Files) will we parse those units that only have an
839 -- impl and no spec to make sure whether we have a Separate in fact
840 -- (that significantly reduces the number of times we need to parse
841 -- the files, since we are then only interested in those with no
842 -- spec). We still need those dummy units in the table, since that's
843 -- the name we find in the ALI file
845 UData := Units_Htable.Get (Data.Tree.Units_HT, Unit);
847 if UData = No_Unit_Index then
848 UData := new Unit_Data;
850 Units_Htable.Set (Data.Tree.Units_HT, Unit, UData);
855 -- Note that this updates Unit information as well
857 Override_Kind (Id, Kind);
860 if Path /= No_Path_Information then
862 Source_Paths_Htable.Set (Data.Tree.Source_Paths_HT, Path.Name, Id);
866 Project.Has_Multi_Unit_Sources := True;
869 -- Add the source to the language list
871 Id.Next_In_Lang := Lang_Id.First_Source;
872 Lang_Id.First_Source := Id;
874 if Source_To_Replace /= No_Source then
875 Remove_Source (Source_To_Replace, Id);
878 Files_Htable.Set (Data.File_To_Source, File_Name, Id);
881 ------------------------------
882 -- Canonical_Case_File_Name --
883 ------------------------------
885 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type is
887 if Osint.File_Names_Case_Sensitive then
888 return File_Name_Type (Name);
890 Get_Name_String (Name);
891 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
894 end Canonical_Case_File_Name;
896 -----------------------------
897 -- Check_Aggregate_Project --
898 -----------------------------
900 procedure Check_Aggregate_Project
901 (Project : Project_Id;
902 Data : in out Tree_Processing_Data)
904 Project_Files : constant Prj.Variable_Value :=
906 (Snames.Name_Project_Files,
907 Project.Decl.Attributes,
910 if Project_Files.Default then
911 Error_Msg_Name_1 := Snames.Name_Project_Files;
914 "Attribute %% must be specified in aggregate project",
915 Project.Location, Project);
917 end Check_Aggregate_Project;
919 ----------------------------
920 -- Check_Abstract_Project --
921 ----------------------------
923 procedure Check_Abstract_Project
924 (Project : Project_Id;
925 Data : in out Tree_Processing_Data)
927 Source_Dirs : constant Variable_Value :=
930 Project.Decl.Attributes, Data.Tree);
931 Source_Files : constant Variable_Value :=
934 Project.Decl.Attributes, Data.Tree);
935 Source_List_File : constant Variable_Value :=
937 (Name_Source_List_File,
938 Project.Decl.Attributes, Data.Tree);
939 Languages : constant Variable_Value :=
942 Project.Decl.Attributes, Data.Tree);
945 if Project.Source_Dirs /= Nil_String then
946 if Source_Dirs.Values = Nil_String
947 and then Source_Files.Values = Nil_String
948 and then Languages.Values = Nil_String
949 and then Source_List_File.Default
951 Project.Source_Dirs := Nil_String;
956 "at least one of Source_Files, Source_Dirs or Languages "
957 & "must be declared empty for an abstract project",
958 Project.Location, Project);
961 end Check_Abstract_Project;
968 (Project : Project_Id;
969 Data : in out Tree_Processing_Data)
971 Prj_Data : Project_Processing_Data;
974 Initialize (Prj_Data, Project);
976 Check_If_Externally_Built (Project, Data);
977 Get_Directories (Project, Data);
978 Check_Programming_Languages (Project, Data);
980 case Project.Qualifier is
981 when Aggregate => Check_Aggregate_Project (Project, Data);
982 when Dry => Check_Abstract_Project (Project, Data);
986 -- Check configuration. This must be done even for gnatmake (even though
987 -- no user configuration file was provided) since the default config we
988 -- generate indicates whether libraries are supported for instance.
990 Check_Configuration (Project, Data);
992 Check_Library_Attributes (Project, Data);
994 if Current_Verbosity = High then
995 Show_Source_Dirs (Project, Data.Tree);
998 Check_Package_Naming (Project, Data);
1000 if Project.Qualifier /= Aggregate then
1001 Look_For_Sources (Prj_Data, Data);
1004 Check_Interfaces (Project, Data);
1006 if Project.Library then
1007 Check_Stand_Alone_Library (Project, Data);
1010 Get_Mains (Project, Data);
1015 --------------------
1016 -- Check_Ada_Name --
1017 --------------------
1019 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
1020 The_Name : String := Name;
1021 Real_Name : Name_Id;
1022 Need_Letter : Boolean := True;
1023 Last_Underscore : Boolean := False;
1024 OK : Boolean := The_Name'Length > 0;
1027 function Is_Reserved (Name : Name_Id) return Boolean;
1028 function Is_Reserved (S : String) return Boolean;
1029 -- Check that the given name is not an Ada 95 reserved word. The reason
1030 -- for the Ada 95 here is that we do not want to exclude the case of an
1031 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
1032 -- name would be rejected anyway by the compiler. That means there is no
1033 -- requirement that the project file parser reject this.
1039 function Is_Reserved (S : String) return Boolean is
1042 Add_Str_To_Name_Buffer (S);
1043 return Is_Reserved (Name_Find);
1050 function Is_Reserved (Name : Name_Id) return Boolean is
1052 if Get_Name_Table_Byte (Name) /= 0
1053 and then Name /= Name_Project
1054 and then Name /= Name_Extends
1055 and then Name /= Name_External
1056 and then Name not in Ada_2005_Reserved_Words
1060 if Current_Verbosity = High then
1061 Write_Str (The_Name);
1062 Write_Line (" is an Ada reserved word.");
1072 -- Start of processing for Check_Ada_Name
1075 To_Lower (The_Name);
1077 Name_Len := The_Name'Length;
1078 Name_Buffer (1 .. Name_Len) := The_Name;
1080 -- Special cases of children of packages A, G, I and S on VMS
1082 if OpenVMS_On_Target
1083 and then Name_Len > 3
1084 and then Name_Buffer (2 .. 3) = "__"
1086 ((Name_Buffer (1) = 'a') or else
1087 (Name_Buffer (1) = 'g') or else
1088 (Name_Buffer (1) = 'i') or else
1089 (Name_Buffer (1) = 's'))
1091 Name_Buffer (2) := '.';
1092 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
1093 Name_Len := Name_Len - 1;
1096 Real_Name := Name_Find;
1098 if Is_Reserved (Real_Name) then
1102 First := The_Name'First;
1104 for Index in The_Name'Range loop
1107 -- We need a letter (at the beginning, and following a dot),
1108 -- but we don't have one.
1110 if Is_Letter (The_Name (Index)) then
1111 Need_Letter := False;
1116 if Current_Verbosity = High then
1117 Write_Int (Types.Int (Index));
1119 Write_Char (The_Name (Index));
1120 Write_Line ("' is not a letter.");
1126 elsif Last_Underscore
1127 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
1129 -- Two underscores are illegal, and a dot cannot follow
1134 if Current_Verbosity = High then
1135 Write_Int (Types.Int (Index));
1137 Write_Char (The_Name (Index));
1138 Write_Line ("' is illegal here.");
1143 elsif The_Name (Index) = '.' then
1145 -- First, check if the name before the dot is not a reserved word
1147 if Is_Reserved (The_Name (First .. Index - 1)) then
1153 -- We need a letter after a dot
1155 Need_Letter := True;
1157 elsif The_Name (Index) = '_' then
1158 Last_Underscore := True;
1161 -- We need an letter or a digit
1163 Last_Underscore := False;
1165 if not Is_Alphanumeric (The_Name (Index)) then
1168 if Current_Verbosity = High then
1169 Write_Int (Types.Int (Index));
1171 Write_Char (The_Name (Index));
1172 Write_Line ("' is not alphanumeric.");
1180 -- Cannot end with an underscore or a dot
1182 OK := OK and then not Need_Letter and then not Last_Underscore;
1185 if First /= Name'First and then
1186 Is_Reserved (The_Name (First .. The_Name'Last))
1194 -- Signal a problem with No_Name
1200 -------------------------
1201 -- Check_Configuration --
1202 -------------------------
1204 procedure Check_Configuration
1205 (Project : Project_Id;
1206 Data : in out Tree_Processing_Data)
1208 Dot_Replacement : File_Name_Type := No_File;
1209 Casing : Casing_Type := All_Lower_Case;
1210 Separate_Suffix : File_Name_Type := No_File;
1212 Lang_Index : Language_Ptr := No_Language_Index;
1213 -- The index of the language data being checked
1215 Prev_Index : Language_Ptr := No_Language_Index;
1216 -- The index of the previous language
1218 procedure Process_Project_Level_Simple_Attributes;
1219 -- Process the simple attributes at the project level
1221 procedure Process_Project_Level_Array_Attributes;
1222 -- Process the associate array attributes at the project level
1224 procedure Process_Packages;
1225 -- Read the packages of the project
1227 ----------------------
1228 -- Process_Packages --
1229 ----------------------
1231 procedure Process_Packages is
1232 Packages : Package_Id;
1233 Element : Package_Element;
1235 procedure Process_Binder (Arrays : Array_Id);
1236 -- Process the associate array attributes of package Binder
1238 procedure Process_Builder (Attributes : Variable_Id);
1239 -- Process the simple attributes of package Builder
1241 procedure Process_Compiler (Arrays : Array_Id);
1242 -- Process the associate array attributes of package Compiler
1244 procedure Process_Naming (Attributes : Variable_Id);
1245 -- Process the simple attributes of package Naming
1247 procedure Process_Naming (Arrays : Array_Id);
1248 -- Process the associate array attributes of package Naming
1250 procedure Process_Linker (Attributes : Variable_Id);
1251 -- Process the simple attributes of package Linker of a
1252 -- configuration project.
1254 --------------------
1255 -- Process_Binder --
1256 --------------------
1258 procedure Process_Binder (Arrays : Array_Id) is
1259 Current_Array_Id : Array_Id;
1260 Current_Array : Array_Data;
1261 Element_Id : Array_Element_Id;
1262 Element : Array_Element;
1265 -- Process the associative array attribute of package Binder
1267 Current_Array_Id := Arrays;
1268 while Current_Array_Id /= No_Array loop
1269 Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
1271 Element_Id := Current_Array.Value;
1272 while Element_Id /= No_Array_Element loop
1273 Element := Data.Tree.Array_Elements.Table (Element_Id);
1275 if Element.Index /= All_Other_Names then
1277 -- Get the name of the language
1280 Get_Language_From_Name
1281 (Project, Get_Name_String (Element.Index));
1283 if Lang_Index /= No_Language_Index then
1284 case Current_Array.Name is
1287 -- Attribute Driver (<language>)
1289 Lang_Index.Config.Binder_Driver :=
1290 File_Name_Type (Element.Value.Value);
1292 when Name_Required_Switches =>
1295 Lang_Index.Config.Binder_Required_Switches,
1296 From_List => Element.Value.Values,
1297 In_Tree => Data.Tree);
1301 -- Attribute Prefix (<language>)
1303 Lang_Index.Config.Binder_Prefix :=
1304 Element.Value.Value;
1306 when Name_Objects_Path =>
1308 -- Attribute Objects_Path (<language>)
1310 Lang_Index.Config.Objects_Path :=
1311 Element.Value.Value;
1313 when Name_Objects_Path_File =>
1315 -- Attribute Objects_Path (<language>)
1317 Lang_Index.Config.Objects_Path_File :=
1318 Element.Value.Value;
1326 Element_Id := Element.Next;
1329 Current_Array_Id := Current_Array.Next;
1333 ---------------------
1334 -- Process_Builder --
1335 ---------------------
1337 procedure Process_Builder (Attributes : Variable_Id) is
1338 Attribute_Id : Variable_Id;
1339 Attribute : Variable;
1342 -- Process non associated array attribute from package Builder
1344 Attribute_Id := Attributes;
1345 while Attribute_Id /= No_Variable loop
1347 Data.Tree.Variable_Elements.Table (Attribute_Id);
1349 if not Attribute.Value.Default then
1350 if Attribute.Name = Name_Executable_Suffix then
1352 -- Attribute Executable_Suffix: the suffix of the
1355 Project.Config.Executable_Suffix :=
1356 Attribute.Value.Value;
1360 Attribute_Id := Attribute.Next;
1362 end Process_Builder;
1364 ----------------------
1365 -- Process_Compiler --
1366 ----------------------
1368 procedure Process_Compiler (Arrays : Array_Id) is
1369 Current_Array_Id : Array_Id;
1370 Current_Array : Array_Data;
1371 Element_Id : Array_Element_Id;
1372 Element : Array_Element;
1373 List : String_List_Id;
1376 -- Process the associative array attribute of package Compiler
1378 Current_Array_Id := Arrays;
1379 while Current_Array_Id /= No_Array loop
1380 Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
1382 Element_Id := Current_Array.Value;
1383 while Element_Id /= No_Array_Element loop
1384 Element := Data.Tree.Array_Elements.Table (Element_Id);
1386 if Element.Index /= All_Other_Names then
1388 -- Get the name of the language
1390 Lang_Index := Get_Language_From_Name
1391 (Project, Get_Name_String (Element.Index));
1393 if Lang_Index /= No_Language_Index then
1394 case Current_Array.Name is
1395 when Name_Dependency_Switches =>
1397 -- Attribute Dependency_Switches (<language>)
1399 if Lang_Index.Config.Dependency_Kind = None then
1400 Lang_Index.Config.Dependency_Kind := Makefile;
1403 List := Element.Value.Values;
1405 if List /= Nil_String then
1407 Lang_Index.Config.Dependency_Option,
1409 In_Tree => Data.Tree);
1412 when Name_Dependency_Driver =>
1414 -- Attribute Dependency_Driver (<language>)
1416 if Lang_Index.Config.Dependency_Kind = None then
1417 Lang_Index.Config.Dependency_Kind := Makefile;
1420 List := Element.Value.Values;
1422 if List /= Nil_String then
1424 Lang_Index.Config.Compute_Dependency,
1426 In_Tree => Data.Tree);
1429 when Name_Include_Switches =>
1431 -- Attribute Include_Switches (<language>)
1433 List := Element.Value.Values;
1435 if List = Nil_String then
1437 (Data.Flags, "include option cannot be null",
1438 Element.Value.Location, Project);
1441 Put (Into_List => Lang_Index.Config.Include_Option,
1443 In_Tree => Data.Tree);
1445 when Name_Include_Path =>
1447 -- Attribute Include_Path (<language>)
1449 Lang_Index.Config.Include_Path :=
1450 Element.Value.Value;
1452 when Name_Include_Path_File =>
1454 -- Attribute Include_Path_File (<language>)
1456 Lang_Index.Config.Include_Path_File :=
1457 Element.Value.Value;
1461 -- Attribute Driver (<language>)
1463 Lang_Index.Config.Compiler_Driver :=
1464 File_Name_Type (Element.Value.Value);
1466 when Name_Required_Switches |
1467 Name_Leading_Required_Switches =>
1470 Compiler_Leading_Required_Switches,
1471 From_List => Element.Value.Values,
1472 In_Tree => Data.Tree);
1474 when Name_Trailing_Required_Switches =>
1477 Compiler_Trailing_Required_Switches,
1478 From_List => Element.Value.Values,
1479 In_Tree => Data.Tree);
1481 when Name_Multi_Unit_Switches =>
1483 Lang_Index.Config.Multi_Unit_Switches,
1484 From_List => Element.Value.Values,
1485 In_Tree => Data.Tree);
1487 when Name_Multi_Unit_Object_Separator =>
1488 Get_Name_String (Element.Value.Value);
1490 if Name_Len /= 1 then
1493 "multi-unit object separator must have " &
1494 "a single character",
1495 Element.Value.Location, Project);
1497 elsif Name_Buffer (1) = ' ' then
1500 "multi-unit object separator cannot be " &
1502 Element.Value.Location, Project);
1505 Lang_Index.Config.Multi_Unit_Object_Separator :=
1509 when Name_Path_Syntax =>
1511 Lang_Index.Config.Path_Syntax :=
1512 Path_Syntax_Kind'Value
1513 (Get_Name_String (Element.Value.Value));
1516 when Constraint_Error =>
1519 "invalid value for Path_Syntax",
1520 Element.Value.Location, Project);
1523 when Name_Object_File_Suffix =>
1524 if Get_Name_String (Element.Value.Value) = "" then
1527 "object file suffix cannot be empty",
1528 Element.Value.Location, Project);
1531 Lang_Index.Config.Object_File_Suffix :=
1532 Element.Value.Value;
1535 when Name_Object_File_Switches =>
1537 Lang_Index.Config.Object_File_Switches,
1538 From_List => Element.Value.Values,
1539 In_Tree => Data.Tree);
1541 when Name_Pic_Option =>
1543 -- Attribute Compiler_Pic_Option (<language>)
1545 List := Element.Value.Values;
1547 if List = Nil_String then
1550 "compiler PIC option cannot be null",
1551 Element.Value.Location, Project);
1555 Lang_Index.Config.Compilation_PIC_Option,
1557 In_Tree => Data.Tree);
1559 when Name_Mapping_File_Switches =>
1561 -- Attribute Mapping_File_Switches (<language>)
1563 List := Element.Value.Values;
1565 if List = Nil_String then
1568 "mapping file switches cannot be null",
1569 Element.Value.Location, Project);
1573 Lang_Index.Config.Mapping_File_Switches,
1575 In_Tree => Data.Tree);
1577 when Name_Mapping_Spec_Suffix =>
1579 -- Attribute Mapping_Spec_Suffix (<language>)
1581 Lang_Index.Config.Mapping_Spec_Suffix :=
1582 File_Name_Type (Element.Value.Value);
1584 when Name_Mapping_Body_Suffix =>
1586 -- Attribute Mapping_Body_Suffix (<language>)
1588 Lang_Index.Config.Mapping_Body_Suffix :=
1589 File_Name_Type (Element.Value.Value);
1591 when Name_Config_File_Switches =>
1593 -- Attribute Config_File_Switches (<language>)
1595 List := Element.Value.Values;
1597 if List = Nil_String then
1600 "config file switches cannot be null",
1601 Element.Value.Location, Project);
1605 Lang_Index.Config.Config_File_Switches,
1607 In_Tree => Data.Tree);
1609 when Name_Objects_Path =>
1611 -- Attribute Objects_Path (<language>)
1613 Lang_Index.Config.Objects_Path :=
1614 Element.Value.Value;
1616 when Name_Objects_Path_File =>
1618 -- Attribute Objects_Path_File (<language>)
1620 Lang_Index.Config.Objects_Path_File :=
1621 Element.Value.Value;
1623 when Name_Config_Body_File_Name =>
1625 -- Attribute Config_Body_File_Name (<language>)
1627 Lang_Index.Config.Config_Body :=
1628 Element.Value.Value;
1630 when Name_Config_Body_File_Name_Index =>
1632 -- Attribute Config_Body_File_Name_Index
1635 Lang_Index.Config.Config_Body_Index :=
1636 Element.Value.Value;
1638 when Name_Config_Body_File_Name_Pattern =>
1640 -- Attribute Config_Body_File_Name_Pattern
1643 Lang_Index.Config.Config_Body_Pattern :=
1644 Element.Value.Value;
1646 when Name_Config_Spec_File_Name =>
1648 -- Attribute Config_Spec_File_Name (<language>)
1650 Lang_Index.Config.Config_Spec :=
1651 Element.Value.Value;
1653 when Name_Config_Spec_File_Name_Index =>
1655 -- Attribute Config_Spec_File_Name_Index
1658 Lang_Index.Config.Config_Spec_Index :=
1659 Element.Value.Value;
1661 when Name_Config_Spec_File_Name_Pattern =>
1663 -- Attribute Config_Spec_File_Name_Pattern
1666 Lang_Index.Config.Config_Spec_Pattern :=
1667 Element.Value.Value;
1669 when Name_Config_File_Unique =>
1671 -- Attribute Config_File_Unique (<language>)
1674 Lang_Index.Config.Config_File_Unique :=
1676 (Get_Name_String (Element.Value.Value));
1678 when Constraint_Error =>
1681 "illegal value for Config_File_Unique",
1682 Element.Value.Location, Project);
1691 Element_Id := Element.Next;
1694 Current_Array_Id := Current_Array.Next;
1696 end Process_Compiler;
1698 --------------------
1699 -- Process_Naming --
1700 --------------------
1702 procedure Process_Naming (Attributes : Variable_Id) is
1703 Attribute_Id : Variable_Id;
1704 Attribute : Variable;
1707 -- Process non associated array attribute from package Naming
1709 Attribute_Id := Attributes;
1710 while Attribute_Id /= No_Variable loop
1711 Attribute := Data.Tree.Variable_Elements.Table (Attribute_Id);
1713 if not Attribute.Value.Default then
1714 if Attribute.Name = Name_Separate_Suffix then
1716 -- Attribute Separate_Suffix
1718 Get_Name_String (Attribute.Value.Value);
1719 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
1720 Separate_Suffix := Name_Find;
1722 elsif Attribute.Name = Name_Casing then
1728 Value (Get_Name_String (Attribute.Value.Value));
1731 when Constraint_Error =>
1734 "invalid value for Casing",
1735 Attribute.Value.Location, Project);
1738 elsif Attribute.Name = Name_Dot_Replacement then
1740 -- Attribute Dot_Replacement
1742 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1747 Attribute_Id := Attribute.Next;
1751 procedure Process_Naming (Arrays : Array_Id) is
1752 Current_Array_Id : Array_Id;
1753 Current_Array : Array_Data;
1754 Element_Id : Array_Element_Id;
1755 Element : Array_Element;
1758 -- Process the associative array attribute of package Naming
1760 Current_Array_Id := Arrays;
1761 while Current_Array_Id /= No_Array loop
1762 Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
1764 Element_Id := Current_Array.Value;
1765 while Element_Id /= No_Array_Element loop
1766 Element := Data.Tree.Array_Elements.Table (Element_Id);
1768 -- Get the name of the language
1770 Lang_Index := Get_Language_From_Name
1771 (Project, Get_Name_String (Element.Index));
1773 if Lang_Index /= No_Language_Index then
1774 case Current_Array.Name is
1775 when Name_Spec_Suffix | Name_Specification_Suffix =>
1777 -- Attribute Spec_Suffix (<language>)
1779 Get_Name_String (Element.Value.Value);
1780 Canonical_Case_File_Name
1781 (Name_Buffer (1 .. Name_Len));
1782 Lang_Index.Config.Naming_Data.Spec_Suffix :=
1785 when Name_Implementation_Suffix | Name_Body_Suffix =>
1787 Get_Name_String (Element.Value.Value);
1788 Canonical_Case_File_Name
1789 (Name_Buffer (1 .. Name_Len));
1791 -- Attribute Body_Suffix (<language>)
1793 Lang_Index.Config.Naming_Data.Body_Suffix :=
1795 Lang_Index.Config.Naming_Data.Separate_Suffix :=
1796 Lang_Index.Config.Naming_Data.Body_Suffix;
1803 Element_Id := Element.Next;
1806 Current_Array_Id := Current_Array.Next;
1810 --------------------
1811 -- Process_Linker --
1812 --------------------
1814 procedure Process_Linker (Attributes : Variable_Id) is
1815 Attribute_Id : Variable_Id;
1816 Attribute : Variable;
1819 -- Process non associated array attribute from package Linker
1821 Attribute_Id := Attributes;
1822 while Attribute_Id /= No_Variable loop
1824 Data.Tree.Variable_Elements.Table (Attribute_Id);
1826 if not Attribute.Value.Default then
1827 if Attribute.Name = Name_Driver then
1829 -- Attribute Linker'Driver: the default linker to use
1831 Project.Config.Linker :=
1832 Path_Name_Type (Attribute.Value.Value);
1834 -- Linker'Driver is also used to link shared libraries
1835 -- if the obsolescent attribute Library_GCC has not been
1838 if Project.Config.Shared_Lib_Driver = No_File then
1839 Project.Config.Shared_Lib_Driver :=
1840 File_Name_Type (Attribute.Value.Value);
1843 elsif Attribute.Name = Name_Required_Switches then
1845 -- Attribute Required_Switches: the minimum trailing
1846 -- options to use when invoking the linker
1849 Project.Config.Trailing_Linker_Required_Switches,
1850 From_List => Attribute.Value.Values,
1851 In_Tree => Data.Tree);
1853 elsif Attribute.Name = Name_Map_File_Option then
1854 Project.Config.Map_File_Option := Attribute.Value.Value;
1856 elsif Attribute.Name = Name_Max_Command_Line_Length then
1858 Project.Config.Max_Command_Line_Length :=
1859 Natural'Value (Get_Name_String
1860 (Attribute.Value.Value));
1863 when Constraint_Error =>
1866 "value must be positive or equal to 0",
1867 Attribute.Value.Location, Project);
1870 elsif Attribute.Name = Name_Response_File_Format then
1875 Get_Name_String (Attribute.Value.Value);
1876 To_Lower (Name_Buffer (1 .. Name_Len));
1879 if Name = Name_None then
1880 Project.Config.Resp_File_Format := None;
1882 elsif Name = Name_Gnu then
1883 Project.Config.Resp_File_Format := GNU;
1885 elsif Name = Name_Object_List then
1886 Project.Config.Resp_File_Format := Object_List;
1888 elsif Name = Name_Option_List then
1889 Project.Config.Resp_File_Format := Option_List;
1891 elsif Name_Buffer (1 .. Name_Len) = "gcc" then
1892 Project.Config.Resp_File_Format := GCC;
1894 elsif Name_Buffer (1 .. Name_Len) = "gcc_gnu" then
1895 Project.Config.Resp_File_Format := GCC_GNU;
1898 Name_Buffer (1 .. Name_Len) = "gcc_option_list"
1900 Project.Config.Resp_File_Format := GCC_Option_List;
1903 Name_Buffer (1 .. Name_Len) = "gcc_object_list"
1905 Project.Config.Resp_File_Format := GCC_Object_List;
1910 "illegal response file format",
1911 Attribute.Value.Location, Project);
1915 elsif Attribute.Name = Name_Response_File_Switches then
1916 Put (Into_List => Project.Config.Resp_File_Options,
1917 From_List => Attribute.Value.Values,
1918 In_Tree => Data.Tree);
1922 Attribute_Id := Attribute.Next;
1926 -- Start of processing for Process_Packages
1929 Packages := Project.Decl.Packages;
1930 while Packages /= No_Package loop
1931 Element := Data.Tree.Packages.Table (Packages);
1933 case Element.Name is
1936 -- Process attributes of package Binder
1938 Process_Binder (Element.Decl.Arrays);
1940 when Name_Builder =>
1942 -- Process attributes of package Builder
1944 Process_Builder (Element.Decl.Attributes);
1946 when Name_Compiler =>
1948 -- Process attributes of package Compiler
1950 Process_Compiler (Element.Decl.Arrays);
1954 -- Process attributes of package Linker
1956 Process_Linker (Element.Decl.Attributes);
1960 -- Process attributes of package Naming
1962 Process_Naming (Element.Decl.Attributes);
1963 Process_Naming (Element.Decl.Arrays);
1969 Packages := Element.Next;
1971 end Process_Packages;
1973 ---------------------------------------------
1974 -- Process_Project_Level_Simple_Attributes --
1975 ---------------------------------------------
1977 procedure Process_Project_Level_Simple_Attributes is
1978 Attribute_Id : Variable_Id;
1979 Attribute : Variable;
1980 List : String_List_Id;
1983 -- Process non associated array attribute at project level
1985 Attribute_Id := Project.Decl.Attributes;
1986 while Attribute_Id /= No_Variable loop
1988 Data.Tree.Variable_Elements.Table (Attribute_Id);
1990 if not Attribute.Value.Default then
1991 if Attribute.Name = Name_Target then
1993 -- Attribute Target: the target specified
1995 Project.Config.Target := Attribute.Value.Value;
1997 elsif Attribute.Name = Name_Library_Builder then
1999 -- Attribute Library_Builder: the application to invoke
2000 -- to build libraries.
2002 Project.Config.Library_Builder :=
2003 Path_Name_Type (Attribute.Value.Value);
2005 elsif Attribute.Name = Name_Archive_Builder then
2007 -- Attribute Archive_Builder: the archive builder
2008 -- (usually "ar") and its minimum options (usually "cr").
2010 List := Attribute.Value.Values;
2012 if List = Nil_String then
2015 "archive builder cannot be null",
2016 Attribute.Value.Location, Project);
2019 Put (Into_List => Project.Config.Archive_Builder,
2021 In_Tree => Data.Tree);
2023 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
2025 -- Attribute Archive_Builder: the archive builder
2026 -- (usually "ar") and its minimum options (usually "cr").
2028 List := Attribute.Value.Values;
2030 if List /= Nil_String then
2033 Project.Config.Archive_Builder_Append_Option,
2035 In_Tree => Data.Tree);
2038 elsif Attribute.Name = Name_Archive_Indexer then
2040 -- Attribute Archive_Indexer: the optional archive
2041 -- indexer (usually "ranlib") with its minimum options
2044 List := Attribute.Value.Values;
2046 if List = Nil_String then
2049 "archive indexer cannot be null",
2050 Attribute.Value.Location, Project);
2053 Put (Into_List => Project.Config.Archive_Indexer,
2055 In_Tree => Data.Tree);
2057 elsif Attribute.Name = Name_Library_Partial_Linker then
2059 -- Attribute Library_Partial_Linker: the optional linker
2060 -- driver with its minimum options, to partially link
2063 List := Attribute.Value.Values;
2065 if List = Nil_String then
2068 "partial linker cannot be null",
2069 Attribute.Value.Location, Project);
2072 Put (Into_List => Project.Config.Lib_Partial_Linker,
2074 In_Tree => Data.Tree);
2076 elsif Attribute.Name = Name_Library_GCC then
2077 Project.Config.Shared_Lib_Driver :=
2078 File_Name_Type (Attribute.Value.Value);
2081 "?Library_'G'C'C is an obsolescent attribute, " &
2082 "use Linker''Driver instead",
2083 Attribute.Value.Location, Project);
2085 elsif Attribute.Name = Name_Archive_Suffix then
2086 Project.Config.Archive_Suffix :=
2087 File_Name_Type (Attribute.Value.Value);
2089 elsif Attribute.Name = Name_Linker_Executable_Option then
2091 -- Attribute Linker_Executable_Option: optional options
2092 -- to specify an executable name. Defaults to "-o".
2094 List := Attribute.Value.Values;
2096 if List = Nil_String then
2099 "linker executable option cannot be null",
2100 Attribute.Value.Location, Project);
2103 Put (Into_List => Project.Config.Linker_Executable_Option,
2105 In_Tree => Data.Tree);
2107 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2109 -- Attribute Linker_Lib_Dir_Option: optional options
2110 -- to specify a library search directory. Defaults to
2113 Get_Name_String (Attribute.Value.Value);
2115 if Name_Len = 0 then
2118 "linker library directory option cannot be empty",
2119 Attribute.Value.Location, Project);
2122 Project.Config.Linker_Lib_Dir_Option :=
2123 Attribute.Value.Value;
2125 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2127 -- Attribute Linker_Lib_Name_Option: optional options
2128 -- to specify the name of a library to be linked in.
2129 -- Defaults to "-l".
2131 Get_Name_String (Attribute.Value.Value);
2133 if Name_Len = 0 then
2136 "linker library name option cannot be empty",
2137 Attribute.Value.Location, Project);
2140 Project.Config.Linker_Lib_Name_Option :=
2141 Attribute.Value.Value;
2143 elsif Attribute.Name = Name_Run_Path_Option then
2145 -- Attribute Run_Path_Option: optional options to
2146 -- specify a path for libraries.
2148 List := Attribute.Value.Values;
2150 if List /= Nil_String then
2151 Put (Into_List => Project.Config.Run_Path_Option,
2153 In_Tree => Data.Tree);
2156 elsif Attribute.Name = Name_Run_Path_Origin then
2157 Get_Name_String (Attribute.Value.Value);
2159 if Name_Len = 0 then
2162 "run path origin cannot be empty",
2163 Attribute.Value.Location, Project);
2166 Project.Config.Run_Path_Origin := Attribute.Value.Value;
2168 elsif Attribute.Name = Name_Library_Install_Name_Option then
2169 Project.Config.Library_Install_Name_Option :=
2170 Attribute.Value.Value;
2172 elsif Attribute.Name = Name_Separate_Run_Path_Options then
2174 pragma Unsuppress (All_Checks);
2176 Project.Config.Separate_Run_Path_Options :=
2177 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2179 when Constraint_Error =>
2182 "invalid value """ &
2183 Get_Name_String (Attribute.Value.Value) &
2184 """ for Separate_Run_Path_Options",
2185 Attribute.Value.Location, Project);
2188 elsif Attribute.Name = Name_Library_Support then
2190 pragma Unsuppress (All_Checks);
2192 Project.Config.Lib_Support :=
2193 Library_Support'Value (Get_Name_String
2194 (Attribute.Value.Value));
2196 when Constraint_Error =>
2199 "invalid value """ &
2200 Get_Name_String (Attribute.Value.Value) &
2201 """ for Library_Support",
2202 Attribute.Value.Location, Project);
2205 elsif Attribute.Name = Name_Shared_Library_Prefix then
2206 Project.Config.Shared_Lib_Prefix :=
2207 File_Name_Type (Attribute.Value.Value);
2209 elsif Attribute.Name = Name_Shared_Library_Suffix then
2210 Project.Config.Shared_Lib_Suffix :=
2211 File_Name_Type (Attribute.Value.Value);
2213 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2215 pragma Unsuppress (All_Checks);
2217 Project.Config.Symbolic_Link_Supported :=
2218 Boolean'Value (Get_Name_String
2219 (Attribute.Value.Value));
2221 when Constraint_Error =>
2225 & Get_Name_String (Attribute.Value.Value)
2226 & """ for Symbolic_Link_Supported",
2227 Attribute.Value.Location, Project);
2231 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2234 pragma Unsuppress (All_Checks);
2236 Project.Config.Lib_Maj_Min_Id_Supported :=
2237 Boolean'Value (Get_Name_String
2238 (Attribute.Value.Value));
2240 when Constraint_Error =>
2243 "invalid value """ &
2244 Get_Name_String (Attribute.Value.Value) &
2245 """ for Library_Major_Minor_Id_Supported",
2246 Attribute.Value.Location, Project);
2249 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2251 pragma Unsuppress (All_Checks);
2253 Project.Config.Auto_Init_Supported :=
2254 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2256 when Constraint_Error =>
2260 & Get_Name_String (Attribute.Value.Value)
2261 & """ for Library_Auto_Init_Supported",
2262 Attribute.Value.Location, Project);
2265 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2266 List := Attribute.Value.Values;
2268 if List /= Nil_String then
2269 Put (Into_List => Project.Config.Shared_Lib_Min_Options,
2271 In_Tree => Data.Tree);
2274 elsif Attribute.Name = Name_Library_Version_Switches then
2275 List := Attribute.Value.Values;
2277 if List /= Nil_String then
2278 Put (Into_List => Project.Config.Lib_Version_Options,
2280 In_Tree => Data.Tree);
2285 Attribute_Id := Attribute.Next;
2287 end Process_Project_Level_Simple_Attributes;
2289 --------------------------------------------
2290 -- Process_Project_Level_Array_Attributes --
2291 --------------------------------------------
2293 procedure Process_Project_Level_Array_Attributes is
2294 Current_Array_Id : Array_Id;
2295 Current_Array : Array_Data;
2296 Element_Id : Array_Element_Id;
2297 Element : Array_Element;
2298 List : String_List_Id;
2301 -- Process the associative array attributes at project level
2303 Current_Array_Id := Project.Decl.Arrays;
2304 while Current_Array_Id /= No_Array loop
2305 Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
2307 Element_Id := Current_Array.Value;
2308 while Element_Id /= No_Array_Element loop
2309 Element := Data.Tree.Array_Elements.Table (Element_Id);
2311 -- Get the name of the language
2314 Get_Language_From_Name
2315 (Project, Get_Name_String (Element.Index));
2317 if Lang_Index /= No_Language_Index then
2318 case Current_Array.Name is
2319 when Name_Inherit_Source_Path =>
2320 List := Element.Value.Values;
2322 if List /= Nil_String then
2325 Lang_Index.Config.Include_Compatible_Languages,
2327 In_Tree => Data.Tree,
2328 Lower_Case => True);
2331 when Name_Toolchain_Description =>
2333 -- Attribute Toolchain_Description (<language>)
2335 Lang_Index.Config.Toolchain_Description :=
2336 Element.Value.Value;
2338 when Name_Toolchain_Version =>
2340 -- Attribute Toolchain_Version (<language>)
2342 Lang_Index.Config.Toolchain_Version :=
2343 Element.Value.Value;
2345 when Name_Runtime_Library_Dir =>
2347 -- Attribute Runtime_Library_Dir (<language>)
2349 Lang_Index.Config.Runtime_Library_Dir :=
2350 Element.Value.Value;
2352 when Name_Runtime_Source_Dir =>
2354 -- Attribute Runtime_Library_Dir (<language>)
2356 Lang_Index.Config.Runtime_Source_Dir :=
2357 Element.Value.Value;
2359 when Name_Object_Generated =>
2361 pragma Unsuppress (All_Checks);
2367 (Get_Name_String (Element.Value.Value));
2369 Lang_Index.Config.Object_Generated := Value;
2371 -- If no object is generated, no object may be
2375 Lang_Index.Config.Objects_Linked := False;
2379 when Constraint_Error =>
2383 & Get_Name_String (Element.Value.Value)
2384 & """ for Object_Generated",
2385 Element.Value.Location, Project);
2388 when Name_Objects_Linked =>
2390 pragma Unsuppress (All_Checks);
2396 (Get_Name_String (Element.Value.Value));
2398 -- No change if Object_Generated is False, as this
2399 -- forces Objects_Linked to be False too.
2401 if Lang_Index.Config.Object_Generated then
2402 Lang_Index.Config.Objects_Linked := Value;
2406 when Constraint_Error =>
2410 & Get_Name_String (Element.Value.Value)
2411 & """ for Objects_Linked",
2412 Element.Value.Location, Project);
2419 Element_Id := Element.Next;
2422 Current_Array_Id := Current_Array.Next;
2424 end Process_Project_Level_Array_Attributes;
2426 -- Start of processing for Check_Configuration
2429 Process_Project_Level_Simple_Attributes;
2430 Process_Project_Level_Array_Attributes;
2433 -- For unit based languages, set Casing, Dot_Replacement and
2434 -- Separate_Suffix in Naming_Data.
2436 Lang_Index := Project.Languages;
2437 while Lang_Index /= No_Language_Index loop
2438 if Lang_Index.Name = Name_Ada then
2439 Lang_Index.Config.Naming_Data.Casing := Casing;
2440 Lang_Index.Config.Naming_Data.Dot_Replacement := Dot_Replacement;
2442 if Separate_Suffix /= No_File then
2443 Lang_Index.Config.Naming_Data.Separate_Suffix :=
2450 Lang_Index := Lang_Index.Next;
2453 -- Give empty names to various prefixes/suffixes, if they have not
2454 -- been specified in the configuration.
2456 if Project.Config.Archive_Suffix = No_File then
2457 Project.Config.Archive_Suffix := Empty_File;
2460 if Project.Config.Shared_Lib_Prefix = No_File then
2461 Project.Config.Shared_Lib_Prefix := Empty_File;
2464 if Project.Config.Shared_Lib_Suffix = No_File then
2465 Project.Config.Shared_Lib_Suffix := Empty_File;
2468 Lang_Index := Project.Languages;
2469 while Lang_Index /= No_Language_Index loop
2471 -- For all languages, Compiler_Driver needs to be specified. This is
2472 -- only needed if we do intend to compile (not in GPS for instance).
2474 if Data.Flags.Compiler_Driver_Mandatory
2475 and then Lang_Index.Config.Compiler_Driver = No_File
2477 Error_Msg_Name_1 := Lang_Index.Display_Name;
2480 "?no compiler specified for language %%" &
2481 ", ignoring all its sources",
2482 No_Location, Project);
2484 if Lang_Index = Project.Languages then
2485 Project.Languages := Lang_Index.Next;
2487 Prev_Index.Next := Lang_Index.Next;
2490 elsif Lang_Index.Name = Name_Ada then
2491 Prev_Index := Lang_Index;
2493 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2494 -- Body_Suffix need to be specified.
2496 if Lang_Index.Config.Naming_Data.Dot_Replacement = No_File then
2499 "Dot_Replacement not specified for Ada",
2500 No_Location, Project);
2503 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File then
2506 "Spec_Suffix not specified for Ada",
2507 No_Location, Project);
2510 if Lang_Index.Config.Naming_Data.Body_Suffix = No_File then
2513 "Body_Suffix not specified for Ada",
2514 No_Location, Project);
2518 Prev_Index := Lang_Index;
2520 -- For file based languages, either Spec_Suffix or Body_Suffix
2521 -- need to be specified.
2523 if Data.Flags.Require_Sources_Other_Lang
2524 and then Lang_Index.Config.Naming_Data.Spec_Suffix = No_File
2525 and then Lang_Index.Config.Naming_Data.Body_Suffix = No_File
2527 Error_Msg_Name_1 := Lang_Index.Display_Name;
2530 "no suffixes specified for %%",
2531 No_Location, Project);
2535 Lang_Index := Lang_Index.Next;
2537 end Check_Configuration;
2539 -------------------------------
2540 -- Check_If_Externally_Built --
2541 -------------------------------
2543 procedure Check_If_Externally_Built
2544 (Project : Project_Id;
2545 Data : in out Tree_Processing_Data)
2547 Externally_Built : constant Variable_Value :=
2549 (Name_Externally_Built,
2550 Project.Decl.Attributes, Data.Tree);
2553 if not Externally_Built.Default then
2554 Get_Name_String (Externally_Built.Value);
2555 To_Lower (Name_Buffer (1 .. Name_Len));
2557 if Name_Buffer (1 .. Name_Len) = "true" then
2558 Project.Externally_Built := True;
2560 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2561 Error_Msg (Data.Flags,
2562 "Externally_Built may only be true or false",
2563 Externally_Built.Location, Project);
2567 -- A virtual project extending an externally built project is itself
2568 -- externally built.
2570 if Project.Virtual and then Project.Extends /= No_Project then
2571 Project.Externally_Built := Project.Extends.Externally_Built;
2574 if Current_Verbosity = High then
2575 Write_Str ("Project is ");
2577 if not Project.Externally_Built then
2581 Write_Line ("externally built.");
2583 end Check_If_Externally_Built;
2585 ----------------------
2586 -- Check_Interfaces --
2587 ----------------------
2589 procedure Check_Interfaces
2590 (Project : Project_Id;
2591 Data : in out Tree_Processing_Data)
2593 Interfaces : constant Prj.Variable_Value :=
2595 (Snames.Name_Interfaces,
2596 Project.Decl.Attributes,
2599 Library_Interface : constant Prj.Variable_Value :=
2601 (Snames.Name_Library_Interface,
2602 Project.Decl.Attributes,
2605 List : String_List_Id;
2606 Element : String_Element;
2607 Name : File_Name_Type;
2608 Iter : Source_Iterator;
2610 Project_2 : Project_Id;
2614 if not Interfaces.Default then
2616 -- Set In_Interfaces to False for all sources. It will be set to True
2617 -- later for the sources in the Interfaces list.
2619 Project_2 := Project;
2620 while Project_2 /= No_Project loop
2621 Iter := For_Each_Source (Data.Tree, Project_2);
2623 Source := Prj.Element (Iter);
2624 exit when Source = No_Source;
2625 Source.In_Interfaces := False;
2629 Project_2 := Project_2.Extends;
2632 List := Interfaces.Values;
2633 while List /= Nil_String loop
2634 Element := Data.Tree.String_Elements.Table (List);
2635 Name := Canonical_Case_File_Name (Element.Value);
2637 Project_2 := Project;
2639 while Project_2 /= No_Project loop
2640 Iter := For_Each_Source (Data.Tree, Project_2);
2643 Source := Prj.Element (Iter);
2644 exit when Source = No_Source;
2646 if Source.File = Name then
2647 if not Source.Locally_Removed then
2648 Source.In_Interfaces := True;
2649 Source.Declared_In_Interfaces := True;
2651 Other := Other_Part (Source);
2653 if Other /= No_Source then
2654 Other.In_Interfaces := True;
2655 Other.Declared_In_Interfaces := True;
2658 if Current_Verbosity = High then
2659 Write_Str (" interface: ");
2660 Write_Line (Get_Name_String (Source.Path.Name));
2670 Project_2 := Project_2.Extends;
2673 if Source = No_Source then
2674 Error_Msg_File_1 := File_Name_Type (Element.Value);
2675 Error_Msg_Name_1 := Project.Name;
2679 "{ cannot be an interface of project %% "
2680 & "as it is not one of its sources",
2681 Element.Location, Project);
2684 List := Element.Next;
2687 Project.Interfaces_Defined := True;
2689 elsif Project.Library and then not Library_Interface.Default then
2691 -- Set In_Interfaces to False for all sources. It will be set to True
2692 -- later for the sources in the Library_Interface list.
2694 Project_2 := Project;
2695 while Project_2 /= No_Project loop
2696 Iter := For_Each_Source (Data.Tree, Project_2);
2698 Source := Prj.Element (Iter);
2699 exit when Source = No_Source;
2700 Source.In_Interfaces := False;
2704 Project_2 := Project_2.Extends;
2707 List := Library_Interface.Values;
2708 while List /= Nil_String loop
2709 Element := Data.Tree.String_Elements.Table (List);
2710 Get_Name_String (Element.Value);
2711 To_Lower (Name_Buffer (1 .. Name_Len));
2714 Project_2 := Project;
2716 while Project_2 /= No_Project loop
2717 Iter := For_Each_Source (Data.Tree, Project_2);
2720 Source := Prj.Element (Iter);
2721 exit when Source = No_Source;
2723 if Source.Unit /= No_Unit_Index and then
2724 Source.Unit.Name = Name_Id (Name)
2726 if not Source.Locally_Removed then
2727 Source.In_Interfaces := True;
2728 Source.Declared_In_Interfaces := True;
2730 Other := Other_Part (Source);
2732 if Other /= No_Source then
2733 Other.In_Interfaces := True;
2734 Other.Declared_In_Interfaces := True;
2737 if Current_Verbosity = High then
2738 Write_Str (" interface: ");
2739 Write_Line (Get_Name_String (Source.Path.Name));
2749 Project_2 := Project_2.Extends;
2750 end loop Big_Loop_2;
2752 List := Element.Next;
2755 Project.Interfaces_Defined := True;
2757 elsif Project.Extends /= No_Project
2758 and then Project.Extends.Interfaces_Defined
2760 Project.Interfaces_Defined := True;
2762 Iter := For_Each_Source (Data.Tree, Project);
2764 Source := Prj.Element (Iter);
2765 exit when Source = No_Source;
2767 if not Source.Declared_In_Interfaces then
2768 Source.In_Interfaces := False;
2774 end Check_Interfaces;
2776 --------------------------
2777 -- Check_Package_Naming --
2778 --------------------------
2780 procedure Check_Package_Naming
2781 (Project : Project_Id;
2782 Data : in out Tree_Processing_Data)
2784 Naming_Id : constant Package_Id :=
2786 (Name_Naming, Project.Decl.Packages, Data.Tree);
2787 Naming : Package_Element;
2789 Ada_Body_Suffix_Loc : Source_Ptr := No_Location;
2791 procedure Check_Naming;
2792 -- Check the validity of the Naming package (suffixes valid, ...)
2794 procedure Check_Common
2795 (Dot_Replacement : in out File_Name_Type;
2796 Casing : in out Casing_Type;
2797 Casing_Defined : out Boolean;
2798 Separate_Suffix : in out File_Name_Type;
2799 Sep_Suffix_Loc : out Source_Ptr);
2800 -- Check attributes common
2802 procedure Process_Exceptions_File_Based
2803 (Lang_Id : Language_Ptr;
2804 Kind : Source_Kind);
2805 procedure Process_Exceptions_Unit_Based
2806 (Lang_Id : Language_Ptr;
2807 Kind : Source_Kind);
2808 -- Process the naming exceptions for the two types of languages
2810 procedure Initialize_Naming_Data;
2811 -- Initialize internal naming data for the various languages
2817 procedure Check_Common
2818 (Dot_Replacement : in out File_Name_Type;
2819 Casing : in out Casing_Type;
2820 Casing_Defined : out Boolean;
2821 Separate_Suffix : in out File_Name_Type;
2822 Sep_Suffix_Loc : out Source_Ptr)
2824 Dot_Repl : constant Variable_Value :=
2826 (Name_Dot_Replacement,
2827 Naming.Decl.Attributes,
2829 Casing_String : constant Variable_Value :=
2832 Naming.Decl.Attributes,
2834 Sep_Suffix : constant Variable_Value :=
2836 (Name_Separate_Suffix,
2837 Naming.Decl.Attributes,
2839 Dot_Repl_Loc : Source_Ptr;
2842 Sep_Suffix_Loc := No_Location;
2844 if not Dot_Repl.Default then
2846 (Dot_Repl.Kind = Single, "Dot_Replacement is not a string");
2848 if Length_Of_Name (Dot_Repl.Value) = 0 then
2850 (Data.Flags, "Dot_Replacement cannot be empty",
2851 Dot_Repl.Location, Project);
2854 Dot_Replacement := Canonical_Case_File_Name (Dot_Repl.Value);
2855 Dot_Repl_Loc := Dot_Repl.Location;
2858 Repl : constant String := Get_Name_String (Dot_Replacement);
2861 -- Dot_Replacement cannot
2863 -- - start or end with an alphanumeric
2864 -- - be a single '_'
2865 -- - start with an '_' followed by an alphanumeric
2866 -- - contain a '.' except if it is "."
2869 or else Is_Alphanumeric (Repl (Repl'First))
2870 or else Is_Alphanumeric (Repl (Repl'Last))
2871 or else (Repl (Repl'First) = '_'
2875 Is_Alphanumeric (Repl (Repl'First + 1))))
2876 or else (Repl'Length > 1
2878 Index (Source => Repl, Pattern => ".") /= 0)
2883 """ is illegal for Dot_Replacement.",
2884 Dot_Repl_Loc, Project);
2889 if Dot_Replacement /= No_File then
2891 ("Dot_Replacement", Get_Name_String (Dot_Replacement));
2894 Casing_Defined := False;
2896 if not Casing_String.Default then
2898 (Casing_String.Kind = Single, "Casing is not a string");
2901 Casing_Image : constant String :=
2902 Get_Name_String (Casing_String.Value);
2905 if Casing_Image'Length = 0 then
2908 "Casing cannot be an empty string",
2909 Casing_String.Location, Project);
2912 Casing := Value (Casing_Image);
2913 Casing_Defined := True;
2916 when Constraint_Error =>
2917 Name_Len := Casing_Image'Length;
2918 Name_Buffer (1 .. Name_Len) := Casing_Image;
2919 Err_Vars.Error_Msg_Name_1 := Name_Find;
2922 "%% is not a correct Casing",
2923 Casing_String.Location, Project);
2927 Write_Attr ("Casing", Image (Casing));
2929 if not Sep_Suffix.Default then
2930 if Length_Of_Name (Sep_Suffix.Value) = 0 then
2933 "Separate_Suffix cannot be empty",
2934 Sep_Suffix.Location, Project);
2937 Separate_Suffix := Canonical_Case_File_Name (Sep_Suffix.Value);
2938 Sep_Suffix_Loc := Sep_Suffix.Location;
2940 Check_Illegal_Suffix
2941 (Project, Separate_Suffix,
2942 Dot_Replacement, "Separate_Suffix", Sep_Suffix.Location,
2947 if Separate_Suffix /= No_File then
2949 ("Separate_Suffix", Get_Name_String (Separate_Suffix));
2953 -----------------------------------
2954 -- Process_Exceptions_File_Based --
2955 -----------------------------------
2957 procedure Process_Exceptions_File_Based
2958 (Lang_Id : Language_Ptr;
2961 Lang : constant Name_Id := Lang_Id.Name;
2962 Exceptions : Array_Element_Id;
2963 Exception_List : Variable_Value;
2964 Element_Id : String_List_Id;
2965 Element : String_Element;
2966 File_Name : File_Name_Type;
2968 Iter : Source_Iterator;
2975 (Name_Implementation_Exceptions,
2976 In_Arrays => Naming.Decl.Arrays,
2977 In_Tree => Data.Tree);
2982 (Name_Specification_Exceptions,
2983 In_Arrays => Naming.Decl.Arrays,
2984 In_Tree => Data.Tree);
2987 Exception_List := Value_Of
2989 In_Array => Exceptions,
2990 In_Tree => Data.Tree);
2992 if Exception_List /= Nil_Variable_Value then
2993 Element_Id := Exception_List.Values;
2994 while Element_Id /= Nil_String loop
2995 Element := Data.Tree.String_Elements.Table (Element_Id);
2996 File_Name := Canonical_Case_File_Name (Element.Value);
2998 Iter := For_Each_Source (Data.Tree, Project);
3000 Source := Prj.Element (Iter);
3001 exit when Source = No_Source or else Source.File = File_Name;
3005 if Source = No_Source then
3010 Source_Dir_Rank => 0,
3013 File_Name => File_Name,
3014 Display_File => File_Name_Type (Element.Value),
3015 Naming_Exception => True,
3016 Location => Element.Location);
3019 -- Check if the file name is already recorded for another
3020 -- language or another kind.
3022 if Source.Language /= Lang_Id then
3025 "the same file cannot be a source of two languages",
3026 Element.Location, Project);
3028 elsif Source.Kind /= Kind then
3031 "the same file cannot be a source and a template",
3032 Element.Location, Project);
3035 -- If the file is already recorded for the same
3036 -- language and the same kind, it means that the file
3037 -- name appears several times in the *_Exceptions
3038 -- attribute; so there is nothing to do.
3041 Element_Id := Element.Next;
3044 end Process_Exceptions_File_Based;
3046 -----------------------------------
3047 -- Process_Exceptions_Unit_Based --
3048 -----------------------------------
3050 procedure Process_Exceptions_Unit_Based
3051 (Lang_Id : Language_Ptr;
3054 Lang : constant Name_Id := Lang_Id.Name;
3055 Exceptions : Array_Element_Id;
3056 Element : Array_Element;
3059 File_Name : File_Name_Type;
3068 In_Arrays => Naming.Decl.Arrays,
3069 In_Tree => Data.Tree);
3071 if Exceptions = No_Array_Element then
3074 (Name_Implementation,
3075 In_Arrays => Naming.Decl.Arrays,
3076 In_Tree => Data.Tree);
3083 In_Arrays => Naming.Decl.Arrays,
3084 In_Tree => Data.Tree);
3086 if Exceptions = No_Array_Element then
3090 In_Arrays => Naming.Decl.Arrays,
3091 In_Tree => Data.Tree);
3095 while Exceptions /= No_Array_Element loop
3096 Element := Data.Tree.Array_Elements.Table (Exceptions);
3097 File_Name := Canonical_Case_File_Name (Element.Value.Value);
3099 Get_Name_String (Element.Index);
3100 To_Lower (Name_Buffer (1 .. Name_Len));
3102 Index := Element.Value.Index;
3104 -- For Ada, check if it is a valid unit name
3106 if Lang = Name_Ada then
3107 Get_Name_String (Element.Index);
3108 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
3110 if Unit = No_Name then
3111 Err_Vars.Error_Msg_Name_1 := Element.Index;
3114 "%% is not a valid unit name.",
3115 Element.Value.Location, Project);
3119 if Unit /= No_Name then
3124 Source_Dir_Rank => 0,
3127 File_Name => File_Name,
3128 Display_File => File_Name_Type (Element.Value.Value),
3131 Location => Element.Value.Location,
3132 Naming_Exception => True);
3135 Exceptions := Element.Next;
3137 end Process_Exceptions_Unit_Based;
3143 procedure Check_Naming is
3144 Dot_Replacement : File_Name_Type :=
3146 (First_Name_Id + Character'Pos ('-'));
3147 Separate_Suffix : File_Name_Type := No_File;
3148 Casing : Casing_Type := All_Lower_Case;
3149 Casing_Defined : Boolean;
3150 Lang_Id : Language_Ptr;
3151 Sep_Suffix_Loc : Source_Ptr;
3152 Suffix : Variable_Value;
3157 (Dot_Replacement => Dot_Replacement,
3159 Casing_Defined => Casing_Defined,
3160 Separate_Suffix => Separate_Suffix,
3161 Sep_Suffix_Loc => Sep_Suffix_Loc);
3163 -- For all unit based languages, if any, set the specified value
3164 -- of Dot_Replacement, Casing and/or Separate_Suffix. Do not
3165 -- systematically overwrite, since the defaults come from the
3166 -- configuration file.
3168 if Dot_Replacement /= No_File
3169 or else Casing_Defined
3170 or else Separate_Suffix /= No_File
3172 Lang_Id := Project.Languages;
3173 while Lang_Id /= No_Language_Index loop
3174 if Lang_Id.Config.Kind = Unit_Based then
3175 if Dot_Replacement /= No_File then
3176 Lang_Id.Config.Naming_Data.Dot_Replacement :=
3180 if Casing_Defined then
3181 Lang_Id.Config.Naming_Data.Casing := Casing;
3185 Lang_Id := Lang_Id.Next;
3189 -- Next, get the spec and body suffixes
3191 Lang_Id := Project.Languages;
3192 while Lang_Id /= No_Language_Index loop
3193 Lang := Lang_Id.Name;
3199 Attribute_Or_Array_Name => Name_Spec_Suffix,
3200 In_Package => Naming_Id,
3201 In_Tree => Data.Tree);
3203 if Suffix = Nil_Variable_Value then
3206 Attribute_Or_Array_Name => Name_Specification_Suffix,
3207 In_Package => Naming_Id,
3208 In_Tree => Data.Tree);
3211 if Suffix /= Nil_Variable_Value then
3212 Lang_Id.Config.Naming_Data.Spec_Suffix :=
3213 File_Name_Type (Suffix.Value);
3215 Check_Illegal_Suffix
3217 Lang_Id.Config.Naming_Data.Spec_Suffix,
3218 Lang_Id.Config.Naming_Data.Dot_Replacement,
3219 "Spec_Suffix", Suffix.Location, Data);
3223 Get_Name_String (Lang_Id.Config.Naming_Data.Spec_Suffix));
3231 Attribute_Or_Array_Name => Name_Body_Suffix,
3232 In_Package => Naming_Id,
3233 In_Tree => Data.Tree);
3235 if Suffix = Nil_Variable_Value then
3239 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3240 In_Package => Naming_Id,
3241 In_Tree => Data.Tree);
3244 if Suffix /= Nil_Variable_Value then
3245 Lang_Id.Config.Naming_Data.Body_Suffix :=
3246 File_Name_Type (Suffix.Value);
3248 -- The default value of separate suffix should be the same as
3249 -- the body suffix, so we need to compute that first.
3251 if Separate_Suffix = No_File then
3252 Lang_Id.Config.Naming_Data.Separate_Suffix :=
3253 Lang_Id.Config.Naming_Data.Body_Suffix;
3257 (Lang_Id.Config.Naming_Data.Separate_Suffix));
3259 Lang_Id.Config.Naming_Data.Separate_Suffix :=
3263 Check_Illegal_Suffix
3265 Lang_Id.Config.Naming_Data.Body_Suffix,
3266 Lang_Id.Config.Naming_Data.Dot_Replacement,
3267 "Body_Suffix", Suffix.Location, Data);
3271 Get_Name_String (Lang_Id.Config.Naming_Data.Body_Suffix));
3273 elsif Separate_Suffix /= No_File then
3274 Lang_Id.Config.Naming_Data.Separate_Suffix := Separate_Suffix;
3277 -- Spec_Suffix cannot be equal to Body_Suffix or Separate_Suffix,
3278 -- since that would cause a clear ambiguity. Note that we do allow
3279 -- a Spec_Suffix to have the same termination as one of these,
3280 -- which causes a potential ambiguity, but we resolve that my
3281 -- matching the longest possible suffix.
3283 if Lang_Id.Config.Naming_Data.Spec_Suffix /= No_File
3284 and then Lang_Id.Config.Naming_Data.Spec_Suffix =
3285 Lang_Id.Config.Naming_Data.Body_Suffix
3290 & Get_Name_String (Lang_Id.Config.Naming_Data.Body_Suffix)
3291 & """) cannot be the same as Spec_Suffix.",
3292 Ada_Body_Suffix_Loc, Project);
3295 if Lang_Id.Config.Naming_Data.Body_Suffix /=
3296 Lang_Id.Config.Naming_Data.Separate_Suffix
3297 and then Lang_Id.Config.Naming_Data.Spec_Suffix =
3298 Lang_Id.Config.Naming_Data.Separate_Suffix
3302 "Separate_Suffix ("""
3304 (Lang_Id.Config.Naming_Data.Separate_Suffix)
3305 & """) cannot be the same as Spec_Suffix.",
3306 Sep_Suffix_Loc, Project);
3309 Lang_Id := Lang_Id.Next;
3312 -- Get the naming exceptions for all languages
3314 for Kind in Spec_Or_Body loop
3315 Lang_Id := Project.Languages;
3316 while Lang_Id /= No_Language_Index loop
3317 case Lang_Id.Config.Kind is
3319 Process_Exceptions_File_Based (Lang_Id, Kind);
3322 Process_Exceptions_Unit_Based (Lang_Id, Kind);
3325 Lang_Id := Lang_Id.Next;
3330 ----------------------------
3331 -- Initialize_Naming_Data --
3332 ----------------------------
3334 procedure Initialize_Naming_Data is
3335 Specs : Array_Element_Id :=
3341 Impls : Array_Element_Id :=
3347 Lang : Language_Ptr;
3348 Lang_Name : Name_Id;
3349 Value : Variable_Value;
3350 Extended : Project_Id;
3353 -- At this stage, the project already contains the default extensions
3354 -- for the various languages. We now merge those suffixes read in the
3355 -- user project, and they override the default.
3357 while Specs /= No_Array_Element loop
3358 Lang_Name := Data.Tree.Array_Elements.Table (Specs).Index;
3360 Get_Language_From_Name
3361 (Project, Name => Get_Name_String (Lang_Name));
3363 -- An extending project inherits its parent projects' languages
3364 -- so if needed we should create entries for those languages
3367 Extended := Project.Extends;
3368 while Extended /= null loop
3369 Lang := Get_Language_From_Name
3370 (Extended, Name => Get_Name_String (Lang_Name));
3371 exit when Lang /= null;
3373 Extended := Extended.Extends;
3376 if Lang /= null then
3377 Lang := new Language_Data'(Lang.all);
3378 Lang.First_Source := null;
3379 Lang.Next := Project.Languages;
3380 Project.Languages := Lang;
3384 -- If language was not found in project or the projects it extends
3387 if Current_Verbosity = High then
3389 ("Ignoring spec naming data for "
3390 & Get_Name_String (Lang_Name)
3391 & " since language is not defined for this project");
3395 Value := Data.Tree.Array_Elements.Table (Specs).Value;
3397 if Value.Kind = Single then
3398 Lang.Config.Naming_Data.Spec_Suffix :=
3399 Canonical_Case_File_Name (Value.Value);
3403 Specs := Data.Tree.Array_Elements.Table (Specs).Next;
3406 while Impls /= No_Array_Element loop
3407 Lang_Name := Data.Tree.Array_Elements.Table (Impls).Index;
3409 Get_Language_From_Name
3410 (Project, Name => Get_Name_String (Lang_Name));
3413 if Current_Verbosity = High then
3415 ("Ignoring impl naming data for "
3416 & Get_Name_String (Lang_Name)
3417 & " since language is not defined for this project");
3420 Value := Data.Tree.Array_Elements.Table (Impls).Value;
3422 if Lang.Name = Name_Ada then
3423 Ada_Body_Suffix_Loc := Value.Location;
3426 if Value.Kind = Single then
3427 Lang.Config.Naming_Data.Body_Suffix :=
3428 Canonical_Case_File_Name (Value.Value);
3432 Impls := Data.Tree.Array_Elements.Table (Impls).Next;
3434 end Initialize_Naming_Data;
3436 -- Start of processing for Check_Naming_Schemes
3439 -- No Naming package or parsing a configuration file? nothing to do
3441 if Naming_Id /= No_Package
3442 and then Project.Qualifier /= Configuration
3444 Naming := Data.Tree.Packages.Table (Naming_Id);
3446 if Current_Verbosity = High then
3447 Write_Line ("Checking package Naming for project "
3448 & Get_Name_String (Project.Name));
3451 Initialize_Naming_Data;
3454 end Check_Package_Naming;
3456 ------------------------------
3457 -- Check_Library_Attributes --
3458 ------------------------------
3460 procedure Check_Library_Attributes
3461 (Project : Project_Id;
3462 Data : in out Tree_Processing_Data)
3464 Attributes : constant Prj.Variable_Id := Project.Decl.Attributes;
3466 Lib_Dir : constant Prj.Variable_Value :=
3468 (Snames.Name_Library_Dir, Attributes, Data.Tree);
3470 Lib_Name : constant Prj.Variable_Value :=
3472 (Snames.Name_Library_Name, Attributes, Data.Tree);
3474 Lib_Version : constant Prj.Variable_Value :=
3476 (Snames.Name_Library_Version, Attributes, Data.Tree);
3478 Lib_ALI_Dir : constant Prj.Variable_Value :=
3480 (Snames.Name_Library_Ali_Dir, Attributes, Data.Tree);
3482 Lib_GCC : constant Prj.Variable_Value :=
3484 (Snames.Name_Library_GCC, Attributes, Data.Tree);
3486 The_Lib_Kind : constant Prj.Variable_Value :=
3488 (Snames.Name_Library_Kind, Attributes, Data.Tree);
3490 Imported_Project_List : Project_List;
3492 Continuation : String_Access := No_Continuation_String'Access;
3494 Support_For_Libraries : Library_Support;
3496 Library_Directory_Present : Boolean;
3498 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3499 -- Check if an imported or extended project if also a library project
3505 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3507 Iter : Source_Iterator;
3510 if Proj /= No_Project then
3511 if not Proj.Library then
3513 -- The only not library projects that are OK are those that
3514 -- have no sources. However, header files from non-Ada
3515 -- languages are OK, as there is nothing to compile.
3517 Iter := For_Each_Source (Data.Tree, Proj);
3519 Src_Id := Prj.Element (Iter);
3520 exit when Src_Id = No_Source
3521 or else Src_Id.Language.Config.Kind /= File_Based
3522 or else Src_Id.Kind /= Spec;
3526 if Src_Id /= No_Source then
3527 Error_Msg_Name_1 := Project.Name;
3528 Error_Msg_Name_2 := Proj.Name;
3531 if Project.Library_Kind /= Static then
3535 "shared library project %% cannot extend " &
3536 "project %% that is not a library project",
3537 Project.Location, Project);
3538 Continuation := Continuation_String'Access;
3541 elsif (not Unchecked_Shared_Lib_Imports)
3542 and then Project.Library_Kind /= Static
3547 "shared library project %% cannot import project %% " &
3548 "that is not a shared library project",
3549 Project.Location, Project);
3550 Continuation := Continuation_String'Access;
3554 elsif Project.Library_Kind /= Static and then
3555 Proj.Library_Kind = Static
3557 Error_Msg_Name_1 := Project.Name;
3558 Error_Msg_Name_2 := Proj.Name;
3564 "shared library project %% cannot extend static " &
3565 "library project %%",
3566 Project.Location, Project);
3567 Continuation := Continuation_String'Access;
3569 elsif not Unchecked_Shared_Lib_Imports then
3573 "shared library project %% cannot import static " &
3574 "library project %%",
3575 Project.Location, Project);
3576 Continuation := Continuation_String'Access;
3583 Dir_Exists : Boolean;
3585 -- Start of processing for Check_Library_Attributes
3588 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3590 -- Special case of extending project
3592 if Project.Extends /= No_Project then
3594 -- If the project extended is a library project, we inherit the
3595 -- library name, if it is not redefined; we check that the library
3596 -- directory is specified.
3598 if Project.Extends.Library then
3599 if Project.Qualifier = Standard then
3602 "a standard project cannot extend a library project",
3603 Project.Location, Project);
3606 if Lib_Name.Default then
3607 Project.Library_Name := Project.Extends.Library_Name;
3610 if Lib_Dir.Default then
3611 if not Project.Virtual then
3614 "a project extending a library project must " &
3615 "specify an attribute Library_Dir",
3616 Project.Location, Project);
3619 -- For a virtual project extending a library project,
3620 -- inherit library directory.
3622 Project.Library_Dir := Project.Extends.Library_Dir;
3623 Library_Directory_Present := True;
3630 pragma Assert (Lib_Name.Kind = Single);
3632 if Lib_Name.Value = Empty_String then
3633 if Current_Verbosity = High
3634 and then Project.Library_Name = No_Name
3636 Write_Line ("No library name");
3640 -- There is no restriction on the syntax of library names
3642 Project.Library_Name := Lib_Name.Value;
3645 if Project.Library_Name /= No_Name then
3646 if Current_Verbosity = High then
3648 ("Library name", Get_Name_String (Project.Library_Name));
3651 pragma Assert (Lib_Dir.Kind = Single);
3653 if not Library_Directory_Present then
3654 if Current_Verbosity = High then
3655 Write_Line ("No library directory");
3659 -- Find path name (unless inherited), check that it is a directory
3661 if Project.Library_Dir = No_Path_Information then
3664 File_Name_Type (Lib_Dir.Value),
3665 Path => Project.Library_Dir,
3666 Dir_Exists => Dir_Exists,
3668 Create => "library",
3669 Must_Exist => False,
3670 Location => Lib_Dir.Location,
3671 Externally_Built => Project.Externally_Built);
3677 (Project.Library_Dir.Display_Name));
3680 if not Dir_Exists then
3682 -- Get the absolute name of the library directory that
3683 -- does not exist, to report an error.
3685 Err_Vars.Error_Msg_File_1 :=
3686 File_Name_Type (Project.Library_Dir.Display_Name);
3689 "library directory { does not exist",
3690 Lib_Dir.Location, Project);
3692 elsif not Project.Externally_Built then
3694 -- The library directory cannot be the same as the Object
3697 if Project.Library_Dir.Name = Project.Object_Directory.Name then
3700 "library directory cannot be the same " &
3701 "as object directory",
3702 Lib_Dir.Location, Project);
3703 Project.Library_Dir := No_Path_Information;
3707 OK : Boolean := True;
3708 Dirs_Id : String_List_Id;
3709 Dir_Elem : String_Element;
3713 -- The library directory cannot be the same as a source
3714 -- directory of the current project.
3716 Dirs_Id := Project.Source_Dirs;
3717 while Dirs_Id /= Nil_String loop
3718 Dir_Elem := Data.Tree.String_Elements.Table (Dirs_Id);
3719 Dirs_Id := Dir_Elem.Next;
3721 if Project.Library_Dir.Name =
3722 Path_Name_Type (Dir_Elem.Value)
3724 Err_Vars.Error_Msg_File_1 :=
3725 File_Name_Type (Dir_Elem.Value);
3728 "library directory cannot be the same " &
3729 "as source directory {",
3730 Lib_Dir.Location, Project);
3738 -- The library directory cannot be the same as a
3739 -- source directory of another project either.
3741 Pid := Data.Tree.Projects;
3743 exit Project_Loop when Pid = null;
3745 if Pid.Project /= Project then
3746 Dirs_Id := Pid.Project.Source_Dirs;
3748 Dir_Loop : while Dirs_Id /= Nil_String loop
3750 Data.Tree.String_Elements.Table (Dirs_Id);
3751 Dirs_Id := Dir_Elem.Next;
3753 if Project.Library_Dir.Name =
3754 Path_Name_Type (Dir_Elem.Value)
3756 Err_Vars.Error_Msg_File_1 :=
3757 File_Name_Type (Dir_Elem.Value);
3758 Err_Vars.Error_Msg_Name_1 :=
3763 "library directory cannot be the same" &
3764 " as source directory { of project %%",
3765 Lib_Dir.Location, Project);
3773 end loop Project_Loop;
3777 Project.Library_Dir := No_Path_Information;
3779 elsif Current_Verbosity = High then
3781 -- Display the Library directory in high verbosity
3784 ("Library directory",
3785 Get_Name_String (Project.Library_Dir.Display_Name));
3795 Project.Library_Dir /= No_Path_Information
3796 and then Project.Library_Name /= No_Name;
3798 if Project.Extends = No_Project then
3799 case Project.Qualifier is
3801 if Project.Library then
3804 "a standard project cannot be a library project",
3805 Lib_Name.Location, Project);
3809 if not Project.Library then
3810 if Project.Library_Dir = No_Path_Information then
3813 "\attribute Library_Dir not declared",
3814 Project.Location, Project);
3817 if Project.Library_Name = No_Name then
3820 "\attribute Library_Name not declared",
3821 Project.Location, Project);
3831 if Project.Library then
3832 Support_For_Libraries := Project.Config.Lib_Support;
3834 if Support_For_Libraries = Prj.None then
3837 "?libraries are not supported on this platform",
3838 Lib_Name.Location, Project);
3839 Project.Library := False;
3842 if Lib_ALI_Dir.Value = Empty_String then
3843 if Current_Verbosity = High then
3844 Write_Line ("No library ALI directory specified");
3847 Project.Library_ALI_Dir := Project.Library_Dir;
3850 -- Find path name, check that it is a directory
3854 File_Name_Type (Lib_ALI_Dir.Value),
3855 Path => Project.Library_ALI_Dir,
3856 Create => "library ALI",
3857 Dir_Exists => Dir_Exists,
3859 Must_Exist => False,
3860 Location => Lib_ALI_Dir.Location,
3861 Externally_Built => Project.Externally_Built);
3863 if not Dir_Exists then
3865 -- Get the absolute name of the library ALI directory that
3866 -- does not exist, to report an error.
3868 Err_Vars.Error_Msg_File_1 :=
3869 File_Name_Type (Project.Library_ALI_Dir.Display_Name);
3872 "library 'A'L'I directory { does not exist",
3873 Lib_ALI_Dir.Location, Project);
3876 if (not Project.Externally_Built) and then
3877 Project.Library_ALI_Dir /= Project.Library_Dir
3879 -- The library ALI directory cannot be the same as the
3880 -- Object directory.
3882 if Project.Library_ALI_Dir = Project.Object_Directory then
3885 "library 'A'L'I directory cannot be the same " &
3886 "as object directory",
3887 Lib_ALI_Dir.Location, Project);
3888 Project.Library_ALI_Dir := No_Path_Information;
3892 OK : Boolean := True;
3893 Dirs_Id : String_List_Id;
3894 Dir_Elem : String_Element;
3898 -- The library ALI directory cannot be the same as
3899 -- a source directory of the current project.
3901 Dirs_Id := Project.Source_Dirs;
3902 while Dirs_Id /= Nil_String loop
3904 Data.Tree.String_Elements.Table (Dirs_Id);
3905 Dirs_Id := Dir_Elem.Next;
3907 if Project.Library_ALI_Dir.Name =
3908 Path_Name_Type (Dir_Elem.Value)
3910 Err_Vars.Error_Msg_File_1 :=
3911 File_Name_Type (Dir_Elem.Value);
3914 "library 'A'L'I directory cannot be " &
3915 "the same as source directory {",
3916 Lib_ALI_Dir.Location, Project);
3924 -- The library ALI directory cannot be the same as
3925 -- a source directory of another project either.
3927 Pid := Data.Tree.Projects;
3928 ALI_Project_Loop : loop
3929 exit ALI_Project_Loop when Pid = null;
3931 if Pid.Project /= Project then
3932 Dirs_Id := Pid.Project.Source_Dirs;
3935 while Dirs_Id /= Nil_String loop
3937 Data.Tree.String_Elements.Table
3939 Dirs_Id := Dir_Elem.Next;
3941 if Project.Library_ALI_Dir.Name =
3942 Path_Name_Type (Dir_Elem.Value)
3944 Err_Vars.Error_Msg_File_1 :=
3945 File_Name_Type (Dir_Elem.Value);
3946 Err_Vars.Error_Msg_Name_1 :=
3951 "library 'A'L'I directory cannot " &
3952 "be the same as source directory " &
3954 Lib_ALI_Dir.Location, Project);
3956 exit ALI_Project_Loop;
3958 end loop ALI_Dir_Loop;
3961 end loop ALI_Project_Loop;
3965 Project.Library_ALI_Dir := No_Path_Information;
3967 elsif Current_Verbosity = High then
3969 -- Display Library ALI directory in high verbosity
3974 (Project.Library_ALI_Dir.Display_Name));
3981 pragma Assert (Lib_Version.Kind = Single);
3983 if Lib_Version.Value = Empty_String then
3984 if Current_Verbosity = High then
3985 Write_Line ("No library version specified");
3989 Project.Lib_Internal_Name := Lib_Version.Value;
3992 pragma Assert (The_Lib_Kind.Kind = Single);
3994 if The_Lib_Kind.Value = Empty_String then
3995 if Current_Verbosity = High then
3996 Write_Line ("No library kind specified");
4000 Get_Name_String (The_Lib_Kind.Value);
4003 Kind_Name : constant String :=
4004 To_Lower (Name_Buffer (1 .. Name_Len));
4006 OK : Boolean := True;
4009 if Kind_Name = "static" then
4010 Project.Library_Kind := Static;
4012 elsif Kind_Name = "dynamic" then
4013 Project.Library_Kind := Dynamic;
4015 elsif Kind_Name = "relocatable" then
4016 Project.Library_Kind := Relocatable;
4021 "illegal value for Library_Kind",
4022 The_Lib_Kind.Location, Project);
4026 if Current_Verbosity = High and then OK then
4027 Write_Attr ("Library kind", Kind_Name);
4030 if Project.Library_Kind /= Static then
4031 if Support_For_Libraries = Prj.Static_Only then
4034 "only static libraries are supported " &
4036 The_Lib_Kind.Location, Project);
4037 Project.Library := False;
4040 -- Check if (obsolescent) attribute Library_GCC or
4041 -- Linker'Driver is declared.
4043 if Lib_GCC.Value /= Empty_String then
4046 "?Library_'G'C'C is an obsolescent attribute, " &
4047 "use Linker''Driver instead",
4048 Lib_GCC.Location, Project);
4049 Project.Config.Shared_Lib_Driver :=
4050 File_Name_Type (Lib_GCC.Value);
4054 Linker : constant Package_Id :=
4057 Project.Decl.Packages,
4059 Driver : constant Variable_Value :=
4062 Attribute_Or_Array_Name =>
4064 In_Package => Linker,
4065 In_Tree => Data.Tree);
4068 if Driver /= Nil_Variable_Value
4069 and then Driver.Value /= Empty_String
4071 Project.Config.Shared_Lib_Driver :=
4072 File_Name_Type (Driver.Value);
4081 if Project.Library then
4082 if Current_Verbosity = High then
4083 Write_Line ("This is a library project file");
4086 Check_Library (Project.Extends, Extends => True);
4088 Imported_Project_List := Project.Imported_Projects;
4089 while Imported_Project_List /= null loop
4091 (Imported_Project_List.Project,
4093 Imported_Project_List := Imported_Project_List.Next;
4100 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4101 -- Warn if they are declared, as it is a common error to think that
4102 -- library are "linked" with Linker switches.
4104 if Project.Library then
4106 Linker_Package_Id : constant Package_Id :=
4109 Project.Decl.Packages, Data.Tree);
4110 Linker_Package : Package_Element;
4111 Switches : Array_Element_Id := No_Array_Element;
4114 if Linker_Package_Id /= No_Package then
4115 Linker_Package := Data.Tree.Packages.Table (Linker_Package_Id);
4119 (Name => Name_Switches,
4120 In_Arrays => Linker_Package.Decl.Arrays,
4121 In_Tree => Data.Tree);
4123 if Switches = No_Array_Element then
4126 (Name => Name_Default_Switches,
4127 In_Arrays => Linker_Package.Decl.Arrays,
4128 In_Tree => Data.Tree);
4131 if Switches /= No_Array_Element then
4134 "?Linker switches not taken into account in library " &
4136 No_Location, Project);
4142 if Project.Extends /= No_Project and then Project.Extends.Library then
4144 -- Remove the library name from Lib_Data_Table
4146 for J in 1 .. Lib_Data_Table.Last loop
4147 if Lib_Data_Table.Table (J).Proj = Project.Extends then
4148 Lib_Data_Table.Table (J) :=
4149 Lib_Data_Table.Table (Lib_Data_Table.Last);
4150 Lib_Data_Table.Set_Last (Lib_Data_Table.Last - 1);
4155 Project.Extends.Library := False;
4158 if Project.Library and then not Lib_Name.Default then
4160 -- Check if the same library name is used in an other library project
4162 for J in 1 .. Lib_Data_Table.Last loop
4163 if Lib_Data_Table.Table (J).Name = Project.Library_Name then
4164 Error_Msg_Name_1 := Lib_Data_Table.Table (J).Proj.Name;
4167 "Library name cannot be the same as in project %%",
4168 Lib_Name.Location, Project);
4169 Project.Library := False;
4175 if Project.Library then
4177 -- Record the library name
4179 Lib_Data_Table.Append
4180 ((Name => Project.Library_Name, Proj => Project));
4182 end Check_Library_Attributes;
4184 ---------------------------------
4185 -- Check_Programming_Languages --
4186 ---------------------------------
4188 procedure Check_Programming_Languages
4189 (Project : Project_Id;
4190 Data : in out Tree_Processing_Data)
4192 Languages : Variable_Value := Nil_Variable_Value;
4193 Def_Lang : Variable_Value := Nil_Variable_Value;
4194 Def_Lang_Id : Name_Id;
4196 procedure Add_Language (Name, Display_Name : Name_Id);
4197 -- Add a new language to the list of languages for the project.
4198 -- Nothing is done if the language has already been defined
4204 procedure Add_Language (Name, Display_Name : Name_Id) is
4205 Lang : Language_Ptr;
4208 Lang := Project.Languages;
4209 while Lang /= No_Language_Index loop
4210 if Name = Lang.Name then
4217 Lang := new Language_Data'(No_Language_Data);
4218 Lang.Next := Project.Languages;
4219 Project.Languages := Lang;
4221 Lang.Display_Name := Display_Name;
4223 if Name = Name_Ada then
4224 Lang.Config.Kind := Unit_Based;
4225 Lang.Config.Dependency_Kind := ALI_File;
4227 Lang.Config.Kind := File_Based;
4231 -- Start of processing for Check_Programming_Languages
4234 Project.Languages := null;
4236 Prj.Util.Value_Of (Name_Languages, Project.Decl.Attributes, Data.Tree);
4239 (Name_Default_Language, Project.Decl.Attributes, Data.Tree);
4241 if Project.Source_Dirs /= Nil_String then
4243 -- Check if languages are specified in this project
4245 if Languages.Default then
4247 -- Fail if there is no default language defined
4249 if Def_Lang.Default then
4252 "no languages defined for this project",
4253 Project.Location, Project);
4254 Def_Lang_Id := No_Name;
4257 Get_Name_String (Def_Lang.Value);
4258 To_Lower (Name_Buffer (1 .. Name_Len));
4259 Def_Lang_Id := Name_Find;
4262 if Def_Lang_Id /= No_Name then
4263 Get_Name_String (Def_Lang_Id);
4264 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4266 (Name => Def_Lang_Id,
4267 Display_Name => Name_Find);
4272 Current : String_List_Id := Languages.Values;
4273 Element : String_Element;
4276 -- If there are no languages declared, there are no sources
4278 if Current = Nil_String then
4279 Project.Source_Dirs := Nil_String;
4281 if Project.Qualifier = Standard then
4284 "a standard project must have at least one language",
4285 Languages.Location, Project);
4289 -- Look through all the languages specified in attribute
4292 while Current /= Nil_String loop
4293 Element := Data.Tree.String_Elements.Table (Current);
4294 Get_Name_String (Element.Value);
4295 To_Lower (Name_Buffer (1 .. Name_Len));
4299 Display_Name => Element.Value);
4301 Current := Element.Next;
4307 end Check_Programming_Languages;
4309 -------------------------------
4310 -- Check_Stand_Alone_Library --
4311 -------------------------------
4313 procedure Check_Stand_Alone_Library
4314 (Project : Project_Id;
4315 Data : in out Tree_Processing_Data)
4317 Lib_Interfaces : constant Prj.Variable_Value :=
4319 (Snames.Name_Library_Interface,
4320 Project.Decl.Attributes,
4323 Lib_Auto_Init : constant Prj.Variable_Value :=
4325 (Snames.Name_Library_Auto_Init,
4326 Project.Decl.Attributes,
4329 Lib_Src_Dir : constant Prj.Variable_Value :=
4331 (Snames.Name_Library_Src_Dir,
4332 Project.Decl.Attributes,
4335 Lib_Symbol_File : constant Prj.Variable_Value :=
4337 (Snames.Name_Library_Symbol_File,
4338 Project.Decl.Attributes,
4341 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4343 (Snames.Name_Library_Symbol_Policy,
4344 Project.Decl.Attributes,
4347 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4349 (Snames.Name_Library_Reference_Symbol_File,
4350 Project.Decl.Attributes,
4353 Auto_Init_Supported : Boolean;
4354 OK : Boolean := True;
4356 Next_Proj : Project_Id;
4357 Iter : Source_Iterator;
4360 Auto_Init_Supported := Project.Config.Auto_Init_Supported;
4362 pragma Assert (Lib_Interfaces.Kind = List);
4364 -- It is a stand-alone library project file if attribute
4365 -- Library_Interface is defined.
4367 if not Lib_Interfaces.Default then
4369 Interfaces : String_List_Id := Lib_Interfaces.Values;
4370 Interface_ALIs : String_List_Id := Nil_String;
4374 Project.Standalone_Library := True;
4376 -- Library_Interface cannot be an empty list
4378 if Interfaces = Nil_String then
4381 "Library_Interface cannot be an empty list",
4382 Lib_Interfaces.Location, Project);
4385 -- Process each unit name specified in the attribute
4386 -- Library_Interface.
4388 while Interfaces /= Nil_String loop
4390 (Data.Tree.String_Elements.Table (Interfaces).Value);
4391 To_Lower (Name_Buffer (1 .. Name_Len));
4393 if Name_Len = 0 then
4396 "an interface cannot be an empty string",
4397 Data.Tree.String_Elements.Table (Interfaces).Location,
4402 Error_Msg_Name_1 := Unit;
4404 Next_Proj := Project.Extends;
4405 Iter := For_Each_Source (Data.Tree, Project);
4407 while Prj.Element (Iter) /= No_Source
4409 (Prj.Element (Iter).Unit = null
4410 or else Prj.Element (Iter).Unit.Name /= Unit)
4415 Source := Prj.Element (Iter);
4416 exit when Source /= No_Source
4417 or else Next_Proj = No_Project;
4419 Iter := For_Each_Source (Data.Tree, Next_Proj);
4420 Next_Proj := Next_Proj.Extends;
4423 if Source /= No_Source then
4424 if Source.Kind = Sep then
4425 Source := No_Source;
4427 elsif Source.Kind = Spec
4428 and then Other_Part (Source) /= No_Source
4430 Source := Other_Part (Source);
4434 if Source /= No_Source then
4435 if Source.Project /= Project
4436 and then not Is_Extending (Project, Source.Project)
4438 Source := No_Source;
4442 if Source = No_Source then
4445 "%% is not a unit of this project",
4446 Data.Tree.String_Elements.Table
4447 (Interfaces).Location, Project);
4450 if Source.Kind = Spec
4451 and then Other_Part (Source) /= No_Source
4453 Source := Other_Part (Source);
4456 String_Element_Table.Increment_Last
4457 (Data.Tree.String_Elements);
4459 Data.Tree.String_Elements.Table
4460 (String_Element_Table.Last
4461 (Data.Tree.String_Elements)) :=
4462 (Value => Name_Id (Source.Dep_Name),
4464 Display_Value => Name_Id (Source.Dep_Name),
4466 Data.Tree.String_Elements.Table
4467 (Interfaces).Location,
4469 Next => Interface_ALIs);
4472 String_Element_Table.Last
4473 (Data.Tree.String_Elements);
4477 Interfaces := Data.Tree.String_Elements.Table (Interfaces).Next;
4480 -- Put the list of Interface ALIs in the project data
4482 Project.Lib_Interface_ALIs := Interface_ALIs;
4484 -- Check value of attribute Library_Auto_Init and set
4485 -- Lib_Auto_Init accordingly.
4487 if Lib_Auto_Init.Default then
4489 -- If no attribute Library_Auto_Init is declared, then set auto
4490 -- init only if it is supported.
4492 Project.Lib_Auto_Init := Auto_Init_Supported;
4495 Get_Name_String (Lib_Auto_Init.Value);
4496 To_Lower (Name_Buffer (1 .. Name_Len));
4498 if Name_Buffer (1 .. Name_Len) = "false" then
4499 Project.Lib_Auto_Init := False;
4501 elsif Name_Buffer (1 .. Name_Len) = "true" then
4502 if Auto_Init_Supported then
4503 Project.Lib_Auto_Init := True;
4506 -- Library_Auto_Init cannot be "true" if auto init is not
4511 "library auto init not supported " &
4513 Lib_Auto_Init.Location, Project);
4519 "invalid value for attribute Library_Auto_Init",
4520 Lib_Auto_Init.Location, Project);
4525 -- If attribute Library_Src_Dir is defined and not the empty string,
4526 -- check if the directory exist and is not the object directory or
4527 -- one of the source directories. This is the directory where copies
4528 -- of the interface sources will be copied. Note that this directory
4529 -- may be the library directory.
4531 if Lib_Src_Dir.Value /= Empty_String then
4533 Dir_Id : constant File_Name_Type :=
4534 File_Name_Type (Lib_Src_Dir.Value);
4535 Dir_Exists : Boolean;
4541 Path => Project.Library_Src_Dir,
4542 Dir_Exists => Dir_Exists,
4544 Must_Exist => False,
4545 Create => "library source copy",
4546 Location => Lib_Src_Dir.Location,
4547 Externally_Built => Project.Externally_Built);
4549 -- If directory does not exist, report an error
4551 if not Dir_Exists then
4553 -- Get the absolute name of the library directory that does
4554 -- not exist, to report an error.
4556 Err_Vars.Error_Msg_File_1 :=
4557 File_Name_Type (Project.Library_Src_Dir.Display_Name);
4560 "Directory { does not exist",
4561 Lib_Src_Dir.Location, Project);
4563 -- Report error if it is the same as the object directory
4565 elsif Project.Library_Src_Dir = Project.Object_Directory then
4568 "directory to copy interfaces cannot be " &
4569 "the object directory",
4570 Lib_Src_Dir.Location, Project);
4571 Project.Library_Src_Dir := No_Path_Information;
4575 Src_Dirs : String_List_Id;
4576 Src_Dir : String_Element;
4580 -- Interface copy directory cannot be one of the source
4581 -- directory of the current project.
4583 Src_Dirs := Project.Source_Dirs;
4584 while Src_Dirs /= Nil_String loop
4585 Src_Dir := Data.Tree.String_Elements.Table (Src_Dirs);
4587 -- Report error if it is one of the source directories
4589 if Project.Library_Src_Dir.Name =
4590 Path_Name_Type (Src_Dir.Value)
4594 "directory to copy interfaces cannot " &
4595 "be one of the source directories",
4596 Lib_Src_Dir.Location, Project);
4597 Project.Library_Src_Dir := No_Path_Information;
4601 Src_Dirs := Src_Dir.Next;
4604 if Project.Library_Src_Dir /= No_Path_Information then
4606 -- It cannot be a source directory of any other
4609 Pid := Data.Tree.Projects;
4611 exit Project_Loop when Pid = null;
4613 Src_Dirs := Pid.Project.Source_Dirs;
4614 Dir_Loop : while Src_Dirs /= Nil_String loop
4616 Data.Tree.String_Elements.Table (Src_Dirs);
4618 -- Report error if it is one of the source
4621 if Project.Library_Src_Dir.Name =
4622 Path_Name_Type (Src_Dir.Value)
4625 File_Name_Type (Src_Dir.Value);
4626 Error_Msg_Name_1 := Pid.Project.Name;
4629 "directory to copy interfaces cannot " &
4630 "be the same as source directory { of " &
4632 Lib_Src_Dir.Location, Project);
4633 Project.Library_Src_Dir :=
4634 No_Path_Information;
4638 Src_Dirs := Src_Dir.Next;
4642 end loop Project_Loop;
4646 -- In high verbosity, if there is a valid Library_Src_Dir,
4647 -- display its path name.
4649 if Project.Library_Src_Dir /= No_Path_Information
4650 and then Current_Verbosity = High
4653 ("Directory to copy interfaces",
4654 Get_Name_String (Project.Library_Src_Dir.Name));
4660 -- Check the symbol related attributes
4662 -- First, the symbol policy
4664 if not Lib_Symbol_Policy.Default then
4666 Value : constant String :=
4668 (Get_Name_String (Lib_Symbol_Policy.Value));
4671 -- Symbol policy must hove one of a limited number of values
4673 if Value = "autonomous" or else Value = "default" then
4674 Project.Symbol_Data.Symbol_Policy := Autonomous;
4676 elsif Value = "compliant" then
4677 Project.Symbol_Data.Symbol_Policy := Compliant;
4679 elsif Value = "controlled" then
4680 Project.Symbol_Data.Symbol_Policy := Controlled;
4682 elsif Value = "restricted" then
4683 Project.Symbol_Data.Symbol_Policy := Restricted;
4685 elsif Value = "direct" then
4686 Project.Symbol_Data.Symbol_Policy := Direct;
4691 "illegal value for Library_Symbol_Policy",
4692 Lib_Symbol_Policy.Location, Project);
4697 -- If attribute Library_Symbol_File is not specified, symbol policy
4698 -- cannot be Restricted.
4700 if Lib_Symbol_File.Default then
4701 if Project.Symbol_Data.Symbol_Policy = Restricted then
4704 "Library_Symbol_File needs to be defined when " &
4705 "symbol policy is Restricted",
4706 Lib_Symbol_Policy.Location, Project);
4710 -- Library_Symbol_File is defined
4712 Project.Symbol_Data.Symbol_File :=
4713 Path_Name_Type (Lib_Symbol_File.Value);
4715 Get_Name_String (Lib_Symbol_File.Value);
4717 if Name_Len = 0 then
4720 "symbol file name cannot be an empty string",
4721 Lib_Symbol_File.Location, Project);
4724 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
4727 for J in 1 .. Name_Len loop
4728 if Name_Buffer (J) = '/'
4729 or else Name_Buffer (J) = Directory_Separator
4738 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
4741 "symbol file name { is illegal. " &
4742 "Name cannot include directory info.",
4743 Lib_Symbol_File.Location, Project);
4748 -- If attribute Library_Reference_Symbol_File is not defined,
4749 -- symbol policy cannot be Compliant or Controlled.
4751 if Lib_Ref_Symbol_File.Default then
4752 if Project.Symbol_Data.Symbol_Policy = Compliant
4753 or else Project.Symbol_Data.Symbol_Policy = Controlled
4757 "a reference symbol file needs to be defined",
4758 Lib_Symbol_Policy.Location, Project);
4762 -- Library_Reference_Symbol_File is defined, check file exists
4764 Project.Symbol_Data.Reference :=
4765 Path_Name_Type (Lib_Ref_Symbol_File.Value);
4767 Get_Name_String (Lib_Ref_Symbol_File.Value);
4769 if Name_Len = 0 then
4772 "reference symbol file name cannot be an empty string",
4773 Lib_Symbol_File.Location, Project);
4776 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
4778 Add_Str_To_Name_Buffer
4779 (Get_Name_String (Project.Directory.Name));
4780 Add_Str_To_Name_Buffer
4781 (Get_Name_String (Lib_Ref_Symbol_File.Value));
4782 Project.Symbol_Data.Reference := Name_Find;
4785 if not Is_Regular_File
4786 (Get_Name_String (Project.Symbol_Data.Reference))
4789 File_Name_Type (Lib_Ref_Symbol_File.Value);
4791 -- For controlled and direct symbol policies, it is an error
4792 -- if the reference symbol file does not exist. For other
4793 -- symbol policies, this is just a warning
4796 Project.Symbol_Data.Symbol_Policy /= Controlled
4797 and then Project.Symbol_Data.Symbol_Policy /= Direct;
4801 "<library reference symbol file { does not exist",
4802 Lib_Ref_Symbol_File.Location, Project);
4804 -- In addition in the non-controlled case, if symbol policy
4805 -- is Compliant, it is changed to Autonomous, because there
4806 -- is no reference to check against, and we don't want to
4807 -- fail in this case.
4809 if Project.Symbol_Data.Symbol_Policy /= Controlled then
4810 if Project.Symbol_Data.Symbol_Policy = Compliant then
4811 Project.Symbol_Data.Symbol_Policy := Autonomous;
4816 -- If both the reference symbol file and the symbol file are
4817 -- defined, then check that they are not the same file.
4819 if Project.Symbol_Data.Symbol_File /= No_Path then
4820 Get_Name_String (Project.Symbol_Data.Symbol_File);
4822 if Name_Len > 0 then
4824 -- We do not need to pass a Directory to
4825 -- Normalize_Pathname, since the path_information
4826 -- already contains absolute information.
4828 Symb_Path : constant String :=
4831 (Project.Object_Directory.Name) &
4832 Name_Buffer (1 .. Name_Len),
4835 Opt.Follow_Links_For_Files);
4836 Ref_Path : constant String :=
4839 (Project.Symbol_Data.Reference),
4842 Opt.Follow_Links_For_Files);
4844 if Symb_Path = Ref_Path then
4847 "library reference symbol file and library" &
4848 " symbol file cannot be the same file",
4849 Lib_Ref_Symbol_File.Location, Project);
4857 end Check_Stand_Alone_Library;
4859 ----------------------------
4860 -- Compute_Directory_Last --
4861 ----------------------------
4863 function Compute_Directory_Last (Dir : String) return Natural is
4866 and then (Dir (Dir'Last - 1) = Directory_Separator
4868 Dir (Dir'Last - 1) = '/')
4870 return Dir'Last - 1;
4874 end Compute_Directory_Last;
4876 ---------------------
4877 -- Get_Directories --
4878 ---------------------
4880 procedure Get_Directories
4881 (Project : Project_Id;
4882 Data : in out Tree_Processing_Data)
4884 Object_Dir : constant Variable_Value :=
4886 (Name_Object_Dir, Project.Decl.Attributes, Data.Tree);
4888 Exec_Dir : constant Variable_Value :=
4890 (Name_Exec_Dir, Project.Decl.Attributes, Data.Tree);
4892 Source_Dirs : constant Variable_Value :=
4894 (Name_Source_Dirs, Project.Decl.Attributes, Data.Tree);
4896 Excluded_Source_Dirs : constant Variable_Value :=
4898 (Name_Excluded_Source_Dirs,
4899 Project.Decl.Attributes,
4902 Source_Files : constant Variable_Value :=
4905 Project.Decl.Attributes, Data.Tree);
4907 Last_Source_Dir : String_List_Id := Nil_String;
4908 Last_Src_Dir_Rank : Number_List_Index := No_Number_List;
4910 Languages : constant Variable_Value :=
4912 (Name_Languages, Project.Decl.Attributes, Data.Tree);
4914 Remove_Source_Dirs : Boolean := False;
4916 procedure Add_To_Or_Remove_From_Source_Dirs
4917 (Path_Id : Path_Name_Type;
4918 Display_Path_Id : Path_Name_Type;
4920 -- When Removed = False, the directory Path_Id to the list of
4921 -- source_dirs if not already in the list. When Removed = True,
4922 -- removed directory Path_Id if in the list.
4924 procedure Find_Source_Dirs is new Expand_Subdirectory_Pattern
4925 (Add_To_Or_Remove_From_Source_Dirs);
4927 ---------------------------------------
4928 -- Add_To_Or_Remove_From_Source_Dirs --
4929 ---------------------------------------
4931 procedure Add_To_Or_Remove_From_Source_Dirs
4932 (Path_Id : Path_Name_Type;
4933 Display_Path_Id : Path_Name_Type;
4936 List : String_List_Id;
4937 Prev : String_List_Id;
4938 Rank_List : Number_List_Index;
4939 Prev_Rank : Number_List_Index;
4940 Element : String_Element;
4944 Prev_Rank := No_Number_List;
4945 List := Project.Source_Dirs;
4946 Rank_List := Project.Source_Dir_Ranks;
4947 while List /= Nil_String loop
4948 Element := Data.Tree.String_Elements.Table (List);
4949 exit when Element.Value = Name_Id (Path_Id);
4951 List := Element.Next;
4952 Prev_Rank := Rank_List;
4953 Rank_List := Data.Tree.Number_Lists.Table (Prev_Rank).Next;
4956 -- The directory is in the list if List is not Nil_String
4958 if not Remove_Source_Dirs and then List = Nil_String then
4959 if Current_Verbosity = High then
4960 Write_Str (" Adding Source Dir=");
4961 Write_Line (Get_Name_String (Display_Path_Id));
4964 String_Element_Table.Increment_Last (Data.Tree.String_Elements);
4966 (Value => Name_Id (Path_Id),
4968 Display_Value => Name_Id (Display_Path_Id),
4969 Location => No_Location,
4971 Next => Nil_String);
4973 Number_List_Table.Increment_Last (Data.Tree.Number_Lists);
4975 if Last_Source_Dir = Nil_String then
4977 -- This is the first source directory
4979 Project.Source_Dirs :=
4980 String_Element_Table.Last (Data.Tree.String_Elements);
4981 Project.Source_Dir_Ranks :=
4982 Number_List_Table.Last (Data.Tree.Number_Lists);
4985 -- We already have source directories, link the previous
4986 -- last to the new one.
4988 Data.Tree.String_Elements.Table (Last_Source_Dir).Next :=
4989 String_Element_Table.Last (Data.Tree.String_Elements);
4990 Data.Tree.Number_Lists.Table (Last_Src_Dir_Rank).Next :=
4991 Number_List_Table.Last (Data.Tree.Number_Lists);
4994 -- And register this source directory as the new last
4997 String_Element_Table.Last (Data.Tree.String_Elements);
4998 Data.Tree.String_Elements.Table (Last_Source_Dir) := Element;
4999 Last_Src_Dir_Rank :=
5000 Number_List_Table.Last (Data.Tree.Number_Lists);
5001 Data.Tree.Number_Lists.Table (Last_Src_Dir_Rank) :=
5002 (Number => Rank, Next => No_Number_List);
5004 elsif Remove_Source_Dirs and then List /= Nil_String then
5006 -- Remove source dir, if present
5008 if Prev = Nil_String then
5009 Project.Source_Dirs :=
5010 Data.Tree.String_Elements.Table (List).Next;
5011 Project.Source_Dir_Ranks :=
5012 Data.Tree.Number_Lists.Table (Rank_List).Next;
5015 Data.Tree.String_Elements.Table (Prev).Next :=
5016 Data.Tree.String_Elements.Table (List).Next;
5017 Data.Tree.Number_Lists.Table (Prev_Rank).Next :=
5018 Data.Tree.Number_Lists.Table (Rank_List).Next;
5021 end Add_To_Or_Remove_From_Source_Dirs;
5023 -- Local declarations
5025 Dir_Exists : Boolean;
5027 No_Sources : constant Boolean :=
5028 ((not Source_Files.Default
5029 and then Source_Files.Values = Nil_String)
5031 (not Source_Dirs.Default
5032 and then Source_Dirs.Values = Nil_String)
5034 (not Languages.Default
5035 and then Languages.Values = Nil_String))
5036 and then Project.Extends = No_Project;
5038 -- Start of processing for Get_Directories
5041 if Current_Verbosity = High then
5042 Write_Line ("Starting to look for directories");
5045 -- Set the object directory to its default which may be nil, if there
5046 -- is no sources in the project.
5049 Project.Object_Directory := No_Path_Information;
5051 Project.Object_Directory := Project.Directory;
5054 -- Check the object directory
5056 if Object_Dir.Value /= Empty_String then
5057 Get_Name_String (Object_Dir.Value);
5059 if Name_Len = 0 then
5062 "Object_Dir cannot be empty",
5063 Object_Dir.Location, Project);
5065 elsif not No_Sources then
5067 -- We check that the specified object directory does exist.
5068 -- However, even when it doesn't exist, we set it to a default
5069 -- value. This is for the benefit of tools that recover from
5070 -- errors; for example, these tools could create the non existent
5071 -- directory. We always return an absolute directory name though.
5075 File_Name_Type (Object_Dir.Value),
5076 Path => Project.Object_Directory,
5078 Dir_Exists => Dir_Exists,
5080 Location => Object_Dir.Location,
5081 Must_Exist => False,
5082 Externally_Built => Project.Externally_Built);
5085 and then not Project.Externally_Built
5087 -- The object directory does not exist, report an error if the
5088 -- project is not externally built.
5090 Err_Vars.Error_Msg_File_1 :=
5091 File_Name_Type (Object_Dir.Value);
5093 (Data.Flags, Data.Flags.Require_Obj_Dirs,
5094 "object directory { not found", Project.Location, Project);
5098 elsif not No_Sources and then Subdirs /= null then
5100 Name_Buffer (1) := '.';
5104 Path => Project.Object_Directory,
5106 Dir_Exists => Dir_Exists,
5108 Location => Object_Dir.Location,
5109 Externally_Built => Project.Externally_Built);
5112 if Current_Verbosity = High then
5113 if Project.Object_Directory = No_Path_Information then
5114 Write_Line ("No object directory");
5117 ("Object directory",
5118 Get_Name_String (Project.Object_Directory.Display_Name));
5122 -- Check the exec directory
5124 -- We set the object directory to its default
5126 Project.Exec_Directory := Project.Object_Directory;
5128 if Exec_Dir.Value /= Empty_String then
5129 Get_Name_String (Exec_Dir.Value);
5131 if Name_Len = 0 then
5134 "Exec_Dir cannot be empty",
5135 Exec_Dir.Location, Project);
5137 elsif not No_Sources then
5139 -- We check that the specified exec directory does exist
5143 File_Name_Type (Exec_Dir.Value),
5144 Path => Project.Exec_Directory,
5145 Dir_Exists => Dir_Exists,
5148 Location => Exec_Dir.Location,
5149 Externally_Built => Project.Externally_Built);
5151 if not Dir_Exists then
5152 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
5154 (Data.Flags, Data.Flags.Missing_Source_Files,
5155 "exec directory { not found", Project.Location, Project);
5160 if Current_Verbosity = High then
5161 if Project.Exec_Directory = No_Path_Information then
5162 Write_Line ("No exec directory");
5164 Write_Str ("Exec directory: """);
5165 Write_Str (Get_Name_String (Project.Exec_Directory.Display_Name));
5170 -- Look for the source directories
5172 if Current_Verbosity = High then
5173 Write_Line ("Starting to look for source directories");
5176 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
5178 if not Source_Files.Default
5179 and then Source_Files.Values = Nil_String
5181 Project.Source_Dirs := Nil_String;
5183 if Project.Qualifier = Standard then
5186 "a standard project cannot have no sources",
5187 Source_Files.Location, Project);
5190 elsif Source_Dirs.Default then
5191 -- No Source_Dirs specified: the single source directory is the one
5192 -- containing the project file.
5194 Remove_Source_Dirs := False;
5195 Add_To_Or_Remove_From_Source_Dirs
5196 (Path_Id => Project.Directory.Name,
5197 Display_Path_Id => Project.Directory.Display_Name,
5201 Remove_Source_Dirs := False;
5203 (Project => Project,
5205 Patterns => Source_Dirs.Values,
5206 Search_For => Search_Directories,
5207 Resolve_Links => Opt.Follow_Links_For_Dirs);
5209 if Project.Source_Dirs = Nil_String
5210 and then Project.Qualifier = Standard
5214 "a standard project cannot have no source directories",
5215 Source_Dirs.Location, Project);
5219 if not Excluded_Source_Dirs.Default
5220 and then Excluded_Source_Dirs.Values /= Nil_String
5222 Remove_Source_Dirs := True;
5224 (Project => Project,
5226 Patterns => Excluded_Source_Dirs.Values,
5227 Search_For => Search_Directories,
5228 Resolve_Links => Opt.Follow_Links_For_Dirs);
5231 if Current_Verbosity = High then
5232 Write_Line ("Putting source directories in canonical cases");
5236 Current : String_List_Id := Project.Source_Dirs;
5237 Element : String_Element;
5240 while Current /= Nil_String loop
5241 Element := Data.Tree.String_Elements.Table (Current);
5242 if Element.Value /= No_Name then
5244 Name_Id (Canonical_Case_File_Name (Element.Value));
5245 Data.Tree.String_Elements.Table (Current) := Element;
5248 Current := Element.Next;
5251 end Get_Directories;
5258 (Project : Project_Id;
5259 Data : in out Tree_Processing_Data)
5261 Mains : constant Variable_Value :=
5263 (Name_Main, Project.Decl.Attributes, Data.Tree);
5264 List : String_List_Id;
5265 Elem : String_Element;
5268 Project.Mains := Mains.Values;
5270 -- If no Mains were specified, and if we are an extending project,
5271 -- inherit the Mains from the project we are extending.
5273 if Mains.Default then
5274 if not Project.Library and then Project.Extends /= No_Project then
5275 Project.Mains := Project.Extends.Mains;
5278 -- In a library project file, Main cannot be specified
5280 elsif Project.Library then
5283 "a library project file cannot have Main specified",
5284 Mains.Location, Project);
5287 List := Mains.Values;
5288 while List /= Nil_String loop
5289 Elem := Data.Tree.String_Elements.Table (List);
5291 if Length_Of_Name (Elem.Value) = 0 then
5294 "?a main cannot have an empty name",
5295 Elem.Location, Project);
5304 ---------------------------
5305 -- Get_Sources_From_File --
5306 ---------------------------
5308 procedure Get_Sources_From_File
5310 Location : Source_Ptr;
5311 Project : in out Project_Processing_Data;
5312 Data : in out Tree_Processing_Data)
5314 File : Prj.Util.Text_File;
5315 Line : String (1 .. 250);
5317 Source_Name : File_Name_Type;
5318 Name_Loc : Name_Location;
5321 if Current_Verbosity = High then
5322 Write_Str ("Opening """);
5329 Prj.Util.Open (File, Path);
5331 if not Prj.Util.Is_Valid (File) then
5333 (Data.Flags, "file does not exist", Location, Project.Project);
5336 -- Read the lines one by one
5338 while not Prj.Util.End_Of_File (File) loop
5339 Prj.Util.Get_Line (File, Line, Last);
5341 -- A non empty, non comment line should contain a file name
5344 and then (Last = 1 or else Line (1 .. 2) /= "--")
5347 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
5348 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5349 Source_Name := Name_Find;
5351 -- Check that there is no directory information
5353 for J in 1 .. Last loop
5354 if Line (J) = '/' or else Line (J) = Directory_Separator then
5355 Error_Msg_File_1 := Source_Name;
5358 "file name cannot include directory information ({)",
5359 Location, Project.Project);
5364 Name_Loc := Source_Names_Htable.Get
5365 (Project.Source_Names, Source_Name);
5367 if Name_Loc = No_Name_Location then
5369 (Name => Source_Name,
5370 Location => Location,
5371 Source => No_Source,
5376 Name_Loc.Listed := True;
5379 Source_Names_Htable.Set
5380 (Project.Source_Names, Source_Name, Name_Loc);
5384 Prj.Util.Close (File);
5387 end Get_Sources_From_File;
5389 -----------------------
5390 -- Compute_Unit_Name --
5391 -----------------------
5393 procedure Compute_Unit_Name
5394 (File_Name : File_Name_Type;
5395 Naming : Lang_Naming_Data;
5396 Kind : out Source_Kind;
5398 Project : Project_Processing_Data;
5399 In_Tree : Project_Tree_Ref)
5401 Filename : constant String := Get_Name_String (File_Name);
5402 Last : Integer := Filename'Last;
5407 Unit_Except : Unit_Exception;
5408 Masked : Boolean := False;
5414 if Naming.Separate_Suffix = No_File
5415 or else Naming.Body_Suffix = No_File
5416 or else Naming.Spec_Suffix = No_File
5421 if Naming.Dot_Replacement = No_File then
5422 if Current_Verbosity = High then
5423 Write_Line (" No dot_replacement specified");
5429 Sep_Len := Integer (Length_Of_Name (Naming.Separate_Suffix));
5430 Spec_Len := Integer (Length_Of_Name (Naming.Spec_Suffix));
5431 Body_Len := Integer (Length_Of_Name (Naming.Body_Suffix));
5433 -- Choose the longest suffix that matches. If there are several matches,
5434 -- give priority to specs, then bodies, then separates.
5436 if Naming.Separate_Suffix /= Naming.Body_Suffix
5437 and then Suffix_Matches (Filename, Naming.Separate_Suffix)
5439 Last := Filename'Last - Sep_Len;
5443 if Filename'Last - Body_Len <= Last
5444 and then Suffix_Matches (Filename, Naming.Body_Suffix)
5446 Last := Natural'Min (Last, Filename'Last - Body_Len);
5450 if Filename'Last - Spec_Len <= Last
5451 and then Suffix_Matches (Filename, Naming.Spec_Suffix)
5453 Last := Natural'Min (Last, Filename'Last - Spec_Len);
5457 if Last = Filename'Last then
5458 if Current_Verbosity = High then
5459 Write_Line (" no matching suffix");
5465 -- Check that the casing matches
5467 if File_Names_Case_Sensitive then
5468 case Naming.Casing is
5469 when All_Lower_Case =>
5470 for J in Filename'First .. Last loop
5471 if Is_Letter (Filename (J))
5472 and then not Is_Lower (Filename (J))
5474 if Current_Verbosity = High then
5475 Write_Line (" Invalid casing");
5482 when All_Upper_Case =>
5483 for J in Filename'First .. Last loop
5484 if Is_Letter (Filename (J))
5485 and then not Is_Upper (Filename (J))
5487 if Current_Verbosity = High then
5488 Write_Line (" Invalid casing");
5495 when Mixed_Case | Unknown =>
5500 -- If Dot_Replacement is not a single dot, then there should not
5501 -- be any dot in the name.
5504 Dot_Repl : constant String :=
5505 Get_Name_String (Naming.Dot_Replacement);
5508 if Dot_Repl /= "." then
5509 for Index in Filename'First .. Last loop
5510 if Filename (Index) = '.' then
5511 if Current_Verbosity = High then
5512 Write_Line (" Invalid name, contains dot");
5519 Replace_Into_Name_Buffer
5520 (Filename (Filename'First .. Last), Dot_Repl, '.');
5523 Name_Len := Last - Filename'First + 1;
5524 Name_Buffer (1 .. Name_Len) := Filename (Filename'First .. Last);
5526 (Source => Name_Buffer (1 .. Name_Len),
5527 Mapping => Lower_Case_Map);
5531 -- In the standard GNAT naming scheme, check for special cases: children
5532 -- or separates of A, G, I or S, and run time sources.
5534 if Is_Standard_GNAT_Naming (Naming)
5535 and then Name_Len >= 3
5538 S1 : constant Character := Name_Buffer (1);
5539 S2 : constant Character := Name_Buffer (2);
5540 S3 : constant Character := Name_Buffer (3);
5548 -- Children or separates of packages A, G, I or S. These names
5549 -- are x__ ... or x~... (where x is a, g, i, or s). Both
5550 -- versions (x__... and x~...) are allowed in all platforms,
5551 -- because it is not possible to know the platform before
5552 -- processing of the project files.
5554 if S2 = '_' and then S3 = '_' then
5555 Name_Buffer (2) := '.';
5556 Name_Buffer (3 .. Name_Len - 1) :=
5557 Name_Buffer (4 .. Name_Len);
5558 Name_Len := Name_Len - 1;
5561 Name_Buffer (2) := '.';
5565 -- If it is potentially a run time source
5573 -- Name_Buffer contains the name of the the unit in lower-cases. Check
5574 -- that this is a valid unit name
5576 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
5578 -- If there is a naming exception for the same unit, the file is not
5579 -- a source for the unit.
5581 if Unit /= No_Name then
5583 Unit_Exceptions_Htable.Get (Project.Unit_Exceptions, Unit);
5586 Masked := Unit_Except.Spec /= No_File
5588 Unit_Except.Spec /= File_Name;
5590 Masked := Unit_Except.Impl /= No_File
5592 Unit_Except.Impl /= File_Name;
5596 if Current_Verbosity = High then
5597 Write_Str (" """ & Filename & """ contains the ");
5600 Write_Str ("spec of a unit found in """);
5601 Write_Str (Get_Name_String (Unit_Except.Spec));
5603 Write_Str ("body of a unit found in """);
5604 Write_Str (Get_Name_String (Unit_Except.Impl));
5607 Write_Line (""" (ignored)");
5615 and then Current_Verbosity = High
5618 when Spec => Write_Str (" spec of ");
5619 when Impl => Write_Str (" body of ");
5620 when Sep => Write_Str (" sep of ");
5623 Write_Line (Get_Name_String (Unit));
5625 end Compute_Unit_Name;
5627 --------------------------
5628 -- Check_Illegal_Suffix --
5629 --------------------------
5631 procedure Check_Illegal_Suffix
5632 (Project : Project_Id;
5633 Suffix : File_Name_Type;
5634 Dot_Replacement : File_Name_Type;
5635 Attribute_Name : String;
5636 Location : Source_Ptr;
5637 Data : in out Tree_Processing_Data)
5639 Suffix_Str : constant String := Get_Name_String (Suffix);
5642 if Suffix_Str'Length = 0 then
5648 elsif Index (Suffix_Str, ".") = 0 then
5649 Err_Vars.Error_Msg_File_1 := Suffix;
5652 "{ is illegal for " & Attribute_Name & ": must have a dot",
5657 -- Case of dot replacement is a single dot, and first character of
5658 -- suffix is also a dot.
5660 if Dot_Replacement /= No_File
5661 and then Get_Name_String (Dot_Replacement) = "."
5662 and then Suffix_Str (Suffix_Str'First) = '.'
5664 for Index in Suffix_Str'First + 1 .. Suffix_Str'Last loop
5666 -- If there are multiple dots in the name
5668 if Suffix_Str (Index) = '.' then
5670 -- It is illegal to have a letter following the initial dot
5672 if Is_Letter (Suffix_Str (Suffix_Str'First + 1)) then
5673 Err_Vars.Error_Msg_File_1 := Suffix;
5676 "{ is illegal for " & Attribute_Name
5677 & ": ambiguous prefix when Dot_Replacement is a dot",
5684 end Check_Illegal_Suffix;
5686 ----------------------
5687 -- Locate_Directory --
5688 ----------------------
5690 procedure Locate_Directory
5691 (Project : Project_Id;
5692 Name : File_Name_Type;
5693 Path : out Path_Information;
5694 Dir_Exists : out Boolean;
5695 Data : in out Tree_Processing_Data;
5696 Create : String := "";
5697 Location : Source_Ptr := No_Location;
5698 Must_Exist : Boolean := True;
5699 Externally_Built : Boolean := False)
5701 Parent : constant Path_Name_Type :=
5702 Project.Directory.Display_Name;
5703 The_Parent : constant String :=
5704 Get_Name_String (Parent);
5705 The_Parent_Last : constant Natural :=
5706 Compute_Directory_Last (The_Parent);
5707 Full_Name : File_Name_Type;
5708 The_Name : File_Name_Type;
5711 Get_Name_String (Name);
5713 -- Add Subdirs.all if it is a directory that may be created and
5714 -- Subdirs is not null;
5716 if Create /= "" and then Subdirs /= null then
5717 if Name_Buffer (Name_Len) /= Directory_Separator then
5718 Add_Char_To_Name_Buffer (Directory_Separator);
5721 Add_Str_To_Name_Buffer (Subdirs.all);
5724 -- Convert '/' to directory separator (for Windows)
5726 for J in 1 .. Name_Len loop
5727 if Name_Buffer (J) = '/' then
5728 Name_Buffer (J) := Directory_Separator;
5732 The_Name := Name_Find;
5734 if Current_Verbosity = High then
5735 Write_Str ("Locate_Directory (""");
5736 Write_Str (Get_Name_String (The_Name));
5737 Write_Str (""", """);
5738 Write_Str (The_Parent);
5742 Path := No_Path_Information;
5743 Dir_Exists := False;
5745 if Is_Absolute_Path (Get_Name_String (The_Name)) then
5746 Full_Name := The_Name;
5750 Add_Str_To_Name_Buffer
5751 (The_Parent (The_Parent'First .. The_Parent_Last));
5752 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
5753 Full_Name := Name_Find;
5757 Full_Path_Name : String_Access :=
5758 new String'(Get_Name_String (Full_Name));
5761 if (Setup_Projects or else Subdirs /= null)
5762 and then Create'Length > 0
5764 if not Is_Directory (Full_Path_Name.all) then
5766 -- If project is externally built, do not create a subdir,
5767 -- use the specified directory, without the subdir.
5769 if Externally_Built then
5770 if Is_Absolute_Path (Get_Name_String (Name)) then
5771 Get_Name_String (Name);
5775 Add_Str_To_Name_Buffer
5776 (The_Parent (The_Parent'First .. The_Parent_Last));
5777 Add_Str_To_Name_Buffer (Get_Name_String (Name));
5780 Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
5784 Create_Path (Full_Path_Name.all);
5786 if not Quiet_Output then
5788 Write_Str (" directory """);
5789 Write_Str (Full_Path_Name.all);
5790 Write_Str (""" created for project ");
5791 Write_Line (Get_Name_String (Project.Name));
5798 "could not create " & Create &
5799 " directory " & Full_Path_Name.all,
5806 Dir_Exists := Is_Directory (Full_Path_Name.all);
5808 if not Must_Exist or else Dir_Exists then
5810 Normed : constant String :=
5812 (Full_Path_Name.all,
5814 The_Parent (The_Parent'First .. The_Parent_Last),
5815 Resolve_Links => False,
5816 Case_Sensitive => True);
5818 Canonical_Path : constant String :=
5823 (The_Parent'First .. The_Parent_Last),
5825 Opt.Follow_Links_For_Dirs,
5826 Case_Sensitive => False);
5829 Name_Len := Normed'Length;
5830 Name_Buffer (1 .. Name_Len) := Normed;
5832 -- Directories should always end with a directory separator
5834 if Name_Buffer (Name_Len) /= Directory_Separator then
5835 Add_Char_To_Name_Buffer (Directory_Separator);
5838 Path.Display_Name := Name_Find;
5840 Name_Len := Canonical_Path'Length;
5841 Name_Buffer (1 .. Name_Len) := Canonical_Path;
5843 if Name_Buffer (Name_Len) /= Directory_Separator then
5844 Add_Char_To_Name_Buffer (Directory_Separator);
5847 Path.Name := Name_Find;
5851 Free (Full_Path_Name);
5853 end Locate_Directory;
5855 ---------------------------
5856 -- Find_Excluded_Sources --
5857 ---------------------------
5859 procedure Find_Excluded_Sources
5860 (Project : in out Project_Processing_Data;
5861 Data : in out Tree_Processing_Data)
5863 Excluded_Source_List_File : constant Variable_Value :=
5865 (Name_Excluded_Source_List_File,
5866 Project.Project.Decl.Attributes,
5868 Excluded_Sources : Variable_Value := Util.Value_Of
5869 (Name_Excluded_Source_Files,
5870 Project.Project.Decl.Attributes,
5873 Current : String_List_Id;
5874 Element : String_Element;
5875 Location : Source_Ptr;
5876 Name : File_Name_Type;
5877 File : Prj.Util.Text_File;
5878 Line : String (1 .. 300);
5880 Locally_Removed : Boolean := False;
5883 -- If Excluded_Source_Files is not declared, check Locally_Removed_Files
5885 if Excluded_Sources.Default then
5886 Locally_Removed := True;
5889 (Name_Locally_Removed_Files,
5890 Project.Project.Decl.Attributes, Data.Tree);
5893 -- If there are excluded sources, put them in the table
5895 if not Excluded_Sources.Default then
5896 if not Excluded_Source_List_File.Default then
5897 if Locally_Removed then
5900 "?both attributes Locally_Removed_Files and " &
5901 "Excluded_Source_List_File are present",
5902 Excluded_Source_List_File.Location, Project.Project);
5906 "?both attributes Excluded_Source_Files and " &
5907 "Excluded_Source_List_File are present",
5908 Excluded_Source_List_File.Location, Project.Project);
5912 Current := Excluded_Sources.Values;
5913 while Current /= Nil_String loop
5914 Element := Data.Tree.String_Elements.Table (Current);
5915 Name := Canonical_Case_File_Name (Element.Value);
5917 -- If the element has no location, then use the location of
5918 -- Excluded_Sources to report possible errors.
5920 if Element.Location = No_Location then
5921 Location := Excluded_Sources.Location;
5923 Location := Element.Location;
5926 Excluded_Sources_Htable.Set
5927 (Project.Excluded, Name, (Name, False, Location));
5928 Current := Element.Next;
5931 elsif not Excluded_Source_List_File.Default then
5932 Location := Excluded_Source_List_File.Location;
5935 Source_File_Path_Name : constant String :=
5938 (Excluded_Source_List_File.Value),
5939 Project.Project.Directory.Name);
5942 if Source_File_Path_Name'Length = 0 then
5943 Err_Vars.Error_Msg_File_1 :=
5944 File_Name_Type (Excluded_Source_List_File.Value);
5947 "file with excluded sources { does not exist",
5948 Excluded_Source_List_File.Location, Project.Project);
5953 Prj.Util.Open (File, Source_File_Path_Name);
5955 if not Prj.Util.Is_Valid (File) then
5957 (Data.Flags, "file does not exist",
5958 Location, Project.Project);
5960 -- Read the lines one by one
5962 while not Prj.Util.End_Of_File (File) loop
5963 Prj.Util.Get_Line (File, Line, Last);
5965 -- Non empty, non comment line should contain a file name
5968 and then (Last = 1 or else Line (1 .. 2) /= "--")
5971 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
5972 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5975 -- Check that there is no directory information
5977 for J in 1 .. Last loop
5979 or else Line (J) = Directory_Separator
5981 Error_Msg_File_1 := Name;
5984 "file name cannot include " &
5985 "directory information ({)",
5986 Location, Project.Project);
5991 Excluded_Sources_Htable.Set
5992 (Project.Excluded, Name, (Name, False, Location));
5996 Prj.Util.Close (File);
6001 end Find_Excluded_Sources;
6007 procedure Find_Sources
6008 (Project : in out Project_Processing_Data;
6009 Data : in out Tree_Processing_Data)
6011 Sources : constant Variable_Value :=
6014 Project.Project.Decl.Attributes,
6017 Source_List_File : constant Variable_Value :=
6019 (Name_Source_List_File,
6020 Project.Project.Decl.Attributes,
6023 Name_Loc : Name_Location;
6024 Has_Explicit_Sources : Boolean;
6027 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
6029 (Source_List_File.Kind = Single,
6030 "Source_List_File is not a single string");
6032 Project.Source_List_File_Location := Source_List_File.Location;
6034 -- If the user has specified a Source_Files attribute
6036 if not Sources.Default then
6037 if not Source_List_File.Default then
6040 "?both attributes source_files and " &
6041 "source_list_file are present",
6042 Source_List_File.Location, Project.Project);
6045 -- Sources is a list of file names
6048 Current : String_List_Id := Sources.Values;
6049 Element : String_Element;
6050 Location : Source_Ptr;
6051 Name : File_Name_Type;
6054 if Current = Nil_String then
6055 Project.Project.Languages := No_Language_Index;
6057 -- This project contains no source. For projects that don't
6058 -- extend other projects, this also means that there is no
6059 -- need for an object directory, if not specified.
6061 if Project.Project.Extends = No_Project
6062 and then Project.Project.Object_Directory =
6063 Project.Project.Directory
6065 Project.Project.Object_Directory := No_Path_Information;
6069 while Current /= Nil_String loop
6070 Element := Data.Tree.String_Elements.Table (Current);
6071 Name := Canonical_Case_File_Name (Element.Value);
6072 Get_Name_String (Element.Value);
6074 -- If the element has no location, then use the location of
6075 -- Sources to report possible errors.
6077 if Element.Location = No_Location then
6078 Location := Sources.Location;
6080 Location := Element.Location;
6083 -- Check that there is no directory information
6085 for J in 1 .. Name_Len loop
6086 if Name_Buffer (J) = '/'
6087 or else Name_Buffer (J) = Directory_Separator
6089 Error_Msg_File_1 := Name;
6092 "file name cannot include directory " &
6094 Location, Project.Project);
6099 -- Check whether the file is already there: the same file name
6100 -- may be in the list. If the source is missing, the error will
6101 -- be on the first mention of the source file name.
6103 Name_Loc := Source_Names_Htable.Get
6104 (Project.Source_Names, Name);
6106 if Name_Loc = No_Name_Location then
6109 Location => Location,
6110 Source => No_Source,
6115 Name_Loc.Listed := True;
6118 Source_Names_Htable.Set
6119 (Project.Source_Names, Name, Name_Loc);
6121 Current := Element.Next;
6124 Has_Explicit_Sources := True;
6127 -- If we have no Source_Files attribute, check the Source_List_File
6130 elsif not Source_List_File.Default then
6132 -- Source_List_File is the name of the file that contains the source
6136 Source_File_Path_Name : constant String :=
6138 (File_Name_Type (Source_List_File.Value),
6139 Project.Project.Directory.Name);
6142 Has_Explicit_Sources := True;
6144 if Source_File_Path_Name'Length = 0 then
6145 Err_Vars.Error_Msg_File_1 :=
6146 File_Name_Type (Source_List_File.Value);
6149 "file with sources { does not exist",
6150 Source_List_File.Location, Project.Project);
6153 Get_Sources_From_File
6154 (Source_File_Path_Name, Source_List_File.Location,
6160 -- Neither Source_Files nor Source_List_File has been specified. Find
6161 -- all the files that satisfy the naming scheme in all the source
6164 Has_Explicit_Sources := False;
6167 -- Remove any exception that is not in the specified list of sources
6169 if Has_Explicit_Sources then
6172 Iter : Source_Iterator;
6179 Iter := For_Each_Source (Data.Tree, Project.Project);
6183 Source := Prj.Element (Iter);
6184 exit Source_Loop when Source = No_Source;
6186 if Source.Naming_Exception then
6187 NL := Source_Names_Htable.Get
6188 (Project.Source_Names, Source.File);
6190 if NL /= No_Name_Location and then not NL.Listed then
6191 -- Remove the exception
6192 Source_Names_Htable.Set
6193 (Project.Source_Names,
6196 Remove_Source (Source, No_Source);
6198 Error_Msg_Name_1 := Name_Id (Source.File);
6201 "? unknown source file %%",
6211 end loop Source_Loop;
6213 exit Iter_Loop when not Again;
6221 For_All_Sources => Sources.Default and then Source_List_File.Default);
6223 -- Check if all exceptions have been found
6227 Iter : Source_Iterator;
6228 Found : Boolean := False;
6229 Path : Path_Information;
6232 Iter := For_Each_Source (Data.Tree, Project.Project);
6234 Source := Prj.Element (Iter);
6235 exit when Source = No_Source;
6237 if Source.Naming_Exception
6238 and then Source.Path = No_Path_Information
6240 if Source.Unit /= No_Unit_Index then
6243 -- For multi-unit source files, source_id gets duplicated
6244 -- once for every unit. Only the first source_id got its
6247 if Source.Index /= 0 then
6248 Path := Files_Htable.Get
6249 (Data.File_To_Source, Source.File).Path;
6251 if Path /= No_Path_Information then
6257 Error_Msg_Name_1 := Name_Id (Source.Display_File);
6258 Error_Msg_Name_2 := Source.Unit.Name;
6260 (Data.Flags, Data.Flags.Missing_Source_Files,
6261 "source file %% for unit %% not found",
6262 No_Location, Project.Project);
6265 Source.Path := Path;
6267 if Current_Verbosity = High then
6268 if Source.Path /= No_Path_Information then
6269 Write_Line ("Setting full path for "
6270 & Get_Name_String (Source.File)
6271 & " at" & Source.Index'Img
6273 & Get_Name_String (Path.Name));
6279 if Source.Path = No_Path_Information then
6280 Remove_Source (Source, No_Source);
6288 -- It is an error if a source file name in a source list or in a source
6289 -- list file is not found.
6291 if Has_Explicit_Sources then
6294 First_Error : Boolean;
6297 NL := Source_Names_Htable.Get_First (Project.Source_Names);
6298 First_Error := True;
6299 while NL /= No_Name_Location loop
6300 if not NL.Found then
6301 Err_Vars.Error_Msg_File_1 := NL.Name;
6304 (Data.Flags, Data.Flags.Missing_Source_Files,
6305 "source file { not found",
6306 NL.Location, Project.Project);
6307 First_Error := False;
6310 (Data.Flags, Data.Flags.Missing_Source_Files,
6311 "\source file { not found",
6312 NL.Location, Project.Project);
6316 NL := Source_Names_Htable.Get_Next (Project.Source_Names);
6326 procedure Initialize
6327 (Data : out Tree_Processing_Data;
6328 Tree : Project_Tree_Ref;
6329 Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
6330 Flags : Prj.Processing_Flags)
6333 Files_Htable.Reset (Data.File_To_Source);
6335 Data.Node_Tree := Node_Tree;
6336 Data.Flags := Flags;
6343 procedure Free (Data : in out Tree_Processing_Data) is
6345 Files_Htable.Reset (Data.File_To_Source);
6352 procedure Initialize
6353 (Data : in out Project_Processing_Data;
6354 Project : Project_Id)
6357 Data.Project := Project;
6364 procedure Free (Data : in out Project_Processing_Data) is
6366 Source_Names_Htable.Reset (Data.Source_Names);
6367 Unit_Exceptions_Htable.Reset (Data.Unit_Exceptions);
6368 Excluded_Sources_Htable.Reset (Data.Excluded);
6371 -------------------------------
6372 -- Check_File_Naming_Schemes --
6373 -------------------------------
6375 procedure Check_File_Naming_Schemes
6376 (In_Tree : Project_Tree_Ref;
6377 Project : Project_Processing_Data;
6378 File_Name : File_Name_Type;
6379 Alternate_Languages : out Language_List;
6380 Language : out Language_Ptr;
6381 Display_Language_Name : out Name_Id;
6383 Lang_Kind : out Language_Kind;
6384 Kind : out Source_Kind)
6386 Filename : constant String := Get_Name_String (File_Name);
6387 Config : Language_Config;
6388 Tmp_Lang : Language_Ptr;
6390 Header_File : Boolean := False;
6391 -- True if we found at least one language for which the file is a header
6392 -- In such a case, we search for all possible languages where this is
6393 -- also a header (C and C++ for instance), since the file might be used
6394 -- for several such languages.
6396 procedure Check_File_Based_Lang;
6397 -- Does the naming scheme test for file-based languages. For those,
6398 -- there is no Unit. Just check if the file name has the implementation
6399 -- or, if it is specified, the template suffix of the language.
6401 -- Returns True if the file belongs to the current language and we
6402 -- should stop searching for matching languages. Not that a given header
6403 -- file could belong to several languages (C and C++ for instance). Thus
6404 -- if we found a header we'll check whether it matches other languages.
6406 ---------------------------
6407 -- Check_File_Based_Lang --
6408 ---------------------------
6410 procedure Check_File_Based_Lang is
6413 and then Suffix_Matches (Filename, Config.Naming_Data.Body_Suffix)
6417 Language := Tmp_Lang;
6419 if Current_Verbosity = High then
6420 Write_Str (" implementation of language ");
6421 Write_Line (Get_Name_String (Display_Language_Name));
6424 elsif Suffix_Matches (Filename, Config.Naming_Data.Spec_Suffix) then
6425 if Current_Verbosity = High then
6426 Write_Str (" header of language ");
6427 Write_Line (Get_Name_String (Display_Language_Name));
6431 Alternate_Languages := new Language_List_Element'
6432 (Language => Language,
6433 Next => Alternate_Languages);
6436 Header_File := True;
6439 Language := Tmp_Lang;
6442 end Check_File_Based_Lang;
6444 -- Start of processing for Check_File_Naming_Schemes
6447 Language := No_Language_Index;
6448 Alternate_Languages := null;
6449 Display_Language_Name := No_Name;
6451 Lang_Kind := File_Based;
6454 Tmp_Lang := Project.Project.Languages;
6455 while Tmp_Lang /= No_Language_Index loop
6456 if Current_Verbosity = High then
6458 (" Testing language "
6459 & Get_Name_String (Tmp_Lang.Name)
6460 & " Header_File=" & Header_File'Img);
6463 Display_Language_Name := Tmp_Lang.Display_Name;
6464 Config := Tmp_Lang.Config;
6465 Lang_Kind := Config.Kind;
6469 Check_File_Based_Lang;
6470 exit when Kind = Impl;
6474 -- We know it belongs to a least a file_based language, no
6475 -- need to check unit-based ones.
6477 if not Header_File then
6479 (File_Name => File_Name,
6480 Naming => Config.Naming_Data,
6484 In_Tree => In_Tree);
6486 if Unit /= No_Name then
6487 Language := Tmp_Lang;
6493 Tmp_Lang := Tmp_Lang.Next;
6496 if Language = No_Language_Index
6497 and then Current_Verbosity = High
6499 Write_Line (" not a source of any language");
6501 end Check_File_Naming_Schemes;
6507 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind) is
6509 -- If the file was previously already associated with a unit, change it
6511 if Source.Unit /= null
6512 and then Source.Kind in Spec_Or_Body
6513 and then Source.Unit.File_Names (Source.Kind) /= null
6515 -- If we had another file referencing the same unit (for instance it
6516 -- was in an extended project), that source file is in fact invisible
6517 -- from now on, and in particular doesn't belong to the same unit.
6519 if Source.Unit.File_Names (Source.Kind) /= Source then
6520 Source.Unit.File_Names (Source.Kind).Unit := No_Unit_Index;
6523 Source.Unit.File_Names (Source.Kind) := null;
6526 Source.Kind := Kind;
6528 if Current_Verbosity = High
6529 and then Source.File /= No_File
6531 Write_Line ("Override kind for "
6532 & Get_Name_String (Source.File)
6533 & " kind=" & Source.Kind'Img);
6536 if Source.Kind in Spec_Or_Body and then Source.Unit /= null then
6537 Source.Unit.File_Names (Source.Kind) := Source;
6545 procedure Check_File
6546 (Project : in out Project_Processing_Data;
6547 Data : in out Tree_Processing_Data;
6548 Source_Dir_Rank : Natural;
6549 Path : Path_Name_Type;
6550 Display_Path : Path_Name_Type;
6551 File_Name : File_Name_Type;
6552 Display_File_Name : File_Name_Type;
6553 Locally_Removed : Boolean;
6554 For_All_Sources : Boolean)
6556 Name_Loc : Name_Location :=
6557 Source_Names_Htable.Get
6558 (Project.Source_Names, File_Name);
6559 Check_Name : Boolean := False;
6560 Alternate_Languages : Language_List;
6561 Language : Language_Ptr;
6563 Src_Ind : Source_File_Index;
6565 Display_Language_Name : Name_Id;
6566 Lang_Kind : Language_Kind;
6567 Kind : Source_Kind := Spec;
6570 if Current_Verbosity = High then
6571 Write_Line ("Checking file:");
6572 Write_Str (" Path = ");
6573 Write_Line (Get_Name_String (Path));
6574 Write_Str (" Rank =");
6575 Write_Line (Source_Dir_Rank'Img);
6578 if Name_Loc = No_Name_Location then
6579 Check_Name := For_All_Sources;
6582 if Name_Loc.Found then
6584 -- Check if it is OK to have the same file name in several
6585 -- source directories.
6587 if Source_Dir_Rank = Name_Loc.Source.Source_Dir_Rank then
6588 Error_Msg_File_1 := File_Name;
6591 "{ is found in several source directories",
6592 Name_Loc.Location, Project.Project);
6596 Name_Loc.Found := True;
6598 Source_Names_Htable.Set
6599 (Project.Source_Names, File_Name, Name_Loc);
6601 if Name_Loc.Source = No_Source then
6605 Name_Loc.Source.Path := (Path, Display_Path);
6607 Source_Paths_Htable.Set
6608 (Data.Tree.Source_Paths_HT,
6612 -- Check if this is a subunit
6614 if Name_Loc.Source.Unit /= No_Unit_Index
6615 and then Name_Loc.Source.Kind = Impl
6617 Src_Ind := Sinput.P.Load_Project_File
6618 (Get_Name_String (Display_Path));
6620 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
6621 Override_Kind (Name_Loc.Source, Sep);
6626 (Data.File_To_Source, File_Name, Name_Loc.Source);
6632 Check_File_Naming_Schemes
6633 (In_Tree => Data.Tree,
6635 File_Name => File_Name,
6636 Alternate_Languages => Alternate_Languages,
6637 Language => Language,
6638 Display_Language_Name => Display_Language_Name,
6640 Lang_Kind => Lang_Kind,
6643 if Language = No_Language_Index then
6645 -- A file name in a list must be a source of a language
6647 if Data.Flags.Error_On_Unknown_Language
6648 and then Name_Loc.Found
6650 Error_Msg_File_1 := File_Name;
6653 "language unknown for {",
6654 Name_Loc.Location, Project.Project);
6660 Project => Project.Project,
6661 Source_Dir_Rank => Source_Dir_Rank,
6662 Lang_Id => Language,
6665 Alternate_Languages => Alternate_Languages,
6666 File_Name => File_Name,
6667 Display_File => Display_File_Name,
6669 Locally_Removed => Locally_Removed,
6670 Path => (Path, Display_Path));
6672 -- If it is a source specified in a list, update the entry in
6673 -- the Source_Names table.
6675 if Name_Loc.Found and then Name_Loc.Source = No_Source then
6676 Name_Loc.Source := Source;
6677 Source_Names_Htable.Set
6678 (Project.Source_Names, File_Name, Name_Loc);
6684 ---------------------------------
6685 -- Expand_Subdirectory_Pattern --
6686 ---------------------------------
6688 procedure Expand_Subdirectory_Pattern
6689 (Project : Project_Id;
6690 Data : in out Tree_Processing_Data;
6691 Patterns : String_List_Id;
6692 Search_For : Search_Type;
6693 Resolve_Links : Boolean)
6695 pragma Unreferenced (Search_For);
6696 package Recursive_Dirs is new GNAT.Dynamic_HTables.Simple_HTable
6697 (Header_Num => Header_Num,
6699 No_Element => False,
6700 Key => Path_Name_Type,
6703 -- Hash table stores recursive source directories, to avoid looking
6704 -- several times, and to avoid cycles that may be introduced by symbolic
6707 Visited : Recursive_Dirs.Instance;
6709 procedure Find_Pattern
6710 (Pattern : String; Rank : Natural; Location : Source_Ptr);
6711 -- Find a specific pattern
6713 procedure Recursive_Find_Dirs (Normalized_Path : String; Rank : Natural);
6714 -- Search all the subdirectories (recursively) of Path
6716 procedure Check_Directory_And_Subdirs
6717 (Directory : String;
6718 Include_Subdirs : Boolean;
6720 Location : Source_Ptr);
6721 -- Make sur that Directory exists (and if not report an error/warning
6722 -- message depending on the flags.
6723 -- Calls Callback for Directory itself and all its subdirectories if
6724 -- Include_Subdirs is True).
6726 -------------------------
6727 -- Recursive_Find_Dirs --
6728 -------------------------
6730 procedure Recursive_Find_Dirs
6731 (Normalized_Path : String; Rank : Natural)
6734 Name : String (1 .. 250);
6737 Non_Canonical_Path : Path_Name_Type := No_Path;
6738 Canonical_Path : Path_Name_Type := No_Path;
6740 The_Path_Last : constant Natural :=
6741 Compute_Directory_Last (Normalized_Path);
6745 Add_Str_To_Name_Buffer
6746 (Normalized_Path (Normalized_Path'First .. The_Path_Last));
6747 Non_Canonical_Path := Name_Find;
6751 (Canonical_Case_File_Name (Name_Id (Non_Canonical_Path)));
6753 if Recursive_Dirs.Get (Visited, Canonical_Path) then
6757 Recursive_Dirs.Set (Visited, Canonical_Path, True);
6759 Callback (Canonical_Path, Non_Canonical_Path, Rank);
6761 Open (Dir, Normalized_Path (Normalized_Path'First .. The_Path_Last));
6764 Read (Dir, Name, Last);
6767 if Name (1 .. Last) /= "."
6768 and then Name (1 .. Last) /= ".."
6770 if Current_Verbosity = High then
6771 Write_Str (" Checking ");
6772 Write_Line (Name (1 .. Last));
6776 Path_Name : constant String :=
6778 (Name => Name (1 .. Last),
6781 (Normalized_Path'First .. The_Path_Last),
6782 Resolve_Links => Resolve_Links)
6783 & Directory_Separator;
6785 if Is_Directory (Path_Name) then
6786 Recursive_Find_Dirs (Path_Name, Rank);
6795 when Directory_Error =>
6797 end Recursive_Find_Dirs;
6799 ---------------------------------
6800 -- Check_Directory_And_Subdirs --
6801 ---------------------------------
6803 procedure Check_Directory_And_Subdirs
6804 (Directory : String;
6805 Include_Subdirs : Boolean;
6807 Location : Source_Ptr)
6809 Dir : File_Name_Type;
6810 Path_Name : Path_Information;
6811 Dir_Exists : Boolean;
6812 Has_Error : Boolean := False;
6814 Name_Len := Directory'Length;
6815 Name_Buffer (1 .. Name_Len) := Directory;
6819 (Project => Project,
6822 Dir_Exists => Dir_Exists,
6824 Must_Exist => False);
6826 if not Dir_Exists then
6827 Err_Vars.Error_Msg_File_1 := Dir;
6829 (Data.Flags, Data.Flags.Missing_Source_Files,
6830 "{ is not a valid directory", Location, Project);
6831 Has_Error := Data.Flags.Missing_Source_Files = Error;
6834 if not Has_Error then
6835 -- Links have been resolved if necessary, and Path_Name
6836 -- always ends with a directory separator.
6838 if Include_Subdirs then
6839 if Current_Verbosity = High then
6840 Write_Str ("Looking for all subdirectories of """);
6841 Write_Str (Directory);
6845 Recursive_Find_Dirs (Get_Name_String (Path_Name.Name), Rank);
6847 if Current_Verbosity = High then
6848 Write_Line ("End of looking for source directories.");
6852 Callback (Path_Name.Name, Path_Name.Display_Name, Rank);
6855 end Check_Directory_And_Subdirs;
6861 procedure Find_Pattern
6862 (Pattern : String; Rank : Natural; Location : Source_Ptr) is
6864 if Current_Verbosity = High then
6865 Write_Str ("Expand_Subdirectory_Pattern (""");
6866 Write_Str (Pattern);
6870 -- First, check if we are looking for a directory tree, indicated
6871 -- by "/**" at the end.
6873 if Pattern'Length >= 3
6874 and then Pattern (Pattern'Last - 1 .. Pattern'Last) = "**"
6875 and then (Pattern (Pattern'Last - 2) = '/'
6876 or else Pattern (Pattern'Last - 2) = Directory_Separator)
6878 if Pattern'Length = 3 then
6879 -- Case of "/**": all directories in file system
6880 Check_Directory_And_Subdirs
6881 (Pattern (Pattern'First .. Pattern'First),
6882 True, Rank, Location);
6884 Check_Directory_And_Subdirs
6885 (Pattern (Pattern'First .. Pattern'Last - 3),
6886 True, Rank, Location);
6889 Check_Directory_And_Subdirs (Pattern, False, Rank, Location);
6893 -- Start of processing for Expand_Subdirectory_Pattern
6895 Pattern_Id : String_List_Id := Patterns;
6896 Element : String_Element;
6897 Rank : Natural := 1;
6899 while Pattern_Id /= Nil_String loop
6900 Element := Data.Tree.String_Elements.Table (Pattern_Id);
6902 (Get_Name_String (Element.Value), Rank, Element.Location);
6904 Pattern_Id := Element.Next;
6907 Recursive_Dirs.Reset (Visited);
6908 end Expand_Subdirectory_Pattern;
6910 ------------------------
6911 -- Search_Directories --
6912 ------------------------
6914 procedure Search_Directories
6915 (Project : in out Project_Processing_Data;
6916 Data : in out Tree_Processing_Data;
6917 For_All_Sources : Boolean)
6919 Source_Dir : String_List_Id;
6920 Element : String_Element;
6921 Src_Dir_Rank : Number_List_Index;
6922 Num_Nod : Number_Node;
6924 Name : String (1 .. 1_000);
6926 File_Name : File_Name_Type;
6927 Display_File_Name : File_Name_Type;
6930 if Current_Verbosity = High then
6931 Write_Line ("Looking for sources:");
6934 -- Loop through subdirectories
6936 Source_Dir := Project.Project.Source_Dirs;
6937 Src_Dir_Rank := Project.Project.Source_Dir_Ranks;
6938 while Source_Dir /= Nil_String loop
6940 Num_Nod := Data.Tree.Number_Lists.Table (Src_Dir_Rank);
6941 Element := Data.Tree.String_Elements.Table (Source_Dir);
6943 -- Use Element.Value in this test, not Display_Value, because we
6944 -- want the symbolic links to be resolved when appropriate.
6946 if Element.Value /= No_Name then
6948 Source_Directory : constant String :=
6949 Get_Name_String (Element.Value)
6950 & Directory_Separator;
6952 Dir_Last : constant Natural :=
6953 Compute_Directory_Last (Source_Directory);
6955 Display_Source_Directory : constant String :=
6957 (Element.Display_Value)
6958 & Directory_Separator;
6959 -- Display_Source_Directory is to allow us to open a UTF-8
6960 -- encoded directory on Windows.
6963 if Current_Verbosity = High then
6966 Source_Directory (Source_Directory'First .. Dir_Last));
6967 Write_Line (Num_Nod.Number'Img);
6970 -- We look to every entry in the source directory
6972 Open (Dir, Display_Source_Directory);
6975 Read (Dir, Name, Last);
6979 -- In fast project loading mode (without -eL), the user
6980 -- guarantees that no directory has a name which is a
6981 -- valid source name, so we can avoid doing a system call
6982 -- here. This provides a very significant speed up on
6983 -- slow file systems (remote files for instance).
6985 if not Opt.Follow_Links_For_Files
6986 or else Is_Regular_File
6987 (Display_Source_Directory & Name (1 .. Last))
6989 if Current_Verbosity = High then
6990 Write_Str (" Checking ");
6991 Write_Line (Name (1 .. Last));
6995 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
6996 Display_File_Name := Name_Find;
6998 if Osint.File_Names_Case_Sensitive then
6999 File_Name := Display_File_Name;
7001 Canonical_Case_File_Name
7002 (Name_Buffer (1 .. Name_Len));
7003 File_Name := Name_Find;
7007 Path_Name : constant String :=
7012 (Source_Directory'First ..
7015 Opt.Follow_Links_For_Files,
7016 Case_Sensitive => True);
7018 Path : Path_Name_Type;
7020 Excluded_Sources_Htable.Get
7021 (Project.Excluded, File_Name);
7022 To_Remove : Boolean := False;
7025 Name_Len := Path_Name'Length;
7026 Name_Buffer (1 .. Name_Len) := Path_Name;
7028 if Osint.File_Names_Case_Sensitive then
7031 Canonical_Case_File_Name
7032 (Name_Buffer (1 .. Name_Len));
7036 if FF /= No_File_Found then
7037 if not FF.Found then
7039 Excluded_Sources_Htable.Set
7040 (Project.Excluded, File_Name, FF);
7042 if Current_Verbosity = High then
7043 Write_Str (" excluded source """);
7045 (Get_Name_String (Display_File_Name));
7049 -- Will mark the file as removed, but we
7050 -- still need to add it to the list: if we
7051 -- don't, the file will not appear in the
7052 -- mapping file and will cause the compiler
7059 -- Preserve the user's original casing and use of
7060 -- links. The display_value (a directory) already
7061 -- ends with a directory separator by construction,
7062 -- so no need to add one.
7064 Get_Name_String (Element.Display_Value);
7065 Get_Name_String_And_Append (Display_File_Name);
7068 (Project => Project,
7069 Source_Dir_Rank => Num_Nod.Number,
7072 Display_Path => Name_Find,
7073 File_Name => File_Name,
7074 Locally_Removed => To_Remove,
7075 Display_File_Name => Display_File_Name,
7076 For_All_Sources => For_All_Sources);
7086 when Directory_Error =>
7090 Source_Dir := Element.Next;
7091 Src_Dir_Rank := Num_Nod.Next;
7094 if Current_Verbosity = High then
7095 Write_Line ("end Looking for sources.");
7097 end Search_Directories;
7099 ----------------------------
7100 -- Load_Naming_Exceptions --
7101 ----------------------------
7103 procedure Load_Naming_Exceptions
7104 (Project : in out Project_Processing_Data;
7105 Data : in out Tree_Processing_Data)
7108 Iter : Source_Iterator;
7111 Iter := For_Each_Source (Data.Tree, Project.Project);
7113 Source := Prj.Element (Iter);
7114 exit when Source = No_Source;
7116 -- An excluded file cannot also be an exception file name
7118 if Excluded_Sources_Htable.Get (Project.Excluded, Source.File) /=
7121 Error_Msg_File_1 := Source.File;
7124 "{ cannot be both excluded and an exception file name",
7125 No_Location, Project.Project);
7128 if Current_Verbosity = High then
7129 Write_Str ("Naming exception: Putting source file ");
7130 Write_Str (Get_Name_String (Source.File));
7131 Write_Line (" in Source_Names");
7134 Source_Names_Htable.Set
7135 (Project.Source_Names,
7138 (Name => Source.File,
7139 Location => Source.Location,
7144 -- If this is an Ada exception, record in table Unit_Exceptions
7146 if Source.Unit /= No_Unit_Index then
7148 Unit_Except : Unit_Exception :=
7149 Unit_Exceptions_Htable.Get
7150 (Project.Unit_Exceptions, Source.Unit.Name);
7153 Unit_Except.Name := Source.Unit.Name;
7155 if Source.Kind = Spec then
7156 Unit_Except.Spec := Source.File;
7158 Unit_Except.Impl := Source.File;
7161 Unit_Exceptions_Htable.Set
7162 (Project.Unit_Exceptions, Source.Unit.Name, Unit_Except);
7168 end Load_Naming_Exceptions;
7170 ----------------------
7171 -- Look_For_Sources --
7172 ----------------------
7174 procedure Look_For_Sources
7175 (Project : in out Project_Processing_Data;
7176 Data : in out Tree_Processing_Data)
7178 Object_Files : Object_File_Names_Htable.Instance;
7179 Iter : Source_Iterator;
7182 procedure Check_Object (Src : Source_Id);
7183 -- Check if object file name of Src is already used in the project tree,
7184 -- and report an error if so.
7186 procedure Check_Object_Files;
7187 -- Check that no two sources of this project have the same object file
7189 procedure Mark_Excluded_Sources;
7190 -- Mark as such the sources that are declared as excluded
7192 procedure Check_Missing_Sources;
7193 -- Check whether one of the languages has no sources, and report an
7194 -- error when appropriate
7196 procedure Get_Sources_From_Source_Info;
7197 -- Get the source information from the tabes that were created when a
7198 -- source info fie was read.
7200 ---------------------------
7201 -- Check_Missing_Sources --
7202 ---------------------------
7204 procedure Check_Missing_Sources is
7205 Extending : constant Boolean :=
7206 Project.Project.Extends /= No_Project;
7207 Language : Language_Ptr;
7209 Alt_Lang : Language_List;
7210 Continuation : Boolean := False;
7211 Iter : Source_Iterator;
7213 if not Project.Project.Externally_Built
7214 and then not Extending
7216 Language := Project.Project.Languages;
7217 while Language /= No_Language_Index loop
7219 -- If there are no sources for this language, check if there
7220 -- are sources for which this is an alternate language.
7222 if Language.First_Source = No_Source
7223 and then (Data.Flags.Require_Sources_Other_Lang
7224 or else Language.Name = Name_Ada)
7226 Iter := For_Each_Source (In_Tree => Data.Tree,
7227 Project => Project.Project);
7229 Source := Element (Iter);
7230 exit Source_Loop when Source = No_Source
7231 or else Source.Language = Language;
7233 Alt_Lang := Source.Alternate_Languages;
7234 while Alt_Lang /= null loop
7235 exit Source_Loop when Alt_Lang.Language = Language;
7236 Alt_Lang := Alt_Lang.Next;
7240 end loop Source_Loop;
7242 if Source = No_Source then
7245 Get_Name_String (Language.Display_Name),
7247 Project.Source_List_File_Location,
7249 Continuation := True;
7253 Language := Language.Next;
7256 end Check_Missing_Sources;
7262 procedure Check_Object (Src : Source_Id) is
7266 Source := Object_File_Names_Htable.Get (Object_Files, Src.Object);
7268 -- We cannot just check on "Source /= Src", since we might have
7269 -- two different entries for the same file (and since that's
7270 -- the same file it is expected that it has the same object)
7272 if Source /= No_Source
7273 and then Source.Path /= Src.Path
7275 Error_Msg_File_1 := Src.File;
7276 Error_Msg_File_2 := Source.File;
7279 "{ and { have the same object file name",
7280 No_Location, Project.Project);
7283 Object_File_Names_Htable.Set (Object_Files, Src.Object, Src);
7287 ---------------------------
7288 -- Mark_Excluded_Sources --
7289 ---------------------------
7291 procedure Mark_Excluded_Sources is
7292 Source : Source_Id := No_Source;
7293 Excluded : File_Found;
7297 -- Minor optimization: if there are no excluded files, no need to
7298 -- traverse the list of sources. We cannot however also check whether
7299 -- the existing exceptions have ".Found" set to True (indicating we
7300 -- found them before) because we need to do some final processing on
7301 -- them in any case.
7303 if Excluded_Sources_Htable.Get_First (Project.Excluded) /=
7306 Proj := Project.Project;
7307 while Proj /= No_Project loop
7308 Iter := For_Each_Source (Data.Tree, Proj);
7309 while Prj.Element (Iter) /= No_Source loop
7310 Source := Prj.Element (Iter);
7311 Excluded := Excluded_Sources_Htable.Get
7312 (Project.Excluded, Source.File);
7314 if Excluded /= No_File_Found then
7315 Source.Locally_Removed := True;
7316 Source.In_Interfaces := False;
7318 if Current_Verbosity = High then
7319 Write_Str ("Removing file ");
7321 (Get_Name_String (Excluded.File)
7322 & " " & Get_Name_String (Source.Project.Name));
7325 Excluded_Sources_Htable.Remove
7326 (Project.Excluded, Source.File);
7332 Proj := Proj.Extends;
7336 -- If we have any excluded element left, that means we did not find
7339 Excluded := Excluded_Sources_Htable.Get_First (Project.Excluded);
7340 while Excluded /= No_File_Found loop
7341 if not Excluded.Found then
7343 -- Check if the file belongs to another imported project to
7344 -- provide a better error message.
7347 (In_Tree => Data.Tree,
7348 Project => Project.Project,
7349 In_Imported_Only => True,
7350 Base_Name => Excluded.File);
7352 Err_Vars.Error_Msg_File_1 := Excluded.File;
7354 if Src = No_Source then
7357 "unknown file {", Excluded.Location, Project.Project);
7361 "cannot remove a source from an imported project: {",
7362 Excluded.Location, Project.Project);
7366 Excluded := Excluded_Sources_Htable.Get_Next (Project.Excluded);
7368 end Mark_Excluded_Sources;
7370 ------------------------
7371 -- Check_Object_Files --
7372 ------------------------
7374 procedure Check_Object_Files is
7375 Iter : Source_Iterator;
7377 Src_Ind : Source_File_Index;
7380 Iter := For_Each_Source (Data.Tree);
7382 Src_Id := Prj.Element (Iter);
7383 exit when Src_Id = No_Source;
7385 if Is_Compilable (Src_Id)
7386 and then Src_Id.Language.Config.Object_Generated
7387 and then Is_Extending (Project.Project, Src_Id.Project)
7389 if Src_Id.Unit = No_Unit_Index then
7390 if Src_Id.Kind = Impl then
7391 Check_Object (Src_Id);
7397 if Other_Part (Src_Id) = No_Source then
7398 Check_Object (Src_Id);
7405 if Other_Part (Src_Id) /= No_Source then
7406 Check_Object (Src_Id);
7409 -- Check if it is a subunit
7412 Sinput.P.Load_Project_File
7413 (Get_Name_String (Src_Id.Path.Display_Name));
7415 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7416 Override_Kind (Src_Id, Sep);
7418 Check_Object (Src_Id);
7427 end Check_Object_Files;
7429 ----------------------------------
7430 -- Get_Sources_From_Source_Info --
7431 ----------------------------------
7433 procedure Get_Sources_From_Source_Info is
7434 Iter : Source_Info_Iterator;
7437 Lang_Id : Language_Ptr;
7439 Initialize (Iter, Project.Project.Name);
7442 Src := Source_Info_Of (Iter);
7444 exit when Src = No_Source_Info;
7446 Id := new Source_Data;
7448 Id.Project := Project.Project;
7450 Lang_Id := Project.Project.Languages;
7451 while Lang_Id /= No_Language_Index and then
7452 Lang_Id.Name /= Src.Language
7454 Lang_Id := Lang_Id.Next;
7457 if Lang_Id = No_Language_Index then
7459 ("unknown language " &
7460 Get_Name_String (Src.Language) &
7462 Get_Name_String (Src.Project) &
7463 " in source info file");
7466 Id.Language := Lang_Id;
7467 Id.Kind := Src.Kind;
7469 Id.Index := Src.Index;
7472 (Path_Name_Type (Src.Display_Path_Name),
7473 Path_Name_Type (Src.Path_Name));
7476 Add_Str_To_Name_Buffer
7477 (Ada.Directories.Simple_Name
7478 (Get_Name_String (Src.Path_Name)));
7479 Id.File := Name_Find;
7482 Add_Str_To_Name_Buffer
7483 (Ada.Directories.Simple_Name
7484 (Get_Name_String (Src.Display_Path_Name)));
7485 Id.Display_File := Name_Find;
7487 Id.Dep_Name := Dependency_Name
7488 (Id.File, Id.Language.Config.Dependency_Kind);
7489 Id.Naming_Exception := Src.Naming_Exception;
7490 Id.Object := Object_Name
7491 (Id.File, Id.Language.Config.Object_File_Suffix);
7492 Id.Switches := Switches_Name (Id.File);
7494 -- Add the source id to the Unit_Sources_HT hash table, if the
7495 -- unit name is not null.
7497 if Src.Kind /= Sep and then Src.Unit_Name /= No_Name then
7500 UData : Unit_Index :=
7501 Units_Htable.Get (Data.Tree.Units_HT, Src.Unit_Name);
7503 if UData = No_Unit_Index then
7504 UData := new Unit_Data;
7505 UData.Name := Src.Unit_Name;
7507 (Data.Tree.Units_HT, Src.Unit_Name, UData);
7513 -- Note that this updates Unit information as well
7515 Override_Kind (Id, Id.Kind);
7518 if Src.Index /= 0 then
7519 Project.Project.Has_Multi_Unit_Sources := True;
7522 -- Add the source to the language list
7524 Id.Next_In_Lang := Id.Language.First_Source;
7525 Id.Language.First_Source := Id;
7527 Files_Htable.Set (Data.File_To_Source, Id.File, Id);
7531 end Get_Sources_From_Source_Info;
7533 -- Start of processing for Look_For_Sources
7536 if Data.Tree.Source_Info_File_Exists then
7537 Get_Sources_From_Source_Info;
7540 if Project.Project.Source_Dirs /= Nil_String then
7541 Find_Excluded_Sources (Project, Data);
7543 if Project.Project.Languages /= No_Language_Index then
7544 Load_Naming_Exceptions (Project, Data);
7545 Find_Sources (Project, Data);
7546 Mark_Excluded_Sources;
7548 Check_Missing_Sources;
7552 Object_File_Names_Htable.Reset (Object_Files);
7554 end Look_For_Sources;
7560 function Path_Name_Of
7561 (File_Name : File_Name_Type;
7562 Directory : Path_Name_Type) return String
7564 Result : String_Access;
7565 The_Directory : constant String := Get_Name_String (Directory);
7568 Get_Name_String (File_Name);
7571 (File_Name => Name_Buffer (1 .. Name_Len),
7572 Path => The_Directory);
7574 if Result = null then
7578 R : String := Result.all;
7581 Canonical_Case_File_Name (R);
7591 procedure Remove_Source
7593 Replaced_By : Source_Id)
7598 if Current_Verbosity = High then
7599 Write_Str ("Removing source ");
7600 Write_Str (Get_Name_String (Id.File));
7602 if Id.Index /= 0 then
7603 Write_Str (" at" & Id.Index'Img);
7609 if Replaced_By /= No_Source then
7610 Id.Replaced_By := Replaced_By;
7611 Replaced_By.Declared_In_Interfaces := Id.Declared_In_Interfaces;
7614 Id.In_Interfaces := False;
7615 Id.Locally_Removed := True;
7617 -- ??? Should we remove the source from the unit ? The file is not used,
7618 -- so probably should not be referenced from the unit. On the other hand
7619 -- it might give useful additional info
7620 -- if Id.Unit /= null then
7621 -- Id.Unit.File_Names (Id.Kind) := null;
7624 Source := Id.Language.First_Source;
7627 Id.Language.First_Source := Id.Next_In_Lang;
7630 while Source.Next_In_Lang /= Id loop
7631 Source := Source.Next_In_Lang;
7634 Source.Next_In_Lang := Id.Next_In_Lang;
7638 -----------------------
7639 -- Report_No_Sources --
7640 -----------------------
7642 procedure Report_No_Sources
7643 (Project : Project_Id;
7645 Data : Tree_Processing_Data;
7646 Location : Source_Ptr;
7647 Continuation : Boolean := False)
7650 case Data.Flags.When_No_Sources is
7654 when Warning | Error =>
7656 Msg : constant String :=
7659 " sources in this project";
7662 Error_Msg_Warn := Data.Flags.When_No_Sources = Warning;
7664 if Continuation then
7665 Error_Msg (Data.Flags, "\" & Msg, Location, Project);
7667 Error_Msg (Data.Flags, Msg, Location, Project);
7671 end Report_No_Sources;
7673 ----------------------
7674 -- Show_Source_Dirs --
7675 ----------------------
7677 procedure Show_Source_Dirs
7678 (Project : Project_Id;
7679 In_Tree : Project_Tree_Ref)
7681 Current : String_List_Id;
7682 Element : String_Element;
7685 Write_Line ("Source_Dirs:");
7687 Current := Project.Source_Dirs;
7688 while Current /= Nil_String loop
7689 Element := In_Tree.String_Elements.Table (Current);
7691 Write_Line (Get_Name_String (Element.Display_Value));
7692 Current := Element.Next;
7695 Write_Line ("end Source_Dirs.");
7696 end Show_Source_Dirs;
7698 ---------------------------
7699 -- Process_Naming_Scheme --
7700 ---------------------------
7702 procedure Process_Naming_Scheme
7703 (Tree : Project_Tree_Ref;
7704 Root_Project : Project_Id;
7705 Node_Tree : Prj.Tree.Project_Node_Tree_Ref;
7706 Flags : Processing_Flags)
7708 procedure Recursive_Check
7709 (Project : Project_Id;
7710 Data : in out Tree_Processing_Data);
7711 -- Check_Naming_Scheme for the project
7713 ---------------------
7714 -- Recursive_Check --
7715 ---------------------
7717 procedure Recursive_Check
7718 (Project : Project_Id;
7719 Data : in out Tree_Processing_Data)
7722 if Verbose_Mode then
7723 Write_Str ("Processing_Naming_Scheme for project """);
7724 Write_Str (Get_Name_String (Project.Name));
7728 Prj.Nmsc.Check (Project, Data);
7729 end Recursive_Check;
7731 procedure Check_All_Projects is new
7732 For_Every_Project_Imported (Tree_Processing_Data, Recursive_Check);
7734 Data : Tree_Processing_Data;
7736 -- Start of processing for Process_Naming_Scheme
7738 Lib_Data_Table.Init;
7739 Initialize (Data, Tree => Tree, Node_Tree => Node_Tree, Flags => Flags);
7740 Check_All_Projects (Root_Project, Data, Imported_First => True);
7743 -- Adjust language configs for projects that are extended
7746 List : Project_List;
7749 Lang : Language_Ptr;
7750 Elng : Language_Ptr;
7753 List := Tree.Projects;
7754 while List /= null loop
7755 Proj := List.Project;
7757 while Exte.Extended_By /= No_Project loop
7758 Exte := Exte.Extended_By;
7761 if Exte /= Proj then
7762 Lang := Proj.Languages;
7764 if Lang /= No_Language_Index then
7766 Elng := Get_Language_From_Name
7767 (Exte, Get_Name_String (Lang.Name));
7768 exit when Elng /= No_Language_Index;
7769 Exte := Exte.Extends;
7772 if Elng /= Lang then
7773 Lang.Config := Elng.Config;
7781 end Process_Naming_Scheme;