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;
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 Location : Source_Ptr := No_Location);
205 -- Add a new source to the different lists: list of all sources in the
206 -- project tree, list of source of a project and list of sources of a
209 -- If Path is specified, the file is also added to Source_Paths_HT.
211 -- Location is used for error messages
213 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type;
214 -- Same as Osint.Canonical_Case_File_Name but applies to Name_Id.
215 -- This alters Name_Buffer
217 function Suffix_Matches
219 Suffix : File_Name_Type) return Boolean;
220 -- True if the file name ends with the given suffix. Always returns False
221 -- if Suffix is No_Name.
223 procedure Replace_Into_Name_Buffer
226 Replacement : Character);
227 -- Copy Str into Name_Buffer, replacing Pattern with Replacement. Str is
228 -- converted to lower-case at the same time.
230 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
231 -- Check that a name is a valid Ada unit name
233 procedure Check_Package_Naming
234 (Project : Project_Id;
235 Data : in out Tree_Processing_Data;
236 Bodies : out Array_Element_Id;
237 Specs : out Array_Element_Id);
238 -- Check the naming scheme part of Data, and initialize the naming scheme
239 -- data in the config of the various languages. This also returns the
240 -- naming scheme exceptions for unit-based languages (Bodies and Specs are
241 -- associative arrays mapping individual unit names to source file names).
243 procedure Check_Configuration
244 (Project : Project_Id;
245 Data : in out Tree_Processing_Data);
246 -- Check the configuration attributes for the project
248 procedure Check_If_Externally_Built
249 (Project : Project_Id;
250 Data : in out Tree_Processing_Data);
251 -- Check attribute Externally_Built of project Project in project tree
252 -- Data.Tree and modify its data Data if it has the value "true".
254 procedure Check_Interfaces
255 (Project : Project_Id;
256 Data : in out Tree_Processing_Data);
257 -- If a list of sources is specified in attribute Interfaces, set
258 -- In_Interfaces only for the sources specified in the list.
260 procedure Check_Library_Attributes
261 (Project : Project_Id;
262 Data : in out Tree_Processing_Data);
263 -- Check the library attributes of project Project in project tree
264 -- and modify its data Data accordingly.
266 procedure Check_Programming_Languages
267 (Project : Project_Id;
268 Data : in out Tree_Processing_Data);
269 -- Check attribute Languages for the project with data Data in project
270 -- tree Data.Tree and set the components of Data for all the programming
271 -- languages indicated in attribute Languages, if any.
273 procedure Check_Stand_Alone_Library
274 (Project : Project_Id;
275 Data : in out Tree_Processing_Data);
276 -- Check if project Project in project tree Data.Tree is a Stand-Alone
277 -- Library project, and modify its data Data accordingly if it is one.
279 function Compute_Directory_Last (Dir : String) return Natural;
280 -- Return the index of the last significant character in Dir. This is used
281 -- to avoid duplicate '/' (slash) characters at the end of directory names.
284 (Project : Project_Id;
286 Flag_Location : Source_Ptr;
287 Data : Tree_Processing_Data);
288 -- Output an error message. If Data.Error_Report is null, simply call
289 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
291 -- If Msg starts with "?", this is a warning, and Warning: is adding at the
292 -- beginning. If Msg starts with "<", see comment
293 -- for Err_Vars.Error_Msg_Warn
295 procedure Search_Directories
296 (Project : in out Project_Processing_Data;
297 Data : in out Tree_Processing_Data;
298 For_All_Sources : Boolean);
299 -- Search the source directories to find the sources. If For_All_Sources is
300 -- True, check each regular file name against the naming schemes of the
301 -- different languages. Otherwise consider only the file names in the hash
302 -- table Source_Names. If Allow_Duplicate_Basenames, then files with the
303 -- same base names are authorized within a project for source-based
304 -- languages (never for unit based languages)
307 (Project : in out Project_Processing_Data;
308 Data : in out Tree_Processing_Data;
309 Path : Path_Name_Type;
310 File_Name : File_Name_Type;
311 Display_File_Name : File_Name_Type;
312 Locally_Removed : Boolean;
313 For_All_Sources : Boolean);
314 -- Check if file File_Name is a valid source of the project. This is used
315 -- in multi-language mode only. When the file matches one of the naming
316 -- schemes, it is added to various htables through Add_Source and to
317 -- Source_Paths_Htable.
319 -- Name is the name of the candidate file. It hasn't been normalized yet
320 -- and is the direct result of readdir().
322 -- File_Name is the same as Name, but has been normalized.
323 -- Display_File_Name, however, has not been normalized.
325 -- Source_Directory is the directory in which the file
326 -- was found. It hasn't been normalized (nor has had links resolved).
327 -- It should not end with a directory separator, to avoid duplicates
330 -- If For_All_Sources is True, then all possible file names are analyzed
331 -- otherwise only those currently set in the Source_Names htable.
333 procedure Check_File_Naming_Schemes
334 (In_Tree : Project_Tree_Ref;
335 Project : Project_Processing_Data;
336 File_Name : File_Name_Type;
337 Alternate_Languages : out Language_List;
338 Language : out Language_Ptr;
339 Display_Language_Name : out Name_Id;
341 Lang_Kind : out Language_Kind;
342 Kind : out Source_Kind);
343 -- Check if the file name File_Name conforms to one of the naming schemes
344 -- of the project. If the file does not match one of the naming schemes,
345 -- set Language to No_Language_Index. Filename is the name of the file
346 -- being investigated. It has been normalized (case-folded). File_Name is
349 procedure Get_Directories
350 (Project : Project_Id;
351 Data : in out Tree_Processing_Data);
352 -- Get the object directory, the exec directory and the source directories
356 (Project : Project_Id;
357 Data : in out Tree_Processing_Data);
358 -- Get the mains of a project from attribute Main, if it exists, and put
359 -- them in the project data.
361 procedure Get_Sources_From_File
363 Location : Source_Ptr;
364 Project : in out Project_Processing_Data;
365 Data : in out Tree_Processing_Data);
366 -- Get the list of sources from a text file and put them in hash table
369 procedure Find_Sources
370 (Project : in out Project_Processing_Data;
371 Data : in out Tree_Processing_Data);
372 -- Process the Source_Files and Source_List_File attributes, and store the
373 -- list of source files into the Source_Names htable. When these attributes
374 -- are not defined, find all files matching the naming schemes in the
375 -- source directories. If Allow_Duplicate_Basenames, then files with the
376 -- same base names are authorized within a project for source-based
377 -- languages (never for unit based languages)
379 procedure Compute_Unit_Name
380 (File_Name : File_Name_Type;
381 Naming : Lang_Naming_Data;
382 Kind : out Source_Kind;
384 Project : Project_Processing_Data;
385 In_Tree : Project_Tree_Ref);
386 -- Check whether the file matches the naming scheme. If it does,
387 -- compute its unit name. If Unit is set to No_Name on exit, none of the
388 -- other out parameters are relevant.
390 procedure Check_Illegal_Suffix
391 (Project : Project_Id;
392 Suffix : File_Name_Type;
393 Dot_Replacement : File_Name_Type;
394 Attribute_Name : String;
395 Location : Source_Ptr;
396 Data : in out Tree_Processing_Data);
397 -- Display an error message if the given suffix is illegal for some reason.
398 -- The name of the attribute we are testing is specified in Attribute_Name,
399 -- which is used in the error message. Location is the location where the
400 -- suffix is defined.
402 procedure Locate_Directory
403 (Project : Project_Id;
404 Name : File_Name_Type;
405 Path : out Path_Information;
406 Dir_Exists : out Boolean;
407 Data : in out Tree_Processing_Data;
408 Create : String := "";
409 Location : Source_Ptr := No_Location;
410 Must_Exist : Boolean := True;
411 Externally_Built : Boolean := False);
412 -- Locate a directory. Name is the directory name. Relative paths are
413 -- resolved relative to the project's directory. If the directory does not
414 -- exist and Setup_Projects is True and Create is a non null string, an
415 -- attempt is made to create the directory. If the directory does not
416 -- exist, it is either created if Setup_Projects is False (and then
417 -- returned), or simply returned without checking for its existence (if
418 -- Must_Exist is False) or No_Path_Information is returned. In all cases,
419 -- Dir_Exists indicates whether the directory now exists. Create is also
420 -- used for debugging traces to show which path we are computing.
422 procedure Look_For_Sources
423 (Project : in out Project_Processing_Data;
424 Data : in out Tree_Processing_Data);
425 -- Find all the sources of project Project in project tree Data.Tree and
426 -- update its Data accordingly. This assumes that Data.First_Source has
427 -- been initialized with the list of excluded sources and special naming
430 function Path_Name_Of
431 (File_Name : File_Name_Type;
432 Directory : Path_Name_Type) return String;
433 -- Returns the path name of a (non project) file. Returns an empty string
434 -- if file cannot be found.
436 procedure Remove_Source
438 Replaced_By : Source_Id);
439 -- Remove a file from the list of sources of a project. This might be
440 -- because the file is replaced by another one in an extending project,
441 -- or because a file was added as a naming exception but was not found
444 procedure Report_No_Sources
445 (Project : Project_Id;
447 Data : Tree_Processing_Data;
448 Location : Source_Ptr;
449 Continuation : Boolean := False);
450 -- Report an error or a warning depending on the value of When_No_Sources
451 -- when there are no sources for language Lang_Name.
453 procedure Show_Source_Dirs
454 (Project : Project_Id; In_Tree : Project_Tree_Ref);
455 -- List all the source directories of a project
457 procedure Write_Attr (Name, Value : String);
458 -- Debug print a value for a specific property. Does nothing when not in
461 ------------------------------
462 -- Replace_Into_Name_Buffer --
463 ------------------------------
465 procedure Replace_Into_Name_Buffer
468 Replacement : Character)
470 Max : constant Integer := Str'Last - Pattern'Length + 1;
477 while J <= Str'Last loop
478 Name_Len := Name_Len + 1;
481 and then Str (J .. J + Pattern'Length - 1) = Pattern
483 Name_Buffer (Name_Len) := Replacement;
484 J := J + Pattern'Length;
487 Name_Buffer (Name_Len) := GNAT.Case_Util.To_Lower (Str (J));
491 end Replace_Into_Name_Buffer;
497 function Suffix_Matches
499 Suffix : File_Name_Type) return Boolean
501 Min_Prefix_Length : Natural := 0;
504 if Suffix = No_File or else Suffix = Empty_File then
509 Suf : constant String := Get_Name_String (Suffix);
512 -- The file name must end with the suffix (which is not an extension)
513 -- For instance a suffix "configure.in" must match a file with the
514 -- same name. To avoid dummy cases, though, a suffix starting with
515 -- '.' requires a file that is at least one character longer ('.cpp'
516 -- should not match a file with the same name)
518 if Suf (Suf'First) = '.' then
519 Min_Prefix_Length := 1;
522 return Filename'Length >= Suf'Length + Min_Prefix_Length
524 (Filename'Last - Suf'Length + 1 .. Filename'Last) = Suf;
532 procedure Write_Attr (Name, Value : String) is
534 if Current_Verbosity = High then
535 Write_Str (" " & Name & " = """);
548 Data : in out Tree_Processing_Data;
549 Project : Project_Id;
550 Lang_Id : Language_Ptr;
552 File_Name : File_Name_Type;
553 Display_File : File_Name_Type;
554 Naming_Exception : Boolean := False;
555 Path : Path_Information := No_Path_Information;
556 Alternate_Languages : Language_List := null;
557 Unit : Name_Id := No_Name;
559 Location : Source_Ptr := No_Location)
561 Config : constant Language_Config := Lang_Id.Config;
565 Prev_Unit : Unit_Index := No_Unit_Index;
566 Source_To_Replace : Source_Id := No_Source;
569 -- Check if the same file name or unit is used in the prj tree
573 if Unit /= No_Name then
574 Prev_Unit := Units_Htable.Get (Data.Tree.Units_HT, Unit);
577 if Prev_Unit /= No_Unit_Index
578 and then (Kind = Impl or Kind = Spec)
579 and then Prev_Unit.File_Names (Kind) /= null
581 -- Suspicious, we need to check later whether this is authorized
584 Source := Prev_Unit.File_Names (Kind);
587 Source := Files_Htable.Get (Data.File_To_Source, File_Name);
589 if Source /= No_Source
590 and then Source.Index = Index
596 -- Duplication of file/unit in same project is allowed if order of
597 -- source directories is known.
599 if Add_Src = False then
602 if Project = Source.Project then
603 if Prev_Unit = No_Unit_Index then
604 if Data.Flags.Allow_Duplicate_Basenames then
607 elsif Project.Known_Order_Of_Source_Dirs then
611 Error_Msg_File_1 := File_Name;
613 (Project, "duplicate source file name {",
619 if Project.Known_Order_Of_Source_Dirs then
622 -- We might be seeing the same file through a different path
623 -- (for instance because of symbolic links).
625 elsif Source.Path.Name /= Path.Name then
626 Error_Msg_Name_1 := Unit;
628 (Project, "duplicate unit %%", Location, Data);
633 -- Do not allow the same unit name in different projects,
634 -- except if one is extending the other.
636 -- For a file based language, the same file name replaces
637 -- a file in a project being extended, but it is allowed
638 -- to have the same file name in unrelated projects.
640 elsif Is_Extending (Project, Source.Project) then
641 Source_To_Replace := Source;
643 elsif Prev_Unit /= No_Unit_Index
644 and then not Source.Locally_Removed
646 -- Path is set if this is a source we found on the disk, in which
647 -- case we can provide more explicit error message. Path is unset
648 -- when the source is added from one of the naming exceptions in
651 if Path /= No_Path_Information then
652 Error_Msg_Name_1 := Unit;
655 "unit %% cannot belong to several projects",
658 Error_Msg_Name_1 := Project.Name;
659 Error_Msg_Name_2 := Name_Id (Path.Name);
661 (Project, "\ project %%, %%", Location, Data);
663 Error_Msg_Name_1 := Source.Project.Name;
664 Error_Msg_Name_2 := Name_Id (Source.Path.Display_Name);
666 (Project, "\ project %%, %%", Location, Data);
669 Error_Msg_Name_1 := Unit;
670 Error_Msg_Name_2 := Source.Project.Name;
672 (Project, "unit %% already belongs to project %%",
678 elsif not Source.Locally_Removed
679 and then not Data.Flags.Allow_Duplicate_Basenames
680 and then Lang_Id.Config.Kind = Unit_Based
682 Error_Msg_File_1 := File_Name;
683 Error_Msg_File_2 := File_Name_Type (Source.Project.Name);
686 "{ is already a source of project {", Location, Data);
688 -- Add the file anyway, to avoid further warnings like "language
701 Id := new Source_Data;
703 if Current_Verbosity = High then
704 Write_Str ("Adding source File: ");
705 Write_Str (Get_Name_String (File_Name));
708 Write_Str (" at" & Index'Img);
711 if Lang_Id.Config.Kind = Unit_Based then
712 Write_Str (" Unit: ");
714 -- ??? in gprclean, it seems we sometimes pass an empty Unit name
715 -- (see test extended_projects).
717 if Unit /= No_Name then
718 Write_Str (Get_Name_String (Unit));
721 Write_Str (" Kind: ");
722 Write_Str (Source_Kind'Image (Kind));
728 Id.Project := Project;
729 Id.Language := Lang_Id;
731 Id.Alternate_Languages := Alternate_Languages;
733 -- Add the source id to the Unit_Sources_HT hash table, if the unit name
736 if Unit /= No_Name then
737 UData := Units_Htable.Get (Data.Tree.Units_HT, Unit);
739 if UData = No_Unit_Index then
740 UData := new Unit_Data;
742 Units_Htable.Set (Data.Tree.Units_HT, Unit, UData);
747 -- Note that this updates Unit information as well
749 Override_Kind (Id, Kind);
753 Id.File := File_Name;
754 Id.Display_File := Display_File;
755 Id.Dep_Name := Dependency_Name
756 (File_Name, Lang_Id.Config.Dependency_Kind);
757 Id.Naming_Exception := Naming_Exception;
759 if Is_Compilable (Id) and then Config.Object_Generated then
760 Id.Object := Object_Name (File_Name, Config.Object_File_Suffix);
761 Id.Switches := Switches_Name (File_Name);
764 if Path /= No_Path_Information then
766 Source_Paths_Htable.Set (Data.Tree.Source_Paths_HT, Path.Name, Id);
769 -- Add the source to the language list
771 Id.Next_In_Lang := Lang_Id.First_Source;
772 Lang_Id.First_Source := Id;
774 if Source_To_Replace /= No_Source then
775 Remove_Source (Source_To_Replace, Id);
778 Files_Htable.Set (Data.File_To_Source, File_Name, Id);
781 ------------------------------
782 -- Canonical_Case_File_Name --
783 ------------------------------
785 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type is
787 if Osint.File_Names_Case_Sensitive then
788 return File_Name_Type (Name);
790 Get_Name_String (Name);
791 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
794 end Canonical_Case_File_Name;
801 (Project : Project_Id;
802 Data : in out Tree_Processing_Data)
804 Specs : Array_Element_Id;
805 Bodies : Array_Element_Id;
806 Extending : Boolean := False;
807 Prj_Data : Project_Processing_Data;
810 Initialize (Prj_Data, Project);
812 Check_If_Externally_Built (Project, Data);
814 -- Object, exec and source directories
816 Get_Directories (Project, Data);
818 -- Get the programming languages
820 Check_Programming_Languages (Project, Data);
822 if Project.Qualifier = Dry
823 and then Project.Source_Dirs /= Nil_String
826 Source_Dirs : constant Variable_Value :=
829 Project.Decl.Attributes, Data.Tree);
830 Source_Files : constant Variable_Value :=
833 Project.Decl.Attributes, Data.Tree);
834 Source_List_File : constant Variable_Value :=
836 (Name_Source_List_File,
837 Project.Decl.Attributes, Data.Tree);
838 Languages : constant Variable_Value :=
841 Project.Decl.Attributes, Data.Tree);
844 if Source_Dirs.Values = Nil_String
845 and then Source_Files.Values = Nil_String
846 and then Languages.Values = Nil_String
847 and then Source_List_File.Default
849 Project.Source_Dirs := Nil_String;
854 "at least one of Source_Files, Source_Dirs or Languages "
855 & "must be declared empty for an abstract project",
856 Project.Location, Data);
861 -- Check configuration. This must be done even for gnatmake (even though
862 -- no user configuration file was provided) since the default config we
863 -- generate indicates whether libraries are supported for instance.
865 Check_Configuration (Project, Data);
867 -- Library attributes
869 Check_Library_Attributes (Project, Data);
871 if Current_Verbosity = High then
872 Show_Source_Dirs (Project, Data.Tree);
875 Extending := Project.Extends /= No_Project;
877 Check_Package_Naming (Project, Data, Bodies => Bodies, Specs => Specs);
881 if Project.Source_Dirs /= Nil_String then
882 Look_For_Sources (Prj_Data, Data);
884 if not Project.Externally_Built
885 and then not Extending
888 Language : Language_Ptr;
890 Alt_Lang : Language_List;
891 Continuation : Boolean := False;
892 Iter : Source_Iterator;
895 Language := Project.Languages;
896 while Language /= No_Language_Index loop
898 -- If there are no sources for this language, check if there
899 -- are sources for which this is an alternate language.
901 if Language.First_Source = No_Source
902 and then (Data.Flags.Require_Sources_Other_Lang
903 or else Language.Name = Name_Ada)
905 Iter := For_Each_Source (In_Tree => Data.Tree,
908 Source := Element (Iter);
909 exit Source_Loop when Source = No_Source
910 or else Source.Language = Language;
912 Alt_Lang := Source.Alternate_Languages;
913 while Alt_Lang /= null loop
914 exit Source_Loop when Alt_Lang.Language = Language;
915 Alt_Lang := Alt_Lang.Next;
919 end loop Source_Loop;
921 if Source = No_Source then
925 Get_Name_String (Language.Display_Name),
927 Prj_Data.Source_List_File_Location,
929 Continuation := True;
933 Language := Language.Next;
939 -- If a list of sources is specified in attribute Interfaces, set
940 -- In_Interfaces only for the sources specified in the list.
942 Check_Interfaces (Project, Data);
944 -- If it is a library project file, check if it is a standalone library
946 if Project.Library then
947 Check_Stand_Alone_Library (Project, Data);
950 -- Put the list of Mains, if any, in the project data
952 Get_Mains (Project, Data);
961 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
962 The_Name : String := Name;
964 Need_Letter : Boolean := True;
965 Last_Underscore : Boolean := False;
966 OK : Boolean := The_Name'Length > 0;
969 function Is_Reserved (Name : Name_Id) return Boolean;
970 function Is_Reserved (S : String) return Boolean;
971 -- Check that the given name is not an Ada 95 reserved word. The reason
972 -- for the Ada 95 here is that we do not want to exclude the case of an
973 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
974 -- name would be rejected anyway by the compiler. That means there is no
975 -- requirement that the project file parser reject this.
981 function Is_Reserved (S : String) return Boolean is
984 Add_Str_To_Name_Buffer (S);
985 return Is_Reserved (Name_Find);
992 function Is_Reserved (Name : Name_Id) return Boolean is
994 if Get_Name_Table_Byte (Name) /= 0
995 and then Name /= Name_Project
996 and then Name /= Name_Extends
997 and then Name /= Name_External
998 and then Name not in Ada_2005_Reserved_Words
1002 if Current_Verbosity = High then
1003 Write_Str (The_Name);
1004 Write_Line (" is an Ada reserved word.");
1014 -- Start of processing for Check_Ada_Name
1017 To_Lower (The_Name);
1019 Name_Len := The_Name'Length;
1020 Name_Buffer (1 .. Name_Len) := The_Name;
1022 -- Special cases of children of packages A, G, I and S on VMS
1024 if OpenVMS_On_Target
1025 and then Name_Len > 3
1026 and then Name_Buffer (2 .. 3) = "__"
1028 ((Name_Buffer (1) = 'a') or else
1029 (Name_Buffer (1) = 'g') or else
1030 (Name_Buffer (1) = 'i') or else
1031 (Name_Buffer (1) = 's'))
1033 Name_Buffer (2) := '.';
1034 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
1035 Name_Len := Name_Len - 1;
1038 Real_Name := Name_Find;
1040 if Is_Reserved (Real_Name) then
1044 First := The_Name'First;
1046 for Index in The_Name'Range loop
1049 -- We need a letter (at the beginning, and following a dot),
1050 -- but we don't have one.
1052 if Is_Letter (The_Name (Index)) then
1053 Need_Letter := False;
1058 if Current_Verbosity = High then
1059 Write_Int (Types.Int (Index));
1061 Write_Char (The_Name (Index));
1062 Write_Line ("' is not a letter.");
1068 elsif Last_Underscore
1069 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
1071 -- Two underscores are illegal, and a dot cannot follow
1076 if Current_Verbosity = High then
1077 Write_Int (Types.Int (Index));
1079 Write_Char (The_Name (Index));
1080 Write_Line ("' is illegal here.");
1085 elsif The_Name (Index) = '.' then
1087 -- First, check if the name before the dot is not a reserved word
1089 if Is_Reserved (The_Name (First .. Index - 1)) then
1095 -- We need a letter after a dot
1097 Need_Letter := True;
1099 elsif The_Name (Index) = '_' then
1100 Last_Underscore := True;
1103 -- We need an letter or a digit
1105 Last_Underscore := False;
1107 if not Is_Alphanumeric (The_Name (Index)) then
1110 if Current_Verbosity = High then
1111 Write_Int (Types.Int (Index));
1113 Write_Char (The_Name (Index));
1114 Write_Line ("' is not alphanumeric.");
1122 -- Cannot end with an underscore or a dot
1124 OK := OK and then not Need_Letter and then not Last_Underscore;
1127 if First /= Name'First and then
1128 Is_Reserved (The_Name (First .. The_Name'Last))
1136 -- Signal a problem with No_Name
1142 -------------------------
1143 -- Check_Configuration --
1144 -------------------------
1146 procedure Check_Configuration
1147 (Project : Project_Id;
1148 Data : in out Tree_Processing_Data)
1150 Dot_Replacement : File_Name_Type := No_File;
1151 Casing : Casing_Type := All_Lower_Case;
1152 Separate_Suffix : File_Name_Type := No_File;
1154 Lang_Index : Language_Ptr := No_Language_Index;
1155 -- The index of the language data being checked
1157 Prev_Index : Language_Ptr := No_Language_Index;
1158 -- The index of the previous language
1160 procedure Process_Project_Level_Simple_Attributes;
1161 -- Process the simple attributes at the project level
1163 procedure Process_Project_Level_Array_Attributes;
1164 -- Process the associate array attributes at the project level
1166 procedure Process_Packages;
1167 -- Read the packages of the project
1169 ----------------------
1170 -- Process_Packages --
1171 ----------------------
1173 procedure Process_Packages is
1174 Packages : Package_Id;
1175 Element : Package_Element;
1177 procedure Process_Binder (Arrays : Array_Id);
1178 -- Process the associate array attributes of package Binder
1180 procedure Process_Builder (Attributes : Variable_Id);
1181 -- Process the simple attributes of package Builder
1183 procedure Process_Compiler (Arrays : Array_Id);
1184 -- Process the associate array attributes of package Compiler
1186 procedure Process_Naming (Attributes : Variable_Id);
1187 -- Process the simple attributes of package Naming
1189 procedure Process_Naming (Arrays : Array_Id);
1190 -- Process the associate array attributes of package Naming
1192 procedure Process_Linker (Attributes : Variable_Id);
1193 -- Process the simple attributes of package Linker of a
1194 -- configuration project.
1196 --------------------
1197 -- Process_Binder --
1198 --------------------
1200 procedure Process_Binder (Arrays : Array_Id) is
1201 Current_Array_Id : Array_Id;
1202 Current_Array : Array_Data;
1203 Element_Id : Array_Element_Id;
1204 Element : Array_Element;
1207 -- Process the associative array attribute of package Binder
1209 Current_Array_Id := Arrays;
1210 while Current_Array_Id /= No_Array loop
1211 Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
1213 Element_Id := Current_Array.Value;
1214 while Element_Id /= No_Array_Element loop
1215 Element := Data.Tree.Array_Elements.Table (Element_Id);
1217 if Element.Index /= All_Other_Names then
1219 -- Get the name of the language
1222 Get_Language_From_Name
1223 (Project, Get_Name_String (Element.Index));
1225 if Lang_Index /= No_Language_Index then
1226 case Current_Array.Name is
1229 -- Attribute Driver (<language>)
1231 Lang_Index.Config.Binder_Driver :=
1232 File_Name_Type (Element.Value.Value);
1234 when Name_Required_Switches =>
1237 Lang_Index.Config.Binder_Required_Switches,
1238 From_List => Element.Value.Values,
1239 In_Tree => Data.Tree);
1243 -- Attribute Prefix (<language>)
1245 Lang_Index.Config.Binder_Prefix :=
1246 Element.Value.Value;
1248 when Name_Objects_Path =>
1250 -- Attribute Objects_Path (<language>)
1252 Lang_Index.Config.Objects_Path :=
1253 Element.Value.Value;
1255 when Name_Objects_Path_File =>
1257 -- Attribute Objects_Path (<language>)
1259 Lang_Index.Config.Objects_Path_File :=
1260 Element.Value.Value;
1268 Element_Id := Element.Next;
1271 Current_Array_Id := Current_Array.Next;
1275 ---------------------
1276 -- Process_Builder --
1277 ---------------------
1279 procedure Process_Builder (Attributes : Variable_Id) is
1280 Attribute_Id : Variable_Id;
1281 Attribute : Variable;
1284 -- Process non associated array attribute from package Builder
1286 Attribute_Id := Attributes;
1287 while Attribute_Id /= No_Variable loop
1289 Data.Tree.Variable_Elements.Table (Attribute_Id);
1291 if not Attribute.Value.Default then
1292 if Attribute.Name = Name_Executable_Suffix then
1294 -- Attribute Executable_Suffix: the suffix of the
1297 Project.Config.Executable_Suffix :=
1298 Attribute.Value.Value;
1302 Attribute_Id := Attribute.Next;
1304 end Process_Builder;
1306 ----------------------
1307 -- Process_Compiler --
1308 ----------------------
1310 procedure Process_Compiler (Arrays : Array_Id) is
1311 Current_Array_Id : Array_Id;
1312 Current_Array : Array_Data;
1313 Element_Id : Array_Element_Id;
1314 Element : Array_Element;
1315 List : String_List_Id;
1318 -- Process the associative array attribute of package Compiler
1320 Current_Array_Id := Arrays;
1321 while Current_Array_Id /= No_Array loop
1322 Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
1324 Element_Id := Current_Array.Value;
1325 while Element_Id /= No_Array_Element loop
1326 Element := Data.Tree.Array_Elements.Table (Element_Id);
1328 if Element.Index /= All_Other_Names then
1330 -- Get the name of the language
1332 Lang_Index := Get_Language_From_Name
1333 (Project, Get_Name_String (Element.Index));
1335 if Lang_Index /= No_Language_Index then
1336 case Current_Array.Name is
1337 when Name_Dependency_Switches =>
1339 -- Attribute Dependency_Switches (<language>)
1341 if Lang_Index.Config.Dependency_Kind = None then
1342 Lang_Index.Config.Dependency_Kind := Makefile;
1345 List := Element.Value.Values;
1347 if List /= Nil_String then
1349 Lang_Index.Config.Dependency_Option,
1351 In_Tree => Data.Tree);
1354 when Name_Dependency_Driver =>
1356 -- Attribute Dependency_Driver (<language>)
1358 if Lang_Index.Config.Dependency_Kind = None then
1359 Lang_Index.Config.Dependency_Kind := Makefile;
1362 List := Element.Value.Values;
1364 if List /= Nil_String then
1366 Lang_Index.Config.Compute_Dependency,
1368 In_Tree => Data.Tree);
1371 when Name_Include_Switches =>
1373 -- Attribute Include_Switches (<language>)
1375 List := Element.Value.Values;
1377 if List = Nil_String then
1379 (Project, "include option cannot be null",
1380 Element.Value.Location, Data);
1383 Put (Into_List => Lang_Index.Config.Include_Option,
1385 In_Tree => Data.Tree);
1387 when Name_Include_Path =>
1389 -- Attribute Include_Path (<language>)
1391 Lang_Index.Config.Include_Path :=
1392 Element.Value.Value;
1394 when Name_Include_Path_File =>
1396 -- Attribute Include_Path_File (<language>)
1398 Lang_Index.Config.Include_Path_File :=
1399 Element.Value.Value;
1403 -- Attribute Driver (<language>)
1405 Lang_Index.Config.Compiler_Driver :=
1406 File_Name_Type (Element.Value.Value);
1408 when Name_Required_Switches |
1409 Name_Leading_Required_Switches =>
1412 Compiler_Leading_Required_Switches,
1413 From_List => Element.Value.Values,
1414 In_Tree => Data.Tree);
1416 when Name_Trailing_Required_Switches =>
1419 Compiler_Trailing_Required_Switches,
1420 From_List => Element.Value.Values,
1421 In_Tree => Data.Tree);
1423 when Name_Path_Syntax =>
1425 Lang_Index.Config.Path_Syntax :=
1426 Path_Syntax_Kind'Value
1427 (Get_Name_String (Element.Value.Value));
1430 when Constraint_Error =>
1432 (Project, "invalid value for Path_Syntax",
1433 Element.Value.Location, Data);
1436 when Name_Object_File_Suffix =>
1437 if Get_Name_String (Element.Value.Value) = "" then
1439 (Project, "object file suffix cannot be empty",
1440 Element.Value.Location, Data);
1443 Lang_Index.Config.Object_File_Suffix :=
1444 Element.Value.Value;
1447 when Name_Object_File_Switches =>
1449 Lang_Index.Config.Object_File_Switches,
1450 From_List => Element.Value.Values,
1451 In_Tree => Data.Tree);
1453 when Name_Pic_Option =>
1455 -- Attribute Compiler_Pic_Option (<language>)
1457 List := Element.Value.Values;
1459 if List = Nil_String then
1461 (Project, "compiler PIC option cannot be null",
1462 Element.Value.Location, Data);
1466 Lang_Index.Config.Compilation_PIC_Option,
1468 In_Tree => Data.Tree);
1470 when Name_Mapping_File_Switches =>
1472 -- Attribute Mapping_File_Switches (<language>)
1474 List := Element.Value.Values;
1476 if List = Nil_String then
1479 "mapping file switches cannot be null",
1480 Element.Value.Location, Data);
1484 Lang_Index.Config.Mapping_File_Switches,
1486 In_Tree => Data.Tree);
1488 when Name_Mapping_Spec_Suffix =>
1490 -- Attribute Mapping_Spec_Suffix (<language>)
1492 Lang_Index.Config.Mapping_Spec_Suffix :=
1493 File_Name_Type (Element.Value.Value);
1495 when Name_Mapping_Body_Suffix =>
1497 -- Attribute Mapping_Body_Suffix (<language>)
1499 Lang_Index.Config.Mapping_Body_Suffix :=
1500 File_Name_Type (Element.Value.Value);
1502 when Name_Config_File_Switches =>
1504 -- Attribute Config_File_Switches (<language>)
1506 List := Element.Value.Values;
1508 if List = Nil_String then
1511 "config file switches cannot be null",
1512 Element.Value.Location, Data);
1516 Lang_Index.Config.Config_File_Switches,
1518 In_Tree => Data.Tree);
1520 when Name_Objects_Path =>
1522 -- Attribute Objects_Path (<language>)
1524 Lang_Index.Config.Objects_Path :=
1525 Element.Value.Value;
1527 when Name_Objects_Path_File =>
1529 -- Attribute Objects_Path_File (<language>)
1531 Lang_Index.Config.Objects_Path_File :=
1532 Element.Value.Value;
1534 when Name_Config_Body_File_Name =>
1536 -- Attribute Config_Body_File_Name (<language>)
1538 Lang_Index.Config.Config_Body :=
1539 Element.Value.Value;
1541 when Name_Config_Body_File_Name_Pattern =>
1543 -- Attribute Config_Body_File_Name_Pattern
1546 Lang_Index.Config.Config_Body_Pattern :=
1547 Element.Value.Value;
1549 when Name_Config_Spec_File_Name =>
1551 -- Attribute Config_Spec_File_Name (<language>)
1553 Lang_Index.Config.Config_Spec :=
1554 Element.Value.Value;
1556 when Name_Config_Spec_File_Name_Pattern =>
1558 -- Attribute Config_Spec_File_Name_Pattern
1561 Lang_Index.Config.Config_Spec_Pattern :=
1562 Element.Value.Value;
1564 when Name_Config_File_Unique =>
1566 -- Attribute Config_File_Unique (<language>)
1569 Lang_Index.Config.Config_File_Unique :=
1571 (Get_Name_String (Element.Value.Value));
1573 when Constraint_Error =>
1576 "illegal value for Config_File_Unique",
1577 Element.Value.Location, Data);
1586 Element_Id := Element.Next;
1589 Current_Array_Id := Current_Array.Next;
1591 end Process_Compiler;
1593 --------------------
1594 -- Process_Naming --
1595 --------------------
1597 procedure Process_Naming (Attributes : Variable_Id) is
1598 Attribute_Id : Variable_Id;
1599 Attribute : Variable;
1602 -- Process non associated array attribute from package Naming
1604 Attribute_Id := Attributes;
1605 while Attribute_Id /= No_Variable loop
1606 Attribute := Data.Tree.Variable_Elements.Table (Attribute_Id);
1608 if not Attribute.Value.Default then
1609 if Attribute.Name = Name_Separate_Suffix then
1611 -- Attribute Separate_Suffix
1613 Get_Name_String (Attribute.Value.Value);
1614 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
1615 Separate_Suffix := Name_Find;
1617 elsif Attribute.Name = Name_Casing then
1623 Value (Get_Name_String (Attribute.Value.Value));
1626 when Constraint_Error =>
1629 "invalid value for Casing",
1630 Attribute.Value.Location, Data);
1633 elsif Attribute.Name = Name_Dot_Replacement then
1635 -- Attribute Dot_Replacement
1637 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1642 Attribute_Id := Attribute.Next;
1646 procedure Process_Naming (Arrays : Array_Id) is
1647 Current_Array_Id : Array_Id;
1648 Current_Array : Array_Data;
1649 Element_Id : Array_Element_Id;
1650 Element : Array_Element;
1653 -- Process the associative array attribute of package Naming
1655 Current_Array_Id := Arrays;
1656 while Current_Array_Id /= No_Array loop
1657 Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
1659 Element_Id := Current_Array.Value;
1660 while Element_Id /= No_Array_Element loop
1661 Element := Data.Tree.Array_Elements.Table (Element_Id);
1663 -- Get the name of the language
1665 Lang_Index := Get_Language_From_Name
1666 (Project, Get_Name_String (Element.Index));
1668 if Lang_Index /= No_Language_Index then
1669 case Current_Array.Name is
1670 when Name_Spec_Suffix | Name_Specification_Suffix =>
1672 -- Attribute Spec_Suffix (<language>)
1674 Get_Name_String (Element.Value.Value);
1675 Canonical_Case_File_Name
1676 (Name_Buffer (1 .. Name_Len));
1677 Lang_Index.Config.Naming_Data.Spec_Suffix :=
1680 when Name_Implementation_Suffix | Name_Body_Suffix =>
1682 Get_Name_String (Element.Value.Value);
1683 Canonical_Case_File_Name
1684 (Name_Buffer (1 .. Name_Len));
1686 -- Attribute Body_Suffix (<language>)
1688 Lang_Index.Config.Naming_Data.Body_Suffix :=
1690 Lang_Index.Config.Naming_Data.Separate_Suffix :=
1691 Lang_Index.Config.Naming_Data.Body_Suffix;
1698 Element_Id := Element.Next;
1701 Current_Array_Id := Current_Array.Next;
1705 --------------------
1706 -- Process_Linker --
1707 --------------------
1709 procedure Process_Linker (Attributes : Variable_Id) is
1710 Attribute_Id : Variable_Id;
1711 Attribute : Variable;
1714 -- Process non associated array attribute from package Linker
1716 Attribute_Id := Attributes;
1717 while Attribute_Id /= No_Variable loop
1719 Data.Tree.Variable_Elements.Table (Attribute_Id);
1721 if not Attribute.Value.Default then
1722 if Attribute.Name = Name_Driver then
1724 -- Attribute Linker'Driver: the default linker to use
1726 Project.Config.Linker :=
1727 Path_Name_Type (Attribute.Value.Value);
1729 -- Linker'Driver is also used to link shared libraries
1730 -- if the obsolescent attribute Library_GCC has not been
1733 if Project.Config.Shared_Lib_Driver = No_File then
1734 Project.Config.Shared_Lib_Driver :=
1735 File_Name_Type (Attribute.Value.Value);
1738 elsif Attribute.Name = Name_Required_Switches then
1740 -- Attribute Required_Switches: the minimum
1741 -- options to use when invoking the linker
1743 Put (Into_List => Project.Config.Minimum_Linker_Options,
1744 From_List => Attribute.Value.Values,
1745 In_Tree => Data.Tree);
1747 elsif Attribute.Name = Name_Map_File_Option then
1748 Project.Config.Map_File_Option := Attribute.Value.Value;
1750 elsif Attribute.Name = Name_Max_Command_Line_Length then
1752 Project.Config.Max_Command_Line_Length :=
1753 Natural'Value (Get_Name_String
1754 (Attribute.Value.Value));
1757 when Constraint_Error =>
1760 "value must be positive or equal to 0",
1761 Attribute.Value.Location, Data);
1764 elsif Attribute.Name = Name_Response_File_Format then
1769 Get_Name_String (Attribute.Value.Value);
1770 To_Lower (Name_Buffer (1 .. Name_Len));
1773 if Name = Name_None then
1774 Project.Config.Resp_File_Format := None;
1776 elsif Name = Name_Gnu then
1777 Project.Config.Resp_File_Format := GNU;
1779 elsif Name = Name_Object_List then
1780 Project.Config.Resp_File_Format := Object_List;
1782 elsif Name = Name_Option_List then
1783 Project.Config.Resp_File_Format := Option_List;
1788 "illegal response file format",
1789 Attribute.Value.Location, Data);
1793 elsif Attribute.Name = Name_Response_File_Switches then
1794 Put (Into_List => Project.Config.Resp_File_Options,
1795 From_List => Attribute.Value.Values,
1796 In_Tree => Data.Tree);
1800 Attribute_Id := Attribute.Next;
1804 -- Start of processing for Process_Packages
1807 Packages := Project.Decl.Packages;
1808 while Packages /= No_Package loop
1809 Element := Data.Tree.Packages.Table (Packages);
1811 case Element.Name is
1814 -- Process attributes of package Binder
1816 Process_Binder (Element.Decl.Arrays);
1818 when Name_Builder =>
1820 -- Process attributes of package Builder
1822 Process_Builder (Element.Decl.Attributes);
1824 when Name_Compiler =>
1826 -- Process attributes of package Compiler
1828 Process_Compiler (Element.Decl.Arrays);
1832 -- Process attributes of package Linker
1834 Process_Linker (Element.Decl.Attributes);
1838 -- Process attributes of package Naming
1840 Process_Naming (Element.Decl.Attributes);
1841 Process_Naming (Element.Decl.Arrays);
1847 Packages := Element.Next;
1849 end Process_Packages;
1851 ---------------------------------------------
1852 -- Process_Project_Level_Simple_Attributes --
1853 ---------------------------------------------
1855 procedure Process_Project_Level_Simple_Attributes is
1856 Attribute_Id : Variable_Id;
1857 Attribute : Variable;
1858 List : String_List_Id;
1861 -- Process non associated array attribute at project level
1863 Attribute_Id := Project.Decl.Attributes;
1864 while Attribute_Id /= No_Variable loop
1866 Data.Tree.Variable_Elements.Table (Attribute_Id);
1868 if not Attribute.Value.Default then
1869 if Attribute.Name = Name_Target then
1871 -- Attribute Target: the target specified
1873 Project.Config.Target := Attribute.Value.Value;
1875 elsif Attribute.Name = Name_Library_Builder then
1877 -- Attribute Library_Builder: the application to invoke
1878 -- to build libraries.
1880 Project.Config.Library_Builder :=
1881 Path_Name_Type (Attribute.Value.Value);
1883 elsif Attribute.Name = Name_Archive_Builder then
1885 -- Attribute Archive_Builder: the archive builder
1886 -- (usually "ar") and its minimum options (usually "cr").
1888 List := Attribute.Value.Values;
1890 if List = Nil_String then
1893 "archive builder cannot be null",
1894 Attribute.Value.Location, Data);
1897 Put (Into_List => Project.Config.Archive_Builder,
1899 In_Tree => Data.Tree);
1901 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1903 -- Attribute Archive_Builder: the archive builder
1904 -- (usually "ar") and its minimum options (usually "cr").
1906 List := Attribute.Value.Values;
1908 if List /= Nil_String then
1911 Project.Config.Archive_Builder_Append_Option,
1913 In_Tree => Data.Tree);
1916 elsif Attribute.Name = Name_Archive_Indexer then
1918 -- Attribute Archive_Indexer: the optional archive
1919 -- indexer (usually "ranlib") with its minimum options
1922 List := Attribute.Value.Values;
1924 if List = Nil_String then
1927 "archive indexer cannot be null",
1928 Attribute.Value.Location, Data);
1931 Put (Into_List => Project.Config.Archive_Indexer,
1933 In_Tree => Data.Tree);
1935 elsif Attribute.Name = Name_Library_Partial_Linker then
1937 -- Attribute Library_Partial_Linker: the optional linker
1938 -- driver with its minimum options, to partially link
1941 List := Attribute.Value.Values;
1943 if List = Nil_String then
1946 "partial linker cannot be null",
1947 Attribute.Value.Location, Data);
1950 Put (Into_List => Project.Config.Lib_Partial_Linker,
1952 In_Tree => Data.Tree);
1954 elsif Attribute.Name = Name_Library_GCC then
1955 Project.Config.Shared_Lib_Driver :=
1956 File_Name_Type (Attribute.Value.Value);
1959 "?Library_'G'C'C is an obsolescent attribute, " &
1960 "use Linker''Driver instead",
1961 Attribute.Value.Location, Data);
1963 elsif Attribute.Name = Name_Archive_Suffix then
1964 Project.Config.Archive_Suffix :=
1965 File_Name_Type (Attribute.Value.Value);
1967 elsif Attribute.Name = Name_Linker_Executable_Option then
1969 -- Attribute Linker_Executable_Option: optional options
1970 -- to specify an executable name. Defaults to "-o".
1972 List := Attribute.Value.Values;
1974 if List = Nil_String then
1977 "linker executable option cannot be null",
1978 Attribute.Value.Location, Data);
1981 Put (Into_List => Project.Config.Linker_Executable_Option,
1983 In_Tree => Data.Tree);
1985 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
1987 -- Attribute Linker_Lib_Dir_Option: optional options
1988 -- to specify a library search directory. Defaults to
1991 Get_Name_String (Attribute.Value.Value);
1993 if Name_Len = 0 then
1996 "linker library directory option cannot be empty",
1997 Attribute.Value.Location, Data);
2000 Project.Config.Linker_Lib_Dir_Option :=
2001 Attribute.Value.Value;
2003 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2005 -- Attribute Linker_Lib_Name_Option: optional options
2006 -- to specify the name of a library to be linked in.
2007 -- Defaults to "-l".
2009 Get_Name_String (Attribute.Value.Value);
2011 if Name_Len = 0 then
2014 "linker library name option cannot be empty",
2015 Attribute.Value.Location, Data);
2018 Project.Config.Linker_Lib_Name_Option :=
2019 Attribute.Value.Value;
2021 elsif Attribute.Name = Name_Run_Path_Option then
2023 -- Attribute Run_Path_Option: optional options to
2024 -- specify a path for libraries.
2026 List := Attribute.Value.Values;
2028 if List /= Nil_String then
2029 Put (Into_List => Project.Config.Run_Path_Option,
2031 In_Tree => Data.Tree);
2034 elsif Attribute.Name = Name_Separate_Run_Path_Options then
2036 pragma Unsuppress (All_Checks);
2038 Project.Config.Separate_Run_Path_Options :=
2039 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2041 when Constraint_Error =>
2044 "invalid value """ &
2045 Get_Name_String (Attribute.Value.Value) &
2046 """ for Separate_Run_Path_Options",
2047 Attribute.Value.Location, Data);
2050 elsif Attribute.Name = Name_Library_Support then
2052 pragma Unsuppress (All_Checks);
2054 Project.Config.Lib_Support :=
2055 Library_Support'Value (Get_Name_String
2056 (Attribute.Value.Value));
2058 when Constraint_Error =>
2061 "invalid value """ &
2062 Get_Name_String (Attribute.Value.Value) &
2063 """ for Library_Support",
2064 Attribute.Value.Location, Data);
2067 elsif Attribute.Name = Name_Shared_Library_Prefix then
2068 Project.Config.Shared_Lib_Prefix :=
2069 File_Name_Type (Attribute.Value.Value);
2071 elsif Attribute.Name = Name_Shared_Library_Suffix then
2072 Project.Config.Shared_Lib_Suffix :=
2073 File_Name_Type (Attribute.Value.Value);
2075 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2077 pragma Unsuppress (All_Checks);
2079 Project.Config.Symbolic_Link_Supported :=
2080 Boolean'Value (Get_Name_String
2081 (Attribute.Value.Value));
2083 when Constraint_Error =>
2087 & Get_Name_String (Attribute.Value.Value)
2088 & """ for Symbolic_Link_Supported",
2089 Attribute.Value.Location, Data);
2093 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2096 pragma Unsuppress (All_Checks);
2098 Project.Config.Lib_Maj_Min_Id_Supported :=
2099 Boolean'Value (Get_Name_String
2100 (Attribute.Value.Value));
2102 when Constraint_Error =>
2105 "invalid value """ &
2106 Get_Name_String (Attribute.Value.Value) &
2107 """ for Library_Major_Minor_Id_Supported",
2108 Attribute.Value.Location, Data);
2111 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2113 pragma Unsuppress (All_Checks);
2115 Project.Config.Auto_Init_Supported :=
2116 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2118 when Constraint_Error =>
2122 & Get_Name_String (Attribute.Value.Value)
2123 & """ for Library_Auto_Init_Supported",
2124 Attribute.Value.Location, Data);
2127 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2128 List := Attribute.Value.Values;
2130 if List /= Nil_String then
2131 Put (Into_List => Project.Config.Shared_Lib_Min_Options,
2133 In_Tree => Data.Tree);
2136 elsif Attribute.Name = Name_Library_Version_Switches then
2137 List := Attribute.Value.Values;
2139 if List /= Nil_String then
2140 Put (Into_List => Project.Config.Lib_Version_Options,
2142 In_Tree => Data.Tree);
2147 Attribute_Id := Attribute.Next;
2149 end Process_Project_Level_Simple_Attributes;
2151 --------------------------------------------
2152 -- Process_Project_Level_Array_Attributes --
2153 --------------------------------------------
2155 procedure Process_Project_Level_Array_Attributes is
2156 Current_Array_Id : Array_Id;
2157 Current_Array : Array_Data;
2158 Element_Id : Array_Element_Id;
2159 Element : Array_Element;
2160 List : String_List_Id;
2163 -- Process the associative array attributes at project level
2165 Current_Array_Id := Project.Decl.Arrays;
2166 while Current_Array_Id /= No_Array loop
2167 Current_Array := Data.Tree.Arrays.Table (Current_Array_Id);
2169 Element_Id := Current_Array.Value;
2170 while Element_Id /= No_Array_Element loop
2171 Element := Data.Tree.Array_Elements.Table (Element_Id);
2173 -- Get the name of the language
2176 Get_Language_From_Name
2177 (Project, Get_Name_String (Element.Index));
2179 if Lang_Index /= No_Language_Index then
2180 case Current_Array.Name is
2181 when Name_Inherit_Source_Path =>
2182 List := Element.Value.Values;
2184 if List /= Nil_String then
2187 Lang_Index.Config.Include_Compatible_Languages,
2189 In_Tree => Data.Tree,
2190 Lower_Case => True);
2193 when Name_Toolchain_Description =>
2195 -- Attribute Toolchain_Description (<language>)
2197 Lang_Index.Config.Toolchain_Description :=
2198 Element.Value.Value;
2200 when Name_Toolchain_Version =>
2202 -- Attribute Toolchain_Version (<language>)
2204 Lang_Index.Config.Toolchain_Version :=
2205 Element.Value.Value;
2207 when Name_Runtime_Library_Dir =>
2209 -- Attribute Runtime_Library_Dir (<language>)
2211 Lang_Index.Config.Runtime_Library_Dir :=
2212 Element.Value.Value;
2214 when Name_Runtime_Source_Dir =>
2216 -- Attribute Runtime_Library_Dir (<language>)
2218 Lang_Index.Config.Runtime_Source_Dir :=
2219 Element.Value.Value;
2221 when Name_Object_Generated =>
2223 pragma Unsuppress (All_Checks);
2229 (Get_Name_String (Element.Value.Value));
2231 Lang_Index.Config.Object_Generated := Value;
2233 -- If no object is generated, no object may be
2237 Lang_Index.Config.Objects_Linked := False;
2241 when Constraint_Error =>
2245 & Get_Name_String (Element.Value.Value)
2246 & """ for Object_Generated",
2247 Element.Value.Location, Data);
2250 when Name_Objects_Linked =>
2252 pragma Unsuppress (All_Checks);
2258 (Get_Name_String (Element.Value.Value));
2260 -- No change if Object_Generated is False, as this
2261 -- forces Objects_Linked to be False too.
2263 if Lang_Index.Config.Object_Generated then
2264 Lang_Index.Config.Objects_Linked := Value;
2268 when Constraint_Error =>
2272 & Get_Name_String (Element.Value.Value)
2273 & """ for Objects_Linked",
2274 Element.Value.Location, Data);
2281 Element_Id := Element.Next;
2284 Current_Array_Id := Current_Array.Next;
2286 end Process_Project_Level_Array_Attributes;
2288 -- Start of processing for Check_Configuration
2291 Process_Project_Level_Simple_Attributes;
2292 Process_Project_Level_Array_Attributes;
2295 -- For unit based languages, set Casing, Dot_Replacement and
2296 -- Separate_Suffix in Naming_Data.
2298 Lang_Index := Project.Languages;
2299 while Lang_Index /= No_Language_Index loop
2300 if Lang_Index.Name = Name_Ada then
2301 Lang_Index.Config.Naming_Data.Casing := Casing;
2302 Lang_Index.Config.Naming_Data.Dot_Replacement := Dot_Replacement;
2304 if Separate_Suffix /= No_File then
2305 Lang_Index.Config.Naming_Data.Separate_Suffix :=
2312 Lang_Index := Lang_Index.Next;
2315 -- Give empty names to various prefixes/suffixes, if they have not
2316 -- been specified in the configuration.
2318 if Project.Config.Archive_Suffix = No_File then
2319 Project.Config.Archive_Suffix := Empty_File;
2322 if Project.Config.Shared_Lib_Prefix = No_File then
2323 Project.Config.Shared_Lib_Prefix := Empty_File;
2326 if Project.Config.Shared_Lib_Suffix = No_File then
2327 Project.Config.Shared_Lib_Suffix := Empty_File;
2330 Lang_Index := Project.Languages;
2331 while Lang_Index /= No_Language_Index loop
2333 -- For all languages, Compiler_Driver needs to be specified. This is
2334 -- only needed if we do intend to compile (not in GPS for instance).
2336 if Data.Flags.Compiler_Driver_Mandatory
2337 and then Lang_Index.Config.Compiler_Driver = No_File
2339 Error_Msg_Name_1 := Lang_Index.Display_Name;
2342 "?no compiler specified for language %%" &
2343 ", ignoring all its sources",
2346 if Lang_Index = Project.Languages then
2347 Project.Languages := Lang_Index.Next;
2349 Prev_Index.Next := Lang_Index.Next;
2352 elsif Lang_Index.Name = Name_Ada then
2353 Prev_Index := Lang_Index;
2355 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2356 -- Body_Suffix need to be specified.
2358 if Lang_Index.Config.Naming_Data.Dot_Replacement = No_File then
2361 "Dot_Replacement not specified for Ada",
2365 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File then
2368 "Spec_Suffix not specified for Ada",
2372 if Lang_Index.Config.Naming_Data.Body_Suffix = No_File then
2375 "Body_Suffix not specified for Ada",
2380 Prev_Index := Lang_Index;
2382 -- For file based languages, either Spec_Suffix or Body_Suffix
2383 -- need to be specified.
2385 if Data.Flags.Require_Sources_Other_Lang
2386 and then Lang_Index.Config.Naming_Data.Spec_Suffix = No_File
2387 and then Lang_Index.Config.Naming_Data.Body_Suffix = No_File
2389 Error_Msg_Name_1 := Lang_Index.Display_Name;
2392 "no suffixes specified for %%",
2397 Lang_Index := Lang_Index.Next;
2399 end Check_Configuration;
2401 -------------------------------
2402 -- Check_If_Externally_Built --
2403 -------------------------------
2405 procedure Check_If_Externally_Built
2406 (Project : Project_Id;
2407 Data : in out Tree_Processing_Data)
2409 Externally_Built : constant Variable_Value :=
2411 (Name_Externally_Built,
2412 Project.Decl.Attributes, Data.Tree);
2415 if not Externally_Built.Default then
2416 Get_Name_String (Externally_Built.Value);
2417 To_Lower (Name_Buffer (1 .. Name_Len));
2419 if Name_Buffer (1 .. Name_Len) = "true" then
2420 Project.Externally_Built := True;
2422 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2424 "Externally_Built may only be true or false",
2425 Externally_Built.Location, Data);
2429 -- A virtual project extending an externally built project is itself
2430 -- externally built.
2432 if Project.Virtual and then Project.Extends /= No_Project then
2433 Project.Externally_Built := Project.Extends.Externally_Built;
2436 if Current_Verbosity = High then
2437 Write_Str ("Project is ");
2439 if not Project.Externally_Built then
2443 Write_Line ("externally built.");
2445 end Check_If_Externally_Built;
2447 ----------------------
2448 -- Check_Interfaces --
2449 ----------------------
2451 procedure Check_Interfaces
2452 (Project : Project_Id;
2453 Data : in out Tree_Processing_Data)
2455 Interfaces : constant Prj.Variable_Value :=
2457 (Snames.Name_Interfaces,
2458 Project.Decl.Attributes,
2461 List : String_List_Id;
2462 Element : String_Element;
2463 Name : File_Name_Type;
2464 Iter : Source_Iterator;
2466 Project_2 : Project_Id;
2470 if not Interfaces.Default then
2472 -- Set In_Interfaces to False for all sources. It will be set to True
2473 -- later for the sources in the Interfaces list.
2475 Project_2 := Project;
2476 while Project_2 /= No_Project loop
2477 Iter := For_Each_Source (Data.Tree, Project_2);
2479 Source := Prj.Element (Iter);
2480 exit when Source = No_Source;
2481 Source.In_Interfaces := False;
2485 Project_2 := Project_2.Extends;
2488 List := Interfaces.Values;
2489 while List /= Nil_String loop
2490 Element := Data.Tree.String_Elements.Table (List);
2491 Name := Canonical_Case_File_Name (Element.Value);
2493 Project_2 := Project;
2495 while Project_2 /= No_Project loop
2496 Iter := For_Each_Source (Data.Tree, Project_2);
2499 Source := Prj.Element (Iter);
2500 exit when Source = No_Source;
2502 if Source.File = Name then
2503 if not Source.Locally_Removed then
2504 Source.In_Interfaces := True;
2505 Source.Declared_In_Interfaces := True;
2507 Other := Other_Part (Source);
2509 if Other /= No_Source then
2510 Other.In_Interfaces := True;
2511 Other.Declared_In_Interfaces := True;
2514 if Current_Verbosity = High then
2515 Write_Str (" interface: ");
2516 Write_Line (Get_Name_String (Source.Path.Name));
2526 Project_2 := Project_2.Extends;
2529 if Source = No_Source then
2530 Error_Msg_File_1 := File_Name_Type (Element.Value);
2531 Error_Msg_Name_1 := Project.Name;
2535 "{ cannot be an interface of project %% "
2536 & "as it is not one of its sources",
2537 Element.Location, Data);
2540 List := Element.Next;
2543 Project.Interfaces_Defined := True;
2545 elsif Project.Extends /= No_Project then
2546 Project.Interfaces_Defined := Project.Extends.Interfaces_Defined;
2548 if Project.Interfaces_Defined then
2549 Iter := For_Each_Source (Data.Tree, Project);
2551 Source := Prj.Element (Iter);
2552 exit when Source = No_Source;
2554 if not Source.Declared_In_Interfaces then
2555 Source.In_Interfaces := False;
2562 end Check_Interfaces;
2564 --------------------------
2565 -- Check_Package_Naming --
2566 --------------------------
2568 procedure Check_Package_Naming
2569 (Project : Project_Id;
2570 Data : in out Tree_Processing_Data;
2571 Bodies : out Array_Element_Id;
2572 Specs : out Array_Element_Id)
2574 Naming_Id : constant Package_Id :=
2576 (Name_Naming, Project.Decl.Packages, Data.Tree);
2577 Naming : Package_Element;
2579 Ada_Body_Suffix_Loc : Source_Ptr := No_Location;
2581 procedure Check_Naming;
2582 -- Check the validity of the Naming package (suffixes valid, ...)
2584 procedure Check_Common
2585 (Dot_Replacement : in out File_Name_Type;
2586 Casing : in out Casing_Type;
2587 Casing_Defined : out Boolean;
2588 Separate_Suffix : in out File_Name_Type;
2589 Sep_Suffix_Loc : out Source_Ptr);
2590 -- Check attributes common
2592 procedure Process_Exceptions_File_Based
2593 (Lang_Id : Language_Ptr;
2594 Kind : Source_Kind);
2595 procedure Process_Exceptions_Unit_Based
2596 (Lang_Id : Language_Ptr;
2597 Kind : Source_Kind);
2598 -- Process the naming exceptions for the two types of languages
2600 procedure Initialize_Naming_Data;
2601 -- Initialize internal naming data for the various languages
2607 procedure Check_Common
2608 (Dot_Replacement : in out File_Name_Type;
2609 Casing : in out Casing_Type;
2610 Casing_Defined : out Boolean;
2611 Separate_Suffix : in out File_Name_Type;
2612 Sep_Suffix_Loc : out Source_Ptr)
2614 Dot_Repl : constant Variable_Value :=
2616 (Name_Dot_Replacement,
2617 Naming.Decl.Attributes,
2619 Casing_String : constant Variable_Value :=
2622 Naming.Decl.Attributes,
2624 Sep_Suffix : constant Variable_Value :=
2626 (Name_Separate_Suffix,
2627 Naming.Decl.Attributes,
2629 Dot_Repl_Loc : Source_Ptr;
2632 Sep_Suffix_Loc := No_Location;
2634 if not Dot_Repl.Default then
2636 (Dot_Repl.Kind = Single, "Dot_Replacement is not a string");
2638 if Length_Of_Name (Dot_Repl.Value) = 0 then
2640 (Project, "Dot_Replacement cannot be empty",
2641 Dot_Repl.Location, Data);
2644 Dot_Replacement := Canonical_Case_File_Name (Dot_Repl.Value);
2645 Dot_Repl_Loc := Dot_Repl.Location;
2648 Repl : constant String := Get_Name_String (Dot_Replacement);
2651 -- Dot_Replacement cannot
2653 -- - start or end with an alphanumeric
2654 -- - be a single '_'
2655 -- - start with an '_' followed by an alphanumeric
2656 -- - contain a '.' except if it is "."
2659 or else Is_Alphanumeric (Repl (Repl'First))
2660 or else Is_Alphanumeric (Repl (Repl'Last))
2661 or else (Repl (Repl'First) = '_'
2665 Is_Alphanumeric (Repl (Repl'First + 1))))
2666 or else (Repl'Length > 1
2668 Index (Source => Repl, Pattern => ".") /= 0)
2673 """ is illegal for Dot_Replacement.",
2674 Dot_Repl_Loc, Data);
2679 if Dot_Replacement /= No_File then
2681 ("Dot_Replacement", Get_Name_String (Dot_Replacement));
2684 Casing_Defined := False;
2686 if not Casing_String.Default then
2688 (Casing_String.Kind = Single, "Casing is not a string");
2691 Casing_Image : constant String :=
2692 Get_Name_String (Casing_String.Value);
2695 if Casing_Image'Length = 0 then
2698 "Casing cannot be an empty string",
2699 Casing_String.Location, Data);
2702 Casing := Value (Casing_Image);
2703 Casing_Defined := True;
2706 when Constraint_Error =>
2707 Name_Len := Casing_Image'Length;
2708 Name_Buffer (1 .. Name_Len) := Casing_Image;
2709 Err_Vars.Error_Msg_Name_1 := Name_Find;
2712 "%% is not a correct Casing",
2713 Casing_String.Location, Data);
2717 Write_Attr ("Casing", Image (Casing));
2719 if not Sep_Suffix.Default then
2720 if Length_Of_Name (Sep_Suffix.Value) = 0 then
2723 "Separate_Suffix cannot be empty",
2724 Sep_Suffix.Location, Data);
2727 Separate_Suffix := Canonical_Case_File_Name (Sep_Suffix.Value);
2728 Sep_Suffix_Loc := Sep_Suffix.Location;
2730 Check_Illegal_Suffix
2731 (Project, Separate_Suffix,
2732 Dot_Replacement, "Separate_Suffix", Sep_Suffix.Location,
2737 if Separate_Suffix /= No_File then
2739 ("Separate_Suffix", Get_Name_String (Separate_Suffix));
2743 -----------------------------------
2744 -- Process_Exceptions_File_Based --
2745 -----------------------------------
2747 procedure Process_Exceptions_File_Based
2748 (Lang_Id : Language_Ptr;
2751 Lang : constant Name_Id := Lang_Id.Name;
2752 Exceptions : Array_Element_Id;
2753 Exception_List : Variable_Value;
2754 Element_Id : String_List_Id;
2755 Element : String_Element;
2756 File_Name : File_Name_Type;
2758 Iter : Source_Iterator;
2765 (Name_Implementation_Exceptions,
2766 In_Arrays => Naming.Decl.Arrays,
2767 In_Tree => Data.Tree);
2772 (Name_Specification_Exceptions,
2773 In_Arrays => Naming.Decl.Arrays,
2774 In_Tree => Data.Tree);
2777 Exception_List := Value_Of
2779 In_Array => Exceptions,
2780 In_Tree => Data.Tree);
2782 if Exception_List /= Nil_Variable_Value then
2783 Element_Id := Exception_List.Values;
2784 while Element_Id /= Nil_String loop
2785 Element := Data.Tree.String_Elements.Table (Element_Id);
2786 File_Name := Canonical_Case_File_Name (Element.Value);
2788 Iter := For_Each_Source (Data.Tree, Project);
2790 Source := Prj.Element (Iter);
2791 exit when Source = No_Source or else Source.File = File_Name;
2795 if Source = No_Source then
2802 File_Name => File_Name,
2803 Display_File => File_Name_Type (Element.Value),
2804 Naming_Exception => True);
2807 -- Check if the file name is already recorded for another
2808 -- language or another kind.
2810 if Source.Language /= Lang_Id then
2813 "the same file cannot be a source of two languages",
2814 Element.Location, Data);
2816 elsif Source.Kind /= Kind then
2819 "the same file cannot be a source and a template",
2820 Element.Location, Data);
2823 -- If the file is already recorded for the same
2824 -- language and the same kind, it means that the file
2825 -- name appears several times in the *_Exceptions
2826 -- attribute; so there is nothing to do.
2829 Element_Id := Element.Next;
2832 end Process_Exceptions_File_Based;
2834 -----------------------------------
2835 -- Process_Exceptions_Unit_Based --
2836 -----------------------------------
2838 procedure Process_Exceptions_Unit_Based
2839 (Lang_Id : Language_Ptr;
2842 Lang : constant Name_Id := Lang_Id.Name;
2843 Exceptions : Array_Element_Id;
2844 Element : Array_Element;
2847 File_Name : File_Name_Type;
2856 In_Arrays => Naming.Decl.Arrays,
2857 In_Tree => Data.Tree);
2859 if Exceptions = No_Array_Element then
2862 (Name_Implementation,
2863 In_Arrays => Naming.Decl.Arrays,
2864 In_Tree => Data.Tree);
2871 In_Arrays => Naming.Decl.Arrays,
2872 In_Tree => Data.Tree);
2874 if Exceptions = No_Array_Element then
2878 In_Arrays => Naming.Decl.Arrays,
2879 In_Tree => Data.Tree);
2883 while Exceptions /= No_Array_Element loop
2884 Element := Data.Tree.Array_Elements.Table (Exceptions);
2885 File_Name := Canonical_Case_File_Name (Element.Value.Value);
2887 Get_Name_String (Element.Index);
2888 To_Lower (Name_Buffer (1 .. Name_Len));
2890 Index := Element.Value.Index;
2892 -- For Ada, check if it is a valid unit name
2894 if Lang = Name_Ada then
2895 Get_Name_String (Element.Index);
2896 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
2898 if Unit = No_Name then
2899 Err_Vars.Error_Msg_Name_1 := Element.Index;
2902 "%% is not a valid unit name.",
2903 Element.Value.Location, Data);
2907 if Unit /= No_Name then
2914 File_Name => File_Name,
2915 Display_File => File_Name_Type (Element.Value.Value),
2918 Location => Element.Value.Location,
2919 Naming_Exception => True);
2922 Exceptions := Element.Next;
2924 end Process_Exceptions_Unit_Based;
2930 procedure Check_Naming is
2931 Dot_Replacement : File_Name_Type :=
2933 (First_Name_Id + Character'Pos ('-'));
2934 Separate_Suffix : File_Name_Type := No_File;
2935 Casing : Casing_Type := All_Lower_Case;
2936 Casing_Defined : Boolean;
2937 Lang_Id : Language_Ptr;
2938 Sep_Suffix_Loc : Source_Ptr;
2939 Suffix : Variable_Value;
2944 (Dot_Replacement => Dot_Replacement,
2946 Casing_Defined => Casing_Defined,
2947 Separate_Suffix => Separate_Suffix,
2948 Sep_Suffix_Loc => Sep_Suffix_Loc);
2950 -- For all unit based languages, if any, set the specified value
2951 -- of Dot_Replacement, Casing and/or Separate_Suffix. Do not
2952 -- systematically overwrite, since the defaults come from the
2953 -- configuration file.
2955 if Dot_Replacement /= No_File
2956 or else Casing_Defined
2957 or else Separate_Suffix /= No_File
2959 Lang_Id := Project.Languages;
2960 while Lang_Id /= No_Language_Index loop
2961 if Lang_Id.Config.Kind = Unit_Based then
2962 if Dot_Replacement /= No_File then
2963 Lang_Id.Config.Naming_Data.Dot_Replacement :=
2967 if Casing_Defined then
2968 Lang_Id.Config.Naming_Data.Casing := Casing;
2972 Lang_Id := Lang_Id.Next;
2976 -- Next, get the spec and body suffixes
2978 Lang_Id := Project.Languages;
2979 while Lang_Id /= No_Language_Index loop
2980 Lang := Lang_Id.Name;
2986 Attribute_Or_Array_Name => Name_Spec_Suffix,
2987 In_Package => Naming_Id,
2988 In_Tree => Data.Tree);
2990 if Suffix = Nil_Variable_Value then
2993 Attribute_Or_Array_Name => Name_Specification_Suffix,
2994 In_Package => Naming_Id,
2995 In_Tree => Data.Tree);
2998 if Suffix /= Nil_Variable_Value then
2999 Lang_Id.Config.Naming_Data.Spec_Suffix :=
3000 File_Name_Type (Suffix.Value);
3002 Check_Illegal_Suffix
3004 Lang_Id.Config.Naming_Data.Spec_Suffix,
3005 Lang_Id.Config.Naming_Data.Dot_Replacement,
3006 "Spec_Suffix", Suffix.Location, Data);
3010 Get_Name_String (Lang_Id.Config.Naming_Data.Spec_Suffix));
3018 Attribute_Or_Array_Name => Name_Body_Suffix,
3019 In_Package => Naming_Id,
3020 In_Tree => Data.Tree);
3022 if Suffix = Nil_Variable_Value then
3026 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3027 In_Package => Naming_Id,
3028 In_Tree => Data.Tree);
3031 if Suffix /= Nil_Variable_Value then
3032 Lang_Id.Config.Naming_Data.Body_Suffix :=
3033 File_Name_Type (Suffix.Value);
3035 -- The default value of separate suffix should be the same as
3036 -- the body suffix, so we need to compute that first.
3038 if Separate_Suffix = No_File then
3039 Lang_Id.Config.Naming_Data.Separate_Suffix :=
3040 Lang_Id.Config.Naming_Data.Body_Suffix;
3044 (Lang_Id.Config.Naming_Data.Separate_Suffix));
3046 Lang_Id.Config.Naming_Data.Separate_Suffix :=
3050 Check_Illegal_Suffix
3052 Lang_Id.Config.Naming_Data.Body_Suffix,
3053 Lang_Id.Config.Naming_Data.Dot_Replacement,
3054 "Body_Suffix", Suffix.Location, Data);
3058 Get_Name_String (Lang_Id.Config.Naming_Data.Body_Suffix));
3060 elsif Separate_Suffix /= No_File then
3061 Lang_Id.Config.Naming_Data.Separate_Suffix := Separate_Suffix;
3064 -- Spec_Suffix cannot be equal to Body_Suffix or Separate_Suffix,
3065 -- since that would cause a clear ambiguity. Note that we do allow
3066 -- a Spec_Suffix to have the same termination as one of these,
3067 -- which causes a potential ambiguity, but we resolve that my
3068 -- matching the longest possible suffix.
3070 if Lang_Id.Config.Naming_Data.Spec_Suffix /= No_File
3071 and then Lang_Id.Config.Naming_Data.Spec_Suffix =
3072 Lang_Id.Config.Naming_Data.Body_Suffix
3077 & Get_Name_String (Lang_Id.Config.Naming_Data.Body_Suffix)
3078 & """) cannot be the same as Spec_Suffix.",
3079 Ada_Body_Suffix_Loc, Data);
3082 if Lang_Id.Config.Naming_Data.Body_Suffix /=
3083 Lang_Id.Config.Naming_Data.Separate_Suffix
3084 and then Lang_Id.Config.Naming_Data.Spec_Suffix =
3085 Lang_Id.Config.Naming_Data.Separate_Suffix
3089 "Separate_Suffix ("""
3091 (Lang_Id.Config.Naming_Data.Separate_Suffix)
3092 & """) cannot be the same as Spec_Suffix.",
3093 Sep_Suffix_Loc, Data);
3096 Lang_Id := Lang_Id.Next;
3099 -- Get the naming exceptions for all languages
3101 for Kind in Spec .. Impl loop
3102 Lang_Id := Project.Languages;
3103 while Lang_Id /= No_Language_Index loop
3104 case Lang_Id.Config.Kind is
3106 Process_Exceptions_File_Based (Lang_Id, Kind);
3109 Process_Exceptions_Unit_Based (Lang_Id, Kind);
3112 Lang_Id := Lang_Id.Next;
3117 ----------------------------
3118 -- Initialize_Naming_Data --
3119 ----------------------------
3121 procedure Initialize_Naming_Data is
3122 Specs : Array_Element_Id :=
3128 Impls : Array_Element_Id :=
3134 Lang : Language_Ptr;
3135 Lang_Name : Name_Id;
3136 Value : Variable_Value;
3137 Extended : Project_Id;
3140 -- At this stage, the project already contains the default extensions
3141 -- for the various languages. We now merge those suffixes read in the
3142 -- user project, and they override the default.
3144 while Specs /= No_Array_Element loop
3145 Lang_Name := Data.Tree.Array_Elements.Table (Specs).Index;
3147 Get_Language_From_Name
3148 (Project, Name => Get_Name_String (Lang_Name));
3150 -- An extending project inherits its parent projects' languages
3151 -- so if needed we should create entries for those languages
3154 Extended := Project.Extends;
3155 while Extended /= null loop
3156 Lang := Get_Language_From_Name
3157 (Extended, Name => Get_Name_String (Lang_Name));
3158 exit when Lang /= null;
3160 Extended := Extended.Extends;
3163 if Lang /= null then
3164 Lang := new Language_Data'(Lang.all);
3165 Lang.First_Source := null;
3166 Lang.Next := Project.Languages;
3167 Project.Languages := Lang;
3171 -- If language was not found in project or the projects it extends
3174 if Current_Verbosity = High then
3176 ("Ignoring spec naming data for "
3177 & Get_Name_String (Lang_Name)
3178 & " since language is not defined for this project");
3182 Value := Data.Tree.Array_Elements.Table (Specs).Value;
3184 if Value.Kind = Single then
3185 Lang.Config.Naming_Data.Spec_Suffix :=
3186 Canonical_Case_File_Name (Value.Value);
3190 Specs := Data.Tree.Array_Elements.Table (Specs).Next;
3193 while Impls /= No_Array_Element loop
3194 Lang_Name := Data.Tree.Array_Elements.Table (Impls).Index;
3196 Get_Language_From_Name
3197 (Project, Name => Get_Name_String (Lang_Name));
3200 if Current_Verbosity = High then
3202 ("Ignoring impl naming data for "
3203 & Get_Name_String (Lang_Name)
3204 & " since language is not defined for this project");
3207 Value := Data.Tree.Array_Elements.Table (Impls).Value;
3209 if Lang.Name = Name_Ada then
3210 Ada_Body_Suffix_Loc := Value.Location;
3213 if Value.Kind = Single then
3214 Lang.Config.Naming_Data.Body_Suffix :=
3215 Canonical_Case_File_Name (Value.Value);
3219 Impls := Data.Tree.Array_Elements.Table (Impls).Next;
3221 end Initialize_Naming_Data;
3223 -- Start of processing for Check_Naming_Schemes
3226 Specs := No_Array_Element;
3227 Bodies := No_Array_Element;
3229 -- No Naming package or parsing a configuration file? nothing to do
3231 if Naming_Id /= No_Package
3232 and Project.Qualifier /= Configuration
3234 Naming := Data.Tree.Packages.Table (Naming_Id);
3236 if Current_Verbosity = High then
3237 Write_Line ("Checking package Naming for project "
3238 & Get_Name_String (Project.Name));
3241 Initialize_Naming_Data;
3244 end Check_Package_Naming;
3246 ------------------------------
3247 -- Check_Library_Attributes --
3248 ------------------------------
3250 procedure Check_Library_Attributes
3251 (Project : Project_Id;
3252 Data : in out Tree_Processing_Data)
3254 Attributes : constant Prj.Variable_Id := Project.Decl.Attributes;
3256 Lib_Dir : constant Prj.Variable_Value :=
3258 (Snames.Name_Library_Dir, Attributes, Data.Tree);
3260 Lib_Name : constant Prj.Variable_Value :=
3262 (Snames.Name_Library_Name, Attributes, Data.Tree);
3264 Lib_Version : constant Prj.Variable_Value :=
3266 (Snames.Name_Library_Version, Attributes, Data.Tree);
3268 Lib_ALI_Dir : constant Prj.Variable_Value :=
3270 (Snames.Name_Library_Ali_Dir, Attributes, Data.Tree);
3272 Lib_GCC : constant Prj.Variable_Value :=
3274 (Snames.Name_Library_GCC, Attributes, Data.Tree);
3276 The_Lib_Kind : constant Prj.Variable_Value :=
3278 (Snames.Name_Library_Kind, Attributes, Data.Tree);
3280 Imported_Project_List : Project_List;
3282 Continuation : String_Access := No_Continuation_String'Access;
3284 Support_For_Libraries : Library_Support;
3286 Library_Directory_Present : Boolean;
3288 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3289 -- Check if an imported or extended project if also a library project
3295 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3297 Iter : Source_Iterator;
3300 if Proj /= No_Project then
3301 if not Proj.Library then
3303 -- The only not library projects that are OK are those that
3304 -- have no sources. However, header files from non-Ada
3305 -- languages are OK, as there is nothing to compile.
3307 Iter := For_Each_Source (Data.Tree, Proj);
3309 Src_Id := Prj.Element (Iter);
3310 exit when Src_Id = No_Source
3311 or else Src_Id.Language.Config.Kind /= File_Based
3312 or else Src_Id.Kind /= Spec;
3316 if Src_Id /= No_Source then
3317 Error_Msg_Name_1 := Project.Name;
3318 Error_Msg_Name_2 := Proj.Name;
3321 if Project.Library_Kind /= Static then
3325 "shared library project %% cannot extend " &
3326 "project %% that is not a library project",
3327 Project.Location, Data);
3328 Continuation := Continuation_String'Access;
3331 elsif (not Unchecked_Shared_Lib_Imports)
3332 and then Project.Library_Kind /= Static
3337 "shared library project %% cannot import project %% " &
3338 "that is not a shared library project",
3339 Project.Location, Data);
3340 Continuation := Continuation_String'Access;
3344 elsif Project.Library_Kind /= Static and then
3345 Proj.Library_Kind = Static
3347 Error_Msg_Name_1 := Project.Name;
3348 Error_Msg_Name_2 := Proj.Name;
3354 "shared library project %% cannot extend static " &
3355 "library project %%",
3356 Project.Location, Data);
3357 Continuation := Continuation_String'Access;
3359 elsif not Unchecked_Shared_Lib_Imports then
3363 "shared library project %% cannot import static " &
3364 "library project %%",
3365 Project.Location, Data);
3366 Continuation := Continuation_String'Access;
3373 Dir_Exists : Boolean;
3375 -- Start of processing for Check_Library_Attributes
3378 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3380 -- Special case of extending project
3382 if Project.Extends /= No_Project then
3384 -- If the project extended is a library project, we inherit the
3385 -- library name, if it is not redefined; we check that the library
3386 -- directory is specified.
3388 if Project.Extends.Library then
3389 if Project.Qualifier = Standard then
3392 "a standard project cannot extend a library project",
3393 Project.Location, Data);
3396 if Lib_Name.Default then
3397 Project.Library_Name := Project.Extends.Library_Name;
3400 if Lib_Dir.Default then
3401 if not Project.Virtual then
3404 "a project extending a library project must " &
3405 "specify an attribute Library_Dir",
3406 Project.Location, Data);
3409 -- For a virtual project extending a library project,
3410 -- inherit library directory.
3412 Project.Library_Dir := Project.Extends.Library_Dir;
3413 Library_Directory_Present := True;
3420 pragma Assert (Lib_Name.Kind = Single);
3422 if Lib_Name.Value = Empty_String then
3423 if Current_Verbosity = High
3424 and then Project.Library_Name = No_Name
3426 Write_Line ("No library name");
3430 -- There is no restriction on the syntax of library names
3432 Project.Library_Name := Lib_Name.Value;
3435 if Project.Library_Name /= No_Name then
3436 if Current_Verbosity = High then
3438 ("Library name", Get_Name_String (Project.Library_Name));
3441 pragma Assert (Lib_Dir.Kind = Single);
3443 if not Library_Directory_Present then
3444 if Current_Verbosity = High then
3445 Write_Line ("No library directory");
3449 -- Find path name (unless inherited), check that it is a directory
3451 if Project.Library_Dir = No_Path_Information then
3454 File_Name_Type (Lib_Dir.Value),
3455 Path => Project.Library_Dir,
3456 Dir_Exists => Dir_Exists,
3458 Create => "library",
3459 Must_Exist => False,
3460 Location => Lib_Dir.Location,
3461 Externally_Built => Project.Externally_Built);
3467 (Project.Library_Dir.Display_Name));
3470 if not Dir_Exists then
3472 -- Get the absolute name of the library directory that
3473 -- does not exist, to report an error.
3475 Err_Vars.Error_Msg_File_1 :=
3476 File_Name_Type (Project.Library_Dir.Display_Name);
3479 "library directory { does not exist",
3480 Lib_Dir.Location, Data);
3482 -- The library directory cannot be the same as the Object
3485 elsif Project.Library_Dir.Name = Project.Object_Directory.Name then
3488 "library directory cannot be the same " &
3489 "as object directory",
3490 Lib_Dir.Location, Data);
3491 Project.Library_Dir := No_Path_Information;
3495 OK : Boolean := True;
3496 Dirs_Id : String_List_Id;
3497 Dir_Elem : String_Element;
3501 -- The library directory cannot be the same as a source
3502 -- directory of the current project.
3504 Dirs_Id := Project.Source_Dirs;
3505 while Dirs_Id /= Nil_String loop
3506 Dir_Elem := Data.Tree.String_Elements.Table (Dirs_Id);
3507 Dirs_Id := Dir_Elem.Next;
3509 if Project.Library_Dir.Name =
3510 Path_Name_Type (Dir_Elem.Value)
3512 Err_Vars.Error_Msg_File_1 :=
3513 File_Name_Type (Dir_Elem.Value);
3516 "library directory cannot be the same " &
3517 "as source directory {",
3518 Lib_Dir.Location, Data);
3526 -- The library directory cannot be the same as a source
3527 -- directory of another project either.
3529 Pid := Data.Tree.Projects;
3531 exit Project_Loop when Pid = null;
3533 if Pid.Project /= Project then
3534 Dirs_Id := Pid.Project.Source_Dirs;
3536 Dir_Loop : while Dirs_Id /= Nil_String loop
3538 Data.Tree.String_Elements.Table (Dirs_Id);
3539 Dirs_Id := Dir_Elem.Next;
3541 if Project.Library_Dir.Name =
3542 Path_Name_Type (Dir_Elem.Value)
3544 Err_Vars.Error_Msg_File_1 :=
3545 File_Name_Type (Dir_Elem.Value);
3546 Err_Vars.Error_Msg_Name_1 := Pid.Project.Name;
3550 "library directory cannot be the same " &
3551 "as source directory { of project %%",
3552 Lib_Dir.Location, Data);
3560 end loop Project_Loop;
3564 Project.Library_Dir := No_Path_Information;
3566 elsif Current_Verbosity = High then
3568 -- Display the Library directory in high verbosity
3571 ("Library directory",
3572 Get_Name_String (Project.Library_Dir.Display_Name));
3581 Project.Library_Dir /= No_Path_Information
3582 and then Project.Library_Name /= No_Name;
3584 if Project.Extends = No_Project then
3585 case Project.Qualifier is
3587 if Project.Library then
3590 "a standard project cannot be a library project",
3591 Lib_Name.Location, Data);
3595 if not Project.Library then
3596 if Project.Library_Dir = No_Path_Information then
3599 "\attribute Library_Dir not declared",
3600 Project.Location, Data);
3603 if Project.Library_Name = No_Name then
3606 "\attribute Library_Name not declared",
3607 Project.Location, Data);
3617 if Project.Library then
3618 Support_For_Libraries := Project.Config.Lib_Support;
3620 if Support_For_Libraries = Prj.None then
3623 "?libraries are not supported on this platform",
3624 Lib_Name.Location, Data);
3625 Project.Library := False;
3628 if Lib_ALI_Dir.Value = Empty_String then
3629 if Current_Verbosity = High then
3630 Write_Line ("No library ALI directory specified");
3633 Project.Library_ALI_Dir := Project.Library_Dir;
3636 -- Find path name, check that it is a directory
3640 File_Name_Type (Lib_ALI_Dir.Value),
3641 Path => Project.Library_ALI_Dir,
3642 Create => "library ALI",
3643 Dir_Exists => Dir_Exists,
3645 Must_Exist => False,
3646 Location => Lib_ALI_Dir.Location,
3647 Externally_Built => Project.Externally_Built);
3649 if not Dir_Exists then
3651 -- Get the absolute name of the library ALI directory that
3652 -- does not exist, to report an error.
3654 Err_Vars.Error_Msg_File_1 :=
3655 File_Name_Type (Project.Library_ALI_Dir.Display_Name);
3658 "library 'A'L'I directory { does not exist",
3659 Lib_ALI_Dir.Location, Data);
3662 if Project.Library_ALI_Dir /= Project.Library_Dir then
3664 -- The library ALI directory cannot be the same as the
3665 -- Object directory.
3667 if Project.Library_ALI_Dir = Project.Object_Directory then
3670 "library 'A'L'I directory cannot be the same " &
3671 "as object directory",
3672 Lib_ALI_Dir.Location, Data);
3673 Project.Library_ALI_Dir := No_Path_Information;
3677 OK : Boolean := True;
3678 Dirs_Id : String_List_Id;
3679 Dir_Elem : String_Element;
3683 -- The library ALI directory cannot be the same as
3684 -- a source directory of the current project.
3686 Dirs_Id := Project.Source_Dirs;
3687 while Dirs_Id /= Nil_String loop
3689 Data.Tree.String_Elements.Table (Dirs_Id);
3690 Dirs_Id := Dir_Elem.Next;
3692 if Project.Library_ALI_Dir.Name =
3693 Path_Name_Type (Dir_Elem.Value)
3695 Err_Vars.Error_Msg_File_1 :=
3696 File_Name_Type (Dir_Elem.Value);
3699 "library 'A'L'I directory cannot be " &
3700 "the same as source directory {",
3701 Lib_ALI_Dir.Location, Data);
3709 -- The library ALI directory cannot be the same as
3710 -- a source directory of another project either.
3712 Pid := Data.Tree.Projects;
3713 ALI_Project_Loop : loop
3714 exit ALI_Project_Loop when Pid = null;
3716 if Pid.Project /= Project then
3717 Dirs_Id := Pid.Project.Source_Dirs;
3720 while Dirs_Id /= Nil_String loop
3722 Data.Tree.String_Elements.Table
3724 Dirs_Id := Dir_Elem.Next;
3726 if Project.Library_ALI_Dir.Name =
3727 Path_Name_Type (Dir_Elem.Value)
3729 Err_Vars.Error_Msg_File_1 :=
3730 File_Name_Type (Dir_Elem.Value);
3731 Err_Vars.Error_Msg_Name_1 :=
3736 "library 'A'L'I directory cannot " &
3737 "be the same as source directory " &
3739 Lib_ALI_Dir.Location, Data);
3741 exit ALI_Project_Loop;
3743 end loop ALI_Dir_Loop;
3746 end loop ALI_Project_Loop;
3750 Project.Library_ALI_Dir := No_Path_Information;
3752 elsif Current_Verbosity = High then
3754 -- Display Library ALI directory in high verbosity
3759 (Project.Library_ALI_Dir.Display_Name));
3766 pragma Assert (Lib_Version.Kind = Single);
3768 if Lib_Version.Value = Empty_String then
3769 if Current_Verbosity = High then
3770 Write_Line ("No library version specified");
3774 Project.Lib_Internal_Name := Lib_Version.Value;
3777 pragma Assert (The_Lib_Kind.Kind = Single);
3779 if The_Lib_Kind.Value = Empty_String then
3780 if Current_Verbosity = High then
3781 Write_Line ("No library kind specified");
3785 Get_Name_String (The_Lib_Kind.Value);
3788 Kind_Name : constant String :=
3789 To_Lower (Name_Buffer (1 .. Name_Len));
3791 OK : Boolean := True;
3794 if Kind_Name = "static" then
3795 Project.Library_Kind := Static;
3797 elsif Kind_Name = "dynamic" then
3798 Project.Library_Kind := Dynamic;
3800 elsif Kind_Name = "relocatable" then
3801 Project.Library_Kind := Relocatable;
3806 "illegal value for Library_Kind",
3807 The_Lib_Kind.Location, Data);
3811 if Current_Verbosity = High and then OK then
3812 Write_Attr ("Library kind", Kind_Name);
3815 if Project.Library_Kind /= Static then
3816 if Support_For_Libraries = Prj.Static_Only then
3819 "only static libraries are supported " &
3821 The_Lib_Kind.Location, Data);
3822 Project.Library := False;
3825 -- Check if (obsolescent) attribute Library_GCC or
3826 -- Linker'Driver is declared.
3828 if Lib_GCC.Value /= Empty_String then
3831 "?Library_'G'C'C is an obsolescent attribute, " &
3832 "use Linker''Driver instead",
3833 Lib_GCC.Location, Data);
3834 Project.Config.Shared_Lib_Driver :=
3835 File_Name_Type (Lib_GCC.Value);
3839 Linker : constant Package_Id :=
3842 Project.Decl.Packages,
3844 Driver : constant Variable_Value :=
3847 Attribute_Or_Array_Name =>
3849 In_Package => Linker,
3850 In_Tree => Data.Tree);
3853 if Driver /= Nil_Variable_Value
3854 and then Driver.Value /= Empty_String
3856 Project.Config.Shared_Lib_Driver :=
3857 File_Name_Type (Driver.Value);
3866 if Project.Library then
3867 if Current_Verbosity = High then
3868 Write_Line ("This is a library project file");
3871 Check_Library (Project.Extends, Extends => True);
3873 Imported_Project_List := Project.Imported_Projects;
3874 while Imported_Project_List /= null loop
3876 (Imported_Project_List.Project,
3878 Imported_Project_List := Imported_Project_List.Next;
3885 -- Check if Linker'Switches or Linker'Default_Switches are declared.
3886 -- Warn if they are declared, as it is a common error to think that
3887 -- library are "linked" with Linker switches.
3889 if Project.Library then
3891 Linker_Package_Id : constant Package_Id :=
3894 Project.Decl.Packages, Data.Tree);
3895 Linker_Package : Package_Element;
3896 Switches : Array_Element_Id := No_Array_Element;
3899 if Linker_Package_Id /= No_Package then
3900 Linker_Package := Data.Tree.Packages.Table (Linker_Package_Id);
3904 (Name => Name_Switches,
3905 In_Arrays => Linker_Package.Decl.Arrays,
3906 In_Tree => Data.Tree);
3908 if Switches = No_Array_Element then
3911 (Name => Name_Default_Switches,
3912 In_Arrays => Linker_Package.Decl.Arrays,
3913 In_Tree => Data.Tree);
3916 if Switches /= No_Array_Element then
3919 "?Linker switches not taken into account in library " &
3927 if Project.Extends /= No_Project then
3928 Project.Extends.Library := False;
3930 end Check_Library_Attributes;
3932 ---------------------------------
3933 -- Check_Programming_Languages --
3934 ---------------------------------
3936 procedure Check_Programming_Languages
3937 (Project : Project_Id;
3938 Data : in out Tree_Processing_Data)
3940 Languages : Variable_Value := Nil_Variable_Value;
3941 Def_Lang : Variable_Value := Nil_Variable_Value;
3942 Def_Lang_Id : Name_Id;
3944 procedure Add_Language (Name, Display_Name : Name_Id);
3945 -- Add a new language to the list of languages for the project.
3946 -- Nothing is done if the language has already been defined
3952 procedure Add_Language (Name, Display_Name : Name_Id) is
3953 Lang : Language_Ptr;
3956 Lang := Project.Languages;
3957 while Lang /= No_Language_Index loop
3958 if Name = Lang.Name then
3965 Lang := new Language_Data'(No_Language_Data);
3966 Lang.Next := Project.Languages;
3967 Project.Languages := Lang;
3969 Lang.Display_Name := Display_Name;
3971 if Name = Name_Ada then
3972 Lang.Config.Kind := Unit_Based;
3973 Lang.Config.Dependency_Kind := ALI_File;
3975 Lang.Config.Kind := File_Based;
3979 -- Start of processing for Check_Programming_Languages
3982 Project.Languages := null;
3984 Prj.Util.Value_Of (Name_Languages, Project.Decl.Attributes, Data.Tree);
3987 (Name_Default_Language, Project.Decl.Attributes, Data.Tree);
3989 if Project.Source_Dirs /= Nil_String then
3991 -- Check if languages are specified in this project
3993 if Languages.Default then
3995 -- Fail if there is no default language defined
3997 if Def_Lang.Default then
4000 "no languages defined for this project",
4001 Project.Location, Data);
4002 Def_Lang_Id := No_Name;
4005 Get_Name_String (Def_Lang.Value);
4006 To_Lower (Name_Buffer (1 .. Name_Len));
4007 Def_Lang_Id := Name_Find;
4010 if Def_Lang_Id /= No_Name then
4011 Get_Name_String (Def_Lang_Id);
4012 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4014 (Name => Def_Lang_Id,
4015 Display_Name => Name_Find);
4020 Current : String_List_Id := Languages.Values;
4021 Element : String_Element;
4024 -- If there are no languages declared, there are no sources
4026 if Current = Nil_String then
4027 Project.Source_Dirs := Nil_String;
4029 if Project.Qualifier = Standard then
4032 "a standard project must have at least one language",
4033 Languages.Location, Data);
4037 -- Look through all the languages specified in attribute
4040 while Current /= Nil_String loop
4041 Element := Data.Tree.String_Elements.Table (Current);
4042 Get_Name_String (Element.Value);
4043 To_Lower (Name_Buffer (1 .. Name_Len));
4047 Display_Name => Element.Value);
4049 Current := Element.Next;
4055 end Check_Programming_Languages;
4057 -------------------------------
4058 -- Check_Stand_Alone_Library --
4059 -------------------------------
4061 procedure Check_Stand_Alone_Library
4062 (Project : Project_Id;
4063 Data : in out Tree_Processing_Data)
4065 Lib_Interfaces : constant Prj.Variable_Value :=
4067 (Snames.Name_Library_Interface,
4068 Project.Decl.Attributes,
4071 Lib_Auto_Init : constant Prj.Variable_Value :=
4073 (Snames.Name_Library_Auto_Init,
4074 Project.Decl.Attributes,
4077 Lib_Src_Dir : constant Prj.Variable_Value :=
4079 (Snames.Name_Library_Src_Dir,
4080 Project.Decl.Attributes,
4083 Lib_Symbol_File : constant Prj.Variable_Value :=
4085 (Snames.Name_Library_Symbol_File,
4086 Project.Decl.Attributes,
4089 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4091 (Snames.Name_Library_Symbol_Policy,
4092 Project.Decl.Attributes,
4095 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4097 (Snames.Name_Library_Reference_Symbol_File,
4098 Project.Decl.Attributes,
4101 Auto_Init_Supported : Boolean;
4102 OK : Boolean := True;
4104 Next_Proj : Project_Id;
4105 Iter : Source_Iterator;
4108 Auto_Init_Supported := Project.Config.Auto_Init_Supported;
4110 pragma Assert (Lib_Interfaces.Kind = List);
4112 -- It is a stand-alone library project file if attribute
4113 -- Library_Interface is defined.
4115 if not Lib_Interfaces.Default then
4117 Interfaces : String_List_Id := Lib_Interfaces.Values;
4118 Interface_ALIs : String_List_Id := Nil_String;
4122 Project.Standalone_Library := True;
4124 -- Library_Interface cannot be an empty list
4126 if Interfaces = Nil_String then
4129 "Library_Interface cannot be an empty list",
4130 Lib_Interfaces.Location, Data);
4133 -- Process each unit name specified in the attribute
4134 -- Library_Interface.
4136 while Interfaces /= Nil_String loop
4138 (Data.Tree.String_Elements.Table (Interfaces).Value);
4139 To_Lower (Name_Buffer (1 .. Name_Len));
4141 if Name_Len = 0 then
4144 "an interface cannot be an empty string",
4145 Data.Tree.String_Elements.Table (Interfaces).Location,
4150 Error_Msg_Name_1 := Unit;
4152 Next_Proj := Project.Extends;
4153 Iter := For_Each_Source (Data.Tree, Project);
4155 while Prj.Element (Iter) /= No_Source
4157 (Prj.Element (Iter).Unit = null
4158 or else Prj.Element (Iter).Unit.Name /= Unit)
4163 Source := Prj.Element (Iter);
4164 exit when Source /= No_Source
4165 or else Next_Proj = No_Project;
4167 Iter := For_Each_Source (Data.Tree, Next_Proj);
4168 Next_Proj := Next_Proj.Extends;
4171 if Source /= No_Source then
4172 if Source.Kind = Sep then
4173 Source := No_Source;
4175 elsif Source.Kind = Spec
4176 and then Other_Part (Source) /= No_Source
4178 Source := Other_Part (Source);
4182 if Source /= No_Source then
4183 if Source.Project /= Project
4184 and then not Is_Extending (Project, Source.Project)
4186 Source := No_Source;
4190 if Source = No_Source then
4193 "%% is not a unit of this project",
4194 Data.Tree.String_Elements.Table
4195 (Interfaces).Location, Data);
4198 if Source.Kind = Spec
4199 and then Other_Part (Source) /= No_Source
4201 Source := Other_Part (Source);
4204 String_Element_Table.Increment_Last
4205 (Data.Tree.String_Elements);
4207 Data.Tree.String_Elements.Table
4208 (String_Element_Table.Last
4209 (Data.Tree.String_Elements)) :=
4210 (Value => Name_Id (Source.Dep_Name),
4212 Display_Value => Name_Id (Source.Dep_Name),
4214 Data.Tree.String_Elements.Table
4215 (Interfaces).Location,
4217 Next => Interface_ALIs);
4220 String_Element_Table.Last
4221 (Data.Tree.String_Elements);
4225 Interfaces := Data.Tree.String_Elements.Table (Interfaces).Next;
4228 -- Put the list of Interface ALIs in the project data
4230 Project.Lib_Interface_ALIs := Interface_ALIs;
4232 -- Check value of attribute Library_Auto_Init and set
4233 -- Lib_Auto_Init accordingly.
4235 if Lib_Auto_Init.Default then
4237 -- If no attribute Library_Auto_Init is declared, then set auto
4238 -- init only if it is supported.
4240 Project.Lib_Auto_Init := Auto_Init_Supported;
4243 Get_Name_String (Lib_Auto_Init.Value);
4244 To_Lower (Name_Buffer (1 .. Name_Len));
4246 if Name_Buffer (1 .. Name_Len) = "false" then
4247 Project.Lib_Auto_Init := False;
4249 elsif Name_Buffer (1 .. Name_Len) = "true" then
4250 if Auto_Init_Supported then
4251 Project.Lib_Auto_Init := True;
4254 -- Library_Auto_Init cannot be "true" if auto init is not
4259 "library auto init not supported " &
4261 Lib_Auto_Init.Location, Data);
4267 "invalid value for attribute Library_Auto_Init",
4268 Lib_Auto_Init.Location, Data);
4273 -- If attribute Library_Src_Dir is defined and not the empty string,
4274 -- check if the directory exist and is not the object directory or
4275 -- one of the source directories. This is the directory where copies
4276 -- of the interface sources will be copied. Note that this directory
4277 -- may be the library directory.
4279 if Lib_Src_Dir.Value /= Empty_String then
4281 Dir_Id : constant File_Name_Type :=
4282 File_Name_Type (Lib_Src_Dir.Value);
4283 Dir_Exists : Boolean;
4289 Path => Project.Library_Src_Dir,
4290 Dir_Exists => Dir_Exists,
4292 Must_Exist => False,
4293 Create => "library source copy",
4294 Location => Lib_Src_Dir.Location,
4295 Externally_Built => Project.Externally_Built);
4297 -- If directory does not exist, report an error
4299 if not Dir_Exists then
4301 -- Get the absolute name of the library directory that does
4302 -- not exist, to report an error.
4304 Err_Vars.Error_Msg_File_1 :=
4305 File_Name_Type (Project.Library_Src_Dir.Display_Name);
4308 "Directory { does not exist",
4309 Lib_Src_Dir.Location, Data);
4311 -- Report error if it is the same as the object directory
4313 elsif Project.Library_Src_Dir = Project.Object_Directory then
4316 "directory to copy interfaces cannot be " &
4317 "the object directory",
4318 Lib_Src_Dir.Location, Data);
4319 Project.Library_Src_Dir := No_Path_Information;
4323 Src_Dirs : String_List_Id;
4324 Src_Dir : String_Element;
4328 -- Interface copy directory cannot be one of the source
4329 -- directory of the current project.
4331 Src_Dirs := Project.Source_Dirs;
4332 while Src_Dirs /= Nil_String loop
4333 Src_Dir := Data.Tree.String_Elements.Table (Src_Dirs);
4335 -- Report error if it is one of the source directories
4337 if Project.Library_Src_Dir.Name =
4338 Path_Name_Type (Src_Dir.Value)
4342 "directory to copy interfaces cannot " &
4343 "be one of the source directories",
4344 Lib_Src_Dir.Location, Data);
4345 Project.Library_Src_Dir := No_Path_Information;
4349 Src_Dirs := Src_Dir.Next;
4352 if Project.Library_Src_Dir /= No_Path_Information then
4354 -- It cannot be a source directory of any other
4357 Pid := Data.Tree.Projects;
4359 exit Project_Loop when Pid = null;
4361 Src_Dirs := Pid.Project.Source_Dirs;
4362 Dir_Loop : while Src_Dirs /= Nil_String loop
4364 Data.Tree.String_Elements.Table (Src_Dirs);
4366 -- Report error if it is one of the source
4369 if Project.Library_Src_Dir.Name =
4370 Path_Name_Type (Src_Dir.Value)
4373 File_Name_Type (Src_Dir.Value);
4374 Error_Msg_Name_1 := Pid.Project.Name;
4377 "directory to copy interfaces cannot " &
4378 "be the same as source directory { of " &
4380 Lib_Src_Dir.Location, Data);
4381 Project.Library_Src_Dir :=
4382 No_Path_Information;
4386 Src_Dirs := Src_Dir.Next;
4390 end loop Project_Loop;
4394 -- In high verbosity, if there is a valid Library_Src_Dir,
4395 -- display its path name.
4397 if Project.Library_Src_Dir /= No_Path_Information
4398 and then Current_Verbosity = High
4401 ("Directory to copy interfaces",
4402 Get_Name_String (Project.Library_Src_Dir.Name));
4408 -- Check the symbol related attributes
4410 -- First, the symbol policy
4412 if not Lib_Symbol_Policy.Default then
4414 Value : constant String :=
4416 (Get_Name_String (Lib_Symbol_Policy.Value));
4419 -- Symbol policy must hove one of a limited number of values
4421 if Value = "autonomous" or else Value = "default" then
4422 Project.Symbol_Data.Symbol_Policy := Autonomous;
4424 elsif Value = "compliant" then
4425 Project.Symbol_Data.Symbol_Policy := Compliant;
4427 elsif Value = "controlled" then
4428 Project.Symbol_Data.Symbol_Policy := Controlled;
4430 elsif Value = "restricted" then
4431 Project.Symbol_Data.Symbol_Policy := Restricted;
4433 elsif Value = "direct" then
4434 Project.Symbol_Data.Symbol_Policy := Direct;
4439 "illegal value for Library_Symbol_Policy",
4440 Lib_Symbol_Policy.Location, Data);
4445 -- If attribute Library_Symbol_File is not specified, symbol policy
4446 -- cannot be Restricted.
4448 if Lib_Symbol_File.Default then
4449 if Project.Symbol_Data.Symbol_Policy = Restricted then
4452 "Library_Symbol_File needs to be defined when " &
4453 "symbol policy is Restricted",
4454 Lib_Symbol_Policy.Location, Data);
4458 -- Library_Symbol_File is defined
4460 Project.Symbol_Data.Symbol_File :=
4461 Path_Name_Type (Lib_Symbol_File.Value);
4463 Get_Name_String (Lib_Symbol_File.Value);
4465 if Name_Len = 0 then
4468 "symbol file name cannot be an empty string",
4469 Lib_Symbol_File.Location, Data);
4472 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
4475 for J in 1 .. Name_Len loop
4476 if Name_Buffer (J) = '/'
4477 or else Name_Buffer (J) = Directory_Separator
4486 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
4489 "symbol file name { is illegal. " &
4490 "Name cannot include directory info.",
4491 Lib_Symbol_File.Location, Data);
4496 -- If attribute Library_Reference_Symbol_File is not defined,
4497 -- symbol policy cannot be Compliant or Controlled.
4499 if Lib_Ref_Symbol_File.Default then
4500 if Project.Symbol_Data.Symbol_Policy = Compliant
4501 or else Project.Symbol_Data.Symbol_Policy = Controlled
4505 "a reference symbol file needs to be defined",
4506 Lib_Symbol_Policy.Location, Data);
4510 -- Library_Reference_Symbol_File is defined, check file exists
4512 Project.Symbol_Data.Reference :=
4513 Path_Name_Type (Lib_Ref_Symbol_File.Value);
4515 Get_Name_String (Lib_Ref_Symbol_File.Value);
4517 if Name_Len = 0 then
4520 "reference symbol file name cannot be an empty string",
4521 Lib_Symbol_File.Location, Data);
4524 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
4526 Add_Str_To_Name_Buffer
4527 (Get_Name_String (Project.Directory.Name));
4528 Add_Str_To_Name_Buffer
4529 (Get_Name_String (Lib_Ref_Symbol_File.Value));
4530 Project.Symbol_Data.Reference := Name_Find;
4533 if not Is_Regular_File
4534 (Get_Name_String (Project.Symbol_Data.Reference))
4537 File_Name_Type (Lib_Ref_Symbol_File.Value);
4539 -- For controlled and direct symbol policies, it is an error
4540 -- if the reference symbol file does not exist. For other
4541 -- symbol policies, this is just a warning
4544 Project.Symbol_Data.Symbol_Policy /= Controlled
4545 and then Project.Symbol_Data.Symbol_Policy /= Direct;
4549 "<library reference symbol file { does not exist",
4550 Lib_Ref_Symbol_File.Location, Data);
4552 -- In addition in the non-controlled case, if symbol policy
4553 -- is Compliant, it is changed to Autonomous, because there
4554 -- is no reference to check against, and we don't want to
4555 -- fail in this case.
4557 if Project.Symbol_Data.Symbol_Policy /= Controlled then
4558 if Project.Symbol_Data.Symbol_Policy = Compliant then
4559 Project.Symbol_Data.Symbol_Policy := Autonomous;
4564 -- If both the reference symbol file and the symbol file are
4565 -- defined, then check that they are not the same file.
4567 if Project.Symbol_Data.Symbol_File /= No_Path then
4568 Get_Name_String (Project.Symbol_Data.Symbol_File);
4570 if Name_Len > 0 then
4572 -- We do not need to pass a Directory to
4573 -- Normalize_Pathname, since the path_information
4574 -- already contains absolute information.
4576 Symb_Path : constant String :=
4579 (Project.Object_Directory.Name) &
4580 Name_Buffer (1 .. Name_Len),
4583 Opt.Follow_Links_For_Files);
4584 Ref_Path : constant String :=
4587 (Project.Symbol_Data.Reference),
4590 Opt.Follow_Links_For_Files);
4592 if Symb_Path = Ref_Path then
4595 "library reference symbol file and library" &
4596 " symbol file cannot be the same file",
4597 Lib_Ref_Symbol_File.Location, Data);
4605 end Check_Stand_Alone_Library;
4607 ----------------------------
4608 -- Compute_Directory_Last --
4609 ----------------------------
4611 function Compute_Directory_Last (Dir : String) return Natural is
4614 and then (Dir (Dir'Last - 1) = Directory_Separator
4616 Dir (Dir'Last - 1) = '/')
4618 return Dir'Last - 1;
4622 end Compute_Directory_Last;
4629 (Project : Project_Id;
4631 Flag_Location : Source_Ptr;
4632 Data : Tree_Processing_Data)
4634 Real_Location : Source_Ptr := Flag_Location;
4635 Error_Buffer : String (1 .. 5_000);
4636 Error_Last : Natural := 0;
4637 Name_Number : Natural := 0;
4638 File_Number : Natural := 0;
4639 First : Positive := Msg'First;
4642 procedure Add (C : Character);
4643 -- Add a character to the buffer
4645 procedure Add (S : String);
4646 -- Add a string to the buffer
4649 -- Add a name to the buffer
4652 -- Add a file name to the buffer
4658 procedure Add (C : Character) is
4660 Error_Last := Error_Last + 1;
4661 Error_Buffer (Error_Last) := C;
4664 procedure Add (S : String) is
4666 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
4667 Error_Last := Error_Last + S'Length;
4674 procedure Add_File is
4675 File : File_Name_Type;
4679 File_Number := File_Number + 1;
4683 File := Err_Vars.Error_Msg_File_1;
4685 File := Err_Vars.Error_Msg_File_2;
4687 File := Err_Vars.Error_Msg_File_3;
4692 Get_Name_String (File);
4693 Add (Name_Buffer (1 .. Name_Len));
4701 procedure Add_Name is
4706 Name_Number := Name_Number + 1;
4710 Name := Err_Vars.Error_Msg_Name_1;
4712 Name := Err_Vars.Error_Msg_Name_2;
4714 Name := Err_Vars.Error_Msg_Name_3;
4719 Get_Name_String (Name);
4720 Add (Name_Buffer (1 .. Name_Len));
4724 -- Start of processing for Error_Msg
4727 -- Display the error message in the traces so that it appears in the
4728 -- correct location in the traces (otherwise error messages are only
4729 -- displayed at the end and it is difficult to see when they were
4732 if Current_Verbosity = High then
4733 Write_Line ("ERROR: " & Msg);
4736 -- If location of error is unknown, use the location of the project
4738 if Real_Location = No_Location then
4739 Real_Location := Project.Location;
4742 if Data.Flags.Report_Error = null then
4743 Prj.Err.Error_Msg (Msg, Real_Location);
4747 -- Ignore continuation character
4749 if Msg (First) = '\' then
4753 if Msg (First) = '?' then
4757 elsif Msg (First) = '<' then
4760 if Err_Vars.Error_Msg_Warn then
4766 while Index <= Msg'Last loop
4767 if Msg (Index) = '{' then
4770 elsif Msg (Index) = '%' then
4771 if Index < Msg'Last and then Msg (Index + 1) = '%' then
4785 Data.Flags.Report_Error
4786 (Error_Buffer (1 .. Error_Last), Project, Data.Tree);
4789 ---------------------
4790 -- Get_Directories --
4791 ---------------------
4793 procedure Get_Directories
4794 (Project : Project_Id;
4795 Data : in out Tree_Processing_Data)
4797 package Recursive_Dirs is new GNAT.Dynamic_HTables.Simple_HTable
4798 (Header_Num => Header_Num,
4800 No_Element => False,
4804 -- Hash table stores recursive source directories, to avoid looking
4805 -- several times, and to avoid cycles that may be introduced by symbolic
4808 Visited : Recursive_Dirs.Instance;
4810 Object_Dir : constant Variable_Value :=
4812 (Name_Object_Dir, Project.Decl.Attributes, Data.Tree);
4814 Exec_Dir : constant Variable_Value :=
4816 (Name_Exec_Dir, Project.Decl.Attributes, Data.Tree);
4818 Source_Dirs : constant Variable_Value :=
4820 (Name_Source_Dirs, Project.Decl.Attributes, Data.Tree);
4822 Excluded_Source_Dirs : constant Variable_Value :=
4824 (Name_Excluded_Source_Dirs,
4825 Project.Decl.Attributes,
4828 Source_Files : constant Variable_Value :=
4831 Project.Decl.Attributes, Data.Tree);
4833 Last_Source_Dir : String_List_Id := Nil_String;
4835 Languages : constant Variable_Value :=
4837 (Name_Languages, Project.Decl.Attributes, Data.Tree);
4839 procedure Find_Source_Dirs
4840 (From : File_Name_Type;
4841 Location : Source_Ptr;
4842 Removed : Boolean := False);
4843 -- Find one or several source directories, and add (or remove, if
4844 -- Removed is True) them to list of source directories of the project.
4846 ----------------------
4847 -- Find_Source_Dirs --
4848 ----------------------
4850 procedure Find_Source_Dirs
4851 (From : File_Name_Type;
4852 Location : Source_Ptr;
4853 Removed : Boolean := False)
4855 Directory : constant String := Get_Name_String (From);
4856 Element : String_Element;
4858 procedure Recursive_Find_Dirs (Path : Name_Id);
4859 -- Find all the subdirectories (recursively) of Path and add them
4860 -- to the list of source directories of the project.
4862 -------------------------
4863 -- Recursive_Find_Dirs --
4864 -------------------------
4866 procedure Recursive_Find_Dirs (Path : Name_Id) is
4868 Name : String (1 .. 250);
4870 List : String_List_Id;
4871 Prev : String_List_Id;
4872 Element : String_Element;
4873 Found : Boolean := False;
4875 Non_Canonical_Path : Name_Id := No_Name;
4876 Canonical_Path : Name_Id := No_Name;
4878 The_Path : constant String :=
4880 (Get_Name_String (Path),
4882 Get_Name_String (Project.Directory.Display_Name),
4883 Resolve_Links => Opt.Follow_Links_For_Dirs) &
4884 Directory_Separator;
4886 The_Path_Last : constant Natural :=
4887 Compute_Directory_Last (The_Path);
4890 Name_Len := The_Path_Last - The_Path'First + 1;
4891 Name_Buffer (1 .. Name_Len) :=
4892 The_Path (The_Path'First .. The_Path_Last);
4893 Non_Canonical_Path := Name_Find;
4895 Name_Id (Canonical_Case_File_Name (Non_Canonical_Path));
4897 -- To avoid processing the same directory several times, check
4898 -- if the directory is already in Recursive_Dirs. If it is, then
4899 -- there is nothing to do, just return. If it is not, put it there
4900 -- and continue recursive processing.
4903 if Recursive_Dirs.Get (Visited, Canonical_Path) then
4906 Recursive_Dirs.Set (Visited, Canonical_Path, True);
4910 -- Check if directory is already in list
4912 List := Project.Source_Dirs;
4914 while List /= Nil_String loop
4915 Element := Data.Tree.String_Elements.Table (List);
4917 if Element.Value /= No_Name then
4918 Found := Element.Value = Canonical_Path;
4923 List := Element.Next;
4926 -- If directory is not already in list, put it there
4928 if (not Removed) and (not Found) then
4929 if Current_Verbosity = High then
4931 Write_Line (The_Path (The_Path'First .. The_Path_Last));
4934 String_Element_Table.Increment_Last (Data.Tree.String_Elements);
4936 (Value => Canonical_Path,
4937 Display_Value => Non_Canonical_Path,
4938 Location => No_Location,
4943 -- Case of first source directory
4945 if Last_Source_Dir = Nil_String then
4946 Project.Source_Dirs :=
4947 String_Element_Table.Last (Data.Tree.String_Elements);
4949 -- Here we already have source directories
4952 -- Link the previous last to the new one
4954 Data.Tree.String_Elements.Table
4955 (Last_Source_Dir).Next :=
4956 String_Element_Table.Last (Data.Tree.String_Elements);
4959 -- And register this source directory as the new last
4962 String_Element_Table.Last (Data.Tree.String_Elements);
4963 Data.Tree.String_Elements.Table (Last_Source_Dir) := Element;
4965 elsif Removed and Found then
4966 if Prev = Nil_String then
4967 Project.Source_Dirs :=
4968 Data.Tree.String_Elements.Table (List).Next;
4970 Data.Tree.String_Elements.Table (Prev).Next :=
4971 Data.Tree.String_Elements.Table (List).Next;
4975 -- Now look for subdirectories. We do that even when this
4976 -- directory is already in the list, because some of its
4977 -- subdirectories may not be in the list yet.
4979 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
4982 Read (Dir, Name, Last);
4985 if Name (1 .. Last) /= "."
4986 and then Name (1 .. Last) /= ".."
4988 -- Avoid . and .. directories
4990 if Current_Verbosity = High then
4991 Write_Str (" Checking ");
4992 Write_Line (Name (1 .. Last));
4996 Path_Name : constant String :=
4998 (Name => Name (1 .. Last),
5000 The_Path (The_Path'First .. The_Path_Last),
5001 Resolve_Links => Opt.Follow_Links_For_Dirs,
5002 Case_Sensitive => True);
5005 if Is_Directory (Path_Name) then
5007 -- We have found a new subdirectory, call self
5009 Name_Len := Path_Name'Length;
5010 Name_Buffer (1 .. Name_Len) := Path_Name;
5011 Recursive_Find_Dirs (Name_Find);
5020 when Directory_Error =>
5022 end Recursive_Find_Dirs;
5024 -- Start of processing for Find_Source_Dirs
5027 if Current_Verbosity = High and then not Removed then
5028 Write_Str ("Find_Source_Dirs (""");
5029 Write_Str (Directory);
5033 -- First, check if we are looking for a directory tree, indicated
5034 -- by "/**" at the end.
5036 if Directory'Length >= 3
5037 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5038 and then (Directory (Directory'Last - 2) = '/'
5040 Directory (Directory'Last - 2) = Directory_Separator)
5043 Project.Known_Order_Of_Source_Dirs := False;
5046 Name_Len := Directory'Length - 3;
5048 if Name_Len = 0 then
5050 -- Case of "/**": all directories in file system
5053 Name_Buffer (1) := Directory (Directory'First);
5056 Name_Buffer (1 .. Name_Len) :=
5057 Directory (Directory'First .. Directory'Last - 3);
5060 if Current_Verbosity = High then
5061 Write_Str ("Looking for all subdirectories of """);
5062 Write_Str (Name_Buffer (1 .. Name_Len));
5067 Base_Dir : constant File_Name_Type := Name_Find;
5068 Root_Dir : constant String :=
5070 (Name => Get_Name_String (Base_Dir),
5073 (Project.Directory.Display_Name),
5074 Resolve_Links => False,
5075 Case_Sensitive => True);
5078 if Root_Dir'Length = 0 then
5079 Err_Vars.Error_Msg_File_1 := Base_Dir;
5081 if Location = No_Location then
5084 "{ is not a valid directory.",
5085 Project.Location, Data);
5089 "{ is not a valid directory.",
5094 -- We have an existing directory, we register it and all of
5095 -- its subdirectories.
5097 if Current_Verbosity = High then
5098 Write_Line ("Looking for source directories:");
5101 Name_Len := Root_Dir'Length;
5102 Name_Buffer (1 .. Name_Len) := Root_Dir;
5103 Recursive_Find_Dirs (Name_Find);
5105 if Current_Verbosity = High then
5106 Write_Line ("End of looking for source directories.");
5111 -- We have a single directory
5115 Path_Name : Path_Information;
5116 List : String_List_Id;
5117 Prev : String_List_Id;
5118 Dir_Exists : Boolean;
5122 (Project => Project,
5125 Dir_Exists => Dir_Exists,
5127 Must_Exist => False);
5129 if not Dir_Exists then
5130 Err_Vars.Error_Msg_File_1 := From;
5132 if Location = No_Location then
5135 "{ is not a valid directory",
5136 Project.Location, Data);
5140 "{ is not a valid directory",
5146 Path : constant String :=
5147 Get_Name_String (Path_Name.Name);
5148 Last_Path : constant Natural :=
5149 Compute_Directory_Last (Path);
5151 Display_Path : constant String :=
5153 (Path_Name.Display_Name);
5154 Last_Display_Path : constant Natural :=
5155 Compute_Directory_Last
5157 Display_Path_Id : Name_Id;
5161 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
5162 Path_Id := Name_Find;
5164 Add_Str_To_Name_Buffer
5166 (Display_Path'First .. Last_Display_Path));
5167 Display_Path_Id := Name_Find;
5171 -- As it is an existing directory, we add it to the
5172 -- list of directories.
5174 String_Element_Table.Increment_Last
5175 (Data.Tree.String_Elements);
5179 Display_Value => Display_Path_Id,
5180 Location => No_Location,
5182 Next => Nil_String);
5184 if Last_Source_Dir = Nil_String then
5186 -- This is the first source directory
5188 Project.Source_Dirs := String_Element_Table.Last
5189 (Data.Tree.String_Elements);
5192 -- We already have source directories, link the
5193 -- previous last to the new one.
5195 Data.Tree.String_Elements.Table
5196 (Last_Source_Dir).Next :=
5197 String_Element_Table.Last
5198 (Data.Tree.String_Elements);
5201 -- And register this source directory as the new last
5203 Last_Source_Dir := String_Element_Table.Last
5204 (Data.Tree.String_Elements);
5205 Data.Tree.String_Elements.Table
5206 (Last_Source_Dir) := Element;
5209 -- Remove source dir, if present
5213 -- Look for source dir in current list
5215 List := Project.Source_Dirs;
5216 while List /= Nil_String loop
5217 Element := Data.Tree.String_Elements.Table (List);
5218 exit when Element.Value = Path_Id;
5220 List := Element.Next;
5223 if List /= Nil_String then
5224 -- Source dir was found, remove it from the list
5226 if Prev = Nil_String then
5227 Project.Source_Dirs :=
5228 Data.Tree.String_Elements.Table (List).Next;
5231 Data.Tree.String_Elements.Table (Prev).Next :=
5232 Data.Tree.String_Elements.Table (List).Next;
5241 Recursive_Dirs.Reset (Visited);
5242 end Find_Source_Dirs;
5244 -- Start of processing for Get_Directories
5246 Dir_Exists : Boolean;
5249 if Current_Verbosity = High then
5250 Write_Line ("Starting to look for directories");
5253 -- Set the object directory to its default which may be nil, if there
5254 -- is no sources in the project.
5256 if (((not Source_Files.Default)
5257 and then Source_Files.Values = Nil_String)
5259 ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
5261 ((not Languages.Default) and then Languages.Values = Nil_String))
5262 and then Project.Extends = No_Project
5264 Project.Object_Directory := No_Path_Information;
5266 Project.Object_Directory := Project.Directory;
5269 -- Check the object directory
5271 if Object_Dir.Value /= Empty_String then
5272 Get_Name_String (Object_Dir.Value);
5274 if Name_Len = 0 then
5277 "Object_Dir cannot be empty",
5278 Object_Dir.Location, Data);
5281 -- We check that the specified object directory does exist.
5282 -- However, even when it doesn't exist, we set it to a default
5283 -- value. This is for the benefit of tools that recover from
5284 -- errors; for example, these tools could create the non existent
5285 -- directory. We always return an absolute directory name though.
5289 File_Name_Type (Object_Dir.Value),
5290 Path => Project.Object_Directory,
5292 Dir_Exists => Dir_Exists,
5294 Location => Object_Dir.Location,
5295 Must_Exist => False,
5296 Externally_Built => Project.Externally_Built);
5299 and then not Project.Externally_Built
5301 -- The object directory does not exist, report an error if
5302 -- the project is not externally built.
5304 Err_Vars.Error_Msg_File_1 :=
5305 File_Name_Type (Object_Dir.Value);
5308 "object directory { not found",
5309 Project.Location, Data);
5313 elsif Project.Object_Directory /= No_Path_Information
5314 and then Subdirs /= null
5317 Name_Buffer (1) := '.';
5321 Path => Project.Object_Directory,
5323 Dir_Exists => Dir_Exists,
5325 Location => Object_Dir.Location,
5326 Externally_Built => Project.Externally_Built);
5329 if Current_Verbosity = High then
5330 if Project.Object_Directory = No_Path_Information then
5331 Write_Line ("No object directory");
5334 ("Object directory",
5335 Get_Name_String (Project.Object_Directory.Display_Name));
5339 -- Check the exec directory
5341 -- We set the object directory to its default
5343 Project.Exec_Directory := Project.Object_Directory;
5345 if Exec_Dir.Value /= Empty_String then
5346 Get_Name_String (Exec_Dir.Value);
5348 if Name_Len = 0 then
5351 "Exec_Dir cannot be empty",
5352 Exec_Dir.Location, Data);
5355 -- We check that the specified exec directory does exist
5359 File_Name_Type (Exec_Dir.Value),
5360 Path => Project.Exec_Directory,
5361 Dir_Exists => Dir_Exists,
5364 Location => Exec_Dir.Location,
5365 Externally_Built => Project.Externally_Built);
5367 if not Dir_Exists then
5368 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
5371 "exec directory { not found",
5372 Project.Location, Data);
5377 if Current_Verbosity = High then
5378 if Project.Exec_Directory = No_Path_Information then
5379 Write_Line ("No exec directory");
5381 Write_Str ("Exec directory: """);
5382 Write_Str (Get_Name_String (Project.Exec_Directory.Display_Name));
5387 -- Look for the source directories
5389 if Current_Verbosity = High then
5390 Write_Line ("Starting to look for source directories");
5393 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
5395 if (not Source_Files.Default)
5396 and then Source_Files.Values = Nil_String
5398 Project.Source_Dirs := Nil_String;
5400 if Project.Qualifier = Standard then
5403 "a standard project cannot have no sources",
5404 Source_Files.Location, Data);
5407 elsif Source_Dirs.Default then
5409 -- No Source_Dirs specified: the single source directory is the one
5410 -- containing the project file.
5412 String_Element_Table.Append (Data.Tree.String_Elements,
5413 (Value => Name_Id (Project.Directory.Name),
5414 Display_Value => Name_Id (Project.Directory.Display_Name),
5415 Location => No_Location,
5420 Project.Source_Dirs :=
5421 String_Element_Table.Last (Data.Tree.String_Elements);
5423 if Current_Verbosity = High then
5425 ("Default source directory",
5426 Get_Name_String (Project.Directory.Display_Name));
5429 elsif Source_Dirs.Values = Nil_String then
5430 if Project.Qualifier = Standard then
5433 "a standard project cannot have no source directories",
5434 Source_Dirs.Location, Data);
5437 Project.Source_Dirs := Nil_String;
5441 Source_Dir : String_List_Id;
5442 Element : String_Element;
5445 -- Process the source directories for each element of the list
5447 Source_Dir := Source_Dirs.Values;
5448 while Source_Dir /= Nil_String loop
5449 Element := Data.Tree.String_Elements.Table (Source_Dir);
5451 (File_Name_Type (Element.Value), Element.Location);
5452 Source_Dir := Element.Next;
5457 if not Excluded_Source_Dirs.Default
5458 and then Excluded_Source_Dirs.Values /= Nil_String
5461 Source_Dir : String_List_Id;
5462 Element : String_Element;
5465 -- Process the source directories for each element of the list
5467 Source_Dir := Excluded_Source_Dirs.Values;
5468 while Source_Dir /= Nil_String loop
5469 Element := Data.Tree.String_Elements.Table (Source_Dir);
5471 (File_Name_Type (Element.Value),
5474 Source_Dir := Element.Next;
5479 if Current_Verbosity = High then
5480 Write_Line ("Putting source directories in canonical cases");
5484 Current : String_List_Id := Project.Source_Dirs;
5485 Element : String_Element;
5488 while Current /= Nil_String loop
5489 Element := Data.Tree.String_Elements.Table (Current);
5490 if Element.Value /= No_Name then
5492 Name_Id (Canonical_Case_File_Name (Name_Id (Element.Value)));
5493 Data.Tree.String_Elements.Table (Current) := Element;
5496 Current := Element.Next;
5499 end Get_Directories;
5506 (Project : Project_Id;
5507 Data : in out Tree_Processing_Data)
5509 Mains : constant Variable_Value :=
5511 (Name_Main, Project.Decl.Attributes, Data.Tree);
5512 List : String_List_Id;
5513 Elem : String_Element;
5516 Project.Mains := Mains.Values;
5518 -- If no Mains were specified, and if we are an extending project,
5519 -- inherit the Mains from the project we are extending.
5521 if Mains.Default then
5522 if not Project.Library and then Project.Extends /= No_Project then
5523 Project.Mains := Project.Extends.Mains;
5526 -- In a library project file, Main cannot be specified
5528 elsif Project.Library then
5531 "a library project file cannot have Main specified",
5532 Mains.Location, Data);
5535 List := Mains.Values;
5536 while List /= Nil_String loop
5537 Elem := Data.Tree.String_Elements.Table (List);
5539 if Length_Of_Name (Elem.Value) = 0 then
5542 "?a main cannot have an empty name",
5543 Elem.Location, Data);
5552 ---------------------------
5553 -- Get_Sources_From_File --
5554 ---------------------------
5556 procedure Get_Sources_From_File
5558 Location : Source_Ptr;
5559 Project : in out Project_Processing_Data;
5560 Data : in out Tree_Processing_Data)
5562 File : Prj.Util.Text_File;
5563 Line : String (1 .. 250);
5565 Source_Name : File_Name_Type;
5566 Name_Loc : Name_Location;
5569 if Current_Verbosity = High then
5570 Write_Str ("Opening """);
5577 Prj.Util.Open (File, Path);
5579 if not Prj.Util.Is_Valid (File) then
5580 Error_Msg (Project.Project, "file does not exist", Location, Data);
5583 -- Read the lines one by one
5585 while not Prj.Util.End_Of_File (File) loop
5586 Prj.Util.Get_Line (File, Line, Last);
5588 -- A non empty, non comment line should contain a file name
5591 and then (Last = 1 or else Line (1 .. 2) /= "--")
5594 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
5595 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5596 Source_Name := Name_Find;
5598 -- Check that there is no directory information
5600 for J in 1 .. Last loop
5601 if Line (J) = '/' or else Line (J) = Directory_Separator then
5602 Error_Msg_File_1 := Source_Name;
5605 "file name cannot include directory information ({)",
5611 Name_Loc := Source_Names_Htable.Get
5612 (Project.Source_Names, Source_Name);
5614 if Name_Loc = No_Name_Location then
5616 (Name => Source_Name,
5617 Location => Location,
5618 Source => No_Source,
5622 Source_Names_Htable.Set
5623 (Project.Source_Names, Source_Name, Name_Loc);
5627 Prj.Util.Close (File);
5630 end Get_Sources_From_File;
5632 -----------------------
5633 -- Compute_Unit_Name --
5634 -----------------------
5636 procedure Compute_Unit_Name
5637 (File_Name : File_Name_Type;
5638 Naming : Lang_Naming_Data;
5639 Kind : out Source_Kind;
5641 Project : Project_Processing_Data;
5642 In_Tree : Project_Tree_Ref)
5644 Filename : constant String := Get_Name_String (File_Name);
5645 Last : Integer := Filename'Last;
5650 Unit_Except : Unit_Exception;
5651 Masked : Boolean := False;
5657 if Naming.Separate_Suffix = No_File
5658 or else Naming.Body_Suffix = No_File
5659 or else Naming.Spec_Suffix = No_File
5664 if Naming.Dot_Replacement = No_File then
5665 if Current_Verbosity = High then
5666 Write_Line (" No dot_replacement specified");
5672 Sep_Len := Integer (Length_Of_Name (Naming.Separate_Suffix));
5673 Spec_Len := Integer (Length_Of_Name (Naming.Spec_Suffix));
5674 Body_Len := Integer (Length_Of_Name (Naming.Body_Suffix));
5676 -- Choose the longest suffix that matches. If there are several matches,
5677 -- give priority to specs, then bodies, then separates.
5679 if Naming.Separate_Suffix /= Naming.Body_Suffix
5680 and then Suffix_Matches (Filename, Naming.Separate_Suffix)
5682 Last := Filename'Last - Sep_Len;
5686 if Filename'Last - Body_Len <= Last
5687 and then Suffix_Matches (Filename, Naming.Body_Suffix)
5689 Last := Natural'Min (Last, Filename'Last - Body_Len);
5693 if Filename'Last - Spec_Len <= Last
5694 and then Suffix_Matches (Filename, Naming.Spec_Suffix)
5696 Last := Natural'Min (Last, Filename'Last - Spec_Len);
5700 if Last = Filename'Last then
5701 if Current_Verbosity = High then
5702 Write_Line (" no matching suffix");
5708 -- Check that the casing matches
5710 if File_Names_Case_Sensitive then
5711 case Naming.Casing is
5712 when All_Lower_Case =>
5713 for J in Filename'First .. Last loop
5714 if Is_Letter (Filename (J))
5715 and then not Is_Lower (Filename (J))
5717 if Current_Verbosity = High then
5718 Write_Line (" Invalid casing");
5725 when All_Upper_Case =>
5726 for J in Filename'First .. Last loop
5727 if Is_Letter (Filename (J))
5728 and then not Is_Upper (Filename (J))
5730 if Current_Verbosity = High then
5731 Write_Line (" Invalid casing");
5738 when Mixed_Case | Unknown =>
5743 -- If Dot_Replacement is not a single dot, then there should not
5744 -- be any dot in the name.
5747 Dot_Repl : constant String :=
5748 Get_Name_String (Naming.Dot_Replacement);
5751 if Dot_Repl /= "." then
5752 for Index in Filename'First .. Last loop
5753 if Filename (Index) = '.' then
5754 if Current_Verbosity = High then
5755 Write_Line (" Invalid name, contains dot");
5762 Replace_Into_Name_Buffer
5763 (Filename (Filename'First .. Last), Dot_Repl, '.');
5766 Name_Len := Last - Filename'First + 1;
5767 Name_Buffer (1 .. Name_Len) := Filename (Filename'First .. Last);
5769 (Source => Name_Buffer (1 .. Name_Len),
5770 Mapping => Lower_Case_Map);
5774 -- In the standard GNAT naming scheme, check for special cases: children
5775 -- or separates of A, G, I or S, and run time sources.
5777 if Is_Standard_GNAT_Naming (Naming)
5778 and then Name_Len >= 3
5781 S1 : constant Character := Name_Buffer (1);
5782 S2 : constant Character := Name_Buffer (2);
5783 S3 : constant Character := Name_Buffer (3);
5791 -- Children or separates of packages A, G, I or S. These names
5792 -- are x__ ... or x~... (where x is a, g, i, or s). Both
5793 -- versions (x__... and x~...) are allowed in all platforms,
5794 -- because it is not possible to know the platform before
5795 -- processing of the project files.
5797 if S2 = '_' and then S3 = '_' then
5798 Name_Buffer (2) := '.';
5799 Name_Buffer (3 .. Name_Len - 1) :=
5800 Name_Buffer (4 .. Name_Len);
5801 Name_Len := Name_Len - 1;
5804 Name_Buffer (2) := '.';
5808 -- If it is potentially a run time source
5816 -- Name_Buffer contains the name of the the unit in lower-cases. Check
5817 -- that this is a valid unit name
5819 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
5821 -- If there is a naming exception for the same unit, the file is not
5822 -- a source for the unit.
5824 if Unit /= No_Name then
5826 Unit_Exceptions_Htable.Get (Project.Unit_Exceptions, Unit);
5829 Masked := Unit_Except.Spec /= No_File
5831 Unit_Except.Spec /= File_Name;
5833 Masked := Unit_Except.Impl /= No_File
5835 Unit_Except.Impl /= File_Name;
5839 if Current_Verbosity = High then
5840 Write_Str (" """ & Filename & """ contains the ");
5843 Write_Str ("spec of a unit found in """);
5844 Write_Str (Get_Name_String (Unit_Except.Spec));
5846 Write_Str ("body of a unit found in """);
5847 Write_Str (Get_Name_String (Unit_Except.Impl));
5850 Write_Line (""" (ignored)");
5858 and then Current_Verbosity = High
5861 when Spec => Write_Str (" spec of ");
5862 when Impl => Write_Str (" body of ");
5863 when Sep => Write_Str (" sep of ");
5866 Write_Line (Get_Name_String (Unit));
5868 end Compute_Unit_Name;
5870 --------------------------
5871 -- Check_Illegal_Suffix --
5872 --------------------------
5874 procedure Check_Illegal_Suffix
5875 (Project : Project_Id;
5876 Suffix : File_Name_Type;
5877 Dot_Replacement : File_Name_Type;
5878 Attribute_Name : String;
5879 Location : Source_Ptr;
5880 Data : in out Tree_Processing_Data)
5882 Suffix_Str : constant String := Get_Name_String (Suffix);
5885 if Suffix_Str'Length = 0 then
5891 elsif Index (Suffix_Str, ".") = 0 then
5892 Err_Vars.Error_Msg_File_1 := Suffix;
5895 "{ is illegal for " & Attribute_Name & ": must have a dot",
5900 -- Case of dot replacement is a single dot, and first character of
5901 -- suffix is also a dot.
5903 if Dot_Replacement /= No_File
5904 and then Get_Name_String (Dot_Replacement) = "."
5905 and then Suffix_Str (Suffix_Str'First) = '.'
5907 for Index in Suffix_Str'First + 1 .. Suffix_Str'Last loop
5909 -- If there are multiple dots in the name
5911 if Suffix_Str (Index) = '.' then
5913 -- It is illegal to have a letter following the initial dot
5915 if Is_Letter (Suffix_Str (Suffix_Str'First + 1)) then
5916 Err_Vars.Error_Msg_File_1 := Suffix;
5919 "{ is illegal for " & Attribute_Name
5920 & ": ambiguous prefix when Dot_Replacement is a dot",
5927 end Check_Illegal_Suffix;
5929 ----------------------
5930 -- Locate_Directory --
5931 ----------------------
5933 procedure Locate_Directory
5934 (Project : Project_Id;
5935 Name : File_Name_Type;
5936 Path : out Path_Information;
5937 Dir_Exists : out Boolean;
5938 Data : in out Tree_Processing_Data;
5939 Create : String := "";
5940 Location : Source_Ptr := No_Location;
5941 Must_Exist : Boolean := True;
5942 Externally_Built : Boolean := False)
5944 Parent : constant Path_Name_Type :=
5945 Project.Directory.Display_Name;
5946 The_Parent : constant String :=
5947 Get_Name_String (Parent);
5948 The_Parent_Last : constant Natural :=
5949 Compute_Directory_Last (The_Parent);
5950 Full_Name : File_Name_Type;
5951 The_Name : File_Name_Type;
5954 Get_Name_String (Name);
5956 -- Add Subdirs.all if it is a directory that may be created and
5957 -- Subdirs is not null;
5959 if Create /= "" and then Subdirs /= null then
5960 if Name_Buffer (Name_Len) /= Directory_Separator then
5961 Add_Char_To_Name_Buffer (Directory_Separator);
5964 Add_Str_To_Name_Buffer (Subdirs.all);
5967 -- Convert '/' to directory separator (for Windows)
5969 for J in 1 .. Name_Len loop
5970 if Name_Buffer (J) = '/' then
5971 Name_Buffer (J) := Directory_Separator;
5975 The_Name := Name_Find;
5977 if Current_Verbosity = High then
5978 Write_Str ("Locate_Directory (""");
5979 Write_Str (Get_Name_String (The_Name));
5980 Write_Str (""", """);
5981 Write_Str (The_Parent);
5985 Path := No_Path_Information;
5986 Dir_Exists := False;
5988 if Is_Absolute_Path (Get_Name_String (The_Name)) then
5989 Full_Name := The_Name;
5993 Add_Str_To_Name_Buffer
5994 (The_Parent (The_Parent'First .. The_Parent_Last));
5995 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
5996 Full_Name := Name_Find;
6000 Full_Path_Name : String_Access :=
6001 new String'(Get_Name_String (Full_Name));
6004 if (Setup_Projects or else Subdirs /= null)
6005 and then Create'Length > 0
6007 if not Is_Directory (Full_Path_Name.all) then
6009 -- If project is externally built, do not create a subdir,
6010 -- use the specified directory, without the subdir.
6012 if Externally_Built then
6013 if Is_Absolute_Path (Get_Name_String (Name)) then
6014 Get_Name_String (Name);
6018 Add_Str_To_Name_Buffer
6019 (The_Parent (The_Parent'First .. The_Parent_Last));
6020 Add_Str_To_Name_Buffer (Get_Name_String (Name));
6023 Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
6027 Create_Path (Full_Path_Name.all);
6029 if not Quiet_Output then
6031 Write_Str (" directory """);
6032 Write_Str (Full_Path_Name.all);
6033 Write_Str (""" created for project ");
6034 Write_Line (Get_Name_String (Project.Name));
6041 "could not create " & Create &
6042 " directory " & Full_Path_Name.all,
6049 Dir_Exists := Is_Directory (Full_Path_Name.all);
6051 if not Must_Exist or else Dir_Exists then
6053 Normed : constant String :=
6055 (Full_Path_Name.all,
6057 The_Parent (The_Parent'First .. The_Parent_Last),
6058 Resolve_Links => False,
6059 Case_Sensitive => True);
6061 Canonical_Path : constant String :=
6066 (The_Parent'First .. The_Parent_Last),
6068 Opt.Follow_Links_For_Dirs,
6069 Case_Sensitive => False);
6072 Name_Len := Normed'Length;
6073 Name_Buffer (1 .. Name_Len) := Normed;
6075 -- Directories should always end with a directory separator
6077 if Name_Buffer (Name_Len) /= Directory_Separator then
6078 Add_Char_To_Name_Buffer (Directory_Separator);
6081 Path.Display_Name := Name_Find;
6083 Name_Len := Canonical_Path'Length;
6084 Name_Buffer (1 .. Name_Len) := Canonical_Path;
6086 if Name_Buffer (Name_Len) /= Directory_Separator then
6087 Add_Char_To_Name_Buffer (Directory_Separator);
6090 Path.Name := Name_Find;
6094 Free (Full_Path_Name);
6096 end Locate_Directory;
6098 ---------------------------
6099 -- Find_Excluded_Sources --
6100 ---------------------------
6102 procedure Find_Excluded_Sources
6103 (Project : in out Project_Processing_Data;
6104 Data : in out Tree_Processing_Data)
6106 Excluded_Source_List_File : constant Variable_Value :=
6108 (Name_Excluded_Source_List_File,
6109 Project.Project.Decl.Attributes,
6111 Excluded_Sources : Variable_Value := Util.Value_Of
6112 (Name_Excluded_Source_Files,
6113 Project.Project.Decl.Attributes,
6116 Current : String_List_Id;
6117 Element : String_Element;
6118 Location : Source_Ptr;
6119 Name : File_Name_Type;
6120 File : Prj.Util.Text_File;
6121 Line : String (1 .. 300);
6123 Locally_Removed : Boolean := False;
6126 -- If Excluded_Source_Files is not declared, check Locally_Removed_Files
6128 if Excluded_Sources.Default then
6129 Locally_Removed := True;
6132 (Name_Locally_Removed_Files,
6133 Project.Project.Decl.Attributes, Data.Tree);
6136 -- If there are excluded sources, put them in the table
6138 if not Excluded_Sources.Default then
6139 if not Excluded_Source_List_File.Default then
6140 if Locally_Removed then
6143 "?both attributes Locally_Removed_Files and " &
6144 "Excluded_Source_List_File are present",
6145 Excluded_Source_List_File.Location, Data);
6149 "?both attributes Excluded_Source_Files and " &
6150 "Excluded_Source_List_File are present",
6151 Excluded_Source_List_File.Location, Data);
6155 Current := Excluded_Sources.Values;
6156 while Current /= Nil_String loop
6157 Element := Data.Tree.String_Elements.Table (Current);
6158 Name := Canonical_Case_File_Name (Element.Value);
6160 -- If the element has no location, then use the location of
6161 -- Excluded_Sources to report possible errors.
6163 if Element.Location = No_Location then
6164 Location := Excluded_Sources.Location;
6166 Location := Element.Location;
6169 Excluded_Sources_Htable.Set
6170 (Project.Excluded, Name, (Name, False, Location));
6171 Current := Element.Next;
6174 elsif not Excluded_Source_List_File.Default then
6175 Location := Excluded_Source_List_File.Location;
6178 Source_File_Path_Name : constant String :=
6181 (Excluded_Source_List_File.Value),
6182 Project.Project.Directory.Name);
6185 if Source_File_Path_Name'Length = 0 then
6186 Err_Vars.Error_Msg_File_1 :=
6187 File_Name_Type (Excluded_Source_List_File.Value);
6190 "file with excluded sources { does not exist",
6191 Excluded_Source_List_File.Location, Data);
6196 Prj.Util.Open (File, Source_File_Path_Name);
6198 if not Prj.Util.Is_Valid (File) then
6200 (Project.Project, "file does not exist", Location, Data);
6202 -- Read the lines one by one
6204 while not Prj.Util.End_Of_File (File) loop
6205 Prj.Util.Get_Line (File, Line, Last);
6207 -- Non empty, non comment line should contain a file name
6210 and then (Last = 1 or else Line (1 .. 2) /= "--")
6213 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6214 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6217 -- Check that there is no directory information
6219 for J in 1 .. Last loop
6221 or else Line (J) = Directory_Separator
6223 Error_Msg_File_1 := Name;
6226 "file name cannot include " &
6227 "directory information ({)",
6233 Excluded_Sources_Htable.Set
6234 (Project.Excluded, Name, (Name, False, Location));
6238 Prj.Util.Close (File);
6243 end Find_Excluded_Sources;
6249 procedure Find_Sources
6250 (Project : in out Project_Processing_Data;
6251 Data : in out Tree_Processing_Data)
6253 Sources : constant Variable_Value :=
6256 Project.Project.Decl.Attributes,
6259 Source_List_File : constant Variable_Value :=
6261 (Name_Source_List_File,
6262 Project.Project.Decl.Attributes,
6265 Name_Loc : Name_Location;
6266 Has_Explicit_Sources : Boolean;
6269 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
6271 (Source_List_File.Kind = Single,
6272 "Source_List_File is not a single string");
6274 Project.Source_List_File_Location := Source_List_File.Location;
6276 -- If the user has specified a Source_Files attribute
6278 if not Sources.Default then
6279 if not Source_List_File.Default then
6282 "?both attributes source_files and " &
6283 "source_list_file are present",
6284 Source_List_File.Location, Data);
6287 -- Sources is a list of file names
6290 Current : String_List_Id := Sources.Values;
6291 Element : String_Element;
6292 Location : Source_Ptr;
6293 Name : File_Name_Type;
6296 if Current = Nil_String then
6297 Project.Project.Languages := No_Language_Index;
6299 -- This project contains no source. For projects that don't
6300 -- extend other projects, this also means that there is no
6301 -- need for an object directory, if not specified.
6303 if Project.Project.Extends = No_Project
6304 and then Project.Project.Object_Directory =
6305 Project.Project.Directory
6307 Project.Project.Object_Directory := No_Path_Information;
6311 while Current /= Nil_String loop
6312 Element := Data.Tree.String_Elements.Table (Current);
6313 Name := Canonical_Case_File_Name (Element.Value);
6314 Get_Name_String (Element.Value);
6316 -- If the element has no location, then use the location of
6317 -- Sources to report possible errors.
6319 if Element.Location = No_Location then
6320 Location := Sources.Location;
6322 Location := Element.Location;
6325 -- Check that there is no directory information
6327 for J in 1 .. Name_Len loop
6328 if Name_Buffer (J) = '/'
6329 or else Name_Buffer (J) = Directory_Separator
6331 Error_Msg_File_1 := Name;
6334 "file name cannot include directory " &
6341 -- Check whether the file is already there: the same file name
6342 -- may be in the list. If the source is missing, the error will
6343 -- be on the first mention of the source file name.
6345 Name_Loc := Source_Names_Htable.Get
6346 (Project.Source_Names, Name);
6348 if Name_Loc = No_Name_Location then
6351 Location => Location,
6352 Source => No_Source,
6354 Source_Names_Htable.Set
6355 (Project.Source_Names, Name, Name_Loc);
6358 Current := Element.Next;
6361 Has_Explicit_Sources := True;
6364 -- If we have no Source_Files attribute, check the Source_List_File
6367 elsif not Source_List_File.Default then
6369 -- Source_List_File is the name of the file that contains the source
6373 Source_File_Path_Name : constant String :=
6375 (File_Name_Type (Source_List_File.Value),
6376 Project.Project.Directory.Name);
6379 Has_Explicit_Sources := True;
6381 if Source_File_Path_Name'Length = 0 then
6382 Err_Vars.Error_Msg_File_1 :=
6383 File_Name_Type (Source_List_File.Value);
6386 "file with sources { does not exist",
6387 Source_List_File.Location, Data);
6390 Get_Sources_From_File
6391 (Source_File_Path_Name, Source_List_File.Location,
6397 -- Neither Source_Files nor Source_List_File has been specified. Find
6398 -- all the files that satisfy the naming scheme in all the source
6401 Has_Explicit_Sources := False;
6407 For_All_Sources => Sources.Default and then Source_List_File.Default);
6409 -- Check if all exceptions have been found.
6413 Iter : Source_Iterator;
6416 Iter := For_Each_Source (Data.Tree, Project.Project);
6418 Source := Prj.Element (Iter);
6419 exit when Source = No_Source;
6421 if Source.Naming_Exception
6422 and then Source.Path = No_Path_Information
6424 if Source.Unit /= No_Unit_Index then
6426 -- For multi-unit source files, source_id gets duplicated
6427 -- once for every unit. Only the first source_id got its
6428 -- full path set. So if it isn't set for that first one,
6429 -- the file wasn't found. Otherwise we need to update for
6430 -- units after the first one.
6433 or else Source.Index = 1
6435 Error_Msg_Name_1 := Name_Id (Source.Display_File);
6436 Error_Msg_Name_2 := Name_Id (Source.Unit.Name);
6439 "source file %% for unit %% not found",
6444 Source.Path := Files_Htable.Get
6445 (Data.File_To_Source, Source.File).Path;
6447 if Current_Verbosity = High then
6448 if Source.Path /= No_Path_Information then
6449 Write_Line ("Setting full path for "
6450 & Get_Name_String (Source.File)
6451 & " at" & Source.Index'Img
6453 & Get_Name_String (Source.Path.Name));
6459 if Source.Path = No_Path_Information then
6460 Remove_Source (Source, No_Source);
6468 -- It is an error if a source file name in a source list or in a source
6469 -- list file is not found.
6471 if Has_Explicit_Sources then
6474 First_Error : Boolean;
6477 NL := Source_Names_Htable.Get_First (Project.Source_Names);
6478 First_Error := True;
6479 while NL /= No_Name_Location loop
6480 if not NL.Found then
6481 Err_Vars.Error_Msg_File_1 := NL.Name;
6486 "source file { not found",
6488 First_Error := False;
6493 "\source file { not found",
6498 NL := Source_Names_Htable.Get_Next (Project.Source_Names);
6508 procedure Initialize
6509 (Data : out Tree_Processing_Data;
6510 Tree : Project_Tree_Ref;
6511 Flags : Prj.Processing_Flags)
6514 Files_Htable.Reset (Data.File_To_Source);
6516 Data.Flags := Flags;
6523 procedure Free (Data : in out Tree_Processing_Data) is
6525 Files_Htable.Reset (Data.File_To_Source);
6532 procedure Initialize
6533 (Data : in out Project_Processing_Data;
6534 Project : Project_Id)
6537 Data.Project := Project;
6544 procedure Free (Data : in out Project_Processing_Data) is
6546 Source_Names_Htable.Reset (Data.Source_Names);
6547 Unit_Exceptions_Htable.Reset (Data.Unit_Exceptions);
6548 Excluded_Sources_Htable.Reset (Data.Excluded);
6551 -------------------------------
6552 -- Check_File_Naming_Schemes --
6553 -------------------------------
6555 procedure Check_File_Naming_Schemes
6556 (In_Tree : Project_Tree_Ref;
6557 Project : Project_Processing_Data;
6558 File_Name : File_Name_Type;
6559 Alternate_Languages : out Language_List;
6560 Language : out Language_Ptr;
6561 Display_Language_Name : out Name_Id;
6563 Lang_Kind : out Language_Kind;
6564 Kind : out Source_Kind)
6566 Filename : constant String := Get_Name_String (File_Name);
6567 Config : Language_Config;
6568 Tmp_Lang : Language_Ptr;
6570 Header_File : Boolean := False;
6571 -- True if we found at least one language for which the file is a header
6572 -- In such a case, we search for all possible languages where this is
6573 -- also a header (C and C++ for instance), since the file might be used
6574 -- for several such languages.
6576 procedure Check_File_Based_Lang;
6577 -- Does the naming scheme test for file-based languages. For those,
6578 -- there is no Unit. Just check if the file name has the implementation
6579 -- or, if it is specified, the template suffix of the language.
6581 -- Returns True if the file belongs to the current language and we
6582 -- should stop searching for matching languages. Not that a given header
6583 -- file could belong to several languages (C and C++ for instance). Thus
6584 -- if we found a header we'll check whether it matches other languages.
6586 ---------------------------
6587 -- Check_File_Based_Lang --
6588 ---------------------------
6590 procedure Check_File_Based_Lang is
6593 and then Suffix_Matches (Filename, Config.Naming_Data.Body_Suffix)
6597 Language := Tmp_Lang;
6599 if Current_Verbosity = High then
6600 Write_Str (" implementation of language ");
6601 Write_Line (Get_Name_String (Display_Language_Name));
6604 elsif Suffix_Matches (Filename, Config.Naming_Data.Spec_Suffix) then
6605 if Current_Verbosity = High then
6606 Write_Str (" header of language ");
6607 Write_Line (Get_Name_String (Display_Language_Name));
6611 Alternate_Languages := new Language_List_Element'
6612 (Language => Language,
6613 Next => Alternate_Languages);
6616 Header_File := True;
6619 Language := Tmp_Lang;
6622 end Check_File_Based_Lang;
6624 -- Start of processing for Check_File_Naming_Schemes
6627 Language := No_Language_Index;
6628 Alternate_Languages := null;
6629 Display_Language_Name := No_Name;
6631 Lang_Kind := File_Based;
6634 Tmp_Lang := Project.Project.Languages;
6635 while Tmp_Lang /= No_Language_Index loop
6636 if Current_Verbosity = High then
6638 (" Testing language "
6639 & Get_Name_String (Tmp_Lang.Name)
6640 & " Header_File=" & Header_File'Img);
6643 Display_Language_Name := Tmp_Lang.Display_Name;
6644 Config := Tmp_Lang.Config;
6645 Lang_Kind := Config.Kind;
6649 Check_File_Based_Lang;
6650 exit when Kind = Impl;
6654 -- We know it belongs to a least a file_based language, no
6655 -- need to check unit-based ones.
6657 if not Header_File then
6659 (File_Name => File_Name,
6660 Naming => Config.Naming_Data,
6664 In_Tree => In_Tree);
6666 if Unit /= No_Name then
6667 Language := Tmp_Lang;
6673 Tmp_Lang := Tmp_Lang.Next;
6676 if Language = No_Language_Index
6677 and then Current_Verbosity = High
6679 Write_Line (" not a source of any language");
6681 end Check_File_Naming_Schemes;
6687 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind) is
6689 -- If the file was previously already associated with a unit, change it
6691 if Source.Unit /= null
6692 and then Source.Kind in Spec_Or_Body
6693 and then Source.Unit.File_Names (Source.Kind) /= null
6695 -- If we had another file referencing the same unit (for instance it
6696 -- was in an extended project), that source file is in fact invisible
6697 -- from now on, and in particular doesn't belong to the same unit.
6699 if Source.Unit.File_Names (Source.Kind) /= Source then
6700 Source.Unit.File_Names (Source.Kind).Unit := No_Unit_Index;
6703 Source.Unit.File_Names (Source.Kind) := null;
6706 Source.Kind := Kind;
6708 if Source.Kind in Spec_Or_Body and then Source.Unit /= null then
6709 Source.Unit.File_Names (Source.Kind) := Source;
6717 procedure Check_File
6718 (Project : in out Project_Processing_Data;
6719 Data : in out Tree_Processing_Data;
6720 Path : Path_Name_Type;
6721 File_Name : File_Name_Type;
6722 Display_File_Name : File_Name_Type;
6723 Locally_Removed : Boolean;
6724 For_All_Sources : Boolean)
6726 Canonical_Path : constant Path_Name_Type :=
6728 (Canonical_Case_File_Name (Name_Id (Path)));
6730 Name_Loc : Name_Location :=
6731 Source_Names_Htable.Get
6732 (Project.Source_Names, File_Name);
6733 Check_Name : Boolean := False;
6734 Alternate_Languages : Language_List;
6735 Language : Language_Ptr;
6737 Src_Ind : Source_File_Index;
6739 Display_Language_Name : Name_Id;
6740 Lang_Kind : Language_Kind;
6741 Kind : Source_Kind := Spec;
6744 if Name_Loc = No_Name_Location then
6745 Check_Name := For_All_Sources;
6748 if Name_Loc.Found then
6750 -- Check if it is OK to have the same file name in several
6751 -- source directories.
6753 if not Project.Project.Known_Order_Of_Source_Dirs then
6754 Error_Msg_File_1 := File_Name;
6757 "{ is found in several source directories",
6758 Name_Loc.Location, Data);
6762 Name_Loc.Found := True;
6764 Source_Names_Htable.Set
6765 (Project.Source_Names, File_Name, Name_Loc);
6767 if Name_Loc.Source = No_Source then
6771 Name_Loc.Source.Path := (Canonical_Path, Path);
6773 Source_Paths_Htable.Set
6774 (Data.Tree.Source_Paths_HT,
6778 -- Check if this is a subunit
6780 if Name_Loc.Source.Unit /= No_Unit_Index
6781 and then Name_Loc.Source.Kind = Impl
6783 Src_Ind := Sinput.P.Load_Project_File
6784 (Get_Name_String (Canonical_Path));
6786 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
6787 Override_Kind (Name_Loc.Source, Sep);
6792 (Data.File_To_Source, File_Name, Name_Loc.Source);
6798 Check_File_Naming_Schemes
6799 (In_Tree => Data.Tree,
6801 File_Name => File_Name,
6802 Alternate_Languages => Alternate_Languages,
6803 Language => Language,
6804 Display_Language_Name => Display_Language_Name,
6806 Lang_Kind => Lang_Kind,
6809 if Language = No_Language_Index then
6811 -- A file name in a list must be a source of a language
6813 if Data.Flags.Error_On_Unknown_Language
6814 and then Name_Loc.Found
6816 Error_Msg_File_1 := File_Name;
6819 "language unknown for {",
6820 Name_Loc.Location, Data);
6826 Project => Project.Project,
6827 Lang_Id => Language,
6830 Alternate_Languages => Alternate_Languages,
6831 File_Name => File_Name,
6832 Display_File => Display_File_Name,
6834 Path => (Canonical_Path, Path));
6836 if Source /= No_Source then
6837 Source.Locally_Removed := Locally_Removed;
6843 ------------------------
6844 -- Search_Directories --
6845 ------------------------
6847 procedure Search_Directories
6848 (Project : in out Project_Processing_Data;
6849 Data : in out Tree_Processing_Data;
6850 For_All_Sources : Boolean)
6852 Source_Dir : String_List_Id;
6853 Element : String_Element;
6855 Name : String (1 .. 1_000);
6857 File_Name : File_Name_Type;
6858 Display_File_Name : File_Name_Type;
6861 if Current_Verbosity = High then
6862 Write_Line ("Looking for sources:");
6865 -- Loop through subdirectories
6867 Source_Dir := Project.Project.Source_Dirs;
6868 while Source_Dir /= Nil_String loop
6870 Element := Data.Tree.String_Elements.Table (Source_Dir);
6871 if Element.Value /= No_Name then
6872 Get_Name_String (Element.Display_Value);
6875 Source_Directory : constant String :=
6876 Name_Buffer (1 .. Name_Len) &
6877 Directory_Separator;
6879 Dir_Last : constant Natural :=
6880 Compute_Directory_Last
6884 if Current_Verbosity = High then
6885 Write_Attr ("Source_Dir", Source_Directory);
6888 -- We look to every entry in the source directory
6890 Open (Dir, Source_Directory);
6893 Read (Dir, Name, Last);
6897 -- ??? Duplicate system call here, we just did a a
6898 -- similar one. Maybe Ada.Directories would be more
6899 -- appropriate here.
6902 (Source_Directory & Name (1 .. Last))
6904 if Current_Verbosity = High then
6905 Write_Str (" Checking ");
6906 Write_Line (Name (1 .. Last));
6910 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
6911 Display_File_Name := Name_Find;
6913 if Osint.File_Names_Case_Sensitive then
6914 File_Name := Display_File_Name;
6916 Canonical_Case_File_Name
6917 (Name_Buffer (1 .. Name_Len));
6918 File_Name := Name_Find;
6922 Path_Name : constant String :=
6927 (Source_Directory'First ..
6930 Opt.Follow_Links_For_Files,
6931 Case_Sensitive => True);
6932 -- Case_Sensitive set True (no folding)
6934 Path : Path_Name_Type;
6935 FF : File_Found := Excluded_Sources_Htable.Get
6936 (Project.Excluded, File_Name);
6937 To_Remove : Boolean := False;
6940 Name_Len := Path_Name'Length;
6941 Name_Buffer (1 .. Name_Len) := Path_Name;
6944 if FF /= No_File_Found then
6945 if not FF.Found then
6947 Excluded_Sources_Htable.Set
6948 (Project.Excluded, File_Name, FF);
6950 if Current_Verbosity = High then
6951 Write_Str (" excluded source """);
6952 Write_Str (Get_Name_String (File_Name));
6956 -- Will mark the file as removed, but we
6957 -- still need to add it to the list: if we
6958 -- don't, the file will not appear in the
6959 -- mapping file and will cause the compiler
6967 (Project => Project,
6970 File_Name => File_Name,
6971 Locally_Removed => To_Remove,
6972 Display_File_Name => Display_File_Name,
6973 For_All_Sources => For_All_Sources);
6983 when Directory_Error =>
6987 Source_Dir := Element.Next;
6990 if Current_Verbosity = High then
6991 Write_Line ("end Looking for sources.");
6993 end Search_Directories;
6995 ----------------------------
6996 -- Load_Naming_Exceptions --
6997 ----------------------------
6999 procedure Load_Naming_Exceptions
7000 (Project : in out Project_Processing_Data;
7001 Data : in out Tree_Processing_Data)
7004 Iter : Source_Iterator;
7007 Iter := For_Each_Source (Data.Tree, Project.Project);
7009 Source := Prj.Element (Iter);
7010 exit when Source = No_Source;
7012 -- An excluded file cannot also be an exception file name
7014 if Excluded_Sources_Htable.Get (Project.Excluded, Source.File) /=
7017 Error_Msg_File_1 := Source.File;
7020 "{ cannot be both excluded and an exception file name",
7024 if Current_Verbosity = High then
7025 Write_Str ("Naming exception: Putting source file ");
7026 Write_Str (Get_Name_String (Source.File));
7027 Write_Line (" in Source_Names");
7030 Source_Names_Htable.Set
7031 (Project.Source_Names,
7034 (Name => Source.File,
7035 Location => No_Location,
7039 -- If this is an Ada exception, record in table Unit_Exceptions
7041 if Source.Unit /= No_Unit_Index then
7043 Unit_Except : Unit_Exception :=
7044 Unit_Exceptions_Htable.Get
7045 (Project.Unit_Exceptions, Source.Unit.Name);
7048 Unit_Except.Name := Source.Unit.Name;
7050 if Source.Kind = Spec then
7051 Unit_Except.Spec := Source.File;
7053 Unit_Except.Impl := Source.File;
7056 Unit_Exceptions_Htable.Set
7057 (Project.Unit_Exceptions, Source.Unit.Name, Unit_Except);
7063 end Load_Naming_Exceptions;
7065 ----------------------
7066 -- Look_For_Sources --
7067 ----------------------
7069 procedure Look_For_Sources
7070 (Project : in out Project_Processing_Data;
7071 Data : in out Tree_Processing_Data)
7073 Object_Files : Object_File_Names_Htable.Instance;
7074 Iter : Source_Iterator;
7077 procedure Check_Object (Src : Source_Id);
7078 -- Check if object file name of Src is already used in the project tree,
7079 -- and report an error if so.
7081 procedure Check_Object_Files;
7082 -- Check that no two sources of this project have the same object file
7084 procedure Mark_Excluded_Sources;
7085 -- Mark as such the sources that are declared as excluded
7091 procedure Check_Object (Src : Source_Id) is
7095 Source := Object_File_Names_Htable.Get (Object_Files, Src.Object);
7097 -- We cannot just check on "Source /= Src", since we might have
7098 -- two different entries for the same file (and since that's
7099 -- the same file it is expected that it has the same object)
7101 if Source /= No_Source
7102 and then Source.Path /= Src.Path
7104 Error_Msg_File_1 := Src.File;
7105 Error_Msg_File_2 := Source.File;
7108 "{ and { have the same object file name",
7112 Object_File_Names_Htable.Set (Object_Files, Src.Object, Src);
7116 ---------------------------
7117 -- Mark_Excluded_Sources --
7118 ---------------------------
7120 procedure Mark_Excluded_Sources is
7121 Source : Source_Id := No_Source;
7122 Excluded : File_Found;
7126 -- Minor optimization: if there are no excluded files, no need to
7127 -- traverse the list of sources. We cannot however also check whether
7128 -- the existing exceptions have ".Found" set to True (indicating we
7129 -- found them before) because we need to do some final processing on
7130 -- them in any case.
7132 if Excluded_Sources_Htable.Get_First (Project.Excluded) /=
7135 Proj := Project.Project;
7136 while Proj /= No_Project loop
7137 Iter := For_Each_Source (Data.Tree, Proj);
7138 while Prj.Element (Iter) /= No_Source loop
7139 Source := Prj.Element (Iter);
7140 Excluded := Excluded_Sources_Htable.Get
7141 (Project.Excluded, Source.File);
7143 if Excluded /= No_File_Found then
7144 Source.Locally_Removed := True;
7145 Source.In_Interfaces := False;
7147 if Current_Verbosity = High then
7148 Write_Str ("Removing file ");
7150 (Get_Name_String (Excluded.File)
7151 & " " & Get_Name_String (Source.Project.Name));
7154 Excluded_Sources_Htable.Remove
7155 (Project.Excluded, Source.File);
7161 Proj := Proj.Extends;
7165 -- If we have any excluded element left, that means we did not find
7168 Excluded := Excluded_Sources_Htable.Get_First (Project.Excluded);
7169 while Excluded /= No_File_Found loop
7170 if not Excluded.Found then
7172 -- Check if the file belongs to another imported project to
7173 -- provide a better error message.
7176 (In_Tree => Data.Tree,
7177 Project => Project.Project,
7178 In_Imported_Only => True,
7179 Base_Name => Excluded.File);
7181 Err_Vars.Error_Msg_File_1 := Excluded.File;
7183 if Src = No_Source then
7186 "unknown file {", Excluded.Location, Data);
7190 "cannot remove a source from an imported project: {",
7191 Excluded.Location, Data);
7195 Excluded := Excluded_Sources_Htable.Get_Next (Project.Excluded);
7197 end Mark_Excluded_Sources;
7199 ------------------------
7200 -- Check_Object_Files --
7201 ------------------------
7203 procedure Check_Object_Files is
7204 Iter : Source_Iterator;
7206 Src_Ind : Source_File_Index;
7209 Iter := For_Each_Source (Data.Tree);
7211 Src_Id := Prj.Element (Iter);
7212 exit when Src_Id = No_Source;
7214 if Is_Compilable (Src_Id)
7215 and then Src_Id.Language.Config.Object_Generated
7216 and then Is_Extending (Project.Project, Src_Id.Project)
7218 if Src_Id.Unit = No_Unit_Index then
7219 if Src_Id.Kind = Impl then
7220 Check_Object (Src_Id);
7226 if Other_Part (Src_Id) = No_Source then
7227 Check_Object (Src_Id);
7234 if Other_Part (Src_Id) /= No_Source then
7235 Check_Object (Src_Id);
7238 -- Check if it is a subunit
7241 Sinput.P.Load_Project_File
7242 (Get_Name_String (Src_Id.Path.Name));
7244 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7245 Override_Kind (Src_Id, Sep);
7247 Check_Object (Src_Id);
7256 end Check_Object_Files;
7258 -- Start of processing for Look_For_Sources
7261 Find_Excluded_Sources (Project, Data);
7263 if Project.Project.Languages /= No_Language_Index then
7264 Load_Naming_Exceptions (Project, Data);
7265 Find_Sources (Project, Data);
7266 Mark_Excluded_Sources;
7270 Object_File_Names_Htable.Reset (Object_Files);
7271 end Look_For_Sources;
7277 function Path_Name_Of
7278 (File_Name : File_Name_Type;
7279 Directory : Path_Name_Type) return String
7281 Result : String_Access;
7282 The_Directory : constant String := Get_Name_String (Directory);
7285 Get_Name_String (File_Name);
7288 (File_Name => Name_Buffer (1 .. Name_Len),
7289 Path => The_Directory);
7291 if Result = null then
7295 R : String := Result.all;
7298 Canonical_Case_File_Name (R);
7308 procedure Remove_Source
7310 Replaced_By : Source_Id)
7315 if Current_Verbosity = High then
7316 Write_Str ("Removing source ");
7317 Write_Line (Get_Name_String (Id.File) & " at" & Id.Index'Img);
7320 if Replaced_By /= No_Source then
7321 Id.Replaced_By := Replaced_By;
7322 Replaced_By.Declared_In_Interfaces := Id.Declared_In_Interfaces;
7325 Id.In_Interfaces := False;
7326 Id.Locally_Removed := True;
7328 -- ??? Should we remove the source from the unit ? The file is not used,
7329 -- so probably should not be referenced from the unit. On the other hand
7330 -- it might give useful additional info
7331 -- if Id.Unit /= null then
7332 -- Id.Unit.File_Names (Id.Kind) := null;
7335 Source := Id.Language.First_Source;
7338 Id.Language.First_Source := Id.Next_In_Lang;
7341 while Source.Next_In_Lang /= Id loop
7342 Source := Source.Next_In_Lang;
7345 Source.Next_In_Lang := Id.Next_In_Lang;
7349 -----------------------
7350 -- Report_No_Sources --
7351 -----------------------
7353 procedure Report_No_Sources
7354 (Project : Project_Id;
7356 Data : Tree_Processing_Data;
7357 Location : Source_Ptr;
7358 Continuation : Boolean := False)
7361 case Data.Flags.When_No_Sources is
7365 when Warning | Error =>
7367 Msg : constant String :=
7370 " sources in this project";
7373 Error_Msg_Warn := Data.Flags.When_No_Sources = Warning;
7375 if Continuation then
7376 Error_Msg (Project, "\" & Msg, Location, Data);
7378 Error_Msg (Project, Msg, Location, Data);
7382 end Report_No_Sources;
7384 ----------------------
7385 -- Show_Source_Dirs --
7386 ----------------------
7388 procedure Show_Source_Dirs
7389 (Project : Project_Id;
7390 In_Tree : Project_Tree_Ref)
7392 Current : String_List_Id;
7393 Element : String_Element;
7396 Write_Line ("Source_Dirs:");
7398 Current := Project.Source_Dirs;
7399 while Current /= Nil_String loop
7400 Element := In_Tree.String_Elements.Table (Current);
7402 Write_Line (Get_Name_String (Element.Value));
7403 Current := Element.Next;
7406 Write_Line ("end Source_Dirs.");
7407 end Show_Source_Dirs;
7409 ---------------------------
7410 -- Process_Naming_Scheme --
7411 ---------------------------
7413 procedure Process_Naming_Scheme
7414 (Tree : Project_Tree_Ref;
7415 Root_Project : Project_Id;
7416 Flags : Processing_Flags)
7418 procedure Recursive_Check
7419 (Project : Project_Id;
7420 Data : in out Tree_Processing_Data);
7421 -- Check_Naming_Scheme for the project
7423 ---------------------
7424 -- Recursive_Check --
7425 ---------------------
7427 procedure Recursive_Check
7428 (Project : Project_Id;
7429 Data : in out Tree_Processing_Data)
7432 if Verbose_Mode then
7433 Write_Str ("Processing_Naming_Scheme for project """);
7434 Write_Str (Get_Name_String (Project.Name));
7438 Prj.Nmsc.Check (Project, Data);
7439 end Recursive_Check;
7441 procedure Check_All_Projects is new
7442 For_Every_Project_Imported (Tree_Processing_Data, Recursive_Check);
7444 Data : Tree_Processing_Data;
7446 -- Start of processing for Process_Naming_Scheme
7448 Initialize (Data, Tree => Tree, Flags => Flags);
7449 Check_All_Projects (Root_Project, Data, Imported_First => True);
7451 end Process_Naming_Scheme;