1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2000-2009, 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;
30 with Err_Vars; use Err_Vars;
32 with Osint; use Osint;
33 with Output; use Output;
34 with Prj.Err; use Prj.Err;
35 with Prj.Util; use Prj.Util;
37 with Snames; use Snames;
38 with Targparm; use Targparm;
40 with Ada.Characters.Handling; use Ada.Characters.Handling;
41 with Ada.Directories; use Ada.Directories;
42 with Ada.Strings; use Ada.Strings;
43 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
44 with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
46 package body Prj.Nmsc is
48 No_Continuation_String : aliased String := "";
49 Continuation_String : aliased String := "\";
50 -- Used in Check_Library for continuation error messages at the same
53 type Name_Location is record
54 Name : File_Name_Type; -- ??? duplicates the key
55 Location : Source_Ptr;
56 Source : Source_Id := No_Source;
57 Found : Boolean := False;
59 No_Name_Location : constant Name_Location :=
60 (No_File, No_Location, No_Source, False);
61 package Source_Names_Htable is new GNAT.Dynamic_HTables.Simple_HTable
62 (Header_Num => Header_Num,
63 Element => Name_Location,
64 No_Element => No_Name_Location,
65 Key => File_Name_Type,
68 -- Information about file names found in string list attribute
69 -- (Source_Files or Source_List_File).
70 -- Except is set to True if source is a naming exception in the project.
71 -- This is used to check that all referenced files were indeed found on the
74 type Unit_Exception is record
75 Name : Name_Id; -- ??? duplicates the key
76 Spec : File_Name_Type;
77 Impl : File_Name_Type;
80 No_Unit_Exception : constant Unit_Exception := (No_Name, No_File, No_File);
82 package Unit_Exceptions_Htable is new GNAT.Dynamic_HTables.Simple_HTable
83 (Header_Num => Header_Num,
84 Element => Unit_Exception,
85 No_Element => No_Unit_Exception,
89 -- Record special naming schemes for Ada units (name of spec file and name
90 -- of implementation file). The elements in this list come from the naming
91 -- exceptions specified in the project files.
93 type File_Found is record
94 File : File_Name_Type := No_File;
95 Found : Boolean := False;
96 Location : Source_Ptr := No_Location;
99 No_File_Found : constant File_Found := (No_File, False, No_Location);
101 package Excluded_Sources_Htable is new GNAT.Dynamic_HTables.Simple_HTable
102 (Header_Num => Header_Num,
103 Element => File_Found,
104 No_Element => No_File_Found,
105 Key => File_Name_Type,
108 -- A hash table to store the base names of excluded files, if any.
110 package Object_File_Names_Htable is new GNAT.Dynamic_HTables.Simple_HTable
111 (Header_Num => Header_Num,
112 Element => Source_Id,
113 No_Element => No_Source,
114 Key => File_Name_Type,
117 -- A hash table to store the object file names for a project, to check that
118 -- two different sources have different object file names.
120 type Project_Processing_Data is record
121 Project : Project_Id;
122 Source_Names : Source_Names_Htable.Instance;
123 Unit_Exceptions : Unit_Exceptions_Htable.Instance;
124 Excluded : Excluded_Sources_Htable.Instance;
126 Source_List_File_Location : Source_Ptr;
127 -- Location of the Source_List_File attribute, for error messages
129 -- This is similar to Tree_Processing_Data, but contains project-specific
130 -- information which is only useful while processing the project, and can
131 -- be discarded as soon as we have finished processing the project
133 package Files_Htable is new GNAT.Dynamic_HTables.Simple_HTable
134 (Header_Num => Header_Num,
135 Element => Source_Id,
136 No_Element => No_Source,
137 Key => File_Name_Type,
140 -- Mapping from base file names to Source_Id (containing full info about
143 type Tree_Processing_Data is record
144 Tree : Project_Tree_Ref;
145 File_To_Source : Files_Htable.Instance;
146 Flags : Prj.Processing_Flags;
148 -- Temporary data which is needed while parsing a project. It does not need
149 -- to be kept in memory once a project has been fully loaded, but is
150 -- necessary while performing consistency checks (duplicate sources,...)
151 -- This data must be initialized before processing any project, and the
152 -- same data is used for processing all projects in the tree.
155 (Data : out Tree_Processing_Data;
156 Tree : Project_Tree_Ref;
157 Flags : Prj.Processing_Flags);
160 procedure Free (Data : in out Tree_Processing_Data);
161 -- Free the memory occupied by Data
164 (Project : Project_Id;
165 Data : in out Tree_Processing_Data);
166 -- Process the naming scheme for a single project.
169 (Data : in out Project_Processing_Data;
170 Project : Project_Id);
171 procedure Free (Data : in out Project_Processing_Data);
172 -- Initialize or free memory for a project-specific data
174 procedure Find_Excluded_Sources
175 (Project : in out Project_Processing_Data;
176 Data : in out Tree_Processing_Data);
177 -- Find the list of files that should not be considered as source files
178 -- for this project. Sets the list in the Project.Excluded_Sources_Htable.
180 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind);
181 -- Override the reference kind for a source file. This properly updates
182 -- the unit data if necessary.
184 procedure Load_Naming_Exceptions
185 (Project : in out Project_Processing_Data;
186 Data : in out Tree_Processing_Data);
187 -- All source files in Data.First_Source are considered as naming
188 -- exceptions, and copied into the Source_Names and Unit_Exceptions tables
193 Data : in out Tree_Processing_Data;
194 Project : Project_Id;
195 Lang_Id : Language_Ptr;
197 File_Name : File_Name_Type;
198 Display_File : File_Name_Type;
199 Naming_Exception : Boolean := False;
200 Path : Path_Information := No_Path_Information;
201 Alternate_Languages : Language_List := null;
202 Unit : Name_Id := No_Name;
204 Locally_Removed : Boolean := False;
205 Location : Source_Ptr := No_Location);
206 -- Add a new source to the different lists: list of all sources in the
207 -- project tree, list of source of a project and list of sources of a
210 -- If Path is specified, the file is also added to Source_Paths_HT.
212 -- Location is used for error messages
214 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type;
215 -- Same as Osint.Canonical_Case_File_Name but applies to Name_Id.
216 -- This alters Name_Buffer
218 function Suffix_Matches
220 Suffix : File_Name_Type) return Boolean;
221 -- True if the file name ends with the given suffix. Always returns False
222 -- if Suffix is No_Name.
224 procedure Replace_Into_Name_Buffer
227 Replacement : Character);
228 -- Copy Str into Name_Buffer, replacing Pattern with Replacement. Str is
229 -- converted to lower-case at the same time.
231 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
232 -- Check that a name is a valid Ada unit name
234 procedure Check_Package_Naming
235 (Project : Project_Id;
236 Data : in out Tree_Processing_Data;
237 Bodies : out Array_Element_Id;
238 Specs : out Array_Element_Id);
239 -- Check the naming scheme part of Data, and initialize the naming scheme
240 -- data in the config of the various languages. This also returns the
241 -- naming scheme exceptions for unit-based languages (Bodies and Specs are
242 -- associative arrays mapping individual unit names to source file names).
244 procedure Check_Configuration
245 (Project : Project_Id;
246 Data : in out Tree_Processing_Data);
247 -- Check the configuration attributes for the project
249 procedure Check_If_Externally_Built
250 (Project : Project_Id;
251 Data : in out Tree_Processing_Data);
252 -- Check attribute Externally_Built of project Project in project tree
253 -- Data.Tree and modify its data Data if it has the value "true".
255 procedure Check_Interfaces
256 (Project : Project_Id;
257 Data : in out Tree_Processing_Data);
258 -- If a list of sources is specified in attribute Interfaces, set
259 -- In_Interfaces only for the sources specified in the list.
261 procedure Check_Library_Attributes
262 (Project : Project_Id;
263 Data : in out Tree_Processing_Data);
264 -- Check the library attributes of project Project in project tree
265 -- and modify its data Data accordingly.
267 procedure Check_Programming_Languages
268 (Project : Project_Id;
269 Data : in out Tree_Processing_Data);
270 -- Check attribute Languages for the project with data Data in project
271 -- tree Data.Tree and set the components of Data for all the programming
272 -- languages indicated in attribute Languages, if any.
274 procedure Check_Stand_Alone_Library
275 (Project : Project_Id;
276 Data : in out Tree_Processing_Data);
277 -- Check if project Project in project tree Data.Tree is a Stand-Alone
278 -- Library project, and modify its data Data accordingly if it is one.
280 function Compute_Directory_Last (Dir : String) return Natural;
281 -- Return the index of the last significant character in Dir. This is used
282 -- to avoid duplicate '/' (slash) characters at the end of directory names.
284 procedure Search_Directories
285 (Project : in out Project_Processing_Data;
286 Data : in out Tree_Processing_Data;
287 For_All_Sources : Boolean);
288 -- Search the source directories to find the sources. If For_All_Sources is
289 -- True, check each regular file name against the naming schemes of the
290 -- various languages. Otherwise consider only the file names in hash table
291 -- Source_Names. If Allow_Duplicate_Basenames then files with identical
292 -- base names are permitted within a project for source-based languages
293 -- (never for unit based languages).
296 (Project : in out Project_Processing_Data;
297 Data : in out Tree_Processing_Data;
298 Path : Path_Name_Type;
299 File_Name : File_Name_Type;
300 Display_File_Name : File_Name_Type;
301 Locally_Removed : Boolean;
302 For_All_Sources : Boolean);
303 -- Check if file File_Name is a valid source of the project. This is used
304 -- in multi-language mode only. When the file matches one of the naming
305 -- schemes, it is added to various htables through Add_Source and to
306 -- Source_Paths_Htable.
308 -- Name is the name of the candidate file. It hasn't been normalized yet
309 -- and is the direct result of readdir().
311 -- File_Name is the same as Name, but has been normalized.
312 -- Display_File_Name, however, has not been normalized.
314 -- Source_Directory is the directory in which the file was found. It is
315 -- neither normalized nor has had links resolved, and must not end with a
316 -- a directory separator, to avoid duplicates later on.
318 -- If For_All_Sources is True, then all possible file names are analyzed
319 -- otherwise only those currently set in the Source_Names hash table.
321 procedure Check_File_Naming_Schemes
322 (In_Tree : Project_Tree_Ref;
323 Project : Project_Processing_Data;
324 File_Name : File_Name_Type;
325 Alternate_Languages : out Language_List;
326 Language : out Language_Ptr;
327 Display_Language_Name : out Name_Id;
329 Lang_Kind : out Language_Kind;
330 Kind : out Source_Kind);
331 -- Check if the file name File_Name conforms to one of the naming schemes
332 -- of the project. If the file does not match one of the naming schemes,
333 -- set Language to No_Language_Index. Filename is the name of the file
334 -- being investigated. It has been normalized (case-folded). File_Name is
337 procedure Get_Directories
338 (Project : Project_Id;
339 Data : in out Tree_Processing_Data);
340 -- Get the object directory, the exec directory and the source directories
344 (Project : Project_Id;
345 Data : in out Tree_Processing_Data);
346 -- Get the mains of a project from attribute Main, if it exists, and put
347 -- them in the project data.
349 procedure Get_Sources_From_File
351 Location : Source_Ptr;
352 Project : in out Project_Processing_Data;
353 Data : in out Tree_Processing_Data);
354 -- Get the list of sources from a text file and put them in hash table
357 procedure Find_Sources
358 (Project : in out Project_Processing_Data;
359 Data : in out Tree_Processing_Data);
360 -- Process the Source_Files and Source_List_File attributes, and store the
361 -- list of source files into the Source_Names htable. When these attributes
362 -- are not defined, find all files matching the naming schemes in the
363 -- source directories. If Allow_Duplicate_Basenames, then files with the
364 -- same base names are authorized within a project for source-based
365 -- languages (never for unit based languages)
367 procedure Compute_Unit_Name
368 (File_Name : File_Name_Type;
369 Naming : Lang_Naming_Data;
370 Kind : out Source_Kind;
372 Project : Project_Processing_Data;
373 In_Tree : Project_Tree_Ref);
374 -- Check whether the file matches the naming scheme. If it does,
375 -- compute its unit name. If Unit is set to No_Name on exit, none of the
376 -- other out parameters are relevant.
378 procedure Check_Illegal_Suffix
379 (Project : Project_Id;
380 Suffix : File_Name_Type;
381 Dot_Replacement : File_Name_Type;
382 Attribute_Name : String;
383 Location : Source_Ptr;
384 Data : in out Tree_Processing_Data);
385 -- Display an error message if the given suffix is illegal for some reason.
386 -- The name of the attribute we are testing is specified in Attribute_Name,
387 -- which is used in the error message. Location is the location where the
388 -- suffix is defined.
390 procedure Locate_Directory
391 (Project : Project_Id;
392 Name : File_Name_Type;
393 Path : out Path_Information;
394 Dir_Exists : out Boolean;
395 Data : in out Tree_Processing_Data;
396 Create : String := "";
397 Location : Source_Ptr := No_Location;
398 Must_Exist : Boolean := True;
399 Externally_Built : Boolean := False);
400 -- Locate a directory. Name is the directory name. Relative paths are
401 -- resolved relative to the project's directory. If the directory does not
402 -- exist and Setup_Projects is True and Create is a non null string, an
403 -- attempt is made to create the directory. If the directory does not
404 -- exist, it is either created if Setup_Projects is False (and then
405 -- returned), or simply returned without checking for its existence (if
406 -- Must_Exist is False) or No_Path_Information is returned. In all cases,
407 -- Dir_Exists indicates whether the directory now exists. Create is also
408 -- used for debugging traces to show which path we are computing.
410 procedure Look_For_Sources
411 (Project : in out Project_Processing_Data;
412 Data : in out Tree_Processing_Data);
413 -- Find all the sources of project Project in project tree Data.Tree and
414 -- update its Data accordingly. This assumes that Data.First_Source has
415 -- been initialized with the list of excluded sources and special naming
418 function Path_Name_Of
419 (File_Name : File_Name_Type;
420 Directory : Path_Name_Type) return String;
421 -- Returns the path name of a (non project) file. Returns an empty string
422 -- if file cannot be found.
424 procedure Remove_Source
426 Replaced_By : Source_Id);
427 -- Remove a file from the list of sources of a project. This might be
428 -- because the file is replaced by another one in an extending project,
429 -- or because a file was added as a naming exception but was not found
432 procedure Report_No_Sources
433 (Project : Project_Id;
435 Data : Tree_Processing_Data;
436 Location : Source_Ptr;
437 Continuation : Boolean := False);
438 -- Report an error or a warning depending on the value of When_No_Sources
439 -- when there are no sources for language Lang_Name.
441 procedure Show_Source_Dirs
442 (Project : Project_Id; In_Tree : Project_Tree_Ref);
443 -- List all the source directories of a project
445 procedure Write_Attr (Name, Value : String);
446 -- Debug print a value for a specific property. Does nothing when not in
449 ------------------------------
450 -- Replace_Into_Name_Buffer --
451 ------------------------------
453 procedure Replace_Into_Name_Buffer
456 Replacement : Character)
458 Max : constant Integer := Str'Last - Pattern'Length + 1;
465 while J <= Str'Last loop
466 Name_Len := Name_Len + 1;
469 and then Str (J .. J + Pattern'Length - 1) = Pattern
471 Name_Buffer (Name_Len) := Replacement;
472 J := J + Pattern'Length;
475 Name_Buffer (Name_Len) := GNAT.Case_Util.To_Lower (Str (J));
479 end Replace_Into_Name_Buffer;
485 function Suffix_Matches
487 Suffix : File_Name_Type) return Boolean
489 Min_Prefix_Length : Natural := 0;
492 if Suffix = No_File or else Suffix = Empty_File then
497 Suf : constant String := Get_Name_String (Suffix);
500 -- The file name must end with the suffix (which is not an extension)
501 -- For instance a suffix "configure.in" must match a file with the
502 -- same name. To avoid dummy cases, though, a suffix starting with
503 -- '.' requires a file that is at least one character longer ('.cpp'
504 -- should not match a file with the same name)
506 if Suf (Suf'First) = '.' then
507 Min_Prefix_Length := 1;
510 return Filename'Length >= Suf'Length + Min_Prefix_Length
512 (Filename'Last - Suf'Length + 1 .. Filename'Last) = Suf;
520 procedure Write_Attr (Name, Value : String) is
522 if Current_Verbosity = High then
523 Write_Str (" " & Name & " = """);
536 Data : in out Tree_Processing_Data;
537 Project : Project_Id;
538 Lang_Id : Language_Ptr;
540 File_Name : File_Name_Type;
541 Display_File : File_Name_Type;
542 Naming_Exception : Boolean := False;
543 Path : Path_Information := No_Path_Information;
544 Alternate_Languages : Language_List := null;
545 Unit : Name_Id := No_Name;
547 Locally_Removed : Boolean := False;
548 Location : Source_Ptr := No_Location)
550 Config : constant Language_Config := Lang_Id.Config;
554 Prev_Unit : Unit_Index := No_Unit_Index;
556 Source_To_Replace : Source_Id := No_Source;
559 -- Check if the same file name or unit is used in the prj tree
563 if Unit /= No_Name then
564 Prev_Unit := Units_Htable.Get (Data.Tree.Units_HT, Unit);
567 if Prev_Unit /= No_Unit_Index
568 and then (Kind = Impl or else Kind = Spec)
569 and then Prev_Unit.File_Names (Kind) /= null
571 -- Suspicious, we need to check later whether this is authorized
574 Source := Prev_Unit.File_Names (Kind);
577 Source := Files_Htable.Get (Data.File_To_Source, File_Name);
579 if Source /= No_Source
580 and then Source.Index = Index
586 -- Duplication of file/unit in same project is allowed if order of
587 -- source directories is known.
589 if Add_Src = False then
592 if Project = Source.Project then
593 if Prev_Unit = No_Unit_Index then
594 if Data.Flags.Allow_Duplicate_Basenames then
597 elsif Project.Known_Order_Of_Source_Dirs then
601 Error_Msg_File_1 := File_Name;
603 (Data.Flags, "duplicate source file name {",
609 if Project.Known_Order_Of_Source_Dirs then
612 -- We might be seeing the same file through a different path
613 -- (for instance because of symbolic links).
615 elsif Source.Path.Name /= Path.Name then
616 Error_Msg_Name_1 := Unit;
618 (Data.Flags, "duplicate unit %%", Location, Project);
623 -- Do not allow the same unit name in different projects, except
624 -- if one is extending the other.
626 -- For a file based language, the same file name replaces a file
627 -- in a project being extended, but it is allowed to have the same
628 -- file name in unrelated projects.
630 elsif Is_Extending (Project, Source.Project) then
631 if not Locally_Removed then
632 Source_To_Replace := Source;
635 elsif Prev_Unit /= No_Unit_Index
636 and then not Source.Locally_Removed
638 -- Path is set if this is a source we found on the disk, in which
639 -- case we can provide more explicit error message. Path is unset
640 -- when the source is added from one of the naming exceptions in
643 if Path /= No_Path_Information then
644 Error_Msg_Name_1 := Unit;
647 "unit %% cannot belong to several projects",
650 Error_Msg_Name_1 := Project.Name;
651 Error_Msg_Name_2 := Name_Id (Path.Name);
653 (Data.Flags, "\ project %%, %%", Location, Project);
655 Error_Msg_Name_1 := Source.Project.Name;
656 Error_Msg_Name_2 := Name_Id (Source.Path.Display_Name);
658 (Data.Flags, "\ project %%, %%", Location, Project);
661 Error_Msg_Name_1 := Unit;
662 Error_Msg_Name_2 := Source.Project.Name;
664 (Data.Flags, "unit %% already belongs to project %%",
670 elsif not Source.Locally_Removed
671 and then not Data.Flags.Allow_Duplicate_Basenames
672 and then Lang_Id.Config.Kind = Unit_Based
674 Error_Msg_File_1 := File_Name;
675 Error_Msg_File_2 := File_Name_Type (Source.Project.Name);
678 "{ is already a source of project {", Location, Project);
680 -- Add the file anyway, to avoid further warnings like "language
693 Id := new Source_Data;
695 if Current_Verbosity = High then
696 Write_Str ("Adding source File: ");
697 Write_Str (Get_Name_String (File_Name));
700 Write_Str (" at" & Index'Img);
703 if Lang_Id.Config.Kind = Unit_Based then
704 Write_Str (" Unit: ");
706 -- ??? in gprclean, it seems we sometimes pass an empty Unit name
707 -- (see test extended_projects).
709 if Unit /= No_Name then
710 Write_Str (Get_Name_String (Unit));
713 Write_Str (" Kind: ");
714 Write_Str (Source_Kind'Image (Kind));
720 Id.Project := Project;
721 Id.Language := Lang_Id;
723 Id.Alternate_Languages := Alternate_Languages;
724 Id.Locally_Removed := Locally_Removed;
726 -- Add the source id to the Unit_Sources_HT hash table, if the unit name
729 if Unit /= No_Name then
730 UData := Units_Htable.Get (Data.Tree.Units_HT, Unit);
732 if UData = No_Unit_Index then
733 UData := new Unit_Data;
735 Units_Htable.Set (Data.Tree.Units_HT, Unit, UData);
740 -- Note that this updates Unit information as well
742 Override_Kind (Id, Kind);
746 Id.File := File_Name;
747 Id.Display_File := Display_File;
748 Id.Dep_Name := Dependency_Name
749 (File_Name, Lang_Id.Config.Dependency_Kind);
750 Id.Naming_Exception := Naming_Exception;
752 if Is_Compilable (Id) and then Config.Object_Generated then
753 Id.Object := Object_Name (File_Name, Config.Object_File_Suffix);
754 Id.Switches := Switches_Name (File_Name);
757 if Path /= No_Path_Information then
759 Source_Paths_Htable.Set (Data.Tree.Source_Paths_HT, Path.Name, Id);
762 -- Add the source to the language list
764 Id.Next_In_Lang := Lang_Id.First_Source;
765 Lang_Id.First_Source := Id;
767 if Source_To_Replace /= No_Source then
768 Remove_Source (Source_To_Replace, Id);
771 Files_Htable.Set (Data.File_To_Source, File_Name, Id);
774 ------------------------------
775 -- Canonical_Case_File_Name --
776 ------------------------------
778 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type is
780 if Osint.File_Names_Case_Sensitive then
781 return File_Name_Type (Name);
783 Get_Name_String (Name);
784 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
787 end Canonical_Case_File_Name;
794 (Project : Project_Id;
795 Data : in out Tree_Processing_Data)
797 Specs : Array_Element_Id;
798 Bodies : Array_Element_Id;
799 Extending : Boolean := False;
800 Prj_Data : Project_Processing_Data;
803 Initialize (Prj_Data, Project);
805 Check_If_Externally_Built (Project, Data);
807 -- Object, exec and source directories
809 Get_Directories (Project, Data);
811 -- Get the programming languages
813 Check_Programming_Languages (Project, Data);
815 if Project.Qualifier = Dry
816 and then Project.Source_Dirs /= Nil_String
819 Source_Dirs : constant Variable_Value :=
822 Project.Decl.Attributes, Data.Tree);
823 Source_Files : constant Variable_Value :=
826 Project.Decl.Attributes, Data.Tree);
827 Source_List_File : constant Variable_Value :=
829 (Name_Source_List_File,
830 Project.Decl.Attributes, Data.Tree);
831 Languages : constant Variable_Value :=
834 Project.Decl.Attributes, Data.Tree);
837 if Source_Dirs.Values = Nil_String
838 and then Source_Files.Values = Nil_String
839 and then Languages.Values = Nil_String
840 and then Source_List_File.Default
842 Project.Source_Dirs := Nil_String;
847 "at least one of Source_Files, Source_Dirs or Languages "
848 & "must be declared empty for an abstract project",
849 Project.Location, Project);
854 -- Check configuration. This must be done even for gnatmake (even though
855 -- no user configuration file was provided) since the default config we
856 -- generate indicates whether libraries are supported for instance.
858 Check_Configuration (Project, Data);
860 -- Library attributes
862 Check_Library_Attributes (Project, Data);
864 if Current_Verbosity = High then
865 Show_Source_Dirs (Project, Data.Tree);
868 Extending := Project.Extends /= No_Project;
870 Check_Package_Naming (Project, Data, Bodies => Bodies, Specs => Specs);
874 if Project.Source_Dirs /= Nil_String then
875 Look_For_Sources (Prj_Data, Data);
877 if not Project.Externally_Built
878 and then not Extending
881 Language : Language_Ptr;
883 Alt_Lang : Language_List;
884 Continuation : Boolean := False;
885 Iter : Source_Iterator;
888 Language := Project.Languages;
889 while Language /= No_Language_Index loop
891 -- If there are no sources for this language, check if there
892 -- are sources for which this is an alternate language.
894 if Language.First_Source = No_Source
895 and then (Data.Flags.Require_Sources_Other_Lang
896 or else Language.Name = Name_Ada)
898 Iter := For_Each_Source (In_Tree => Data.Tree,
901 Source := Element (Iter);
902 exit Source_Loop when Source = No_Source
903 or else Source.Language = Language;
905 Alt_Lang := Source.Alternate_Languages;
906 while Alt_Lang /= null loop
907 exit Source_Loop when Alt_Lang.Language = Language;
908 Alt_Lang := Alt_Lang.Next;
912 end loop Source_Loop;
914 if Source = No_Source then
918 Get_Name_String (Language.Display_Name),
920 Prj_Data.Source_List_File_Location,
922 Continuation := True;
926 Language := Language.Next;
932 -- If a list of sources is specified in attribute Interfaces, set
933 -- In_Interfaces only for the sources specified in the list.
935 Check_Interfaces (Project, Data);
937 -- If it is a library project file, check if it is a standalone library
939 if Project.Library then
940 Check_Stand_Alone_Library (Project, Data);
943 -- Put the list of Mains, if any, in the project data
945 Get_Mains (Project, Data);
954 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
955 The_Name : String := Name;
957 Need_Letter : Boolean := True;
958 Last_Underscore : Boolean := False;
959 OK : Boolean := The_Name'Length > 0;
962 function Is_Reserved (Name : Name_Id) return Boolean;
963 function Is_Reserved (S : String) return Boolean;
964 -- Check that the given name is not an Ada 95 reserved word. The reason
965 -- for the Ada 95 here is that we do not want to exclude the case of an
966 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
967 -- name would be rejected anyway by the compiler. That means there is no
968 -- requirement that the project file parser reject this.
974 function Is_Reserved (S : String) return Boolean is
977 Add_Str_To_Name_Buffer (S);
978 return Is_Reserved (Name_Find);
985 function Is_Reserved (Name : Name_Id) return Boolean is
987 if Get_Name_Table_Byte (Name) /= 0
988 and then Name /= Name_Project
989 and then Name /= Name_Extends
990 and then Name /= Name_External
991 and then Name not in Ada_2005_Reserved_Words
995 if Current_Verbosity = High then
996 Write_Str (The_Name);
997 Write_Line (" is an Ada reserved word.");
1007 -- Start of processing for Check_Ada_Name
1010 To_Lower (The_Name);
1012 Name_Len := The_Name'Length;
1013 Name_Buffer (1 .. Name_Len) := The_Name;
1015 -- Special cases of children of packages A, G, I and S on VMS
1017 if OpenVMS_On_Target
1018 and then Name_Len > 3
1019 and then Name_Buffer (2 .. 3) = "__"
1021 ((Name_Buffer (1) = 'a') or else
1022 (Name_Buffer (1) = 'g') or else
1023 (Name_Buffer (1) = 'i') or else
1024 (Name_Buffer (1) = 's'))
1026 Name_Buffer (2) := '.';
1027 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
1028 Name_Len := Name_Len - 1;
1031 Real_Name := Name_Find;
1033 if Is_Reserved (Real_Name) then
1037 First := The_Name'First;
1039 for Index in The_Name'Range loop
1042 -- We need a letter (at the beginning, and following a dot),
1043 -- but we don't have one.
1045 if Is_Letter (The_Name (Index)) then
1046 Need_Letter := False;
1051 if Current_Verbosity = High then
1052 Write_Int (Types.Int (Index));
1054 Write_Char (The_Name (Index));
1055 Write_Line ("' is not a letter.");
1061 elsif Last_Underscore
1062 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
1064 -- Two underscores are illegal, and a dot cannot follow
1069 if Current_Verbosity = High then
1070 Write_Int (Types.Int (Index));
1072 Write_Char (The_Name (Index));
1073 Write_Line ("' is illegal here.");
1078 elsif The_Name (Index) = '.' then
1080 -- First, check if the name before the dot is not a reserved word
1082 if Is_Reserved (The_Name (First .. Index - 1)) then
1088 -- We need a letter after a dot
1090 Need_Letter := True;
1092 elsif The_Name (Index) = '_' then
1093 Last_Underscore := True;
1096 -- We need an letter or a digit
1098 Last_Underscore := False;
1100 if not Is_Alphanumeric (The_Name (Index)) then
1103 if Current_Verbosity = High then
1104 Write_Int (Types.Int (Index));
1106 Write_Char (The_Name (Index));
1107 Write_Line ("' is not alphanumeric.");
1115 -- Cannot end with an underscore or a dot
1117 OK := OK and then not Need_Letter and then not Last_Underscore;
1120 if First /= Name'First and then
1121 Is_Reserved (The_Name (First .. The_Name'Last))
1129 -- Signal a problem with No_Name
1135 -------------------------
1136 -- Check_Configuration --
1137 -------------------------
1139 procedure Check_Configuration
1140 (Project : Project_Id;
1141 Data : in out Tree_Processing_Data)
1143 Dot_Replacement : File_Name_Type := No_File;
1144 Casing : Casing_Type := All_Lower_Case;
1145 Separate_Suffix : File_Name_Type := No_File;
1147 Lang_Index : Language_Ptr := No_Language_Index;
1148 -- The index of the language data being checked
1150 Prev_Index : Language_Ptr := No_Language_Index;
1151 -- The index of the previous language
1153 procedure Process_Project_Level_Simple_Attributes;
1154 -- Process the simple attributes at the project level
1156 procedure Process_Project_Level_Array_Attributes;
1157 -- Process the associate array attributes at the project level
1159 procedure Process_Packages;
1160 -- Read the packages of the project
1162 ----------------------
1163 -- Process_Packages --
1164 ----------------------
1166 procedure Process_Packages is
1167 Packages : Package_Id;
1168 Element : Package_Element;
1170 procedure Process_Binder (Arrays : Array_Id);
1171 -- Process the associate array attributes of package Binder
1173 procedure Process_Builder (Attributes : Variable_Id);
1174 -- Process the simple attributes of package Builder
1176 procedure Process_Compiler (Arrays : Array_Id);
1177 -- Process the associate array attributes of package Compiler
1179 procedure Process_Naming (Attributes : Variable_Id);
1180 -- Process the simple attributes of package Naming
1182 procedure Process_Naming (Arrays : Array_Id);
1183 -- Process the associate array attributes of package Naming
1185 procedure Process_Linker (Attributes : Variable_Id);
1186 -- Process the simple attributes of package Linker of a
1187 -- configuration project.
1189 --------------------
1190 -- Process_Binder --
1191 --------------------
1193 procedure Process_Binder (Arrays : Array_Id) is
1194 Current_Array_Id : Array_Id;
1195 Current_Array : Array_Data;
1196 Element_Id : Array_Element_Id;
1197 Element : Array_Element;
1200 -- Process the associative array attribute of package Binder
1202 Current_Array_Id := Arrays;
1203 while Current_Array_Id /= No_Array loop
1204 Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
1206 Element_Id := Current_Array.Value;
1207 while Element_Id /= No_Array_Element loop
1208 Element := Data.Tree.Array_Elements.Table (Element_Id);
1210 if Element.Index /= All_Other_Names then
1212 -- Get the name of the language
1215 Get_Language_From_Name
1216 (Project, Get_Name_String (Element.Index));
1218 if Lang_Index /= No_Language_Index then
1219 case Current_Array.Name is
1222 -- Attribute Driver (<language>)
1224 Lang_Index.Config.Binder_Driver :=
1225 File_Name_Type (Element.Value.Value);
1227 when Name_Required_Switches =>
1230 Lang_Index.Config.Binder_Required_Switches,
1231 From_List => Element.Value.Values,
1232 In_Tree => Data.Tree);
1236 -- Attribute Prefix (<language>)
1238 Lang_Index.Config.Binder_Prefix :=
1239 Element.Value.Value;
1241 when Name_Objects_Path =>
1243 -- Attribute Objects_Path (<language>)
1245 Lang_Index.Config.Objects_Path :=
1246 Element.Value.Value;
1248 when Name_Objects_Path_File =>
1250 -- Attribute Objects_Path (<language>)
1252 Lang_Index.Config.Objects_Path_File :=
1253 Element.Value.Value;
1261 Element_Id := Element.Next;
1264 Current_Array_Id := Current_Array.Next;
1268 ---------------------
1269 -- Process_Builder --
1270 ---------------------
1272 procedure Process_Builder (Attributes : Variable_Id) is
1273 Attribute_Id : Variable_Id;
1274 Attribute : Variable;
1277 -- Process non associated array attribute from package Builder
1279 Attribute_Id := Attributes;
1280 while Attribute_Id /= No_Variable loop
1282 Data.Tree.Variable_Elements.Table (Attribute_Id);
1284 if not Attribute.Value.Default then
1285 if Attribute.Name = Name_Executable_Suffix then
1287 -- Attribute Executable_Suffix: the suffix of the
1290 Project.Config.Executable_Suffix :=
1291 Attribute.Value.Value;
1295 Attribute_Id := Attribute.Next;
1297 end Process_Builder;
1299 ----------------------
1300 -- Process_Compiler --
1301 ----------------------
1303 procedure Process_Compiler (Arrays : Array_Id) is
1304 Current_Array_Id : Array_Id;
1305 Current_Array : Array_Data;
1306 Element_Id : Array_Element_Id;
1307 Element : Array_Element;
1308 List : String_List_Id;
1311 -- Process the associative array attribute of package Compiler
1313 Current_Array_Id := Arrays;
1314 while Current_Array_Id /= No_Array loop
1315 Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
1317 Element_Id := Current_Array.Value;
1318 while Element_Id /= No_Array_Element loop
1319 Element := Data.Tree.Array_Elements.Table (Element_Id);
1321 if Element.Index /= All_Other_Names then
1323 -- Get the name of the language
1325 Lang_Index := Get_Language_From_Name
1326 (Project, Get_Name_String (Element.Index));
1328 if Lang_Index /= No_Language_Index then
1329 case Current_Array.Name is
1330 when Name_Dependency_Switches =>
1332 -- Attribute Dependency_Switches (<language>)
1334 if Lang_Index.Config.Dependency_Kind = None then
1335 Lang_Index.Config.Dependency_Kind := Makefile;
1338 List := Element.Value.Values;
1340 if List /= Nil_String then
1342 Lang_Index.Config.Dependency_Option,
1344 In_Tree => Data.Tree);
1347 when Name_Dependency_Driver =>
1349 -- Attribute Dependency_Driver (<language>)
1351 if Lang_Index.Config.Dependency_Kind = None then
1352 Lang_Index.Config.Dependency_Kind := Makefile;
1355 List := Element.Value.Values;
1357 if List /= Nil_String then
1359 Lang_Index.Config.Compute_Dependency,
1361 In_Tree => Data.Tree);
1364 when Name_Include_Switches =>
1366 -- Attribute Include_Switches (<language>)
1368 List := Element.Value.Values;
1370 if List = Nil_String then
1372 (Data.Flags, "include option cannot be null",
1373 Element.Value.Location, Project);
1376 Put (Into_List => Lang_Index.Config.Include_Option,
1378 In_Tree => Data.Tree);
1380 when Name_Include_Path =>
1382 -- Attribute Include_Path (<language>)
1384 Lang_Index.Config.Include_Path :=
1385 Element.Value.Value;
1387 when Name_Include_Path_File =>
1389 -- Attribute Include_Path_File (<language>)
1391 Lang_Index.Config.Include_Path_File :=
1392 Element.Value.Value;
1396 -- Attribute Driver (<language>)
1398 Lang_Index.Config.Compiler_Driver :=
1399 File_Name_Type (Element.Value.Value);
1401 when Name_Required_Switches |
1402 Name_Leading_Required_Switches =>
1405 Compiler_Leading_Required_Switches,
1406 From_List => Element.Value.Values,
1407 In_Tree => Data.Tree);
1409 when Name_Trailing_Required_Switches =>
1412 Compiler_Trailing_Required_Switches,
1413 From_List => Element.Value.Values,
1414 In_Tree => Data.Tree);
1416 when Name_Path_Syntax =>
1418 Lang_Index.Config.Path_Syntax :=
1419 Path_Syntax_Kind'Value
1420 (Get_Name_String (Element.Value.Value));
1423 when Constraint_Error =>
1426 "invalid value for Path_Syntax",
1427 Element.Value.Location, Project);
1430 when Name_Object_File_Suffix =>
1431 if Get_Name_String (Element.Value.Value) = "" then
1434 "object file suffix cannot be empty",
1435 Element.Value.Location, Project);
1438 Lang_Index.Config.Object_File_Suffix :=
1439 Element.Value.Value;
1442 when Name_Object_File_Switches =>
1444 Lang_Index.Config.Object_File_Switches,
1445 From_List => Element.Value.Values,
1446 In_Tree => Data.Tree);
1448 when Name_Pic_Option =>
1450 -- Attribute Compiler_Pic_Option (<language>)
1452 List := Element.Value.Values;
1454 if List = Nil_String then
1457 "compiler PIC option cannot be null",
1458 Element.Value.Location, Project);
1462 Lang_Index.Config.Compilation_PIC_Option,
1464 In_Tree => Data.Tree);
1466 when Name_Mapping_File_Switches =>
1468 -- Attribute Mapping_File_Switches (<language>)
1470 List := Element.Value.Values;
1472 if List = Nil_String then
1475 "mapping file switches cannot be null",
1476 Element.Value.Location, Project);
1480 Lang_Index.Config.Mapping_File_Switches,
1482 In_Tree => Data.Tree);
1484 when Name_Mapping_Spec_Suffix =>
1486 -- Attribute Mapping_Spec_Suffix (<language>)
1488 Lang_Index.Config.Mapping_Spec_Suffix :=
1489 File_Name_Type (Element.Value.Value);
1491 when Name_Mapping_Body_Suffix =>
1493 -- Attribute Mapping_Body_Suffix (<language>)
1495 Lang_Index.Config.Mapping_Body_Suffix :=
1496 File_Name_Type (Element.Value.Value);
1498 when Name_Config_File_Switches =>
1500 -- Attribute Config_File_Switches (<language>)
1502 List := Element.Value.Values;
1504 if List = Nil_String then
1507 "config file switches cannot be null",
1508 Element.Value.Location, Project);
1512 Lang_Index.Config.Config_File_Switches,
1514 In_Tree => Data.Tree);
1516 when Name_Objects_Path =>
1518 -- Attribute Objects_Path (<language>)
1520 Lang_Index.Config.Objects_Path :=
1521 Element.Value.Value;
1523 when Name_Objects_Path_File =>
1525 -- Attribute Objects_Path_File (<language>)
1527 Lang_Index.Config.Objects_Path_File :=
1528 Element.Value.Value;
1530 when Name_Config_Body_File_Name =>
1532 -- Attribute Config_Body_File_Name (<language>)
1534 Lang_Index.Config.Config_Body :=
1535 Element.Value.Value;
1537 when Name_Config_Body_File_Name_Pattern =>
1539 -- Attribute Config_Body_File_Name_Pattern
1542 Lang_Index.Config.Config_Body_Pattern :=
1543 Element.Value.Value;
1545 when Name_Config_Spec_File_Name =>
1547 -- Attribute Config_Spec_File_Name (<language>)
1549 Lang_Index.Config.Config_Spec :=
1550 Element.Value.Value;
1552 when Name_Config_Spec_File_Name_Pattern =>
1554 -- Attribute Config_Spec_File_Name_Pattern
1557 Lang_Index.Config.Config_Spec_Pattern :=
1558 Element.Value.Value;
1560 when Name_Config_File_Unique =>
1562 -- Attribute Config_File_Unique (<language>)
1565 Lang_Index.Config.Config_File_Unique :=
1567 (Get_Name_String (Element.Value.Value));
1569 when Constraint_Error =>
1572 "illegal value for Config_File_Unique",
1573 Element.Value.Location, Project);
1582 Element_Id := Element.Next;
1585 Current_Array_Id := Current_Array.Next;
1587 end Process_Compiler;
1589 --------------------
1590 -- Process_Naming --
1591 --------------------
1593 procedure Process_Naming (Attributes : Variable_Id) is
1594 Attribute_Id : Variable_Id;
1595 Attribute : Variable;
1598 -- Process non associated array attribute from package Naming
1600 Attribute_Id := Attributes;
1601 while Attribute_Id /= No_Variable loop
1602 Attribute := Data.Tree.Variable_Elements.Table (Attribute_Id);
1604 if not Attribute.Value.Default then
1605 if Attribute.Name = Name_Separate_Suffix then
1607 -- Attribute Separate_Suffix
1609 Get_Name_String (Attribute.Value.Value);
1610 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
1611 Separate_Suffix := Name_Find;
1613 elsif Attribute.Name = Name_Casing then
1619 Value (Get_Name_String (Attribute.Value.Value));
1622 when Constraint_Error =>
1625 "invalid value for Casing",
1626 Attribute.Value.Location, Project);
1629 elsif Attribute.Name = Name_Dot_Replacement then
1631 -- Attribute Dot_Replacement
1633 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1638 Attribute_Id := Attribute.Next;
1642 procedure Process_Naming (Arrays : Array_Id) is
1643 Current_Array_Id : Array_Id;
1644 Current_Array : Array_Data;
1645 Element_Id : Array_Element_Id;
1646 Element : Array_Element;
1649 -- Process the associative array attribute of package Naming
1651 Current_Array_Id := Arrays;
1652 while Current_Array_Id /= No_Array loop
1653 Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
1655 Element_Id := Current_Array.Value;
1656 while Element_Id /= No_Array_Element loop
1657 Element := Data.Tree.Array_Elements.Table (Element_Id);
1659 -- Get the name of the language
1661 Lang_Index := Get_Language_From_Name
1662 (Project, Get_Name_String (Element.Index));
1664 if Lang_Index /= No_Language_Index then
1665 case Current_Array.Name is
1666 when Name_Spec_Suffix | Name_Specification_Suffix =>
1668 -- Attribute Spec_Suffix (<language>)
1670 Get_Name_String (Element.Value.Value);
1671 Canonical_Case_File_Name
1672 (Name_Buffer (1 .. Name_Len));
1673 Lang_Index.Config.Naming_Data.Spec_Suffix :=
1676 when Name_Implementation_Suffix | Name_Body_Suffix =>
1678 Get_Name_String (Element.Value.Value);
1679 Canonical_Case_File_Name
1680 (Name_Buffer (1 .. Name_Len));
1682 -- Attribute Body_Suffix (<language>)
1684 Lang_Index.Config.Naming_Data.Body_Suffix :=
1686 Lang_Index.Config.Naming_Data.Separate_Suffix :=
1687 Lang_Index.Config.Naming_Data.Body_Suffix;
1694 Element_Id := Element.Next;
1697 Current_Array_Id := Current_Array.Next;
1701 --------------------
1702 -- Process_Linker --
1703 --------------------
1705 procedure Process_Linker (Attributes : Variable_Id) is
1706 Attribute_Id : Variable_Id;
1707 Attribute : Variable;
1710 -- Process non associated array attribute from package Linker
1712 Attribute_Id := Attributes;
1713 while Attribute_Id /= No_Variable loop
1715 Data.Tree.Variable_Elements.Table (Attribute_Id);
1717 if not Attribute.Value.Default then
1718 if Attribute.Name = Name_Driver then
1720 -- Attribute Linker'Driver: the default linker to use
1722 Project.Config.Linker :=
1723 Path_Name_Type (Attribute.Value.Value);
1725 -- Linker'Driver is also used to link shared libraries
1726 -- if the obsolescent attribute Library_GCC has not been
1729 if Project.Config.Shared_Lib_Driver = No_File then
1730 Project.Config.Shared_Lib_Driver :=
1731 File_Name_Type (Attribute.Value.Value);
1734 elsif Attribute.Name = Name_Required_Switches then
1736 -- Attribute Required_Switches: the minimum
1737 -- options to use when invoking the linker
1739 Put (Into_List => Project.Config.Minimum_Linker_Options,
1740 From_List => Attribute.Value.Values,
1741 In_Tree => Data.Tree);
1743 elsif Attribute.Name = Name_Map_File_Option then
1744 Project.Config.Map_File_Option := Attribute.Value.Value;
1746 elsif Attribute.Name = Name_Max_Command_Line_Length then
1748 Project.Config.Max_Command_Line_Length :=
1749 Natural'Value (Get_Name_String
1750 (Attribute.Value.Value));
1753 when Constraint_Error =>
1756 "value must be positive or equal to 0",
1757 Attribute.Value.Location, Project);
1760 elsif Attribute.Name = Name_Response_File_Format then
1765 Get_Name_String (Attribute.Value.Value);
1766 To_Lower (Name_Buffer (1 .. Name_Len));
1769 if Name = Name_None then
1770 Project.Config.Resp_File_Format := None;
1772 elsif Name = Name_Gnu then
1773 Project.Config.Resp_File_Format := GNU;
1775 elsif Name = Name_Object_List then
1776 Project.Config.Resp_File_Format := Object_List;
1778 elsif Name = Name_Option_List then
1779 Project.Config.Resp_File_Format := Option_List;
1784 "illegal response file format",
1785 Attribute.Value.Location, Project);
1789 elsif Attribute.Name = Name_Response_File_Switches then
1790 Put (Into_List => Project.Config.Resp_File_Options,
1791 From_List => Attribute.Value.Values,
1792 In_Tree => Data.Tree);
1796 Attribute_Id := Attribute.Next;
1800 -- Start of processing for Process_Packages
1803 Packages := Project.Decl.Packages;
1804 while Packages /= No_Package loop
1805 Element := Data.Tree.Packages.Table (Packages);
1807 case Element.Name is
1810 -- Process attributes of package Binder
1812 Process_Binder (Element.Decl.Arrays);
1814 when Name_Builder =>
1816 -- Process attributes of package Builder
1818 Process_Builder (Element.Decl.Attributes);
1820 when Name_Compiler =>
1822 -- Process attributes of package Compiler
1824 Process_Compiler (Element.Decl.Arrays);
1828 -- Process attributes of package Linker
1830 Process_Linker (Element.Decl.Attributes);
1834 -- Process attributes of package Naming
1836 Process_Naming (Element.Decl.Attributes);
1837 Process_Naming (Element.Decl.Arrays);
1843 Packages := Element.Next;
1845 end Process_Packages;
1847 ---------------------------------------------
1848 -- Process_Project_Level_Simple_Attributes --
1849 ---------------------------------------------
1851 procedure Process_Project_Level_Simple_Attributes is
1852 Attribute_Id : Variable_Id;
1853 Attribute : Variable;
1854 List : String_List_Id;
1857 -- Process non associated array attribute at project level
1859 Attribute_Id := Project.Decl.Attributes;
1860 while Attribute_Id /= No_Variable loop
1862 Data.Tree.Variable_Elements.Table (Attribute_Id);
1864 if not Attribute.Value.Default then
1865 if Attribute.Name = Name_Target then
1867 -- Attribute Target: the target specified
1869 Project.Config.Target := Attribute.Value.Value;
1871 elsif Attribute.Name = Name_Library_Builder then
1873 -- Attribute Library_Builder: the application to invoke
1874 -- to build libraries.
1876 Project.Config.Library_Builder :=
1877 Path_Name_Type (Attribute.Value.Value);
1879 elsif Attribute.Name = Name_Archive_Builder then
1881 -- Attribute Archive_Builder: the archive builder
1882 -- (usually "ar") and its minimum options (usually "cr").
1884 List := Attribute.Value.Values;
1886 if List = Nil_String then
1889 "archive builder cannot be null",
1890 Attribute.Value.Location, Project);
1893 Put (Into_List => Project.Config.Archive_Builder,
1895 In_Tree => Data.Tree);
1897 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1899 -- Attribute Archive_Builder: the archive builder
1900 -- (usually "ar") and its minimum options (usually "cr").
1902 List := Attribute.Value.Values;
1904 if List /= Nil_String then
1907 Project.Config.Archive_Builder_Append_Option,
1909 In_Tree => Data.Tree);
1912 elsif Attribute.Name = Name_Archive_Indexer then
1914 -- Attribute Archive_Indexer: the optional archive
1915 -- indexer (usually "ranlib") with its minimum options
1918 List := Attribute.Value.Values;
1920 if List = Nil_String then
1923 "archive indexer cannot be null",
1924 Attribute.Value.Location, Project);
1927 Put (Into_List => Project.Config.Archive_Indexer,
1929 In_Tree => Data.Tree);
1931 elsif Attribute.Name = Name_Library_Partial_Linker then
1933 -- Attribute Library_Partial_Linker: the optional linker
1934 -- driver with its minimum options, to partially link
1937 List := Attribute.Value.Values;
1939 if List = Nil_String then
1942 "partial linker cannot be null",
1943 Attribute.Value.Location, Project);
1946 Put (Into_List => Project.Config.Lib_Partial_Linker,
1948 In_Tree => Data.Tree);
1950 elsif Attribute.Name = Name_Library_GCC then
1951 Project.Config.Shared_Lib_Driver :=
1952 File_Name_Type (Attribute.Value.Value);
1955 "?Library_'G'C'C is an obsolescent attribute, " &
1956 "use Linker''Driver instead",
1957 Attribute.Value.Location, Project);
1959 elsif Attribute.Name = Name_Archive_Suffix then
1960 Project.Config.Archive_Suffix :=
1961 File_Name_Type (Attribute.Value.Value);
1963 elsif Attribute.Name = Name_Linker_Executable_Option then
1965 -- Attribute Linker_Executable_Option: optional options
1966 -- to specify an executable name. Defaults to "-o".
1968 List := Attribute.Value.Values;
1970 if List = Nil_String then
1973 "linker executable option cannot be null",
1974 Attribute.Value.Location, Project);
1977 Put (Into_List => Project.Config.Linker_Executable_Option,
1979 In_Tree => Data.Tree);
1981 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
1983 -- Attribute Linker_Lib_Dir_Option: optional options
1984 -- to specify a library search directory. Defaults to
1987 Get_Name_String (Attribute.Value.Value);
1989 if Name_Len = 0 then
1992 "linker library directory option cannot be empty",
1993 Attribute.Value.Location, Project);
1996 Project.Config.Linker_Lib_Dir_Option :=
1997 Attribute.Value.Value;
1999 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2001 -- Attribute Linker_Lib_Name_Option: optional options
2002 -- to specify the name of a library to be linked in.
2003 -- Defaults to "-l".
2005 Get_Name_String (Attribute.Value.Value);
2007 if Name_Len = 0 then
2010 "linker library name option cannot be empty",
2011 Attribute.Value.Location, Project);
2014 Project.Config.Linker_Lib_Name_Option :=
2015 Attribute.Value.Value;
2017 elsif Attribute.Name = Name_Run_Path_Option then
2019 -- Attribute Run_Path_Option: optional options to
2020 -- specify a path for libraries.
2022 List := Attribute.Value.Values;
2024 if List /= Nil_String then
2025 Put (Into_List => Project.Config.Run_Path_Option,
2027 In_Tree => Data.Tree);
2030 elsif Attribute.Name = Name_Separate_Run_Path_Options then
2032 pragma Unsuppress (All_Checks);
2034 Project.Config.Separate_Run_Path_Options :=
2035 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2037 when Constraint_Error =>
2040 "invalid value """ &
2041 Get_Name_String (Attribute.Value.Value) &
2042 """ for Separate_Run_Path_Options",
2043 Attribute.Value.Location, Project);
2046 elsif Attribute.Name = Name_Library_Support then
2048 pragma Unsuppress (All_Checks);
2050 Project.Config.Lib_Support :=
2051 Library_Support'Value (Get_Name_String
2052 (Attribute.Value.Value));
2054 when Constraint_Error =>
2057 "invalid value """ &
2058 Get_Name_String (Attribute.Value.Value) &
2059 """ for Library_Support",
2060 Attribute.Value.Location, Project);
2063 elsif Attribute.Name = Name_Shared_Library_Prefix then
2064 Project.Config.Shared_Lib_Prefix :=
2065 File_Name_Type (Attribute.Value.Value);
2067 elsif Attribute.Name = Name_Shared_Library_Suffix then
2068 Project.Config.Shared_Lib_Suffix :=
2069 File_Name_Type (Attribute.Value.Value);
2071 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2073 pragma Unsuppress (All_Checks);
2075 Project.Config.Symbolic_Link_Supported :=
2076 Boolean'Value (Get_Name_String
2077 (Attribute.Value.Value));
2079 when Constraint_Error =>
2083 & Get_Name_String (Attribute.Value.Value)
2084 & """ for Symbolic_Link_Supported",
2085 Attribute.Value.Location, Project);
2089 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2092 pragma Unsuppress (All_Checks);
2094 Project.Config.Lib_Maj_Min_Id_Supported :=
2095 Boolean'Value (Get_Name_String
2096 (Attribute.Value.Value));
2098 when Constraint_Error =>
2101 "invalid value """ &
2102 Get_Name_String (Attribute.Value.Value) &
2103 """ for Library_Major_Minor_Id_Supported",
2104 Attribute.Value.Location, Project);
2107 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2109 pragma Unsuppress (All_Checks);
2111 Project.Config.Auto_Init_Supported :=
2112 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2114 when Constraint_Error =>
2118 & Get_Name_String (Attribute.Value.Value)
2119 & """ for Library_Auto_Init_Supported",
2120 Attribute.Value.Location, Project);
2123 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2124 List := Attribute.Value.Values;
2126 if List /= Nil_String then
2127 Put (Into_List => Project.Config.Shared_Lib_Min_Options,
2129 In_Tree => Data.Tree);
2132 elsif Attribute.Name = Name_Library_Version_Switches then
2133 List := Attribute.Value.Values;
2135 if List /= Nil_String then
2136 Put (Into_List => Project.Config.Lib_Version_Options,
2138 In_Tree => Data.Tree);
2143 Attribute_Id := Attribute.Next;
2145 end Process_Project_Level_Simple_Attributes;
2147 --------------------------------------------
2148 -- Process_Project_Level_Array_Attributes --
2149 --------------------------------------------
2151 procedure Process_Project_Level_Array_Attributes is
2152 Current_Array_Id : Array_Id;
2153 Current_Array : Array_Data;
2154 Element_Id : Array_Element_Id;
2155 Element : Array_Element;
2156 List : String_List_Id;
2159 -- Process the associative array attributes at project level
2161 Current_Array_Id := Project.Decl.Arrays;
2162 while Current_Array_Id /= No_Array loop
2163 Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
2165 Element_Id := Current_Array.Value;
2166 while Element_Id /= No_Array_Element loop
2167 Element := Data.Tree.Array_Elements.Table (Element_Id);
2169 -- Get the name of the language
2172 Get_Language_From_Name
2173 (Project, Get_Name_String (Element.Index));
2175 if Lang_Index /= No_Language_Index then
2176 case Current_Array.Name is
2177 when Name_Inherit_Source_Path =>
2178 List := Element.Value.Values;
2180 if List /= Nil_String then
2183 Lang_Index.Config.Include_Compatible_Languages,
2185 In_Tree => Data.Tree,
2186 Lower_Case => True);
2189 when Name_Toolchain_Description =>
2191 -- Attribute Toolchain_Description (<language>)
2193 Lang_Index.Config.Toolchain_Description :=
2194 Element.Value.Value;
2196 when Name_Toolchain_Version =>
2198 -- Attribute Toolchain_Version (<language>)
2200 Lang_Index.Config.Toolchain_Version :=
2201 Element.Value.Value;
2203 when Name_Runtime_Library_Dir =>
2205 -- Attribute Runtime_Library_Dir (<language>)
2207 Lang_Index.Config.Runtime_Library_Dir :=
2208 Element.Value.Value;
2210 when Name_Runtime_Source_Dir =>
2212 -- Attribute Runtime_Library_Dir (<language>)
2214 Lang_Index.Config.Runtime_Source_Dir :=
2215 Element.Value.Value;
2217 when Name_Object_Generated =>
2219 pragma Unsuppress (All_Checks);
2225 (Get_Name_String (Element.Value.Value));
2227 Lang_Index.Config.Object_Generated := Value;
2229 -- If no object is generated, no object may be
2233 Lang_Index.Config.Objects_Linked := False;
2237 when Constraint_Error =>
2241 & Get_Name_String (Element.Value.Value)
2242 & """ for Object_Generated",
2243 Element.Value.Location, Project);
2246 when Name_Objects_Linked =>
2248 pragma Unsuppress (All_Checks);
2254 (Get_Name_String (Element.Value.Value));
2256 -- No change if Object_Generated is False, as this
2257 -- forces Objects_Linked to be False too.
2259 if Lang_Index.Config.Object_Generated then
2260 Lang_Index.Config.Objects_Linked := Value;
2264 when Constraint_Error =>
2268 & Get_Name_String (Element.Value.Value)
2269 & """ for Objects_Linked",
2270 Element.Value.Location, Project);
2277 Element_Id := Element.Next;
2280 Current_Array_Id := Current_Array.Next;
2282 end Process_Project_Level_Array_Attributes;
2284 -- Start of processing for Check_Configuration
2287 Process_Project_Level_Simple_Attributes;
2288 Process_Project_Level_Array_Attributes;
2291 -- For unit based languages, set Casing, Dot_Replacement and
2292 -- Separate_Suffix in Naming_Data.
2294 Lang_Index := Project.Languages;
2295 while Lang_Index /= No_Language_Index loop
2296 if Lang_Index.Name = Name_Ada then
2297 Lang_Index.Config.Naming_Data.Casing := Casing;
2298 Lang_Index.Config.Naming_Data.Dot_Replacement := Dot_Replacement;
2300 if Separate_Suffix /= No_File then
2301 Lang_Index.Config.Naming_Data.Separate_Suffix :=
2308 Lang_Index := Lang_Index.Next;
2311 -- Give empty names to various prefixes/suffixes, if they have not
2312 -- been specified in the configuration.
2314 if Project.Config.Archive_Suffix = No_File then
2315 Project.Config.Archive_Suffix := Empty_File;
2318 if Project.Config.Shared_Lib_Prefix = No_File then
2319 Project.Config.Shared_Lib_Prefix := Empty_File;
2322 if Project.Config.Shared_Lib_Suffix = No_File then
2323 Project.Config.Shared_Lib_Suffix := Empty_File;
2326 Lang_Index := Project.Languages;
2327 while Lang_Index /= No_Language_Index loop
2329 -- For all languages, Compiler_Driver needs to be specified. This is
2330 -- only needed if we do intend to compile (not in GPS for instance).
2332 if Data.Flags.Compiler_Driver_Mandatory
2333 and then Lang_Index.Config.Compiler_Driver = No_File
2335 Error_Msg_Name_1 := Lang_Index.Display_Name;
2338 "?no compiler specified for language %%" &
2339 ", ignoring all its sources",
2340 No_Location, Project);
2342 if Lang_Index = Project.Languages then
2343 Project.Languages := Lang_Index.Next;
2345 Prev_Index.Next := Lang_Index.Next;
2348 elsif Lang_Index.Name = Name_Ada then
2349 Prev_Index := Lang_Index;
2351 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2352 -- Body_Suffix need to be specified.
2354 if Lang_Index.Config.Naming_Data.Dot_Replacement = No_File then
2357 "Dot_Replacement not specified for Ada",
2358 No_Location, Project);
2361 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File then
2364 "Spec_Suffix not specified for Ada",
2365 No_Location, Project);
2368 if Lang_Index.Config.Naming_Data.Body_Suffix = No_File then
2371 "Body_Suffix not specified for Ada",
2372 No_Location, Project);
2376 Prev_Index := Lang_Index;
2378 -- For file based languages, either Spec_Suffix or Body_Suffix
2379 -- need to be specified.
2381 if Data.Flags.Require_Sources_Other_Lang
2382 and then Lang_Index.Config.Naming_Data.Spec_Suffix = No_File
2383 and then Lang_Index.Config.Naming_Data.Body_Suffix = No_File
2385 Error_Msg_Name_1 := Lang_Index.Display_Name;
2388 "no suffixes specified for %%",
2389 No_Location, Project);
2393 Lang_Index := Lang_Index.Next;
2395 end Check_Configuration;
2397 -------------------------------
2398 -- Check_If_Externally_Built --
2399 -------------------------------
2401 procedure Check_If_Externally_Built
2402 (Project : Project_Id;
2403 Data : in out Tree_Processing_Data)
2405 Externally_Built : constant Variable_Value :=
2407 (Name_Externally_Built,
2408 Project.Decl.Attributes, Data.Tree);
2411 if not Externally_Built.Default then
2412 Get_Name_String (Externally_Built.Value);
2413 To_Lower (Name_Buffer (1 .. Name_Len));
2415 if Name_Buffer (1 .. Name_Len) = "true" then
2416 Project.Externally_Built := True;
2418 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2419 Error_Msg (Data.Flags,
2420 "Externally_Built may only be true or false",
2421 Externally_Built.Location, Project);
2425 -- A virtual project extending an externally built project is itself
2426 -- externally built.
2428 if Project.Virtual and then Project.Extends /= No_Project then
2429 Project.Externally_Built := Project.Extends.Externally_Built;
2432 if Current_Verbosity = High then
2433 Write_Str ("Project is ");
2435 if not Project.Externally_Built then
2439 Write_Line ("externally built.");
2441 end Check_If_Externally_Built;
2443 ----------------------
2444 -- Check_Interfaces --
2445 ----------------------
2447 procedure Check_Interfaces
2448 (Project : Project_Id;
2449 Data : in out Tree_Processing_Data)
2451 Interfaces : constant Prj.Variable_Value :=
2453 (Snames.Name_Interfaces,
2454 Project.Decl.Attributes,
2457 List : String_List_Id;
2458 Element : String_Element;
2459 Name : File_Name_Type;
2460 Iter : Source_Iterator;
2462 Project_2 : Project_Id;
2466 if not Interfaces.Default then
2468 -- Set In_Interfaces to False for all sources. It will be set to True
2469 -- later for the sources in the Interfaces list.
2471 Project_2 := Project;
2472 while Project_2 /= No_Project loop
2473 Iter := For_Each_Source (Data.Tree, Project_2);
2475 Source := Prj.Element (Iter);
2476 exit when Source = No_Source;
2477 Source.In_Interfaces := False;
2481 Project_2 := Project_2.Extends;
2484 List := Interfaces.Values;
2485 while List /= Nil_String loop
2486 Element := Data.Tree.String_Elements.Table (List);
2487 Name := Canonical_Case_File_Name (Element.Value);
2489 Project_2 := Project;
2491 while Project_2 /= No_Project loop
2492 Iter := For_Each_Source (Data.Tree, Project_2);
2495 Source := Prj.Element (Iter);
2496 exit when Source = No_Source;
2498 if Source.File = Name then
2499 if not Source.Locally_Removed then
2500 Source.In_Interfaces := True;
2501 Source.Declared_In_Interfaces := True;
2503 Other := Other_Part (Source);
2505 if Other /= No_Source then
2506 Other.In_Interfaces := True;
2507 Other.Declared_In_Interfaces := True;
2510 if Current_Verbosity = High then
2511 Write_Str (" interface: ");
2512 Write_Line (Get_Name_String (Source.Path.Name));
2522 Project_2 := Project_2.Extends;
2525 if Source = No_Source then
2526 Error_Msg_File_1 := File_Name_Type (Element.Value);
2527 Error_Msg_Name_1 := Project.Name;
2531 "{ cannot be an interface of project %% "
2532 & "as it is not one of its sources",
2533 Element.Location, Project);
2536 List := Element.Next;
2539 Project.Interfaces_Defined := True;
2541 elsif Project.Extends /= No_Project then
2542 Project.Interfaces_Defined := Project.Extends.Interfaces_Defined;
2544 if Project.Interfaces_Defined then
2545 Iter := For_Each_Source (Data.Tree, Project);
2547 Source := Prj.Element (Iter);
2548 exit when Source = No_Source;
2550 if not Source.Declared_In_Interfaces then
2551 Source.In_Interfaces := False;
2558 end Check_Interfaces;
2560 --------------------------
2561 -- Check_Package_Naming --
2562 --------------------------
2564 procedure Check_Package_Naming
2565 (Project : Project_Id;
2566 Data : in out Tree_Processing_Data;
2567 Bodies : out Array_Element_Id;
2568 Specs : out Array_Element_Id)
2570 Naming_Id : constant Package_Id :=
2572 (Name_Naming, Project.Decl.Packages, Data.Tree);
2573 Naming : Package_Element;
2575 Ada_Body_Suffix_Loc : Source_Ptr := No_Location;
2577 procedure Check_Naming;
2578 -- Check the validity of the Naming package (suffixes valid, ...)
2580 procedure Check_Common
2581 (Dot_Replacement : in out File_Name_Type;
2582 Casing : in out Casing_Type;
2583 Casing_Defined : out Boolean;
2584 Separate_Suffix : in out File_Name_Type;
2585 Sep_Suffix_Loc : out Source_Ptr);
2586 -- Check attributes common
2588 procedure Process_Exceptions_File_Based
2589 (Lang_Id : Language_Ptr;
2590 Kind : Source_Kind);
2591 procedure Process_Exceptions_Unit_Based
2592 (Lang_Id : Language_Ptr;
2593 Kind : Source_Kind);
2594 -- Process the naming exceptions for the two types of languages
2596 procedure Initialize_Naming_Data;
2597 -- Initialize internal naming data for the various languages
2603 procedure Check_Common
2604 (Dot_Replacement : in out File_Name_Type;
2605 Casing : in out Casing_Type;
2606 Casing_Defined : out Boolean;
2607 Separate_Suffix : in out File_Name_Type;
2608 Sep_Suffix_Loc : out Source_Ptr)
2610 Dot_Repl : constant Variable_Value :=
2612 (Name_Dot_Replacement,
2613 Naming.Decl.Attributes,
2615 Casing_String : constant Variable_Value :=
2618 Naming.Decl.Attributes,
2620 Sep_Suffix : constant Variable_Value :=
2622 (Name_Separate_Suffix,
2623 Naming.Decl.Attributes,
2625 Dot_Repl_Loc : Source_Ptr;
2628 Sep_Suffix_Loc := No_Location;
2630 if not Dot_Repl.Default then
2632 (Dot_Repl.Kind = Single, "Dot_Replacement is not a string");
2634 if Length_Of_Name (Dot_Repl.Value) = 0 then
2636 (Data.Flags, "Dot_Replacement cannot be empty",
2637 Dot_Repl.Location, Project);
2640 Dot_Replacement := Canonical_Case_File_Name (Dot_Repl.Value);
2641 Dot_Repl_Loc := Dot_Repl.Location;
2644 Repl : constant String := Get_Name_String (Dot_Replacement);
2647 -- Dot_Replacement cannot
2649 -- - start or end with an alphanumeric
2650 -- - be a single '_'
2651 -- - start with an '_' followed by an alphanumeric
2652 -- - contain a '.' except if it is "."
2655 or else Is_Alphanumeric (Repl (Repl'First))
2656 or else Is_Alphanumeric (Repl (Repl'Last))
2657 or else (Repl (Repl'First) = '_'
2661 Is_Alphanumeric (Repl (Repl'First + 1))))
2662 or else (Repl'Length > 1
2664 Index (Source => Repl, Pattern => ".") /= 0)
2669 """ is illegal for Dot_Replacement.",
2670 Dot_Repl_Loc, Project);
2675 if Dot_Replacement /= No_File then
2677 ("Dot_Replacement", Get_Name_String (Dot_Replacement));
2680 Casing_Defined := False;
2682 if not Casing_String.Default then
2684 (Casing_String.Kind = Single, "Casing is not a string");
2687 Casing_Image : constant String :=
2688 Get_Name_String (Casing_String.Value);
2691 if Casing_Image'Length = 0 then
2694 "Casing cannot be an empty string",
2695 Casing_String.Location, Project);
2698 Casing := Value (Casing_Image);
2699 Casing_Defined := True;
2702 when Constraint_Error =>
2703 Name_Len := Casing_Image'Length;
2704 Name_Buffer (1 .. Name_Len) := Casing_Image;
2705 Err_Vars.Error_Msg_Name_1 := Name_Find;
2708 "%% is not a correct Casing",
2709 Casing_String.Location, Project);
2713 Write_Attr ("Casing", Image (Casing));
2715 if not Sep_Suffix.Default then
2716 if Length_Of_Name (Sep_Suffix.Value) = 0 then
2719 "Separate_Suffix cannot be empty",
2720 Sep_Suffix.Location, Project);
2723 Separate_Suffix := Canonical_Case_File_Name (Sep_Suffix.Value);
2724 Sep_Suffix_Loc := Sep_Suffix.Location;
2726 Check_Illegal_Suffix
2727 (Project, Separate_Suffix,
2728 Dot_Replacement, "Separate_Suffix", Sep_Suffix.Location,
2733 if Separate_Suffix /= No_File then
2735 ("Separate_Suffix", Get_Name_String (Separate_Suffix));
2739 -----------------------------------
2740 -- Process_Exceptions_File_Based --
2741 -----------------------------------
2743 procedure Process_Exceptions_File_Based
2744 (Lang_Id : Language_Ptr;
2747 Lang : constant Name_Id := Lang_Id.Name;
2748 Exceptions : Array_Element_Id;
2749 Exception_List : Variable_Value;
2750 Element_Id : String_List_Id;
2751 Element : String_Element;
2752 File_Name : File_Name_Type;
2754 Iter : Source_Iterator;
2761 (Name_Implementation_Exceptions,
2762 In_Arrays => Naming.Decl.Arrays,
2763 In_Tree => Data.Tree);
2768 (Name_Specification_Exceptions,
2769 In_Arrays => Naming.Decl.Arrays,
2770 In_Tree => Data.Tree);
2773 Exception_List := Value_Of
2775 In_Array => Exceptions,
2776 In_Tree => Data.Tree);
2778 if Exception_List /= Nil_Variable_Value then
2779 Element_Id := Exception_List.Values;
2780 while Element_Id /= Nil_String loop
2781 Element := Data.Tree.String_Elements.Table (Element_Id);
2782 File_Name := Canonical_Case_File_Name (Element.Value);
2784 Iter := For_Each_Source (Data.Tree, Project);
2786 Source := Prj.Element (Iter);
2787 exit when Source = No_Source or else Source.File = File_Name;
2791 if Source = No_Source then
2798 File_Name => File_Name,
2799 Display_File => File_Name_Type (Element.Value),
2800 Naming_Exception => True);
2803 -- Check if the file name is already recorded for another
2804 -- language or another kind.
2806 if Source.Language /= Lang_Id then
2809 "the same file cannot be a source of two languages",
2810 Element.Location, Project);
2812 elsif Source.Kind /= Kind then
2815 "the same file cannot be a source and a template",
2816 Element.Location, Project);
2819 -- If the file is already recorded for the same
2820 -- language and the same kind, it means that the file
2821 -- name appears several times in the *_Exceptions
2822 -- attribute; so there is nothing to do.
2825 Element_Id := Element.Next;
2828 end Process_Exceptions_File_Based;
2830 -----------------------------------
2831 -- Process_Exceptions_Unit_Based --
2832 -----------------------------------
2834 procedure Process_Exceptions_Unit_Based
2835 (Lang_Id : Language_Ptr;
2838 Lang : constant Name_Id := Lang_Id.Name;
2839 Exceptions : Array_Element_Id;
2840 Element : Array_Element;
2843 File_Name : File_Name_Type;
2852 In_Arrays => Naming.Decl.Arrays,
2853 In_Tree => Data.Tree);
2855 if Exceptions = No_Array_Element then
2858 (Name_Implementation,
2859 In_Arrays => Naming.Decl.Arrays,
2860 In_Tree => Data.Tree);
2867 In_Arrays => Naming.Decl.Arrays,
2868 In_Tree => Data.Tree);
2870 if Exceptions = No_Array_Element then
2874 In_Arrays => Naming.Decl.Arrays,
2875 In_Tree => Data.Tree);
2879 while Exceptions /= No_Array_Element loop
2880 Element := Data.Tree.Array_Elements.Table (Exceptions);
2881 File_Name := Canonical_Case_File_Name (Element.Value.Value);
2883 Get_Name_String (Element.Index);
2884 To_Lower (Name_Buffer (1 .. Name_Len));
2886 Index := Element.Value.Index;
2888 -- For Ada, check if it is a valid unit name
2890 if Lang = Name_Ada then
2891 Get_Name_String (Element.Index);
2892 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
2894 if Unit = No_Name then
2895 Err_Vars.Error_Msg_Name_1 := Element.Index;
2898 "%% is not a valid unit name.",
2899 Element.Value.Location, Project);
2903 if Unit /= No_Name then
2910 File_Name => File_Name,
2911 Display_File => File_Name_Type (Element.Value.Value),
2914 Location => Element.Value.Location,
2915 Naming_Exception => True);
2918 Exceptions := Element.Next;
2920 end Process_Exceptions_Unit_Based;
2926 procedure Check_Naming is
2927 Dot_Replacement : File_Name_Type :=
2929 (First_Name_Id + Character'Pos ('-'));
2930 Separate_Suffix : File_Name_Type := No_File;
2931 Casing : Casing_Type := All_Lower_Case;
2932 Casing_Defined : Boolean;
2933 Lang_Id : Language_Ptr;
2934 Sep_Suffix_Loc : Source_Ptr;
2935 Suffix : Variable_Value;
2940 (Dot_Replacement => Dot_Replacement,
2942 Casing_Defined => Casing_Defined,
2943 Separate_Suffix => Separate_Suffix,
2944 Sep_Suffix_Loc => Sep_Suffix_Loc);
2946 -- For all unit based languages, if any, set the specified value
2947 -- of Dot_Replacement, Casing and/or Separate_Suffix. Do not
2948 -- systematically overwrite, since the defaults come from the
2949 -- configuration file.
2951 if Dot_Replacement /= No_File
2952 or else Casing_Defined
2953 or else Separate_Suffix /= No_File
2955 Lang_Id := Project.Languages;
2956 while Lang_Id /= No_Language_Index loop
2957 if Lang_Id.Config.Kind = Unit_Based then
2958 if Dot_Replacement /= No_File then
2959 Lang_Id.Config.Naming_Data.Dot_Replacement :=
2963 if Casing_Defined then
2964 Lang_Id.Config.Naming_Data.Casing := Casing;
2968 Lang_Id := Lang_Id.Next;
2972 -- Next, get the spec and body suffixes
2974 Lang_Id := Project.Languages;
2975 while Lang_Id /= No_Language_Index loop
2976 Lang := Lang_Id.Name;
2982 Attribute_Or_Array_Name => Name_Spec_Suffix,
2983 In_Package => Naming_Id,
2984 In_Tree => Data.Tree);
2986 if Suffix = Nil_Variable_Value then
2989 Attribute_Or_Array_Name => Name_Specification_Suffix,
2990 In_Package => Naming_Id,
2991 In_Tree => Data.Tree);
2994 if Suffix /= Nil_Variable_Value then
2995 Lang_Id.Config.Naming_Data.Spec_Suffix :=
2996 File_Name_Type (Suffix.Value);
2998 Check_Illegal_Suffix
3000 Lang_Id.Config.Naming_Data.Spec_Suffix,
3001 Lang_Id.Config.Naming_Data.Dot_Replacement,
3002 "Spec_Suffix", Suffix.Location, Data);
3006 Get_Name_String (Lang_Id.Config.Naming_Data.Spec_Suffix));
3014 Attribute_Or_Array_Name => Name_Body_Suffix,
3015 In_Package => Naming_Id,
3016 In_Tree => Data.Tree);
3018 if Suffix = Nil_Variable_Value then
3022 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3023 In_Package => Naming_Id,
3024 In_Tree => Data.Tree);
3027 if Suffix /= Nil_Variable_Value then
3028 Lang_Id.Config.Naming_Data.Body_Suffix :=
3029 File_Name_Type (Suffix.Value);
3031 -- The default value of separate suffix should be the same as
3032 -- the body suffix, so we need to compute that first.
3034 if Separate_Suffix = No_File then
3035 Lang_Id.Config.Naming_Data.Separate_Suffix :=
3036 Lang_Id.Config.Naming_Data.Body_Suffix;
3040 (Lang_Id.Config.Naming_Data.Separate_Suffix));
3042 Lang_Id.Config.Naming_Data.Separate_Suffix :=
3046 Check_Illegal_Suffix
3048 Lang_Id.Config.Naming_Data.Body_Suffix,
3049 Lang_Id.Config.Naming_Data.Dot_Replacement,
3050 "Body_Suffix", Suffix.Location, Data);
3054 Get_Name_String (Lang_Id.Config.Naming_Data.Body_Suffix));
3056 elsif Separate_Suffix /= No_File then
3057 Lang_Id.Config.Naming_Data.Separate_Suffix := Separate_Suffix;
3060 -- Spec_Suffix cannot be equal to Body_Suffix or Separate_Suffix,
3061 -- since that would cause a clear ambiguity. Note that we do allow
3062 -- a Spec_Suffix to have the same termination as one of these,
3063 -- which causes a potential ambiguity, but we resolve that my
3064 -- matching the longest possible suffix.
3066 if Lang_Id.Config.Naming_Data.Spec_Suffix /= No_File
3067 and then Lang_Id.Config.Naming_Data.Spec_Suffix =
3068 Lang_Id.Config.Naming_Data.Body_Suffix
3073 & Get_Name_String (Lang_Id.Config.Naming_Data.Body_Suffix)
3074 & """) cannot be the same as Spec_Suffix.",
3075 Ada_Body_Suffix_Loc, Project);
3078 if Lang_Id.Config.Naming_Data.Body_Suffix /=
3079 Lang_Id.Config.Naming_Data.Separate_Suffix
3080 and then Lang_Id.Config.Naming_Data.Spec_Suffix =
3081 Lang_Id.Config.Naming_Data.Separate_Suffix
3085 "Separate_Suffix ("""
3087 (Lang_Id.Config.Naming_Data.Separate_Suffix)
3088 & """) cannot be the same as Spec_Suffix.",
3089 Sep_Suffix_Loc, Project);
3092 Lang_Id := Lang_Id.Next;
3095 -- Get the naming exceptions for all languages
3097 for Kind in Spec .. Impl loop
3098 Lang_Id := Project.Languages;
3099 while Lang_Id /= No_Language_Index loop
3100 case Lang_Id.Config.Kind is
3102 Process_Exceptions_File_Based (Lang_Id, Kind);
3105 Process_Exceptions_Unit_Based (Lang_Id, Kind);
3108 Lang_Id := Lang_Id.Next;
3113 ----------------------------
3114 -- Initialize_Naming_Data --
3115 ----------------------------
3117 procedure Initialize_Naming_Data is
3118 Specs : Array_Element_Id :=
3124 Impls : Array_Element_Id :=
3130 Lang : Language_Ptr;
3131 Lang_Name : Name_Id;
3132 Value : Variable_Value;
3133 Extended : Project_Id;
3136 -- At this stage, the project already contains the default extensions
3137 -- for the various languages. We now merge those suffixes read in the
3138 -- user project, and they override the default.
3140 while Specs /= No_Array_Element loop
3141 Lang_Name := Data.Tree.Array_Elements.Table (Specs).Index;
3143 Get_Language_From_Name
3144 (Project, Name => Get_Name_String (Lang_Name));
3146 -- An extending project inherits its parent projects' languages
3147 -- so if needed we should create entries for those languages
3150 Extended := Project.Extends;
3151 while Extended /= null loop
3152 Lang := Get_Language_From_Name
3153 (Extended, Name => Get_Name_String (Lang_Name));
3154 exit when Lang /= null;
3156 Extended := Extended.Extends;
3159 if Lang /= null then
3160 Lang := new Language_Data'(Lang.all);
3161 Lang.First_Source := null;
3162 Lang.Next := Project.Languages;
3163 Project.Languages := Lang;
3167 -- If language was not found in project or the projects it extends
3170 if Current_Verbosity = High then
3172 ("Ignoring spec naming data for "
3173 & Get_Name_String (Lang_Name)
3174 & " since language is not defined for this project");
3178 Value := Data.Tree.Array_Elements.Table (Specs).Value;
3180 if Value.Kind = Single then
3181 Lang.Config.Naming_Data.Spec_Suffix :=
3182 Canonical_Case_File_Name (Value.Value);
3186 Specs := Data.Tree.Array_Elements.Table (Specs).Next;
3189 while Impls /= No_Array_Element loop
3190 Lang_Name := Data.Tree.Array_Elements.Table (Impls).Index;
3192 Get_Language_From_Name
3193 (Project, Name => Get_Name_String (Lang_Name));
3196 if Current_Verbosity = High then
3198 ("Ignoring impl naming data for "
3199 & Get_Name_String (Lang_Name)
3200 & " since language is not defined for this project");
3203 Value := Data.Tree.Array_Elements.Table (Impls).Value;
3205 if Lang.Name = Name_Ada then
3206 Ada_Body_Suffix_Loc := Value.Location;
3209 if Value.Kind = Single then
3210 Lang.Config.Naming_Data.Body_Suffix :=
3211 Canonical_Case_File_Name (Value.Value);
3215 Impls := Data.Tree.Array_Elements.Table (Impls).Next;
3217 end Initialize_Naming_Data;
3219 -- Start of processing for Check_Naming_Schemes
3222 Specs := No_Array_Element;
3223 Bodies := No_Array_Element;
3225 -- No Naming package or parsing a configuration file? nothing to do
3227 if Naming_Id /= No_Package
3228 and then Project.Qualifier /= Configuration
3230 Naming := Data.Tree.Packages.Table (Naming_Id);
3232 if Current_Verbosity = High then
3233 Write_Line ("Checking package Naming for project "
3234 & Get_Name_String (Project.Name));
3237 Initialize_Naming_Data;
3240 end Check_Package_Naming;
3242 ------------------------------
3243 -- Check_Library_Attributes --
3244 ------------------------------
3246 procedure Check_Library_Attributes
3247 (Project : Project_Id;
3248 Data : in out Tree_Processing_Data)
3250 Attributes : constant Prj.Variable_Id := Project.Decl.Attributes;
3252 Lib_Dir : constant Prj.Variable_Value :=
3254 (Snames.Name_Library_Dir, Attributes, Data.Tree);
3256 Lib_Name : constant Prj.Variable_Value :=
3258 (Snames.Name_Library_Name, Attributes, Data.Tree);
3260 Lib_Version : constant Prj.Variable_Value :=
3262 (Snames.Name_Library_Version, Attributes, Data.Tree);
3264 Lib_ALI_Dir : constant Prj.Variable_Value :=
3266 (Snames.Name_Library_Ali_Dir, Attributes, Data.Tree);
3268 Lib_GCC : constant Prj.Variable_Value :=
3270 (Snames.Name_Library_GCC, Attributes, Data.Tree);
3272 The_Lib_Kind : constant Prj.Variable_Value :=
3274 (Snames.Name_Library_Kind, Attributes, Data.Tree);
3276 Imported_Project_List : Project_List;
3278 Continuation : String_Access := No_Continuation_String'Access;
3280 Support_For_Libraries : Library_Support;
3282 Library_Directory_Present : Boolean;
3284 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3285 -- Check if an imported or extended project if also a library project
3291 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3293 Iter : Source_Iterator;
3296 if Proj /= No_Project then
3297 if not Proj.Library then
3299 -- The only not library projects that are OK are those that
3300 -- have no sources. However, header files from non-Ada
3301 -- languages are OK, as there is nothing to compile.
3303 Iter := For_Each_Source (Data.Tree, Proj);
3305 Src_Id := Prj.Element (Iter);
3306 exit when Src_Id = No_Source
3307 or else Src_Id.Language.Config.Kind /= File_Based
3308 or else Src_Id.Kind /= Spec;
3312 if Src_Id /= No_Source then
3313 Error_Msg_Name_1 := Project.Name;
3314 Error_Msg_Name_2 := Proj.Name;
3317 if Project.Library_Kind /= Static then
3321 "shared library project %% cannot extend " &
3322 "project %% that is not a library project",
3323 Project.Location, Project);
3324 Continuation := Continuation_String'Access;
3327 elsif (not Unchecked_Shared_Lib_Imports)
3328 and then Project.Library_Kind /= Static
3333 "shared library project %% cannot import project %% " &
3334 "that is not a shared library project",
3335 Project.Location, Project);
3336 Continuation := Continuation_String'Access;
3340 elsif Project.Library_Kind /= Static and then
3341 Proj.Library_Kind = Static
3343 Error_Msg_Name_1 := Project.Name;
3344 Error_Msg_Name_2 := Proj.Name;
3350 "shared library project %% cannot extend static " &
3351 "library project %%",
3352 Project.Location, Project);
3353 Continuation := Continuation_String'Access;
3355 elsif not Unchecked_Shared_Lib_Imports then
3359 "shared library project %% cannot import static " &
3360 "library project %%",
3361 Project.Location, Project);
3362 Continuation := Continuation_String'Access;
3369 Dir_Exists : Boolean;
3371 -- Start of processing for Check_Library_Attributes
3374 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3376 -- Special case of extending project
3378 if Project.Extends /= No_Project then
3380 -- If the project extended is a library project, we inherit the
3381 -- library name, if it is not redefined; we check that the library
3382 -- directory is specified.
3384 if Project.Extends.Library then
3385 if Project.Qualifier = Standard then
3388 "a standard project cannot extend a library project",
3389 Project.Location, Project);
3392 if Lib_Name.Default then
3393 Project.Library_Name := Project.Extends.Library_Name;
3396 if Lib_Dir.Default then
3397 if not Project.Virtual then
3400 "a project extending a library project must " &
3401 "specify an attribute Library_Dir",
3402 Project.Location, Project);
3405 -- For a virtual project extending a library project,
3406 -- inherit library directory.
3408 Project.Library_Dir := Project.Extends.Library_Dir;
3409 Library_Directory_Present := True;
3416 pragma Assert (Lib_Name.Kind = Single);
3418 if Lib_Name.Value = Empty_String then
3419 if Current_Verbosity = High
3420 and then Project.Library_Name = No_Name
3422 Write_Line ("No library name");
3426 -- There is no restriction on the syntax of library names
3428 Project.Library_Name := Lib_Name.Value;
3431 if Project.Library_Name /= No_Name then
3432 if Current_Verbosity = High then
3434 ("Library name", Get_Name_String (Project.Library_Name));
3437 pragma Assert (Lib_Dir.Kind = Single);
3439 if not Library_Directory_Present then
3440 if Current_Verbosity = High then
3441 Write_Line ("No library directory");
3445 -- Find path name (unless inherited), check that it is a directory
3447 if Project.Library_Dir = No_Path_Information then
3450 File_Name_Type (Lib_Dir.Value),
3451 Path => Project.Library_Dir,
3452 Dir_Exists => Dir_Exists,
3454 Create => "library",
3455 Must_Exist => False,
3456 Location => Lib_Dir.Location,
3457 Externally_Built => Project.Externally_Built);
3463 (Project.Library_Dir.Display_Name));
3466 if not Dir_Exists then
3468 -- Get the absolute name of the library directory that
3469 -- does not exist, to report an error.
3471 Err_Vars.Error_Msg_File_1 :=
3472 File_Name_Type (Project.Library_Dir.Display_Name);
3475 "library directory { does not exist",
3476 Lib_Dir.Location, Project);
3478 -- The library directory cannot be the same as the Object
3481 elsif Project.Library_Dir.Name = Project.Object_Directory.Name then
3484 "library directory cannot be the same " &
3485 "as object directory",
3486 Lib_Dir.Location, Project);
3487 Project.Library_Dir := No_Path_Information;
3491 OK : Boolean := True;
3492 Dirs_Id : String_List_Id;
3493 Dir_Elem : String_Element;
3497 -- The library directory cannot be the same as a source
3498 -- directory of the current project.
3500 Dirs_Id := Project.Source_Dirs;
3501 while Dirs_Id /= Nil_String loop
3502 Dir_Elem := Data.Tree.String_Elements.Table (Dirs_Id);
3503 Dirs_Id := Dir_Elem.Next;
3505 if Project.Library_Dir.Name =
3506 Path_Name_Type (Dir_Elem.Value)
3508 Err_Vars.Error_Msg_File_1 :=
3509 File_Name_Type (Dir_Elem.Value);
3512 "library directory cannot be the same " &
3513 "as source directory {",
3514 Lib_Dir.Location, Project);
3522 -- The library directory cannot be the same as a source
3523 -- directory of another project either.
3525 Pid := Data.Tree.Projects;
3527 exit Project_Loop when Pid = null;
3529 if Pid.Project /= Project then
3530 Dirs_Id := Pid.Project.Source_Dirs;
3532 Dir_Loop : while Dirs_Id /= Nil_String loop
3534 Data.Tree.String_Elements.Table (Dirs_Id);
3535 Dirs_Id := Dir_Elem.Next;
3537 if Project.Library_Dir.Name =
3538 Path_Name_Type (Dir_Elem.Value)
3540 Err_Vars.Error_Msg_File_1 :=
3541 File_Name_Type (Dir_Elem.Value);
3542 Err_Vars.Error_Msg_Name_1 := Pid.Project.Name;
3546 "library directory cannot be the same " &
3547 "as source directory { of project %%",
3548 Lib_Dir.Location, Project);
3556 end loop Project_Loop;
3560 Project.Library_Dir := No_Path_Information;
3562 elsif Current_Verbosity = High then
3564 -- Display the Library directory in high verbosity
3567 ("Library directory",
3568 Get_Name_String (Project.Library_Dir.Display_Name));
3577 Project.Library_Dir /= No_Path_Information
3578 and then Project.Library_Name /= No_Name;
3580 if Project.Extends = No_Project then
3581 case Project.Qualifier is
3583 if Project.Library then
3586 "a standard project cannot be a library project",
3587 Lib_Name.Location, Project);
3591 if not Project.Library then
3592 if Project.Library_Dir = No_Path_Information then
3595 "\attribute Library_Dir not declared",
3596 Project.Location, Project);
3599 if Project.Library_Name = No_Name then
3602 "\attribute Library_Name not declared",
3603 Project.Location, Project);
3613 if Project.Library then
3614 Support_For_Libraries := Project.Config.Lib_Support;
3616 if Support_For_Libraries = Prj.None then
3619 "?libraries are not supported on this platform",
3620 Lib_Name.Location, Project);
3621 Project.Library := False;
3624 if Lib_ALI_Dir.Value = Empty_String then
3625 if Current_Verbosity = High then
3626 Write_Line ("No library ALI directory specified");
3629 Project.Library_ALI_Dir := Project.Library_Dir;
3632 -- Find path name, check that it is a directory
3636 File_Name_Type (Lib_ALI_Dir.Value),
3637 Path => Project.Library_ALI_Dir,
3638 Create => "library ALI",
3639 Dir_Exists => Dir_Exists,
3641 Must_Exist => False,
3642 Location => Lib_ALI_Dir.Location,
3643 Externally_Built => Project.Externally_Built);
3645 if not Dir_Exists then
3647 -- Get the absolute name of the library ALI directory that
3648 -- does not exist, to report an error.
3650 Err_Vars.Error_Msg_File_1 :=
3651 File_Name_Type (Project.Library_ALI_Dir.Display_Name);
3654 "library 'A'L'I directory { does not exist",
3655 Lib_ALI_Dir.Location, Project);
3658 if Project.Library_ALI_Dir /= Project.Library_Dir then
3660 -- The library ALI directory cannot be the same as the
3661 -- Object directory.
3663 if Project.Library_ALI_Dir = Project.Object_Directory then
3666 "library 'A'L'I directory cannot be the same " &
3667 "as object directory",
3668 Lib_ALI_Dir.Location, Project);
3669 Project.Library_ALI_Dir := No_Path_Information;
3673 OK : Boolean := True;
3674 Dirs_Id : String_List_Id;
3675 Dir_Elem : String_Element;
3679 -- The library ALI directory cannot be the same as
3680 -- a source directory of the current project.
3682 Dirs_Id := Project.Source_Dirs;
3683 while Dirs_Id /= Nil_String loop
3685 Data.Tree.String_Elements.Table (Dirs_Id);
3686 Dirs_Id := Dir_Elem.Next;
3688 if Project.Library_ALI_Dir.Name =
3689 Path_Name_Type (Dir_Elem.Value)
3691 Err_Vars.Error_Msg_File_1 :=
3692 File_Name_Type (Dir_Elem.Value);
3695 "library 'A'L'I directory cannot be " &
3696 "the same as source directory {",
3697 Lib_ALI_Dir.Location, Project);
3705 -- The library ALI directory cannot be the same as
3706 -- a source directory of another project either.
3708 Pid := Data.Tree.Projects;
3709 ALI_Project_Loop : loop
3710 exit ALI_Project_Loop when Pid = null;
3712 if Pid.Project /= Project then
3713 Dirs_Id := Pid.Project.Source_Dirs;
3716 while Dirs_Id /= Nil_String loop
3718 Data.Tree.String_Elements.Table
3720 Dirs_Id := Dir_Elem.Next;
3722 if Project.Library_ALI_Dir.Name =
3723 Path_Name_Type (Dir_Elem.Value)
3725 Err_Vars.Error_Msg_File_1 :=
3726 File_Name_Type (Dir_Elem.Value);
3727 Err_Vars.Error_Msg_Name_1 :=
3732 "library 'A'L'I directory cannot " &
3733 "be the same as source directory " &
3735 Lib_ALI_Dir.Location, Project);
3737 exit ALI_Project_Loop;
3739 end loop ALI_Dir_Loop;
3742 end loop ALI_Project_Loop;
3746 Project.Library_ALI_Dir := No_Path_Information;
3748 elsif Current_Verbosity = High then
3750 -- Display Library ALI directory in high verbosity
3755 (Project.Library_ALI_Dir.Display_Name));
3762 pragma Assert (Lib_Version.Kind = Single);
3764 if Lib_Version.Value = Empty_String then
3765 if Current_Verbosity = High then
3766 Write_Line ("No library version specified");
3770 Project.Lib_Internal_Name := Lib_Version.Value;
3773 pragma Assert (The_Lib_Kind.Kind = Single);
3775 if The_Lib_Kind.Value = Empty_String then
3776 if Current_Verbosity = High then
3777 Write_Line ("No library kind specified");
3781 Get_Name_String (The_Lib_Kind.Value);
3784 Kind_Name : constant String :=
3785 To_Lower (Name_Buffer (1 .. Name_Len));
3787 OK : Boolean := True;
3790 if Kind_Name = "static" then
3791 Project.Library_Kind := Static;
3793 elsif Kind_Name = "dynamic" then
3794 Project.Library_Kind := Dynamic;
3796 elsif Kind_Name = "relocatable" then
3797 Project.Library_Kind := Relocatable;
3802 "illegal value for Library_Kind",
3803 The_Lib_Kind.Location, Project);
3807 if Current_Verbosity = High and then OK then
3808 Write_Attr ("Library kind", Kind_Name);
3811 if Project.Library_Kind /= Static then
3812 if Support_For_Libraries = Prj.Static_Only then
3815 "only static libraries are supported " &
3817 The_Lib_Kind.Location, Project);
3818 Project.Library := False;
3821 -- Check if (obsolescent) attribute Library_GCC or
3822 -- Linker'Driver is declared.
3824 if Lib_GCC.Value /= Empty_String then
3827 "?Library_'G'C'C is an obsolescent attribute, " &
3828 "use Linker''Driver instead",
3829 Lib_GCC.Location, Project);
3830 Project.Config.Shared_Lib_Driver :=
3831 File_Name_Type (Lib_GCC.Value);
3835 Linker : constant Package_Id :=
3838 Project.Decl.Packages,
3840 Driver : constant Variable_Value :=
3843 Attribute_Or_Array_Name =>
3845 In_Package => Linker,
3846 In_Tree => Data.Tree);
3849 if Driver /= Nil_Variable_Value
3850 and then Driver.Value /= Empty_String
3852 Project.Config.Shared_Lib_Driver :=
3853 File_Name_Type (Driver.Value);
3862 if Project.Library then
3863 if Current_Verbosity = High then
3864 Write_Line ("This is a library project file");
3867 Check_Library (Project.Extends, Extends => True);
3869 Imported_Project_List := Project.Imported_Projects;
3870 while Imported_Project_List /= null loop
3872 (Imported_Project_List.Project,
3874 Imported_Project_List := Imported_Project_List.Next;
3881 -- Check if Linker'Switches or Linker'Default_Switches are declared.
3882 -- Warn if they are declared, as it is a common error to think that
3883 -- library are "linked" with Linker switches.
3885 if Project.Library then
3887 Linker_Package_Id : constant Package_Id :=
3890 Project.Decl.Packages, Data.Tree);
3891 Linker_Package : Package_Element;
3892 Switches : Array_Element_Id := No_Array_Element;
3895 if Linker_Package_Id /= No_Package then
3896 Linker_Package := Data.Tree.Packages.Table (Linker_Package_Id);
3900 (Name => Name_Switches,
3901 In_Arrays => Linker_Package.Decl.Arrays,
3902 In_Tree => Data.Tree);
3904 if Switches = No_Array_Element then
3907 (Name => Name_Default_Switches,
3908 In_Arrays => Linker_Package.Decl.Arrays,
3909 In_Tree => Data.Tree);
3912 if Switches /= No_Array_Element then
3915 "?Linker switches not taken into account in library " &
3917 No_Location, Project);
3923 if Project.Extends /= No_Project then
3924 Project.Extends.Library := False;
3926 end Check_Library_Attributes;
3928 ---------------------------------
3929 -- Check_Programming_Languages --
3930 ---------------------------------
3932 procedure Check_Programming_Languages
3933 (Project : Project_Id;
3934 Data : in out Tree_Processing_Data)
3936 Languages : Variable_Value := Nil_Variable_Value;
3937 Def_Lang : Variable_Value := Nil_Variable_Value;
3938 Def_Lang_Id : Name_Id;
3940 procedure Add_Language (Name, Display_Name : Name_Id);
3941 -- Add a new language to the list of languages for the project.
3942 -- Nothing is done if the language has already been defined
3948 procedure Add_Language (Name, Display_Name : Name_Id) is
3949 Lang : Language_Ptr;
3952 Lang := Project.Languages;
3953 while Lang /= No_Language_Index loop
3954 if Name = Lang.Name then
3961 Lang := new Language_Data'(No_Language_Data);
3962 Lang.Next := Project.Languages;
3963 Project.Languages := Lang;
3965 Lang.Display_Name := Display_Name;
3967 if Name = Name_Ada then
3968 Lang.Config.Kind := Unit_Based;
3969 Lang.Config.Dependency_Kind := ALI_File;
3971 Lang.Config.Kind := File_Based;
3975 -- Start of processing for Check_Programming_Languages
3978 Project.Languages := null;
3980 Prj.Util.Value_Of (Name_Languages, Project.Decl.Attributes, Data.Tree);
3983 (Name_Default_Language, Project.Decl.Attributes, Data.Tree);
3985 if Project.Source_Dirs /= Nil_String then
3987 -- Check if languages are specified in this project
3989 if Languages.Default then
3991 -- Fail if there is no default language defined
3993 if Def_Lang.Default then
3996 "no languages defined for this project",
3997 Project.Location, Project);
3998 Def_Lang_Id := No_Name;
4001 Get_Name_String (Def_Lang.Value);
4002 To_Lower (Name_Buffer (1 .. Name_Len));
4003 Def_Lang_Id := Name_Find;
4006 if Def_Lang_Id /= No_Name then
4007 Get_Name_String (Def_Lang_Id);
4008 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4010 (Name => Def_Lang_Id,
4011 Display_Name => Name_Find);
4016 Current : String_List_Id := Languages.Values;
4017 Element : String_Element;
4020 -- If there are no languages declared, there are no sources
4022 if Current = Nil_String then
4023 Project.Source_Dirs := Nil_String;
4025 if Project.Qualifier = Standard then
4028 "a standard project must have at least one language",
4029 Languages.Location, Project);
4033 -- Look through all the languages specified in attribute
4036 while Current /= Nil_String loop
4037 Element := Data.Tree.String_Elements.Table (Current);
4038 Get_Name_String (Element.Value);
4039 To_Lower (Name_Buffer (1 .. Name_Len));
4043 Display_Name => Element.Value);
4045 Current := Element.Next;
4051 end Check_Programming_Languages;
4053 -------------------------------
4054 -- Check_Stand_Alone_Library --
4055 -------------------------------
4057 procedure Check_Stand_Alone_Library
4058 (Project : Project_Id;
4059 Data : in out Tree_Processing_Data)
4061 Lib_Interfaces : constant Prj.Variable_Value :=
4063 (Snames.Name_Library_Interface,
4064 Project.Decl.Attributes,
4067 Lib_Auto_Init : constant Prj.Variable_Value :=
4069 (Snames.Name_Library_Auto_Init,
4070 Project.Decl.Attributes,
4073 Lib_Src_Dir : constant Prj.Variable_Value :=
4075 (Snames.Name_Library_Src_Dir,
4076 Project.Decl.Attributes,
4079 Lib_Symbol_File : constant Prj.Variable_Value :=
4081 (Snames.Name_Library_Symbol_File,
4082 Project.Decl.Attributes,
4085 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4087 (Snames.Name_Library_Symbol_Policy,
4088 Project.Decl.Attributes,
4091 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4093 (Snames.Name_Library_Reference_Symbol_File,
4094 Project.Decl.Attributes,
4097 Auto_Init_Supported : Boolean;
4098 OK : Boolean := True;
4100 Next_Proj : Project_Id;
4101 Iter : Source_Iterator;
4104 Auto_Init_Supported := Project.Config.Auto_Init_Supported;
4106 pragma Assert (Lib_Interfaces.Kind = List);
4108 -- It is a stand-alone library project file if attribute
4109 -- Library_Interface is defined.
4111 if not Lib_Interfaces.Default then
4113 Interfaces : String_List_Id := Lib_Interfaces.Values;
4114 Interface_ALIs : String_List_Id := Nil_String;
4118 Project.Standalone_Library := True;
4120 -- Library_Interface cannot be an empty list
4122 if Interfaces = Nil_String then
4125 "Library_Interface cannot be an empty list",
4126 Lib_Interfaces.Location, Project);
4129 -- Process each unit name specified in the attribute
4130 -- Library_Interface.
4132 while Interfaces /= Nil_String loop
4134 (Data.Tree.String_Elements.Table (Interfaces).Value);
4135 To_Lower (Name_Buffer (1 .. Name_Len));
4137 if Name_Len = 0 then
4140 "an interface cannot be an empty string",
4141 Data.Tree.String_Elements.Table (Interfaces).Location,
4146 Error_Msg_Name_1 := Unit;
4148 Next_Proj := Project.Extends;
4149 Iter := For_Each_Source (Data.Tree, Project);
4151 while Prj.Element (Iter) /= No_Source
4153 (Prj.Element (Iter).Unit = null
4154 or else Prj.Element (Iter).Unit.Name /= Unit)
4159 Source := Prj.Element (Iter);
4160 exit when Source /= No_Source
4161 or else Next_Proj = No_Project;
4163 Iter := For_Each_Source (Data.Tree, Next_Proj);
4164 Next_Proj := Next_Proj.Extends;
4167 if Source /= No_Source then
4168 if Source.Kind = Sep then
4169 Source := No_Source;
4171 elsif Source.Kind = Spec
4172 and then Other_Part (Source) /= No_Source
4174 Source := Other_Part (Source);
4178 if Source /= No_Source then
4179 if Source.Project /= Project
4180 and then not Is_Extending (Project, Source.Project)
4182 Source := No_Source;
4186 if Source = No_Source then
4189 "%% is not a unit of this project",
4190 Data.Tree.String_Elements.Table
4191 (Interfaces).Location, Project);
4194 if Source.Kind = Spec
4195 and then Other_Part (Source) /= No_Source
4197 Source := Other_Part (Source);
4200 String_Element_Table.Increment_Last
4201 (Data.Tree.String_Elements);
4203 Data.Tree.String_Elements.Table
4204 (String_Element_Table.Last
4205 (Data.Tree.String_Elements)) :=
4206 (Value => Name_Id (Source.Dep_Name),
4208 Display_Value => Name_Id (Source.Dep_Name),
4210 Data.Tree.String_Elements.Table
4211 (Interfaces).Location,
4213 Next => Interface_ALIs);
4216 String_Element_Table.Last
4217 (Data.Tree.String_Elements);
4221 Interfaces := Data.Tree.String_Elements.Table (Interfaces).Next;
4224 -- Put the list of Interface ALIs in the project data
4226 Project.Lib_Interface_ALIs := Interface_ALIs;
4228 -- Check value of attribute Library_Auto_Init and set
4229 -- Lib_Auto_Init accordingly.
4231 if Lib_Auto_Init.Default then
4233 -- If no attribute Library_Auto_Init is declared, then set auto
4234 -- init only if it is supported.
4236 Project.Lib_Auto_Init := Auto_Init_Supported;
4239 Get_Name_String (Lib_Auto_Init.Value);
4240 To_Lower (Name_Buffer (1 .. Name_Len));
4242 if Name_Buffer (1 .. Name_Len) = "false" then
4243 Project.Lib_Auto_Init := False;
4245 elsif Name_Buffer (1 .. Name_Len) = "true" then
4246 if Auto_Init_Supported then
4247 Project.Lib_Auto_Init := True;
4250 -- Library_Auto_Init cannot be "true" if auto init is not
4255 "library auto init not supported " &
4257 Lib_Auto_Init.Location, Project);
4263 "invalid value for attribute Library_Auto_Init",
4264 Lib_Auto_Init.Location, Project);
4269 -- If attribute Library_Src_Dir is defined and not the empty string,
4270 -- check if the directory exist and is not the object directory or
4271 -- one of the source directories. This is the directory where copies
4272 -- of the interface sources will be copied. Note that this directory
4273 -- may be the library directory.
4275 if Lib_Src_Dir.Value /= Empty_String then
4277 Dir_Id : constant File_Name_Type :=
4278 File_Name_Type (Lib_Src_Dir.Value);
4279 Dir_Exists : Boolean;
4285 Path => Project.Library_Src_Dir,
4286 Dir_Exists => Dir_Exists,
4288 Must_Exist => False,
4289 Create => "library source copy",
4290 Location => Lib_Src_Dir.Location,
4291 Externally_Built => Project.Externally_Built);
4293 -- If directory does not exist, report an error
4295 if not Dir_Exists then
4297 -- Get the absolute name of the library directory that does
4298 -- not exist, to report an error.
4300 Err_Vars.Error_Msg_File_1 :=
4301 File_Name_Type (Project.Library_Src_Dir.Display_Name);
4304 "Directory { does not exist",
4305 Lib_Src_Dir.Location, Project);
4307 -- Report error if it is the same as the object directory
4309 elsif Project.Library_Src_Dir = Project.Object_Directory then
4312 "directory to copy interfaces cannot be " &
4313 "the object directory",
4314 Lib_Src_Dir.Location, Project);
4315 Project.Library_Src_Dir := No_Path_Information;
4319 Src_Dirs : String_List_Id;
4320 Src_Dir : String_Element;
4324 -- Interface copy directory cannot be one of the source
4325 -- directory of the current project.
4327 Src_Dirs := Project.Source_Dirs;
4328 while Src_Dirs /= Nil_String loop
4329 Src_Dir := Data.Tree.String_Elements.Table (Src_Dirs);
4331 -- Report error if it is one of the source directories
4333 if Project.Library_Src_Dir.Name =
4334 Path_Name_Type (Src_Dir.Value)
4338 "directory to copy interfaces cannot " &
4339 "be one of the source directories",
4340 Lib_Src_Dir.Location, Project);
4341 Project.Library_Src_Dir := No_Path_Information;
4345 Src_Dirs := Src_Dir.Next;
4348 if Project.Library_Src_Dir /= No_Path_Information then
4350 -- It cannot be a source directory of any other
4353 Pid := Data.Tree.Projects;
4355 exit Project_Loop when Pid = null;
4357 Src_Dirs := Pid.Project.Source_Dirs;
4358 Dir_Loop : while Src_Dirs /= Nil_String loop
4360 Data.Tree.String_Elements.Table (Src_Dirs);
4362 -- Report error if it is one of the source
4365 if Project.Library_Src_Dir.Name =
4366 Path_Name_Type (Src_Dir.Value)
4369 File_Name_Type (Src_Dir.Value);
4370 Error_Msg_Name_1 := Pid.Project.Name;
4373 "directory to copy interfaces cannot " &
4374 "be the same as source directory { of " &
4376 Lib_Src_Dir.Location, Project);
4377 Project.Library_Src_Dir :=
4378 No_Path_Information;
4382 Src_Dirs := Src_Dir.Next;
4386 end loop Project_Loop;
4390 -- In high verbosity, if there is a valid Library_Src_Dir,
4391 -- display its path name.
4393 if Project.Library_Src_Dir /= No_Path_Information
4394 and then Current_Verbosity = High
4397 ("Directory to copy interfaces",
4398 Get_Name_String (Project.Library_Src_Dir.Name));
4404 -- Check the symbol related attributes
4406 -- First, the symbol policy
4408 if not Lib_Symbol_Policy.Default then
4410 Value : constant String :=
4412 (Get_Name_String (Lib_Symbol_Policy.Value));
4415 -- Symbol policy must hove one of a limited number of values
4417 if Value = "autonomous" or else Value = "default" then
4418 Project.Symbol_Data.Symbol_Policy := Autonomous;
4420 elsif Value = "compliant" then
4421 Project.Symbol_Data.Symbol_Policy := Compliant;
4423 elsif Value = "controlled" then
4424 Project.Symbol_Data.Symbol_Policy := Controlled;
4426 elsif Value = "restricted" then
4427 Project.Symbol_Data.Symbol_Policy := Restricted;
4429 elsif Value = "direct" then
4430 Project.Symbol_Data.Symbol_Policy := Direct;
4435 "illegal value for Library_Symbol_Policy",
4436 Lib_Symbol_Policy.Location, Project);
4441 -- If attribute Library_Symbol_File is not specified, symbol policy
4442 -- cannot be Restricted.
4444 if Lib_Symbol_File.Default then
4445 if Project.Symbol_Data.Symbol_Policy = Restricted then
4448 "Library_Symbol_File needs to be defined when " &
4449 "symbol policy is Restricted",
4450 Lib_Symbol_Policy.Location, Project);
4454 -- Library_Symbol_File is defined
4456 Project.Symbol_Data.Symbol_File :=
4457 Path_Name_Type (Lib_Symbol_File.Value);
4459 Get_Name_String (Lib_Symbol_File.Value);
4461 if Name_Len = 0 then
4464 "symbol file name cannot be an empty string",
4465 Lib_Symbol_File.Location, Project);
4468 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
4471 for J in 1 .. Name_Len loop
4472 if Name_Buffer (J) = '/'
4473 or else Name_Buffer (J) = Directory_Separator
4482 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
4485 "symbol file name { is illegal. " &
4486 "Name cannot include directory info.",
4487 Lib_Symbol_File.Location, Project);
4492 -- If attribute Library_Reference_Symbol_File is not defined,
4493 -- symbol policy cannot be Compliant or Controlled.
4495 if Lib_Ref_Symbol_File.Default then
4496 if Project.Symbol_Data.Symbol_Policy = Compliant
4497 or else Project.Symbol_Data.Symbol_Policy = Controlled
4501 "a reference symbol file needs to be defined",
4502 Lib_Symbol_Policy.Location, Project);
4506 -- Library_Reference_Symbol_File is defined, check file exists
4508 Project.Symbol_Data.Reference :=
4509 Path_Name_Type (Lib_Ref_Symbol_File.Value);
4511 Get_Name_String (Lib_Ref_Symbol_File.Value);
4513 if Name_Len = 0 then
4516 "reference symbol file name cannot be an empty string",
4517 Lib_Symbol_File.Location, Project);
4520 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
4522 Add_Str_To_Name_Buffer
4523 (Get_Name_String (Project.Directory.Name));
4524 Add_Str_To_Name_Buffer
4525 (Get_Name_String (Lib_Ref_Symbol_File.Value));
4526 Project.Symbol_Data.Reference := Name_Find;
4529 if not Is_Regular_File
4530 (Get_Name_String (Project.Symbol_Data.Reference))
4533 File_Name_Type (Lib_Ref_Symbol_File.Value);
4535 -- For controlled and direct symbol policies, it is an error
4536 -- if the reference symbol file does not exist. For other
4537 -- symbol policies, this is just a warning
4540 Project.Symbol_Data.Symbol_Policy /= Controlled
4541 and then Project.Symbol_Data.Symbol_Policy /= Direct;
4545 "<library reference symbol file { does not exist",
4546 Lib_Ref_Symbol_File.Location, Project);
4548 -- In addition in the non-controlled case, if symbol policy
4549 -- is Compliant, it is changed to Autonomous, because there
4550 -- is no reference to check against, and we don't want to
4551 -- fail in this case.
4553 if Project.Symbol_Data.Symbol_Policy /= Controlled then
4554 if Project.Symbol_Data.Symbol_Policy = Compliant then
4555 Project.Symbol_Data.Symbol_Policy := Autonomous;
4560 -- If both the reference symbol file and the symbol file are
4561 -- defined, then check that they are not the same file.
4563 if Project.Symbol_Data.Symbol_File /= No_Path then
4564 Get_Name_String (Project.Symbol_Data.Symbol_File);
4566 if Name_Len > 0 then
4568 -- We do not need to pass a Directory to
4569 -- Normalize_Pathname, since the path_information
4570 -- already contains absolute information.
4572 Symb_Path : constant String :=
4575 (Project.Object_Directory.Name) &
4576 Name_Buffer (1 .. Name_Len),
4579 Opt.Follow_Links_For_Files);
4580 Ref_Path : constant String :=
4583 (Project.Symbol_Data.Reference),
4586 Opt.Follow_Links_For_Files);
4588 if Symb_Path = Ref_Path then
4591 "library reference symbol file and library" &
4592 " symbol file cannot be the same file",
4593 Lib_Ref_Symbol_File.Location, Project);
4601 end Check_Stand_Alone_Library;
4603 ----------------------------
4604 -- Compute_Directory_Last --
4605 ----------------------------
4607 function Compute_Directory_Last (Dir : String) return Natural is
4610 and then (Dir (Dir'Last - 1) = Directory_Separator
4612 Dir (Dir'Last - 1) = '/')
4614 return Dir'Last - 1;
4618 end Compute_Directory_Last;
4620 ---------------------
4621 -- Get_Directories --
4622 ---------------------
4624 procedure Get_Directories
4625 (Project : Project_Id;
4626 Data : in out Tree_Processing_Data)
4628 package Recursive_Dirs is new GNAT.Dynamic_HTables.Simple_HTable
4629 (Header_Num => Header_Num,
4631 No_Element => False,
4635 -- Hash table stores recursive source directories, to avoid looking
4636 -- several times, and to avoid cycles that may be introduced by symbolic
4639 Visited : Recursive_Dirs.Instance;
4641 Object_Dir : constant Variable_Value :=
4643 (Name_Object_Dir, Project.Decl.Attributes, Data.Tree);
4645 Exec_Dir : constant Variable_Value :=
4647 (Name_Exec_Dir, Project.Decl.Attributes, Data.Tree);
4649 Source_Dirs : constant Variable_Value :=
4651 (Name_Source_Dirs, Project.Decl.Attributes, Data.Tree);
4653 Excluded_Source_Dirs : constant Variable_Value :=
4655 (Name_Excluded_Source_Dirs,
4656 Project.Decl.Attributes,
4659 Source_Files : constant Variable_Value :=
4662 Project.Decl.Attributes, Data.Tree);
4664 Last_Source_Dir : String_List_Id := Nil_String;
4666 Languages : constant Variable_Value :=
4668 (Name_Languages, Project.Decl.Attributes, Data.Tree);
4670 procedure Find_Source_Dirs
4671 (From : File_Name_Type;
4672 Location : Source_Ptr;
4673 Removed : Boolean := False);
4674 -- Find one or several source directories, and add (or remove, if
4675 -- Removed is True) them to list of source directories of the project.
4677 ----------------------
4678 -- Find_Source_Dirs --
4679 ----------------------
4681 procedure Find_Source_Dirs
4682 (From : File_Name_Type;
4683 Location : Source_Ptr;
4684 Removed : Boolean := False)
4686 Directory : constant String := Get_Name_String (From);
4687 Element : String_Element;
4689 procedure Recursive_Find_Dirs (Path : Name_Id);
4690 -- Find all the subdirectories (recursively) of Path and add them
4691 -- to the list of source directories of the project.
4693 -------------------------
4694 -- Recursive_Find_Dirs --
4695 -------------------------
4697 procedure Recursive_Find_Dirs (Path : Name_Id) is
4699 Name : String (1 .. 250);
4701 List : String_List_Id;
4702 Prev : String_List_Id;
4703 Element : String_Element;
4704 Found : Boolean := False;
4706 Non_Canonical_Path : Name_Id := No_Name;
4707 Canonical_Path : Name_Id := No_Name;
4709 The_Path : constant String :=
4711 (Get_Name_String (Path),
4713 Get_Name_String (Project.Directory.Display_Name),
4714 Resolve_Links => Opt.Follow_Links_For_Dirs) &
4715 Directory_Separator;
4717 The_Path_Last : constant Natural :=
4718 Compute_Directory_Last (The_Path);
4721 Name_Len := The_Path_Last - The_Path'First + 1;
4722 Name_Buffer (1 .. Name_Len) :=
4723 The_Path (The_Path'First .. The_Path_Last);
4724 Non_Canonical_Path := Name_Find;
4726 Name_Id (Canonical_Case_File_Name (Non_Canonical_Path));
4728 -- To avoid processing the same directory several times, check
4729 -- if the directory is already in Recursive_Dirs. If it is, then
4730 -- there is nothing to do, just return. If it is not, put it there
4731 -- and continue recursive processing.
4734 if Recursive_Dirs.Get (Visited, Canonical_Path) then
4737 Recursive_Dirs.Set (Visited, Canonical_Path, True);
4741 -- Check if directory is already in list
4743 List := Project.Source_Dirs;
4745 while List /= Nil_String loop
4746 Element := Data.Tree.String_Elements.Table (List);
4748 if Element.Value /= No_Name then
4749 Found := Element.Value = Canonical_Path;
4754 List := Element.Next;
4757 -- If directory is not already in list, put it there
4759 if (not Removed) and (not Found) then
4760 if Current_Verbosity = High then
4762 Write_Line (The_Path (The_Path'First .. The_Path_Last));
4765 String_Element_Table.Increment_Last (Data.Tree.String_Elements);
4767 (Value => Canonical_Path,
4768 Display_Value => Non_Canonical_Path,
4769 Location => No_Location,
4774 -- Case of first source directory
4776 if Last_Source_Dir = Nil_String then
4777 Project.Source_Dirs :=
4778 String_Element_Table.Last (Data.Tree.String_Elements);
4780 -- Here we already have source directories
4783 -- Link the previous last to the new one
4785 Data.Tree.String_Elements.Table
4786 (Last_Source_Dir).Next :=
4787 String_Element_Table.Last (Data.Tree.String_Elements);
4790 -- And register this source directory as the new last
4793 String_Element_Table.Last (Data.Tree.String_Elements);
4794 Data.Tree.String_Elements.Table (Last_Source_Dir) := Element;
4796 elsif Removed and Found then
4797 if Prev = Nil_String then
4798 Project.Source_Dirs :=
4799 Data.Tree.String_Elements.Table (List).Next;
4801 Data.Tree.String_Elements.Table (Prev).Next :=
4802 Data.Tree.String_Elements.Table (List).Next;
4806 -- Now look for subdirectories. We do that even when this
4807 -- directory is already in the list, because some of its
4808 -- subdirectories may not be in the list yet.
4810 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
4813 Read (Dir, Name, Last);
4816 if Name (1 .. Last) /= "."
4817 and then Name (1 .. Last) /= ".."
4819 -- Avoid . and .. directories
4821 if Current_Verbosity = High then
4822 Write_Str (" Checking ");
4823 Write_Line (Name (1 .. Last));
4827 Path_Name : constant String :=
4829 (Name => Name (1 .. Last),
4831 The_Path (The_Path'First .. The_Path_Last),
4832 Resolve_Links => Opt.Follow_Links_For_Dirs,
4833 Case_Sensitive => True);
4836 if Is_Directory (Path_Name) then
4838 -- We have found a new subdirectory, call self
4840 Name_Len := Path_Name'Length;
4841 Name_Buffer (1 .. Name_Len) := Path_Name;
4842 Recursive_Find_Dirs (Name_Find);
4851 when Directory_Error =>
4853 end Recursive_Find_Dirs;
4855 -- Start of processing for Find_Source_Dirs
4858 if Current_Verbosity = High and then not Removed then
4859 Write_Str ("Find_Source_Dirs (""");
4860 Write_Str (Directory);
4864 -- First, check if we are looking for a directory tree, indicated
4865 -- by "/**" at the end.
4867 if Directory'Length >= 3
4868 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
4869 and then (Directory (Directory'Last - 2) = '/'
4871 Directory (Directory'Last - 2) = Directory_Separator)
4874 Project.Known_Order_Of_Source_Dirs := False;
4877 Name_Len := Directory'Length - 3;
4879 if Name_Len = 0 then
4881 -- Case of "/**": all directories in file system
4884 Name_Buffer (1) := Directory (Directory'First);
4887 Name_Buffer (1 .. Name_Len) :=
4888 Directory (Directory'First .. Directory'Last - 3);
4891 if Current_Verbosity = High then
4892 Write_Str ("Looking for all subdirectories of """);
4893 Write_Str (Name_Buffer (1 .. Name_Len));
4898 Base_Dir : constant File_Name_Type := Name_Find;
4899 Root_Dir : constant String :=
4901 (Name => Get_Name_String (Base_Dir),
4904 (Project.Directory.Display_Name),
4905 Resolve_Links => False,
4906 Case_Sensitive => True);
4909 if Root_Dir'Length = 0 then
4910 Err_Vars.Error_Msg_File_1 := Base_Dir;
4912 if Location = No_Location then
4915 "{ is not a valid directory.",
4916 Project.Location, Project);
4920 "{ is not a valid directory.",
4925 -- We have an existing directory, we register it and all of
4926 -- its subdirectories.
4928 if Current_Verbosity = High then
4929 Write_Line ("Looking for source directories:");
4932 Name_Len := Root_Dir'Length;
4933 Name_Buffer (1 .. Name_Len) := Root_Dir;
4934 Recursive_Find_Dirs (Name_Find);
4936 if Current_Verbosity = High then
4937 Write_Line ("End of looking for source directories.");
4942 -- We have a single directory
4946 Path_Name : Path_Information;
4947 List : String_List_Id;
4948 Prev : String_List_Id;
4949 Dir_Exists : Boolean;
4953 (Project => Project,
4956 Dir_Exists => Dir_Exists,
4958 Must_Exist => False);
4960 if not Dir_Exists then
4961 Err_Vars.Error_Msg_File_1 := From;
4963 if Location = No_Location then
4966 "{ is not a valid directory",
4967 Project.Location, Project);
4971 "{ is not a valid directory",
4977 Path : constant String :=
4978 Get_Name_String (Path_Name.Name);
4979 Last_Path : constant Natural :=
4980 Compute_Directory_Last (Path);
4982 Display_Path : constant String :=
4984 (Path_Name.Display_Name);
4985 Last_Display_Path : constant Natural :=
4986 Compute_Directory_Last
4988 Display_Path_Id : Name_Id;
4992 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
4993 Path_Id := Name_Find;
4995 Add_Str_To_Name_Buffer
4997 (Display_Path'First .. Last_Display_Path));
4998 Display_Path_Id := Name_Find;
5002 -- As it is an existing directory, we add it to the
5003 -- list of directories.
5005 String_Element_Table.Increment_Last
5006 (Data.Tree.String_Elements);
5010 Display_Value => Display_Path_Id,
5011 Location => No_Location,
5013 Next => Nil_String);
5015 if Last_Source_Dir = Nil_String then
5017 -- This is the first source directory
5019 Project.Source_Dirs := String_Element_Table.Last
5020 (Data.Tree.String_Elements);
5023 -- We already have source directories, link the
5024 -- previous last to the new one.
5026 Data.Tree.String_Elements.Table
5027 (Last_Source_Dir).Next :=
5028 String_Element_Table.Last
5029 (Data.Tree.String_Elements);
5032 -- And register this source directory as the new last
5034 Last_Source_Dir := String_Element_Table.Last
5035 (Data.Tree.String_Elements);
5036 Data.Tree.String_Elements.Table
5037 (Last_Source_Dir) := Element;
5040 -- Remove source dir, if present
5044 -- Look for source dir in current list
5046 List := Project.Source_Dirs;
5047 while List /= Nil_String loop
5048 Element := Data.Tree.String_Elements.Table (List);
5049 exit when Element.Value = Path_Id;
5051 List := Element.Next;
5054 if List /= Nil_String then
5055 -- Source dir was found, remove it from the list
5057 if Prev = Nil_String then
5058 Project.Source_Dirs :=
5059 Data.Tree.String_Elements.Table (List).Next;
5062 Data.Tree.String_Elements.Table (Prev).Next :=
5063 Data.Tree.String_Elements.Table (List).Next;
5072 Recursive_Dirs.Reset (Visited);
5073 end Find_Source_Dirs;
5075 -- Start of processing for Get_Directories
5077 Dir_Exists : Boolean;
5080 if Current_Verbosity = High then
5081 Write_Line ("Starting to look for directories");
5084 -- Set the object directory to its default which may be nil, if there
5085 -- is no sources in the project.
5087 if (((not Source_Files.Default)
5088 and then Source_Files.Values = Nil_String)
5090 ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
5092 ((not Languages.Default) and then Languages.Values = Nil_String))
5093 and then Project.Extends = No_Project
5095 Project.Object_Directory := No_Path_Information;
5097 Project.Object_Directory := Project.Directory;
5100 -- Check the object directory
5102 if Object_Dir.Value /= Empty_String then
5103 Get_Name_String (Object_Dir.Value);
5105 if Name_Len = 0 then
5108 "Object_Dir cannot be empty",
5109 Object_Dir.Location, Project);
5112 -- We check that the specified object directory does exist.
5113 -- However, even when it doesn't exist, we set it to a default
5114 -- value. This is for the benefit of tools that recover from
5115 -- errors; for example, these tools could create the non existent
5116 -- directory. We always return an absolute directory name though.
5120 File_Name_Type (Object_Dir.Value),
5121 Path => Project.Object_Directory,
5123 Dir_Exists => Dir_Exists,
5125 Location => Object_Dir.Location,
5126 Must_Exist => False,
5127 Externally_Built => Project.Externally_Built);
5130 and then not Project.Externally_Built
5132 -- The object directory does not exist, report an error if
5133 -- the project is not externally built.
5135 Err_Vars.Error_Msg_File_1 :=
5136 File_Name_Type (Object_Dir.Value);
5139 "object directory { not found",
5140 Project.Location, Project);
5144 elsif Project.Object_Directory /= No_Path_Information
5145 and then Subdirs /= null
5148 Name_Buffer (1) := '.';
5152 Path => Project.Object_Directory,
5154 Dir_Exists => Dir_Exists,
5156 Location => Object_Dir.Location,
5157 Externally_Built => Project.Externally_Built);
5160 if Current_Verbosity = High then
5161 if Project.Object_Directory = No_Path_Information then
5162 Write_Line ("No object directory");
5165 ("Object directory",
5166 Get_Name_String (Project.Object_Directory.Display_Name));
5170 -- Check the exec directory
5172 -- We set the object directory to its default
5174 Project.Exec_Directory := Project.Object_Directory;
5176 if Exec_Dir.Value /= Empty_String then
5177 Get_Name_String (Exec_Dir.Value);
5179 if Name_Len = 0 then
5182 "Exec_Dir cannot be empty",
5183 Exec_Dir.Location, Project);
5186 -- We check that the specified exec directory does exist
5190 File_Name_Type (Exec_Dir.Value),
5191 Path => Project.Exec_Directory,
5192 Dir_Exists => Dir_Exists,
5195 Location => Exec_Dir.Location,
5196 Externally_Built => Project.Externally_Built);
5198 if not Dir_Exists then
5199 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
5202 "exec directory { not found",
5203 Project.Location, Project);
5208 if Current_Verbosity = High then
5209 if Project.Exec_Directory = No_Path_Information then
5210 Write_Line ("No exec directory");
5212 Write_Str ("Exec directory: """);
5213 Write_Str (Get_Name_String (Project.Exec_Directory.Display_Name));
5218 -- Look for the source directories
5220 if Current_Verbosity = High then
5221 Write_Line ("Starting to look for source directories");
5224 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
5226 if (not Source_Files.Default)
5227 and then Source_Files.Values = Nil_String
5229 Project.Source_Dirs := Nil_String;
5231 if Project.Qualifier = Standard then
5234 "a standard project cannot have no sources",
5235 Source_Files.Location, Project);
5238 elsif Source_Dirs.Default then
5240 -- No Source_Dirs specified: the single source directory is the one
5241 -- containing the project file.
5243 String_Element_Table.Append (Data.Tree.String_Elements,
5244 (Value => Name_Id (Project.Directory.Name),
5245 Display_Value => Name_Id (Project.Directory.Display_Name),
5246 Location => No_Location,
5251 Project.Source_Dirs :=
5252 String_Element_Table.Last (Data.Tree.String_Elements);
5254 if Current_Verbosity = High then
5256 ("Default source directory",
5257 Get_Name_String (Project.Directory.Display_Name));
5260 elsif Source_Dirs.Values = Nil_String then
5261 if Project.Qualifier = Standard then
5264 "a standard project cannot have no source directories",
5265 Source_Dirs.Location, Project);
5268 Project.Source_Dirs := Nil_String;
5272 Source_Dir : String_List_Id;
5273 Element : String_Element;
5276 -- Process the source directories for each element of the list
5278 Source_Dir := Source_Dirs.Values;
5279 while Source_Dir /= Nil_String loop
5280 Element := Data.Tree.String_Elements.Table (Source_Dir);
5282 (File_Name_Type (Element.Value), Element.Location);
5283 Source_Dir := Element.Next;
5288 if not Excluded_Source_Dirs.Default
5289 and then Excluded_Source_Dirs.Values /= Nil_String
5292 Source_Dir : String_List_Id;
5293 Element : String_Element;
5296 -- Process the source directories for each element of the list
5298 Source_Dir := Excluded_Source_Dirs.Values;
5299 while Source_Dir /= Nil_String loop
5300 Element := Data.Tree.String_Elements.Table (Source_Dir);
5302 (File_Name_Type (Element.Value),
5305 Source_Dir := Element.Next;
5310 if Current_Verbosity = High then
5311 Write_Line ("Putting source directories in canonical cases");
5315 Current : String_List_Id := Project.Source_Dirs;
5316 Element : String_Element;
5319 while Current /= Nil_String loop
5320 Element := Data.Tree.String_Elements.Table (Current);
5321 if Element.Value /= No_Name then
5323 Name_Id (Canonical_Case_File_Name (Name_Id (Element.Value)));
5324 Data.Tree.String_Elements.Table (Current) := Element;
5327 Current := Element.Next;
5330 end Get_Directories;
5337 (Project : Project_Id;
5338 Data : in out Tree_Processing_Data)
5340 Mains : constant Variable_Value :=
5342 (Name_Main, Project.Decl.Attributes, Data.Tree);
5343 List : String_List_Id;
5344 Elem : String_Element;
5347 Project.Mains := Mains.Values;
5349 -- If no Mains were specified, and if we are an extending project,
5350 -- inherit the Mains from the project we are extending.
5352 if Mains.Default then
5353 if not Project.Library and then Project.Extends /= No_Project then
5354 Project.Mains := Project.Extends.Mains;
5357 -- In a library project file, Main cannot be specified
5359 elsif Project.Library then
5362 "a library project file cannot have Main specified",
5363 Mains.Location, Project);
5366 List := Mains.Values;
5367 while List /= Nil_String loop
5368 Elem := Data.Tree.String_Elements.Table (List);
5370 if Length_Of_Name (Elem.Value) = 0 then
5373 "?a main cannot have an empty name",
5374 Elem.Location, Project);
5383 ---------------------------
5384 -- Get_Sources_From_File --
5385 ---------------------------
5387 procedure Get_Sources_From_File
5389 Location : Source_Ptr;
5390 Project : in out Project_Processing_Data;
5391 Data : in out Tree_Processing_Data)
5393 File : Prj.Util.Text_File;
5394 Line : String (1 .. 250);
5396 Source_Name : File_Name_Type;
5397 Name_Loc : Name_Location;
5400 if Current_Verbosity = High then
5401 Write_Str ("Opening """);
5408 Prj.Util.Open (File, Path);
5410 if not Prj.Util.Is_Valid (File) then
5412 (Data.Flags, "file does not exist", Location, Project.Project);
5415 -- Read the lines one by one
5417 while not Prj.Util.End_Of_File (File) loop
5418 Prj.Util.Get_Line (File, Line, Last);
5420 -- A non empty, non comment line should contain a file name
5423 and then (Last = 1 or else Line (1 .. 2) /= "--")
5426 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
5427 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5428 Source_Name := Name_Find;
5430 -- Check that there is no directory information
5432 for J in 1 .. Last loop
5433 if Line (J) = '/' or else Line (J) = Directory_Separator then
5434 Error_Msg_File_1 := Source_Name;
5437 "file name cannot include directory information ({)",
5438 Location, Project.Project);
5443 Name_Loc := Source_Names_Htable.Get
5444 (Project.Source_Names, Source_Name);
5446 if Name_Loc = No_Name_Location then
5448 (Name => Source_Name,
5449 Location => Location,
5450 Source => No_Source,
5454 Source_Names_Htable.Set
5455 (Project.Source_Names, Source_Name, Name_Loc);
5459 Prj.Util.Close (File);
5462 end Get_Sources_From_File;
5464 -----------------------
5465 -- Compute_Unit_Name --
5466 -----------------------
5468 procedure Compute_Unit_Name
5469 (File_Name : File_Name_Type;
5470 Naming : Lang_Naming_Data;
5471 Kind : out Source_Kind;
5473 Project : Project_Processing_Data;
5474 In_Tree : Project_Tree_Ref)
5476 Filename : constant String := Get_Name_String (File_Name);
5477 Last : Integer := Filename'Last;
5482 Unit_Except : Unit_Exception;
5483 Masked : Boolean := False;
5489 if Naming.Separate_Suffix = No_File
5490 or else Naming.Body_Suffix = No_File
5491 or else Naming.Spec_Suffix = No_File
5496 if Naming.Dot_Replacement = No_File then
5497 if Current_Verbosity = High then
5498 Write_Line (" No dot_replacement specified");
5504 Sep_Len := Integer (Length_Of_Name (Naming.Separate_Suffix));
5505 Spec_Len := Integer (Length_Of_Name (Naming.Spec_Suffix));
5506 Body_Len := Integer (Length_Of_Name (Naming.Body_Suffix));
5508 -- Choose the longest suffix that matches. If there are several matches,
5509 -- give priority to specs, then bodies, then separates.
5511 if Naming.Separate_Suffix /= Naming.Body_Suffix
5512 and then Suffix_Matches (Filename, Naming.Separate_Suffix)
5514 Last := Filename'Last - Sep_Len;
5518 if Filename'Last - Body_Len <= Last
5519 and then Suffix_Matches (Filename, Naming.Body_Suffix)
5521 Last := Natural'Min (Last, Filename'Last - Body_Len);
5525 if Filename'Last - Spec_Len <= Last
5526 and then Suffix_Matches (Filename, Naming.Spec_Suffix)
5528 Last := Natural'Min (Last, Filename'Last - Spec_Len);
5532 if Last = Filename'Last then
5533 if Current_Verbosity = High then
5534 Write_Line (" no matching suffix");
5540 -- Check that the casing matches
5542 if File_Names_Case_Sensitive then
5543 case Naming.Casing is
5544 when All_Lower_Case =>
5545 for J in Filename'First .. Last loop
5546 if Is_Letter (Filename (J))
5547 and then not Is_Lower (Filename (J))
5549 if Current_Verbosity = High then
5550 Write_Line (" Invalid casing");
5557 when All_Upper_Case =>
5558 for J in Filename'First .. Last loop
5559 if Is_Letter (Filename (J))
5560 and then not Is_Upper (Filename (J))
5562 if Current_Verbosity = High then
5563 Write_Line (" Invalid casing");
5570 when Mixed_Case | Unknown =>
5575 -- If Dot_Replacement is not a single dot, then there should not
5576 -- be any dot in the name.
5579 Dot_Repl : constant String :=
5580 Get_Name_String (Naming.Dot_Replacement);
5583 if Dot_Repl /= "." then
5584 for Index in Filename'First .. Last loop
5585 if Filename (Index) = '.' then
5586 if Current_Verbosity = High then
5587 Write_Line (" Invalid name, contains dot");
5594 Replace_Into_Name_Buffer
5595 (Filename (Filename'First .. Last), Dot_Repl, '.');
5598 Name_Len := Last - Filename'First + 1;
5599 Name_Buffer (1 .. Name_Len) := Filename (Filename'First .. Last);
5601 (Source => Name_Buffer (1 .. Name_Len),
5602 Mapping => Lower_Case_Map);
5606 -- In the standard GNAT naming scheme, check for special cases: children
5607 -- or separates of A, G, I or S, and run time sources.
5609 if Is_Standard_GNAT_Naming (Naming)
5610 and then Name_Len >= 3
5613 S1 : constant Character := Name_Buffer (1);
5614 S2 : constant Character := Name_Buffer (2);
5615 S3 : constant Character := Name_Buffer (3);
5623 -- Children or separates of packages A, G, I or S. These names
5624 -- are x__ ... or x~... (where x is a, g, i, or s). Both
5625 -- versions (x__... and x~...) are allowed in all platforms,
5626 -- because it is not possible to know the platform before
5627 -- processing of the project files.
5629 if S2 = '_' and then S3 = '_' then
5630 Name_Buffer (2) := '.';
5631 Name_Buffer (3 .. Name_Len - 1) :=
5632 Name_Buffer (4 .. Name_Len);
5633 Name_Len := Name_Len - 1;
5636 Name_Buffer (2) := '.';
5640 -- If it is potentially a run time source
5648 -- Name_Buffer contains the name of the the unit in lower-cases. Check
5649 -- that this is a valid unit name
5651 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
5653 -- If there is a naming exception for the same unit, the file is not
5654 -- a source for the unit.
5656 if Unit /= No_Name then
5658 Unit_Exceptions_Htable.Get (Project.Unit_Exceptions, Unit);
5661 Masked := Unit_Except.Spec /= No_File
5663 Unit_Except.Spec /= File_Name;
5665 Masked := Unit_Except.Impl /= No_File
5667 Unit_Except.Impl /= File_Name;
5671 if Current_Verbosity = High then
5672 Write_Str (" """ & Filename & """ contains the ");
5675 Write_Str ("spec of a unit found in """);
5676 Write_Str (Get_Name_String (Unit_Except.Spec));
5678 Write_Str ("body of a unit found in """);
5679 Write_Str (Get_Name_String (Unit_Except.Impl));
5682 Write_Line (""" (ignored)");
5690 and then Current_Verbosity = High
5693 when Spec => Write_Str (" spec of ");
5694 when Impl => Write_Str (" body of ");
5695 when Sep => Write_Str (" sep of ");
5698 Write_Line (Get_Name_String (Unit));
5700 end Compute_Unit_Name;
5702 --------------------------
5703 -- Check_Illegal_Suffix --
5704 --------------------------
5706 procedure Check_Illegal_Suffix
5707 (Project : Project_Id;
5708 Suffix : File_Name_Type;
5709 Dot_Replacement : File_Name_Type;
5710 Attribute_Name : String;
5711 Location : Source_Ptr;
5712 Data : in out Tree_Processing_Data)
5714 Suffix_Str : constant String := Get_Name_String (Suffix);
5717 if Suffix_Str'Length = 0 then
5723 elsif Index (Suffix_Str, ".") = 0 then
5724 Err_Vars.Error_Msg_File_1 := Suffix;
5727 "{ is illegal for " & Attribute_Name & ": must have a dot",
5732 -- Case of dot replacement is a single dot, and first character of
5733 -- suffix is also a dot.
5735 if Dot_Replacement /= No_File
5736 and then Get_Name_String (Dot_Replacement) = "."
5737 and then Suffix_Str (Suffix_Str'First) = '.'
5739 for Index in Suffix_Str'First + 1 .. Suffix_Str'Last loop
5741 -- If there are multiple dots in the name
5743 if Suffix_Str (Index) = '.' then
5745 -- It is illegal to have a letter following the initial dot
5747 if Is_Letter (Suffix_Str (Suffix_Str'First + 1)) then
5748 Err_Vars.Error_Msg_File_1 := Suffix;
5751 "{ is illegal for " & Attribute_Name
5752 & ": ambiguous prefix when Dot_Replacement is a dot",
5759 end Check_Illegal_Suffix;
5761 ----------------------
5762 -- Locate_Directory --
5763 ----------------------
5765 procedure Locate_Directory
5766 (Project : Project_Id;
5767 Name : File_Name_Type;
5768 Path : out Path_Information;
5769 Dir_Exists : out Boolean;
5770 Data : in out Tree_Processing_Data;
5771 Create : String := "";
5772 Location : Source_Ptr := No_Location;
5773 Must_Exist : Boolean := True;
5774 Externally_Built : Boolean := False)
5776 Parent : constant Path_Name_Type :=
5777 Project.Directory.Display_Name;
5778 The_Parent : constant String :=
5779 Get_Name_String (Parent);
5780 The_Parent_Last : constant Natural :=
5781 Compute_Directory_Last (The_Parent);
5782 Full_Name : File_Name_Type;
5783 The_Name : File_Name_Type;
5786 Get_Name_String (Name);
5788 -- Add Subdirs.all if it is a directory that may be created and
5789 -- Subdirs is not null;
5791 if Create /= "" and then Subdirs /= null then
5792 if Name_Buffer (Name_Len) /= Directory_Separator then
5793 Add_Char_To_Name_Buffer (Directory_Separator);
5796 Add_Str_To_Name_Buffer (Subdirs.all);
5799 -- Convert '/' to directory separator (for Windows)
5801 for J in 1 .. Name_Len loop
5802 if Name_Buffer (J) = '/' then
5803 Name_Buffer (J) := Directory_Separator;
5807 The_Name := Name_Find;
5809 if Current_Verbosity = High then
5810 Write_Str ("Locate_Directory (""");
5811 Write_Str (Get_Name_String (The_Name));
5812 Write_Str (""", """);
5813 Write_Str (The_Parent);
5817 Path := No_Path_Information;
5818 Dir_Exists := False;
5820 if Is_Absolute_Path (Get_Name_String (The_Name)) then
5821 Full_Name := The_Name;
5825 Add_Str_To_Name_Buffer
5826 (The_Parent (The_Parent'First .. The_Parent_Last));
5827 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
5828 Full_Name := Name_Find;
5832 Full_Path_Name : String_Access :=
5833 new String'(Get_Name_String (Full_Name));
5836 if (Setup_Projects or else Subdirs /= null)
5837 and then Create'Length > 0
5839 if not Is_Directory (Full_Path_Name.all) then
5841 -- If project is externally built, do not create a subdir,
5842 -- use the specified directory, without the subdir.
5844 if Externally_Built then
5845 if Is_Absolute_Path (Get_Name_String (Name)) then
5846 Get_Name_String (Name);
5850 Add_Str_To_Name_Buffer
5851 (The_Parent (The_Parent'First .. The_Parent_Last));
5852 Add_Str_To_Name_Buffer (Get_Name_String (Name));
5855 Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
5859 Create_Path (Full_Path_Name.all);
5861 if not Quiet_Output then
5863 Write_Str (" directory """);
5864 Write_Str (Full_Path_Name.all);
5865 Write_Str (""" created for project ");
5866 Write_Line (Get_Name_String (Project.Name));
5873 "could not create " & Create &
5874 " directory " & Full_Path_Name.all,
5881 Dir_Exists := Is_Directory (Full_Path_Name.all);
5883 if not Must_Exist or else Dir_Exists then
5885 Normed : constant String :=
5887 (Full_Path_Name.all,
5889 The_Parent (The_Parent'First .. The_Parent_Last),
5890 Resolve_Links => False,
5891 Case_Sensitive => True);
5893 Canonical_Path : constant String :=
5898 (The_Parent'First .. The_Parent_Last),
5900 Opt.Follow_Links_For_Dirs,
5901 Case_Sensitive => False);
5904 Name_Len := Normed'Length;
5905 Name_Buffer (1 .. Name_Len) := Normed;
5907 -- Directories should always end with a directory separator
5909 if Name_Buffer (Name_Len) /= Directory_Separator then
5910 Add_Char_To_Name_Buffer (Directory_Separator);
5913 Path.Display_Name := Name_Find;
5915 Name_Len := Canonical_Path'Length;
5916 Name_Buffer (1 .. Name_Len) := Canonical_Path;
5918 if Name_Buffer (Name_Len) /= Directory_Separator then
5919 Add_Char_To_Name_Buffer (Directory_Separator);
5922 Path.Name := Name_Find;
5926 Free (Full_Path_Name);
5928 end Locate_Directory;
5930 ---------------------------
5931 -- Find_Excluded_Sources --
5932 ---------------------------
5934 procedure Find_Excluded_Sources
5935 (Project : in out Project_Processing_Data;
5936 Data : in out Tree_Processing_Data)
5938 Excluded_Source_List_File : constant Variable_Value :=
5940 (Name_Excluded_Source_List_File,
5941 Project.Project.Decl.Attributes,
5943 Excluded_Sources : Variable_Value := Util.Value_Of
5944 (Name_Excluded_Source_Files,
5945 Project.Project.Decl.Attributes,
5948 Current : String_List_Id;
5949 Element : String_Element;
5950 Location : Source_Ptr;
5951 Name : File_Name_Type;
5952 File : Prj.Util.Text_File;
5953 Line : String (1 .. 300);
5955 Locally_Removed : Boolean := False;
5958 -- If Excluded_Source_Files is not declared, check Locally_Removed_Files
5960 if Excluded_Sources.Default then
5961 Locally_Removed := True;
5964 (Name_Locally_Removed_Files,
5965 Project.Project.Decl.Attributes, Data.Tree);
5968 -- If there are excluded sources, put them in the table
5970 if not Excluded_Sources.Default then
5971 if not Excluded_Source_List_File.Default then
5972 if Locally_Removed then
5975 "?both attributes Locally_Removed_Files and " &
5976 "Excluded_Source_List_File are present",
5977 Excluded_Source_List_File.Location, Project.Project);
5981 "?both attributes Excluded_Source_Files and " &
5982 "Excluded_Source_List_File are present",
5983 Excluded_Source_List_File.Location, Project.Project);
5987 Current := Excluded_Sources.Values;
5988 while Current /= Nil_String loop
5989 Element := Data.Tree.String_Elements.Table (Current);
5990 Name := Canonical_Case_File_Name (Element.Value);
5992 -- If the element has no location, then use the location of
5993 -- Excluded_Sources to report possible errors.
5995 if Element.Location = No_Location then
5996 Location := Excluded_Sources.Location;
5998 Location := Element.Location;
6001 Excluded_Sources_Htable.Set
6002 (Project.Excluded, Name, (Name, False, Location));
6003 Current := Element.Next;
6006 elsif not Excluded_Source_List_File.Default then
6007 Location := Excluded_Source_List_File.Location;
6010 Source_File_Path_Name : constant String :=
6013 (Excluded_Source_List_File.Value),
6014 Project.Project.Directory.Name);
6017 if Source_File_Path_Name'Length = 0 then
6018 Err_Vars.Error_Msg_File_1 :=
6019 File_Name_Type (Excluded_Source_List_File.Value);
6022 "file with excluded sources { does not exist",
6023 Excluded_Source_List_File.Location, Project.Project);
6028 Prj.Util.Open (File, Source_File_Path_Name);
6030 if not Prj.Util.Is_Valid (File) then
6032 (Data.Flags, "file does not exist",
6033 Location, Project.Project);
6035 -- Read the lines one by one
6037 while not Prj.Util.End_Of_File (File) loop
6038 Prj.Util.Get_Line (File, Line, Last);
6040 -- Non empty, non comment line should contain a file name
6043 and then (Last = 1 or else Line (1 .. 2) /= "--")
6046 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6047 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6050 -- Check that there is no directory information
6052 for J in 1 .. Last loop
6054 or else Line (J) = Directory_Separator
6056 Error_Msg_File_1 := Name;
6059 "file name cannot include " &
6060 "directory information ({)",
6061 Location, Project.Project);
6066 Excluded_Sources_Htable.Set
6067 (Project.Excluded, Name, (Name, False, Location));
6071 Prj.Util.Close (File);
6076 end Find_Excluded_Sources;
6082 procedure Find_Sources
6083 (Project : in out Project_Processing_Data;
6084 Data : in out Tree_Processing_Data)
6086 Sources : constant Variable_Value :=
6089 Project.Project.Decl.Attributes,
6092 Source_List_File : constant Variable_Value :=
6094 (Name_Source_List_File,
6095 Project.Project.Decl.Attributes,
6098 Name_Loc : Name_Location;
6099 Has_Explicit_Sources : Boolean;
6102 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
6104 (Source_List_File.Kind = Single,
6105 "Source_List_File is not a single string");
6107 Project.Source_List_File_Location := Source_List_File.Location;
6109 -- If the user has specified a Source_Files attribute
6111 if not Sources.Default then
6112 if not Source_List_File.Default then
6115 "?both attributes source_files and " &
6116 "source_list_file are present",
6117 Source_List_File.Location, Project.Project);
6120 -- Sources is a list of file names
6123 Current : String_List_Id := Sources.Values;
6124 Element : String_Element;
6125 Location : Source_Ptr;
6126 Name : File_Name_Type;
6129 if Current = Nil_String then
6130 Project.Project.Languages := No_Language_Index;
6132 -- This project contains no source. For projects that don't
6133 -- extend other projects, this also means that there is no
6134 -- need for an object directory, if not specified.
6136 if Project.Project.Extends = No_Project
6137 and then Project.Project.Object_Directory =
6138 Project.Project.Directory
6140 Project.Project.Object_Directory := No_Path_Information;
6144 while Current /= Nil_String loop
6145 Element := Data.Tree.String_Elements.Table (Current);
6146 Name := Canonical_Case_File_Name (Element.Value);
6147 Get_Name_String (Element.Value);
6149 -- If the element has no location, then use the location of
6150 -- Sources to report possible errors.
6152 if Element.Location = No_Location then
6153 Location := Sources.Location;
6155 Location := Element.Location;
6158 -- Check that there is no directory information
6160 for J in 1 .. Name_Len loop
6161 if Name_Buffer (J) = '/'
6162 or else Name_Buffer (J) = Directory_Separator
6164 Error_Msg_File_1 := Name;
6167 "file name cannot include directory " &
6169 Location, Project.Project);
6174 -- Check whether the file is already there: the same file name
6175 -- may be in the list. If the source is missing, the error will
6176 -- be on the first mention of the source file name.
6178 Name_Loc := Source_Names_Htable.Get
6179 (Project.Source_Names, Name);
6181 if Name_Loc = No_Name_Location then
6184 Location => Location,
6185 Source => No_Source,
6187 Source_Names_Htable.Set
6188 (Project.Source_Names, Name, Name_Loc);
6191 Current := Element.Next;
6194 Has_Explicit_Sources := True;
6197 -- If we have no Source_Files attribute, check the Source_List_File
6200 elsif not Source_List_File.Default then
6202 -- Source_List_File is the name of the file that contains the source
6206 Source_File_Path_Name : constant String :=
6208 (File_Name_Type (Source_List_File.Value),
6209 Project.Project.Directory.Name);
6212 Has_Explicit_Sources := True;
6214 if Source_File_Path_Name'Length = 0 then
6215 Err_Vars.Error_Msg_File_1 :=
6216 File_Name_Type (Source_List_File.Value);
6219 "file with sources { does not exist",
6220 Source_List_File.Location, Project.Project);
6223 Get_Sources_From_File
6224 (Source_File_Path_Name, Source_List_File.Location,
6230 -- Neither Source_Files nor Source_List_File has been specified. Find
6231 -- all the files that satisfy the naming scheme in all the source
6234 Has_Explicit_Sources := False;
6240 For_All_Sources => Sources.Default and then Source_List_File.Default);
6242 -- Check if all exceptions have been found.
6246 Iter : Source_Iterator;
6249 Iter := For_Each_Source (Data.Tree, Project.Project);
6251 Source := Prj.Element (Iter);
6252 exit when Source = No_Source;
6254 if Source.Naming_Exception
6255 and then Source.Path = No_Path_Information
6257 if Source.Unit /= No_Unit_Index then
6259 -- For multi-unit source files, source_id gets duplicated
6260 -- once for every unit. Only the first source_id got its
6261 -- full path set. So if it isn't set for that first one,
6262 -- the file wasn't found. Otherwise we need to update for
6263 -- units after the first one.
6266 or else Source.Index = 1
6268 Error_Msg_Name_1 := Name_Id (Source.Display_File);
6269 Error_Msg_Name_2 := Name_Id (Source.Unit.Name);
6272 "source file %% for unit %% not found",
6273 No_Location, Project.Project);
6276 Source.Path := Files_Htable.Get
6277 (Data.File_To_Source, Source.File).Path;
6279 if Current_Verbosity = High then
6280 if Source.Path /= No_Path_Information then
6281 Write_Line ("Setting full path for "
6282 & Get_Name_String (Source.File)
6283 & " at" & Source.Index'Img
6285 & Get_Name_String (Source.Path.Name));
6291 if Source.Path = No_Path_Information then
6292 Remove_Source (Source, No_Source);
6300 -- It is an error if a source file name in a source list or in a source
6301 -- list file is not found.
6303 if Has_Explicit_Sources then
6306 First_Error : Boolean;
6309 NL := Source_Names_Htable.Get_First (Project.Source_Names);
6310 First_Error := True;
6311 while NL /= No_Name_Location loop
6312 if not NL.Found then
6313 Err_Vars.Error_Msg_File_1 := NL.Name;
6318 "source file { not found",
6319 NL.Location, Project.Project);
6320 First_Error := False;
6325 "\source file { not found",
6326 NL.Location, Project.Project);
6330 NL := Source_Names_Htable.Get_Next (Project.Source_Names);
6340 procedure Initialize
6341 (Data : out Tree_Processing_Data;
6342 Tree : Project_Tree_Ref;
6343 Flags : Prj.Processing_Flags)
6346 Files_Htable.Reset (Data.File_To_Source);
6348 Data.Flags := Flags;
6355 procedure Free (Data : in out Tree_Processing_Data) is
6357 Files_Htable.Reset (Data.File_To_Source);
6364 procedure Initialize
6365 (Data : in out Project_Processing_Data;
6366 Project : Project_Id)
6369 Data.Project := Project;
6376 procedure Free (Data : in out Project_Processing_Data) is
6378 Source_Names_Htable.Reset (Data.Source_Names);
6379 Unit_Exceptions_Htable.Reset (Data.Unit_Exceptions);
6380 Excluded_Sources_Htable.Reset (Data.Excluded);
6383 -------------------------------
6384 -- Check_File_Naming_Schemes --
6385 -------------------------------
6387 procedure Check_File_Naming_Schemes
6388 (In_Tree : Project_Tree_Ref;
6389 Project : Project_Processing_Data;
6390 File_Name : File_Name_Type;
6391 Alternate_Languages : out Language_List;
6392 Language : out Language_Ptr;
6393 Display_Language_Name : out Name_Id;
6395 Lang_Kind : out Language_Kind;
6396 Kind : out Source_Kind)
6398 Filename : constant String := Get_Name_String (File_Name);
6399 Config : Language_Config;
6400 Tmp_Lang : Language_Ptr;
6402 Header_File : Boolean := False;
6403 -- True if we found at least one language for which the file is a header
6404 -- In such a case, we search for all possible languages where this is
6405 -- also a header (C and C++ for instance), since the file might be used
6406 -- for several such languages.
6408 procedure Check_File_Based_Lang;
6409 -- Does the naming scheme test for file-based languages. For those,
6410 -- there is no Unit. Just check if the file name has the implementation
6411 -- or, if it is specified, the template suffix of the language.
6413 -- Returns True if the file belongs to the current language and we
6414 -- should stop searching for matching languages. Not that a given header
6415 -- file could belong to several languages (C and C++ for instance). Thus
6416 -- if we found a header we'll check whether it matches other languages.
6418 ---------------------------
6419 -- Check_File_Based_Lang --
6420 ---------------------------
6422 procedure Check_File_Based_Lang is
6425 and then Suffix_Matches (Filename, Config.Naming_Data.Body_Suffix)
6429 Language := Tmp_Lang;
6431 if Current_Verbosity = High then
6432 Write_Str (" implementation of language ");
6433 Write_Line (Get_Name_String (Display_Language_Name));
6436 elsif Suffix_Matches (Filename, Config.Naming_Data.Spec_Suffix) then
6437 if Current_Verbosity = High then
6438 Write_Str (" header of language ");
6439 Write_Line (Get_Name_String (Display_Language_Name));
6443 Alternate_Languages := new Language_List_Element'
6444 (Language => Language,
6445 Next => Alternate_Languages);
6448 Header_File := True;
6451 Language := Tmp_Lang;
6454 end Check_File_Based_Lang;
6456 -- Start of processing for Check_File_Naming_Schemes
6459 Language := No_Language_Index;
6460 Alternate_Languages := null;
6461 Display_Language_Name := No_Name;
6463 Lang_Kind := File_Based;
6466 Tmp_Lang := Project.Project.Languages;
6467 while Tmp_Lang /= No_Language_Index loop
6468 if Current_Verbosity = High then
6470 (" Testing language "
6471 & Get_Name_String (Tmp_Lang.Name)
6472 & " Header_File=" & Header_File'Img);
6475 Display_Language_Name := Tmp_Lang.Display_Name;
6476 Config := Tmp_Lang.Config;
6477 Lang_Kind := Config.Kind;
6481 Check_File_Based_Lang;
6482 exit when Kind = Impl;
6486 -- We know it belongs to a least a file_based language, no
6487 -- need to check unit-based ones.
6489 if not Header_File then
6491 (File_Name => File_Name,
6492 Naming => Config.Naming_Data,
6496 In_Tree => In_Tree);
6498 if Unit /= No_Name then
6499 Language := Tmp_Lang;
6505 Tmp_Lang := Tmp_Lang.Next;
6508 if Language = No_Language_Index
6509 and then Current_Verbosity = High
6511 Write_Line (" not a source of any language");
6513 end Check_File_Naming_Schemes;
6519 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind) is
6521 -- If the file was previously already associated with a unit, change it
6523 if Source.Unit /= null
6524 and then Source.Kind in Spec_Or_Body
6525 and then Source.Unit.File_Names (Source.Kind) /= null
6527 -- If we had another file referencing the same unit (for instance it
6528 -- was in an extended project), that source file is in fact invisible
6529 -- from now on, and in particular doesn't belong to the same unit.
6531 if Source.Unit.File_Names (Source.Kind) /= Source then
6532 Source.Unit.File_Names (Source.Kind).Unit := No_Unit_Index;
6535 Source.Unit.File_Names (Source.Kind) := null;
6538 Source.Kind := Kind;
6540 if Source.Kind in Spec_Or_Body and then Source.Unit /= null then
6541 Source.Unit.File_Names (Source.Kind) := Source;
6549 procedure Check_File
6550 (Project : in out Project_Processing_Data;
6551 Data : in out Tree_Processing_Data;
6552 Path : Path_Name_Type;
6553 File_Name : File_Name_Type;
6554 Display_File_Name : File_Name_Type;
6555 Locally_Removed : Boolean;
6556 For_All_Sources : Boolean)
6558 Canonical_Path : constant Path_Name_Type :=
6560 (Canonical_Case_File_Name (Name_Id (Path)));
6562 Name_Loc : Name_Location :=
6563 Source_Names_Htable.Get
6564 (Project.Source_Names, File_Name);
6565 Check_Name : Boolean := False;
6566 Alternate_Languages : Language_List;
6567 Language : Language_Ptr;
6569 Src_Ind : Source_File_Index;
6571 Display_Language_Name : Name_Id;
6572 Lang_Kind : Language_Kind;
6573 Kind : Source_Kind := Spec;
6576 if Name_Loc = No_Name_Location then
6577 Check_Name := For_All_Sources;
6580 if Name_Loc.Found then
6582 -- Check if it is OK to have the same file name in several
6583 -- source directories.
6585 if not Project.Project.Known_Order_Of_Source_Dirs then
6586 Error_Msg_File_1 := File_Name;
6589 "{ is found in several source directories",
6590 Name_Loc.Location, Project.Project);
6594 Name_Loc.Found := True;
6596 Source_Names_Htable.Set
6597 (Project.Source_Names, File_Name, Name_Loc);
6599 if Name_Loc.Source = No_Source then
6603 Name_Loc.Source.Path := (Canonical_Path, Path);
6605 Source_Paths_Htable.Set
6606 (Data.Tree.Source_Paths_HT,
6610 -- Check if this is a subunit
6612 if Name_Loc.Source.Unit /= No_Unit_Index
6613 and then Name_Loc.Source.Kind = Impl
6615 Src_Ind := Sinput.P.Load_Project_File
6616 (Get_Name_String (Canonical_Path));
6618 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
6619 Override_Kind (Name_Loc.Source, Sep);
6624 (Data.File_To_Source, File_Name, Name_Loc.Source);
6630 Check_File_Naming_Schemes
6631 (In_Tree => Data.Tree,
6633 File_Name => File_Name,
6634 Alternate_Languages => Alternate_Languages,
6635 Language => Language,
6636 Display_Language_Name => Display_Language_Name,
6638 Lang_Kind => Lang_Kind,
6641 if Language = No_Language_Index then
6643 -- A file name in a list must be a source of a language
6645 if Data.Flags.Error_On_Unknown_Language
6646 and then Name_Loc.Found
6648 Error_Msg_File_1 := File_Name;
6651 "language unknown for {",
6652 Name_Loc.Location, Project.Project);
6658 Project => Project.Project,
6659 Lang_Id => Language,
6662 Alternate_Languages => Alternate_Languages,
6663 File_Name => File_Name,
6664 Display_File => Display_File_Name,
6666 Locally_Removed => Locally_Removed,
6667 Path => (Canonical_Path, Path));
6672 ------------------------
6673 -- Search_Directories --
6674 ------------------------
6676 procedure Search_Directories
6677 (Project : in out Project_Processing_Data;
6678 Data : in out Tree_Processing_Data;
6679 For_All_Sources : Boolean)
6681 Source_Dir : String_List_Id;
6682 Element : String_Element;
6684 Name : String (1 .. 1_000);
6686 File_Name : File_Name_Type;
6687 Display_File_Name : File_Name_Type;
6690 if Current_Verbosity = High then
6691 Write_Line ("Looking for sources:");
6694 -- Loop through subdirectories
6696 Source_Dir := Project.Project.Source_Dirs;
6697 while Source_Dir /= Nil_String loop
6699 Element := Data.Tree.String_Elements.Table (Source_Dir);
6700 if Element.Value /= No_Name then
6701 Get_Name_String (Element.Display_Value);
6704 Source_Directory : constant String :=
6705 Name_Buffer (1 .. Name_Len) &
6706 Directory_Separator;
6708 Dir_Last : constant Natural :=
6709 Compute_Directory_Last
6713 if Current_Verbosity = High then
6714 Write_Attr ("Source_Dir", Source_Directory);
6717 -- We look to every entry in the source directory
6719 Open (Dir, Source_Directory);
6722 Read (Dir, Name, Last);
6726 -- ??? Duplicate system call here, we just did a a
6727 -- similar one. Maybe Ada.Directories would be more
6728 -- appropriate here.
6731 (Source_Directory & Name (1 .. Last))
6733 if Current_Verbosity = High then
6734 Write_Str (" Checking ");
6735 Write_Line (Name (1 .. Last));
6739 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
6740 Display_File_Name := Name_Find;
6742 if Osint.File_Names_Case_Sensitive then
6743 File_Name := Display_File_Name;
6745 Canonical_Case_File_Name
6746 (Name_Buffer (1 .. Name_Len));
6747 File_Name := Name_Find;
6751 Path_Name : constant String :=
6756 (Source_Directory'First ..
6759 Opt.Follow_Links_For_Files,
6760 Case_Sensitive => True);
6761 -- Case_Sensitive set True (no folding)
6763 Path : Path_Name_Type;
6764 FF : File_Found := Excluded_Sources_Htable.Get
6765 (Project.Excluded, File_Name);
6766 To_Remove : Boolean := False;
6769 Name_Len := Path_Name'Length;
6770 Name_Buffer (1 .. Name_Len) := Path_Name;
6773 if FF /= No_File_Found then
6774 if not FF.Found then
6776 Excluded_Sources_Htable.Set
6777 (Project.Excluded, File_Name, FF);
6779 if Current_Verbosity = High then
6780 Write_Str (" excluded source """);
6781 Write_Str (Get_Name_String (File_Name));
6785 -- Will mark the file as removed, but we
6786 -- still need to add it to the list: if we
6787 -- don't, the file will not appear in the
6788 -- mapping file and will cause the compiler
6796 (Project => Project,
6799 File_Name => File_Name,
6800 Locally_Removed => To_Remove,
6801 Display_File_Name => Display_File_Name,
6802 For_All_Sources => For_All_Sources);
6812 when Directory_Error =>
6816 Source_Dir := Element.Next;
6819 if Current_Verbosity = High then
6820 Write_Line ("end Looking for sources.");
6822 end Search_Directories;
6824 ----------------------------
6825 -- Load_Naming_Exceptions --
6826 ----------------------------
6828 procedure Load_Naming_Exceptions
6829 (Project : in out Project_Processing_Data;
6830 Data : in out Tree_Processing_Data)
6833 Iter : Source_Iterator;
6836 Iter := For_Each_Source (Data.Tree, Project.Project);
6838 Source := Prj.Element (Iter);
6839 exit when Source = No_Source;
6841 -- An excluded file cannot also be an exception file name
6843 if Excluded_Sources_Htable.Get (Project.Excluded, Source.File) /=
6846 Error_Msg_File_1 := Source.File;
6849 "{ cannot be both excluded and an exception file name",
6850 No_Location, Project.Project);
6853 if Current_Verbosity = High then
6854 Write_Str ("Naming exception: Putting source file ");
6855 Write_Str (Get_Name_String (Source.File));
6856 Write_Line (" in Source_Names");
6859 Source_Names_Htable.Set
6860 (Project.Source_Names,
6863 (Name => Source.File,
6864 Location => No_Location,
6868 -- If this is an Ada exception, record in table Unit_Exceptions
6870 if Source.Unit /= No_Unit_Index then
6872 Unit_Except : Unit_Exception :=
6873 Unit_Exceptions_Htable.Get
6874 (Project.Unit_Exceptions, Source.Unit.Name);
6877 Unit_Except.Name := Source.Unit.Name;
6879 if Source.Kind = Spec then
6880 Unit_Except.Spec := Source.File;
6882 Unit_Except.Impl := Source.File;
6885 Unit_Exceptions_Htable.Set
6886 (Project.Unit_Exceptions, Source.Unit.Name, Unit_Except);
6892 end Load_Naming_Exceptions;
6894 ----------------------
6895 -- Look_For_Sources --
6896 ----------------------
6898 procedure Look_For_Sources
6899 (Project : in out Project_Processing_Data;
6900 Data : in out Tree_Processing_Data)
6902 Object_Files : Object_File_Names_Htable.Instance;
6903 Iter : Source_Iterator;
6906 procedure Check_Object (Src : Source_Id);
6907 -- Check if object file name of Src is already used in the project tree,
6908 -- and report an error if so.
6910 procedure Check_Object_Files;
6911 -- Check that no two sources of this project have the same object file
6913 procedure Mark_Excluded_Sources;
6914 -- Mark as such the sources that are declared as excluded
6920 procedure Check_Object (Src : Source_Id) is
6924 Source := Object_File_Names_Htable.Get (Object_Files, Src.Object);
6926 -- We cannot just check on "Source /= Src", since we might have
6927 -- two different entries for the same file (and since that's
6928 -- the same file it is expected that it has the same object)
6930 if Source /= No_Source
6931 and then Source.Path /= Src.Path
6933 Error_Msg_File_1 := Src.File;
6934 Error_Msg_File_2 := Source.File;
6937 "{ and { have the same object file name",
6938 No_Location, Project.Project);
6941 Object_File_Names_Htable.Set (Object_Files, Src.Object, Src);
6945 ---------------------------
6946 -- Mark_Excluded_Sources --
6947 ---------------------------
6949 procedure Mark_Excluded_Sources is
6950 Source : Source_Id := No_Source;
6951 Excluded : File_Found;
6955 -- Minor optimization: if there are no excluded files, no need to
6956 -- traverse the list of sources. We cannot however also check whether
6957 -- the existing exceptions have ".Found" set to True (indicating we
6958 -- found them before) because we need to do some final processing on
6959 -- them in any case.
6961 if Excluded_Sources_Htable.Get_First (Project.Excluded) /=
6964 Proj := Project.Project;
6965 while Proj /= No_Project loop
6966 Iter := For_Each_Source (Data.Tree, Proj);
6967 while Prj.Element (Iter) /= No_Source loop
6968 Source := Prj.Element (Iter);
6969 Excluded := Excluded_Sources_Htable.Get
6970 (Project.Excluded, Source.File);
6972 if Excluded /= No_File_Found then
6973 Source.Locally_Removed := True;
6974 Source.In_Interfaces := False;
6976 if Current_Verbosity = High then
6977 Write_Str ("Removing file ");
6979 (Get_Name_String (Excluded.File)
6980 & " " & Get_Name_String (Source.Project.Name));
6983 Excluded_Sources_Htable.Remove
6984 (Project.Excluded, Source.File);
6990 Proj := Proj.Extends;
6994 -- If we have any excluded element left, that means we did not find
6997 Excluded := Excluded_Sources_Htable.Get_First (Project.Excluded);
6998 while Excluded /= No_File_Found loop
6999 if not Excluded.Found then
7001 -- Check if the file belongs to another imported project to
7002 -- provide a better error message.
7005 (In_Tree => Data.Tree,
7006 Project => Project.Project,
7007 In_Imported_Only => True,
7008 Base_Name => Excluded.File);
7010 Err_Vars.Error_Msg_File_1 := Excluded.File;
7012 if Src = No_Source then
7015 "unknown file {", Excluded.Location, Project.Project);
7019 "cannot remove a source from an imported project: {",
7020 Excluded.Location, Project.Project);
7024 Excluded := Excluded_Sources_Htable.Get_Next (Project.Excluded);
7026 end Mark_Excluded_Sources;
7028 ------------------------
7029 -- Check_Object_Files --
7030 ------------------------
7032 procedure Check_Object_Files is
7033 Iter : Source_Iterator;
7035 Src_Ind : Source_File_Index;
7038 Iter := For_Each_Source (Data.Tree);
7040 Src_Id := Prj.Element (Iter);
7041 exit when Src_Id = No_Source;
7043 if Is_Compilable (Src_Id)
7044 and then Src_Id.Language.Config.Object_Generated
7045 and then Is_Extending (Project.Project, Src_Id.Project)
7047 if Src_Id.Unit = No_Unit_Index then
7048 if Src_Id.Kind = Impl then
7049 Check_Object (Src_Id);
7055 if Other_Part (Src_Id) = No_Source then
7056 Check_Object (Src_Id);
7063 if Other_Part (Src_Id) /= No_Source then
7064 Check_Object (Src_Id);
7067 -- Check if it is a subunit
7070 Sinput.P.Load_Project_File
7071 (Get_Name_String (Src_Id.Path.Name));
7073 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7074 Override_Kind (Src_Id, Sep);
7076 Check_Object (Src_Id);
7085 end Check_Object_Files;
7087 -- Start of processing for Look_For_Sources
7090 Find_Excluded_Sources (Project, Data);
7092 if Project.Project.Languages /= No_Language_Index then
7093 Load_Naming_Exceptions (Project, Data);
7094 Find_Sources (Project, Data);
7095 Mark_Excluded_Sources;
7099 Object_File_Names_Htable.Reset (Object_Files);
7100 end Look_For_Sources;
7106 function Path_Name_Of
7107 (File_Name : File_Name_Type;
7108 Directory : Path_Name_Type) return String
7110 Result : String_Access;
7111 The_Directory : constant String := Get_Name_String (Directory);
7114 Get_Name_String (File_Name);
7117 (File_Name => Name_Buffer (1 .. Name_Len),
7118 Path => The_Directory);
7120 if Result = null then
7124 R : String := Result.all;
7127 Canonical_Case_File_Name (R);
7137 procedure Remove_Source
7139 Replaced_By : Source_Id)
7144 if Current_Verbosity = High then
7145 Write_Str ("Removing source ");
7146 Write_Line (Get_Name_String (Id.File) & " at" & Id.Index'Img);
7149 if Replaced_By /= No_Source then
7150 Id.Replaced_By := Replaced_By;
7151 Replaced_By.Declared_In_Interfaces := Id.Declared_In_Interfaces;
7154 Id.In_Interfaces := False;
7155 Id.Locally_Removed := True;
7157 -- ??? Should we remove the source from the unit ? The file is not used,
7158 -- so probably should not be referenced from the unit. On the other hand
7159 -- it might give useful additional info
7160 -- if Id.Unit /= null then
7161 -- Id.Unit.File_Names (Id.Kind) := null;
7164 Source := Id.Language.First_Source;
7167 Id.Language.First_Source := Id.Next_In_Lang;
7170 while Source.Next_In_Lang /= Id loop
7171 Source := Source.Next_In_Lang;
7174 Source.Next_In_Lang := Id.Next_In_Lang;
7178 -----------------------
7179 -- Report_No_Sources --
7180 -----------------------
7182 procedure Report_No_Sources
7183 (Project : Project_Id;
7185 Data : Tree_Processing_Data;
7186 Location : Source_Ptr;
7187 Continuation : Boolean := False)
7190 case Data.Flags.When_No_Sources is
7194 when Warning | Error =>
7196 Msg : constant String :=
7199 " sources in this project";
7202 Error_Msg_Warn := Data.Flags.When_No_Sources = Warning;
7204 if Continuation then
7205 Error_Msg (Data.Flags, "\" & Msg, Location, Project);
7207 Error_Msg (Data.Flags, Msg, Location, Project);
7211 end Report_No_Sources;
7213 ----------------------
7214 -- Show_Source_Dirs --
7215 ----------------------
7217 procedure Show_Source_Dirs
7218 (Project : Project_Id;
7219 In_Tree : Project_Tree_Ref)
7221 Current : String_List_Id;
7222 Element : String_Element;
7225 Write_Line ("Source_Dirs:");
7227 Current := Project.Source_Dirs;
7228 while Current /= Nil_String loop
7229 Element := In_Tree.String_Elements.Table (Current);
7231 Write_Line (Get_Name_String (Element.Value));
7232 Current := Element.Next;
7235 Write_Line ("end Source_Dirs.");
7236 end Show_Source_Dirs;
7238 ---------------------------
7239 -- Process_Naming_Scheme --
7240 ---------------------------
7242 procedure Process_Naming_Scheme
7243 (Tree : Project_Tree_Ref;
7244 Root_Project : Project_Id;
7245 Flags : Processing_Flags)
7247 procedure Recursive_Check
7248 (Project : Project_Id;
7249 Data : in out Tree_Processing_Data);
7250 -- Check_Naming_Scheme for the project
7252 ---------------------
7253 -- Recursive_Check --
7254 ---------------------
7256 procedure Recursive_Check
7257 (Project : Project_Id;
7258 Data : in out Tree_Processing_Data)
7261 if Verbose_Mode then
7262 Write_Str ("Processing_Naming_Scheme for project """);
7263 Write_Str (Get_Name_String (Project.Name));
7267 Prj.Nmsc.Check (Project, Data);
7268 end Recursive_Check;
7270 procedure Check_All_Projects is new
7271 For_Every_Project_Imported (Tree_Processing_Data, Recursive_Check);
7273 Data : Tree_Processing_Data;
7275 -- Start of processing for Process_Naming_Scheme
7277 Initialize (Data, Tree => Tree, Flags => Flags);
7278 Check_All_Projects (Root_Project, Data, Imported_First => True);
7280 end Process_Naming_Scheme;