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;
30 with Err_Vars; use Err_Vars;
34 with Osint; use Osint;
35 with Output; use Output;
36 with Prj.Env; use Prj.Env;
38 with Prj.Util; use Prj.Util;
40 with Snames; use Snames;
41 with Table; use Table;
42 with Targparm; use Targparm;
44 with Ada.Characters.Handling; use Ada.Characters.Handling;
45 with Ada.Directories; use Ada.Directories;
46 with Ada.Strings; use Ada.Strings;
47 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
48 with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
50 package body Prj.Nmsc is
52 No_Continuation_String : aliased String := "";
53 Continuation_String : aliased String := "\";
54 -- Used in Check_Library for continuation error messages at the same
57 Error_Report : Put_Line_Access := null;
58 -- Set to point to error reporting procedure
60 When_No_Sources : Error_Warning := Error;
61 -- Indicates what should be done when there is no Ada sources in a non
62 -- extending Ada project.
64 ALI_Suffix : constant String := ".ali";
65 -- File suffix for ali files
67 type Name_Location is record
68 Name : File_Name_Type;
69 Location : Source_Ptr;
70 Source : Source_Id := No_Source;
71 Except : Boolean := False;
72 Found : Boolean := False;
74 -- Information about file names found in string list attribute:
75 -- Source_Files or in a source list file, stored in hash table.
76 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
77 -- Except is set to True if source is a naming exception in the project.
79 No_Name_Location : constant Name_Location :=
81 Location => No_Location,
86 package Source_Names is new GNAT.HTable.Simple_HTable
87 (Header_Num => Header_Num,
88 Element => Name_Location,
89 No_Element => No_Name_Location,
90 Key => File_Name_Type,
93 -- Hash table to store file names found in string list attribute
94 -- Source_Files or in a source list file, stored in hash table
95 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
97 -- ??? Should not be a global table, as it is needed only when processing
100 -- More documentation needed on what unit exceptions are about ???
102 type Unit_Exception is record
104 Spec : File_Name_Type;
105 Impl : File_Name_Type;
107 -- Record special naming schemes for Ada units (name of spec file and name
108 -- of implementation file).
110 No_Unit_Exception : constant Unit_Exception :=
115 package Unit_Exceptions is new GNAT.HTable.Simple_HTable
116 (Header_Num => Header_Num,
117 Element => Unit_Exception,
118 No_Element => No_Unit_Exception,
122 -- Hash table to store the unit exceptions.
123 -- ??? Seems to be used only by the multi_lang mode
124 -- ??? Should not be a global array, but stored in the project_data
126 package Recursive_Dirs is new GNAT.HTable.Simple_HTable
127 (Header_Num => Header_Num,
133 -- Hash table to store recursive source directories, to avoid looking
134 -- several times, and to avoid cycles that may be introduced by symbolic
137 type Ada_Naming_Exception_Id is new Nat;
138 No_Ada_Naming_Exception : constant Ada_Naming_Exception_Id := 0;
140 type Unit_Info is record
143 Next : Ada_Naming_Exception_Id := No_Ada_Naming_Exception;
147 package Ada_Naming_Exception_Table is new Table.Table
148 (Table_Component_Type => Unit_Info,
149 Table_Index_Type => Ada_Naming_Exception_Id,
150 Table_Low_Bound => 1,
152 Table_Increment => 100,
153 Table_Name => "Prj.Nmsc.Ada_Naming_Exception_Table");
155 package Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
156 (Header_Num => Header_Num,
157 Element => Ada_Naming_Exception_Id,
158 No_Element => No_Ada_Naming_Exception,
159 Key => File_Name_Type,
162 -- A hash table to store naming exceptions for Ada. For each file name
163 -- there is one or several unit in table Ada_Naming_Exception_Table.
164 -- ??? This is for ada_only mode, we should be able to merge with
165 -- Unit_Exceptions table, used by multi_lang mode.
167 package Object_File_Names is new GNAT.HTable.Simple_HTable
168 (Header_Num => Header_Num,
169 Element => File_Name_Type,
170 No_Element => No_File,
171 Key => File_Name_Type,
174 -- A hash table to store the object file names for a project, to check that
175 -- two different sources have different object file names.
177 type File_Found is record
178 File : File_Name_Type := No_File;
179 Found : Boolean := False;
180 Location : Source_Ptr := No_Location;
182 No_File_Found : constant File_Found := (No_File, False, No_Location);
183 -- Comments needed ???
185 package Excluded_Sources_Htable is new GNAT.HTable.Simple_HTable
186 (Header_Num => Header_Num,
187 Element => File_Found,
188 No_Element => No_File_Found,
189 Key => File_Name_Type,
192 -- A hash table to store the excluded files, if any. This is filled by
193 -- Find_Excluded_Sources below.
195 procedure Find_Excluded_Sources
196 (Project : Project_Id;
197 In_Tree : Project_Tree_Ref);
198 -- Find the list of files that should not be considered as source files
199 -- for this project. Sets the list in the Excluded_Sources_Htable.
201 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind);
202 -- Override the reference kind for a source file. This properly updates
203 -- the unit data if necessary.
205 function Hash (Unit : Unit_Info) return Header_Num;
207 type Name_And_Index is record
208 Name : Name_Id := No_Name;
211 No_Name_And_Index : constant Name_And_Index :=
212 (Name => No_Name, Index => 0);
213 -- Name of a unit, and its index inside the source file. The first unit has
214 -- index 1 (see doc for pragma Source_File_Name), but the index might be
215 -- set to 0 when the source file contains a single unit.
217 package Reverse_Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
218 (Header_Num => Header_Num,
219 Element => Name_And_Index,
220 No_Element => No_Name_And_Index,
224 -- A table to check if a unit with an exceptional name will hide a source
225 -- with a file name following the naming convention.
227 procedure Load_Naming_Exceptions
228 (Project : Project_Id;
229 In_Tree : Project_Tree_Ref);
230 -- All source files in Data.First_Source are considered as naming
231 -- exceptions, and copied into the Source_Names and Unit_Exceptions tables
236 In_Tree : Project_Tree_Ref;
237 Project : Project_Id;
238 Lang_Id : Language_Ptr;
240 File_Name : File_Name_Type;
241 Display_File : File_Name_Type;
242 Naming_Exception : Boolean := False;
243 Path : Path_Information := No_Path_Information;
244 Alternate_Languages : Language_List := null;
245 Unit : Name_Id := No_Name;
247 Source_To_Replace : Source_Id := No_Source);
248 -- Add a new source to the different lists: list of all sources in the
249 -- project tree, list of source of a project and list of sources of a
252 -- If Path is specified, the file is also added to Source_Paths_HT.
253 -- If Source_To_Replace is specified, it points to the source in the
254 -- extended project that the new file is overriding.
256 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type;
257 -- Same as Osint.Canonical_Case_File_Name but applies to Name_Id.
258 -- This alters Name_Buffer
260 function Suffix_Matches
262 Suffix : File_Name_Type) return Boolean;
263 -- True if the file name ends with the given suffix. Always returns False
264 -- if Suffix is No_Name.
266 procedure Replace_Into_Name_Buffer
269 Replacement : Character);
270 -- Copy Str into Name_Buffer, replacing Pattern with Replacement. Str is
271 -- converted to lower-case at the same time.
273 function ALI_File_Name (Source : String) return String;
274 -- Return the ALI file name corresponding to a source
276 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
277 -- Check that a name is a valid Ada unit name
279 procedure Check_Package_Naming
280 (Project : Project_Id;
281 In_Tree : Project_Tree_Ref;
282 Is_Config_File : Boolean;
283 Bodies : out Array_Element_Id;
284 Specs : out Array_Element_Id);
285 -- Check the naming scheme part of Data, and initialize the naming scheme
286 -- data in the config of the various languages. Is_Config_File should be
287 -- True if Project is a config file (.cgpr) This also returns the naming
288 -- scheme exceptions for unit-based languages (Bodies and Specs are
289 -- associative arrays mapping individual unit names to source file names).
291 procedure Check_Configuration
292 (Project : Project_Id;
293 In_Tree : Project_Tree_Ref;
294 Compiler_Driver_Mandatory : Boolean);
295 -- Check the configuration attributes for the project
296 -- If Compiler_Driver_Mandatory is true, then a Compiler.Driver attribute
297 -- for each language must be defined, or we will not look for its source
300 procedure Check_If_Externally_Built
301 (Project : Project_Id;
302 In_Tree : Project_Tree_Ref);
303 -- Check attribute Externally_Built of project Project in project tree
304 -- In_Tree and modify its data Data if it has the value "true".
306 procedure Check_Interfaces
307 (Project : Project_Id;
308 In_Tree : Project_Tree_Ref);
309 -- If a list of sources is specified in attribute Interfaces, set
310 -- In_Interfaces only for the sources specified in the list.
312 procedure Check_Library_Attributes
313 (Project : Project_Id;
314 In_Tree : Project_Tree_Ref);
315 -- Check the library attributes of project Project in project tree In_Tree
316 -- and modify its data Data accordingly.
317 -- Current_Dir should represent the current directory, and is passed for
318 -- efficiency to avoid system calls to recompute it.
320 procedure Check_Programming_Languages
321 (In_Tree : Project_Tree_Ref;
322 Project : Project_Id);
323 -- Check attribute Languages for the project with data Data in project
324 -- tree In_Tree and set the components of Data for all the programming
325 -- languages indicated in attribute Languages, if any.
327 function Check_Project
329 Root_Project : Project_Id;
330 Extending : Boolean) return Boolean;
331 -- Returns True if P is Root_Project or, if Extending is True, a project
332 -- extended by Root_Project.
334 procedure Check_Stand_Alone_Library
335 (Project : Project_Id;
336 In_Tree : Project_Tree_Ref;
337 Current_Dir : String;
338 Extending : Boolean);
339 -- Check if project Project in project tree In_Tree is a Stand-Alone
340 -- Library project, and modify its data Data accordingly if it is one.
341 -- Current_Dir should represent the current directory, and is passed for
342 -- efficiency to avoid system calls to recompute it.
344 procedure Check_And_Normalize_Unit_Names
345 (Project : Project_Id;
346 In_Tree : Project_Tree_Ref;
347 List : Array_Element_Id;
348 Debug_Name : String);
349 -- Check that a list of unit names contains only valid names. Casing
350 -- is normalized where appropriate.
351 -- Debug_Name is the name representing the list, and is used for debug
354 procedure Find_Ada_Sources
355 (Project : Project_Id;
356 In_Tree : Project_Tree_Ref;
357 Explicit_Sources_Only : Boolean;
358 Proc_Data : in out Processing_Data);
359 -- Find all Ada sources by traversing all source directories. If
360 -- Explicit_Sources_Only is True, then the sources found must belong to
361 -- the list of sources specified explicitly in the project file. If
362 -- Explicit_Sources_Only is False, then all sources matching the naming
363 -- scheme are recorded.
365 function Compute_Directory_Last (Dir : String) return Natural;
366 -- Return the index of the last significant character in Dir. This is used
367 -- to avoid duplicate '/' (slash) characters at the end of directory names.
370 (Project : Project_Id;
371 In_Tree : Project_Tree_Ref;
373 Flag_Location : Source_Ptr);
374 -- Output an error message. If Error_Report is null, simply call
375 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
378 procedure Search_Directories
379 (Project : Project_Id;
380 In_Tree : Project_Tree_Ref;
381 For_All_Sources : Boolean;
382 Allow_Duplicate_Basenames : Boolean);
383 -- Search the source directories to find the sources. If For_All_Sources is
384 -- True, check each regular file name against the naming schemes of the
385 -- different languages. Otherwise consider only the file names in the hash
386 -- table Source_Names. If Allow_Duplicate_Basenames, then files with the
387 -- same base names are authorized within a project for source-based
388 -- languages (never for unit based languages)
391 (Project : Project_Id;
392 In_Tree : Project_Tree_Ref;
393 Path : Path_Name_Type;
394 File_Name : File_Name_Type;
395 Display_File_Name : File_Name_Type;
396 For_All_Sources : Boolean;
397 Allow_Duplicate_Basenames : Boolean);
398 -- Check if file File_Name is a valid source of the project. This is used
399 -- in multi-language mode only. When the file matches one of the naming
400 -- schemes, it is added to various htables through Add_Source and to
401 -- Source_Paths_Htable.
403 -- Name is the name of the candidate file. It hasn't been normalized yet
404 -- and is the direct result of readdir().
406 -- File_Name is the same as Name, but has been normalized.
407 -- Display_File_Name, however, has not been normalized.
409 -- Source_Directory is the directory in which the file
410 -- was found. It hasn't been normalized (nor has had links resolved).
411 -- It should not end with a directory separator, to avoid duplicates
414 -- If For_All_Sources is True, then all possible file names are analyzed
415 -- otherwise only those currently set in the Source_Names htable.
417 -- If Allow_Duplicate_Basenames, then files with the same base names are
418 -- authorized within a project for source-based languages (never for unit
421 procedure Check_File_Naming_Schemes
422 (In_Tree : Project_Tree_Ref;
423 Project : Project_Id;
424 File_Name : File_Name_Type;
425 Alternate_Languages : out Language_List;
426 Language : out Language_Ptr;
427 Display_Language_Name : out Name_Id;
429 Lang_Kind : out Language_Kind;
430 Kind : out Source_Kind);
431 -- Check if the file name File_Name conforms to one of the naming
432 -- schemes of the project.
434 -- If the file does not match one of the naming schemes, set Language
435 -- to No_Language_Index.
437 -- Filename is the name of the file being investigated. It has been
438 -- normalized (case-folded). File_Name is the same value.
440 procedure Free_Ada_Naming_Exceptions;
441 -- Free the internal hash tables used for checking naming exceptions
443 procedure Get_Directories
444 (Project : Project_Id;
445 In_Tree : Project_Tree_Ref;
446 Current_Dir : String);
447 -- Get the object directory, the exec directory and the source directories
450 -- Current_Dir should represent the current directory, and is passed for
451 -- efficiency to avoid system calls to recompute it.
454 (Project : Project_Id;
455 In_Tree : Project_Tree_Ref);
456 -- Get the mains of a project from attribute Main, if it exists, and put
457 -- them in the project data.
459 procedure Get_Sources_From_File
461 Location : Source_Ptr;
462 Project : Project_Id;
463 In_Tree : Project_Tree_Ref);
464 -- Get the list of sources from a text file and put them in hash table
467 procedure Find_Sources
468 (Project : Project_Id;
469 In_Tree : Project_Tree_Ref;
470 Proc_Data : in out Processing_Data;
471 Allow_Duplicate_Basenames : Boolean);
472 -- Process the Source_Files and Source_List_File attributes, and store
473 -- the list of source files into the Source_Names htable.
474 -- When these attributes are not defined, find all files matching the
475 -- naming schemes in the source directories.
476 -- If Allow_Duplicate_Basenames, then files with the same base names are
477 -- authorized within a project for source-based languages (never for unit
480 procedure Compute_Unit_Name
481 (File_Name : File_Name_Type;
482 Naming : Lang_Naming_Data;
483 Kind : out Source_Kind;
485 In_Tree : Project_Tree_Ref);
486 -- Check whether the file matches the naming scheme. If it does,
487 -- compute its unit name. If Unit is set to No_Name on exit, none of the
488 -- other out parameters are relevant.
491 (In_Tree : Project_Tree_Ref;
492 Canonical_File_Name : File_Name_Type;
493 Project : Project_Id;
494 Exception_Id : out Ada_Naming_Exception_Id;
495 Unit_Name : out Name_Id;
496 Unit_Kind : out Spec_Or_Body);
497 -- Find out, from a file name, the unit name, the unit kind and if a
498 -- specific SFN pragma is needed. If the file name corresponds to no unit,
499 -- then Unit_Name will be No_Name. If the file is a multi-unit source or an
500 -- exception to the naming scheme, then Exception_Id is set to the unit or
501 -- units that the source contains, and the other information are not set.
503 function Is_Illegal_Suffix
504 (Suffix : File_Name_Type;
505 Dot_Replacement : File_Name_Type) return Boolean;
506 -- Returns True if the string Suffix cannot be used as a spec suffix, a
507 -- body suffix or a separate suffix.
509 procedure Locate_Directory
510 (Project : Project_Id;
511 In_Tree : Project_Tree_Ref;
512 Name : File_Name_Type;
513 Path : out Path_Information;
514 Dir_Exists : out Boolean;
515 Create : String := "";
516 Location : Source_Ptr := No_Location;
517 Must_Exist : Boolean := True;
518 Externally_Built : Boolean := False);
519 -- Locate a directory. Name is the directory name.
520 -- Relative paths are resolved relative to the project's directory.
521 -- If the directory does not exist and Setup_Projects
522 -- is True and Create is a non null string, an attempt is made to create
524 -- If the directory does not exist, it is either created if Setup_Projects
525 -- is False (and then returned), or simply returned without checking for
526 -- its existence (if Must_Exist is False) or No_Path_Information is
527 -- returned. In all cases, Dir_Exists indicates whether the directory now
530 -- Create is also used for debugging traces to show which path we are
533 procedure Look_For_Sources
534 (Project : Project_Id;
535 In_Tree : Project_Tree_Ref;
536 Proc_Data : in out Processing_Data;
537 Allow_Duplicate_Basenames : Boolean);
538 -- Find all the sources of project Project in project tree In_Tree and
539 -- update its Data accordingly. This assumes that Data.First_Source has
540 -- been initialized with the list of excluded sources and special naming
541 -- exceptions. If Allow_Duplicate_Basenames, then files with the same base
542 -- names are authorized within a project for source-based languages (never
543 -- for unit based languages)
545 function Path_Name_Of
546 (File_Name : File_Name_Type;
547 Directory : Path_Name_Type) return String;
548 -- Returns the path name of a (non project) file. Returns an empty string
549 -- if file cannot be found.
551 procedure Prepare_Ada_Naming_Exceptions
552 (List : Array_Element_Id;
553 In_Tree : Project_Tree_Ref;
554 Kind : Spec_Or_Body);
555 -- Prepare the internal hash tables used for checking naming exceptions
556 -- for Ada. Insert all elements of List in the tables.
558 procedure Record_Ada_Source
559 (File_Name : File_Name_Type;
560 Path_Name : Path_Name_Type;
561 Project : Project_Id;
562 In_Tree : Project_Tree_Ref;
563 Proc_Data : in out Processing_Data;
564 Ada_Language : Language_Ptr;
565 Location : Source_Ptr;
566 Source_Recorded : in out Boolean);
567 -- Put a unit in the list of units of a project, if the file name
568 -- corresponds to a valid unit name. Ada_Language is a pointer to the
569 -- Language_Data for "Ada" in Project.
571 procedure Remove_Source
573 Replaced_By : Source_Id);
574 -- Remove a file from the list of sources of a project.
575 -- This might be because the file is replaced by another one in an
576 -- extending project, or because a file was added as a naming exception
577 -- but was not found in the end.
579 procedure Report_No_Sources
580 (Project : Project_Id;
582 In_Tree : Project_Tree_Ref;
583 Location : Source_Ptr;
584 Continuation : Boolean := False);
585 -- Report an error or a warning depending on the value of When_No_Sources
586 -- when there are no sources for language Lang_Name.
588 procedure Show_Source_Dirs
589 (Project : Project_Id; In_Tree : Project_Tree_Ref);
590 -- List all the source directories of a project
592 procedure Warn_If_Not_Sources
593 (Project : Project_Id;
594 In_Tree : Project_Tree_Ref;
595 Conventions : Array_Element_Id;
597 Extending : Boolean);
598 -- Check that individual naming conventions apply to immediate sources of
599 -- the project. If not, issue a warning.
601 procedure Write_Attr (Name, Value : String);
602 -- Debug print a value for a specific property. Does nothing when not in
605 ------------------------------
606 -- Replace_Into_Name_Buffer --
607 ------------------------------
609 procedure Replace_Into_Name_Buffer
612 Replacement : Character)
614 Max : constant Integer := Str'Last - Pattern'Length + 1;
621 while J <= Str'Last loop
622 Name_Len := Name_Len + 1;
625 and then Str (J .. J + Pattern'Length - 1) = Pattern
627 Name_Buffer (Name_Len) := Replacement;
628 J := J + Pattern'Length;
631 Name_Buffer (Name_Len) := GNAT.Case_Util.To_Lower (Str (J));
635 end Replace_Into_Name_Buffer;
641 function Suffix_Matches
643 Suffix : File_Name_Type) return Boolean
645 Min_Prefix_Length : Natural := 0;
647 if Suffix = No_File or else Suffix = Empty_File then
652 Suf : constant String := Get_Name_String (Suffix);
655 -- The file name must end with the suffix (which is not an extension)
656 -- For instance a suffix "configure.in" must match a file with the
657 -- same name. To avoid dummy cases, though, a suffix starting with
658 -- '.' requires a file that is at least one character longer ('.cpp'
659 -- should not match a file with the same name)
661 if Suf (Suf'First) = '.' then
662 Min_Prefix_Length := 1;
665 return Filename'Length >= Suf'Length + Min_Prefix_Length
667 (Filename'Last - Suf'Length + 1 .. Filename'Last) = Suf;
675 procedure Write_Attr (Name, Value : String) is
677 if Current_Verbosity = High then
678 Write_Str (" " & Name & " = """);
691 In_Tree : Project_Tree_Ref;
692 Project : Project_Id;
693 Lang_Id : Language_Ptr;
695 File_Name : File_Name_Type;
696 Display_File : File_Name_Type;
697 Naming_Exception : Boolean := False;
698 Path : Path_Information := No_Path_Information;
699 Alternate_Languages : Language_List := null;
700 Unit : Name_Id := No_Name;
702 Source_To_Replace : Source_Id := No_Source)
704 Config : constant Language_Config := Lang_Id.Config;
708 Id := new Source_Data;
710 if Current_Verbosity = High then
711 Write_Str ("Adding source File: ");
712 Write_Str (Get_Name_String (File_Name));
714 if Lang_Id.Config.Kind = Unit_Based then
715 Write_Str (" Unit: ");
716 -- ??? in gprclean, it seems we sometimes pass an empty Unit name
717 -- (see test extended_projects)
718 if Unit /= No_Name then
719 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 Unit_Sources_Htable.Set (In_Tree.Unit_Sources_HT, Unit, Id);
739 -- ??? Record_Unit has already fetched that earlier, so this isn't
740 -- the most efficient way. But we can't really pass a parameter since
741 -- Process_Exceptions_Unit_Based and Check_File haven't looked it up.
743 UData := Units_Htable.Get (In_Tree.Units_HT, Unit);
745 if UData = No_Unit_Index then
746 UData := new Unit_Data;
748 Units_Htable.Set (In_Tree.Units_HT, Unit, UData);
753 -- Note that this updates Unit information as well
755 Override_Kind (Id, Kind);
759 Id.File := File_Name;
760 Id.Display_File := Display_File;
761 Id.Dep_Name := Dependency_Name
762 (File_Name, Lang_Id.Config.Dependency_Kind);
763 Id.Naming_Exception := Naming_Exception;
765 if Is_Compilable (Id) and then Config.Object_Generated then
766 Id.Object := Object_Name (File_Name, Config.Object_File_Suffix);
767 Id.Switches := Switches_Name (File_Name);
770 if Path /= No_Path_Information then
772 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path.Name, Id);
775 -- Add the source to the language list
777 Id.Next_In_Lang := Lang_Id.First_Source;
778 Lang_Id.First_Source := Id;
780 if Source_To_Replace /= No_Source then
781 Remove_Source (Source_To_Replace, Id);
789 function ALI_File_Name (Source : String) return String is
791 -- If the source name has extension, replace it with the ALI suffix
793 for Index in reverse Source'First + 1 .. Source'Last loop
794 if Source (Index) = '.' then
795 return Source (Source'First .. Index - 1) & ALI_Suffix;
799 -- If no dot, or if it is the first character, just add the ALI suffix
801 return Source & ALI_Suffix;
804 ------------------------------
805 -- Canonical_Case_File_Name --
806 ------------------------------
808 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type is
810 if Osint.File_Names_Case_Sensitive then
811 return File_Name_Type (Name);
813 Get_Name_String (Name);
814 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
817 end Canonical_Case_File_Name;
824 (Project : Project_Id;
825 In_Tree : Project_Tree_Ref;
826 Report_Error : Put_Line_Access;
827 When_No_Sources : Error_Warning;
828 Current_Dir : String;
829 Proc_Data : in out Processing_Data;
830 Is_Config_File : Boolean;
831 Compiler_Driver_Mandatory : Boolean;
832 Allow_Duplicate_Basenames : Boolean)
834 Specs : Array_Element_Id;
835 Bodies : Array_Element_Id;
836 Extending : Boolean := False;
839 Nmsc.When_No_Sources := When_No_Sources;
840 Error_Report := Report_Error;
842 Recursive_Dirs.Reset;
844 Check_If_Externally_Built (Project, In_Tree);
846 -- Object, exec and source directories
848 Get_Directories (Project, In_Tree, Current_Dir);
850 -- Get the programming languages
852 Check_Programming_Languages (In_Tree, Project);
854 if Project.Qualifier = Dry
855 and then Project.Source_Dirs /= Nil_String
858 Source_Dirs : constant Variable_Value :=
861 Project.Decl.Attributes, In_Tree);
862 Source_Files : constant Variable_Value :=
865 Project.Decl.Attributes, In_Tree);
866 Source_List_File : constant Variable_Value :=
868 (Name_Source_List_File,
869 Project.Decl.Attributes, In_Tree);
870 Languages : constant Variable_Value :=
873 Project.Decl.Attributes, In_Tree);
876 if Source_Dirs.Values = Nil_String
877 and then Source_Files.Values = Nil_String
878 and then Languages.Values = Nil_String
879 and then Source_List_File.Default
881 Project.Source_Dirs := Nil_String;
886 "at least one of Source_Files, Source_Dirs or Languages " &
887 "must be declared empty for an abstract project",
893 -- Check configuration in multi language mode
895 if Must_Check_Configuration then
898 Compiler_Driver_Mandatory => Compiler_Driver_Mandatory);
901 -- Library attributes
903 Check_Library_Attributes (Project, In_Tree);
905 if Current_Verbosity = High then
906 Show_Source_Dirs (Project, In_Tree);
909 Extending := Project.Extends /= No_Project;
911 Check_Package_Naming (Project, In_Tree, Is_Config_File, Bodies, Specs);
913 if Get_Mode = Ada_Only then
914 Prepare_Ada_Naming_Exceptions (Bodies, In_Tree, Impl);
915 Prepare_Ada_Naming_Exceptions (Specs, In_Tree, Spec);
920 if Project.Source_Dirs /= Nil_String then
922 (Project, In_Tree, Proc_Data, Allow_Duplicate_Basenames);
924 if Get_Mode = Ada_Only then
926 -- Check that all individual naming conventions apply to sources
927 -- of this project file.
930 (Project, In_Tree, Bodies,
932 Extending => Extending);
934 (Project, In_Tree, Specs,
936 Extending => Extending);
938 elsif Get_Mode = Multi_Language and then
939 (not Project.Externally_Built) and then
943 Language : Language_Ptr;
945 Alt_Lang : Language_List;
946 Continuation : Boolean := False;
947 Iter : Source_Iterator;
950 Language := Project.Languages;
951 while Language /= No_Language_Index loop
953 -- If there are no sources for this language, check whether
954 -- there are sources for which this is an alternate
957 if Language.First_Source = No_Source then
958 Iter := For_Each_Source (In_Tree => In_Tree,
961 Source := Element (Iter);
962 exit Source_Loop when Source = No_Source
963 or else Source.Language = Language;
965 Alt_Lang := Source.Alternate_Languages;
966 while Alt_Lang /= null loop
967 exit Source_Loop when Alt_Lang.Language = Language;
968 Alt_Lang := Alt_Lang.Next;
972 end loop Source_Loop;
974 if Source = No_Source then
977 Get_Name_String (Language.Display_Name),
981 Continuation := True;
985 Language := Language.Next;
991 if Get_Mode = Multi_Language then
993 -- If a list of sources is specified in attribute Interfaces, set
994 -- In_Interfaces only for the sources specified in the list.
996 Check_Interfaces (Project, In_Tree);
999 -- If it is a library project file, check if it is a standalone library
1001 if Project.Library then
1002 Check_Stand_Alone_Library
1003 (Project, In_Tree, Current_Dir, Extending);
1006 -- Put the list of Mains, if any, in the project data
1008 Get_Mains (Project, In_Tree);
1010 Free_Ada_Naming_Exceptions;
1013 --------------------
1014 -- Check_Ada_Name --
1015 --------------------
1017 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
1018 The_Name : String := Name;
1019 Real_Name : Name_Id;
1020 Need_Letter : Boolean := True;
1021 Last_Underscore : Boolean := False;
1022 OK : Boolean := The_Name'Length > 0;
1025 function Is_Reserved (Name : Name_Id) return Boolean;
1026 function Is_Reserved (S : String) return Boolean;
1027 -- Check that the given name is not an Ada 95 reserved word. The reason
1028 -- for the Ada 95 here is that we do not want to exclude the case of an
1029 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
1030 -- name would be rejected anyway by the compiler. That means there is no
1031 -- requirement that the project file parser reject this.
1037 function Is_Reserved (S : String) return Boolean is
1040 Add_Str_To_Name_Buffer (S);
1041 return Is_Reserved (Name_Find);
1048 function Is_Reserved (Name : Name_Id) return Boolean is
1050 if Get_Name_Table_Byte (Name) /= 0
1051 and then Name /= Name_Project
1052 and then Name /= Name_Extends
1053 and then Name /= Name_External
1054 and then Name not in Ada_2005_Reserved_Words
1058 if Current_Verbosity = High then
1059 Write_Str (The_Name);
1060 Write_Line (" is an Ada reserved word.");
1070 -- Start of processing for Check_Ada_Name
1073 To_Lower (The_Name);
1075 Name_Len := The_Name'Length;
1076 Name_Buffer (1 .. Name_Len) := The_Name;
1078 -- Special cases of children of packages A, G, I and S on VMS
1080 if OpenVMS_On_Target
1081 and then Name_Len > 3
1082 and then Name_Buffer (2 .. 3) = "__"
1084 ((Name_Buffer (1) = 'a') or else
1085 (Name_Buffer (1) = 'g') or else
1086 (Name_Buffer (1) = 'i') or else
1087 (Name_Buffer (1) = 's'))
1089 Name_Buffer (2) := '.';
1090 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
1091 Name_Len := Name_Len - 1;
1094 Real_Name := Name_Find;
1096 if Is_Reserved (Real_Name) then
1100 First := The_Name'First;
1102 for Index in The_Name'Range loop
1105 -- We need a letter (at the beginning, and following a dot),
1106 -- but we don't have one.
1108 if Is_Letter (The_Name (Index)) then
1109 Need_Letter := False;
1114 if Current_Verbosity = High then
1115 Write_Int (Types.Int (Index));
1117 Write_Char (The_Name (Index));
1118 Write_Line ("' is not a letter.");
1124 elsif Last_Underscore
1125 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
1127 -- Two underscores are illegal, and a dot cannot follow
1132 if Current_Verbosity = High then
1133 Write_Int (Types.Int (Index));
1135 Write_Char (The_Name (Index));
1136 Write_Line ("' is illegal here.");
1141 elsif The_Name (Index) = '.' then
1143 -- First, check if the name before the dot is not a reserved word
1144 if Is_Reserved (The_Name (First .. Index - 1)) then
1150 -- We need a letter after a dot
1152 Need_Letter := True;
1154 elsif The_Name (Index) = '_' then
1155 Last_Underscore := True;
1158 -- We need an letter or a digit
1160 Last_Underscore := False;
1162 if not Is_Alphanumeric (The_Name (Index)) then
1165 if Current_Verbosity = High then
1166 Write_Int (Types.Int (Index));
1168 Write_Char (The_Name (Index));
1169 Write_Line ("' is not alphanumeric.");
1177 -- Cannot end with an underscore or a dot
1179 OK := OK and then not Need_Letter and then not Last_Underscore;
1182 if First /= Name'First and then
1183 Is_Reserved (The_Name (First .. The_Name'Last))
1191 -- Signal a problem with No_Name
1197 -------------------------
1198 -- Check_Configuration --
1199 -------------------------
1201 procedure Check_Configuration
1202 (Project : Project_Id;
1203 In_Tree : Project_Tree_Ref;
1204 Compiler_Driver_Mandatory : Boolean)
1206 Dot_Replacement : File_Name_Type := No_File;
1207 Casing : Casing_Type := All_Lower_Case;
1208 Separate_Suffix : File_Name_Type := No_File;
1210 Lang_Index : Language_Ptr := No_Language_Index;
1211 -- The index of the language data being checked
1213 Prev_Index : Language_Ptr := No_Language_Index;
1214 -- The index of the previous language
1216 procedure Process_Project_Level_Simple_Attributes;
1217 -- Process the simple attributes at the project level
1219 procedure Process_Project_Level_Array_Attributes;
1220 -- Process the associate array attributes at the project level
1222 procedure Process_Packages;
1223 -- Read the packages of the project
1225 ----------------------
1226 -- Process_Packages --
1227 ----------------------
1229 procedure Process_Packages is
1230 Packages : Package_Id;
1231 Element : Package_Element;
1233 procedure Process_Binder (Arrays : Array_Id);
1234 -- Process the associate array attributes of package Binder
1236 procedure Process_Builder (Attributes : Variable_Id);
1237 -- Process the simple attributes of package Builder
1239 procedure Process_Compiler (Arrays : Array_Id);
1240 -- Process the associate array attributes of package Compiler
1242 procedure Process_Naming (Attributes : Variable_Id);
1243 -- Process the simple attributes of package Naming
1245 procedure Process_Naming (Arrays : Array_Id);
1246 -- Process the associate array attributes of package Naming
1248 procedure Process_Linker (Attributes : Variable_Id);
1249 -- Process the simple attributes of package Linker of a
1250 -- configuration project.
1252 --------------------
1253 -- Process_Binder --
1254 --------------------
1256 procedure Process_Binder (Arrays : Array_Id) is
1257 Current_Array_Id : Array_Id;
1258 Current_Array : Array_Data;
1259 Element_Id : Array_Element_Id;
1260 Element : Array_Element;
1263 -- Process the associative array attribute of package Binder
1265 Current_Array_Id := Arrays;
1266 while Current_Array_Id /= No_Array loop
1267 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1269 Element_Id := Current_Array.Value;
1270 while Element_Id /= No_Array_Element loop
1271 Element := In_Tree.Array_Elements.Table (Element_Id);
1273 if Element.Index /= All_Other_Names then
1275 -- Get the name of the language
1278 Get_Language_From_Name
1279 (Project, Get_Name_String (Element.Index));
1281 if Lang_Index /= No_Language_Index then
1282 case Current_Array.Name is
1285 -- Attribute Driver (<language>)
1287 Lang_Index.Config.Binder_Driver :=
1288 File_Name_Type (Element.Value.Value);
1290 when Name_Required_Switches =>
1293 Lang_Index.Config.Binder_Required_Switches,
1294 From_List => Element.Value.Values,
1295 In_Tree => In_Tree);
1299 -- Attribute Prefix (<language>)
1301 Lang_Index.Config.Binder_Prefix :=
1302 Element.Value.Value;
1304 when Name_Objects_Path =>
1306 -- Attribute Objects_Path (<language>)
1308 Lang_Index.Config.Objects_Path :=
1309 Element.Value.Value;
1311 when Name_Objects_Path_File =>
1313 -- Attribute Objects_Path (<language>)
1315 Lang_Index.Config.Objects_Path_File :=
1316 Element.Value.Value;
1324 Element_Id := Element.Next;
1327 Current_Array_Id := Current_Array.Next;
1331 ---------------------
1332 -- Process_Builder --
1333 ---------------------
1335 procedure Process_Builder (Attributes : Variable_Id) is
1336 Attribute_Id : Variable_Id;
1337 Attribute : Variable;
1340 -- Process non associated array attribute from package Builder
1342 Attribute_Id := Attributes;
1343 while Attribute_Id /= No_Variable loop
1345 In_Tree.Variable_Elements.Table (Attribute_Id);
1347 if not Attribute.Value.Default then
1348 if Attribute.Name = Name_Executable_Suffix then
1350 -- Attribute Executable_Suffix: the suffix of the
1353 Project.Config.Executable_Suffix :=
1354 Attribute.Value.Value;
1358 Attribute_Id := Attribute.Next;
1360 end Process_Builder;
1362 ----------------------
1363 -- Process_Compiler --
1364 ----------------------
1366 procedure Process_Compiler (Arrays : Array_Id) is
1367 Current_Array_Id : Array_Id;
1368 Current_Array : Array_Data;
1369 Element_Id : Array_Element_Id;
1370 Element : Array_Element;
1371 List : String_List_Id;
1374 -- Process the associative array attribute of package Compiler
1376 Current_Array_Id := Arrays;
1377 while Current_Array_Id /= No_Array loop
1378 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1380 Element_Id := Current_Array.Value;
1381 while Element_Id /= No_Array_Element loop
1382 Element := In_Tree.Array_Elements.Table (Element_Id);
1384 if Element.Index /= All_Other_Names then
1386 -- Get the name of the language
1388 Lang_Index := Get_Language_From_Name
1389 (Project, Get_Name_String (Element.Index));
1391 if Lang_Index /= No_Language_Index then
1392 case Current_Array.Name is
1393 when Name_Dependency_Switches =>
1395 -- Attribute Dependency_Switches (<language>)
1397 if Lang_Index.Config.Dependency_Kind = None then
1398 Lang_Index.Config.Dependency_Kind := Makefile;
1401 List := Element.Value.Values;
1403 if List /= Nil_String then
1405 Lang_Index.Config.Dependency_Option,
1407 In_Tree => In_Tree);
1410 when Name_Dependency_Driver =>
1412 -- Attribute Dependency_Driver (<language>)
1414 if Lang_Index.Config.Dependency_Kind = None then
1415 Lang_Index.Config.Dependency_Kind := Makefile;
1418 List := Element.Value.Values;
1420 if List /= Nil_String then
1422 Lang_Index.Config.Compute_Dependency,
1424 In_Tree => In_Tree);
1427 when Name_Include_Switches =>
1429 -- Attribute Include_Switches (<language>)
1431 List := Element.Value.Values;
1433 if List = Nil_String then
1437 "include option cannot be null",
1438 Element.Value.Location);
1442 Lang_Index.Config.Include_Option,
1444 In_Tree => In_Tree);
1446 when Name_Include_Path =>
1448 -- Attribute Include_Path (<language>)
1450 Lang_Index.Config.Include_Path :=
1451 Element.Value.Value;
1453 when Name_Include_Path_File =>
1455 -- Attribute Include_Path_File (<language>)
1457 Lang_Index.Config.Include_Path_File :=
1458 Element.Value.Value;
1462 -- Attribute Driver (<language>)
1464 Lang_Index.Config.Compiler_Driver :=
1465 File_Name_Type (Element.Value.Value);
1467 when Name_Required_Switches |
1468 Name_Leading_Required_Switches =>
1471 Compiler_Leading_Required_Switches,
1472 From_List => Element.Value.Values,
1473 In_Tree => In_Tree);
1475 when Name_Trailing_Required_Switches =>
1478 Compiler_Trailing_Required_Switches,
1479 From_List => Element.Value.Values,
1480 In_Tree => In_Tree);
1482 when Name_Path_Syntax =>
1484 Lang_Index.Config.Path_Syntax :=
1485 Path_Syntax_Kind'Value
1486 (Get_Name_String (Element.Value.Value));
1489 when Constraint_Error =>
1493 "invalid value for Path_Syntax",
1494 Element.Value.Location);
1497 when Name_Object_File_Suffix =>
1498 if Get_Name_String (Element.Value.Value) = "" then
1501 "object file suffix cannot be empty",
1502 Element.Value.Location);
1505 Lang_Index.Config.Object_File_Suffix :=
1506 Element.Value.Value;
1509 when Name_Object_File_Switches =>
1511 Lang_Index.Config.Object_File_Switches,
1512 From_List => Element.Value.Values,
1513 In_Tree => In_Tree);
1515 when Name_Pic_Option =>
1517 -- Attribute Compiler_Pic_Option (<language>)
1519 List := Element.Value.Values;
1521 if List = Nil_String then
1525 "compiler PIC option cannot be null",
1526 Element.Value.Location);
1530 Lang_Index.Config.Compilation_PIC_Option,
1532 In_Tree => In_Tree);
1534 when Name_Mapping_File_Switches =>
1536 -- Attribute Mapping_File_Switches (<language>)
1538 List := Element.Value.Values;
1540 if List = Nil_String then
1544 "mapping file switches cannot be null",
1545 Element.Value.Location);
1549 Lang_Index.Config.Mapping_File_Switches,
1551 In_Tree => In_Tree);
1553 when Name_Mapping_Spec_Suffix =>
1555 -- Attribute Mapping_Spec_Suffix (<language>)
1557 Lang_Index.Config.Mapping_Spec_Suffix :=
1558 File_Name_Type (Element.Value.Value);
1560 when Name_Mapping_Body_Suffix =>
1562 -- Attribute Mapping_Body_Suffix (<language>)
1564 Lang_Index.Config.Mapping_Body_Suffix :=
1565 File_Name_Type (Element.Value.Value);
1567 when Name_Config_File_Switches =>
1569 -- Attribute Config_File_Switches (<language>)
1571 List := Element.Value.Values;
1573 if List = Nil_String then
1577 "config file switches cannot be null",
1578 Element.Value.Location);
1582 Lang_Index.Config.Config_File_Switches,
1584 In_Tree => In_Tree);
1586 when Name_Objects_Path =>
1588 -- Attribute Objects_Path (<language>)
1590 Lang_Index.Config.Objects_Path :=
1591 Element.Value.Value;
1593 when Name_Objects_Path_File =>
1595 -- Attribute Objects_Path_File (<language>)
1597 Lang_Index.Config.Objects_Path_File :=
1598 Element.Value.Value;
1600 when Name_Config_Body_File_Name =>
1602 -- Attribute Config_Body_File_Name (<language>)
1604 Lang_Index.Config.Config_Body :=
1605 Element.Value.Value;
1607 when Name_Config_Body_File_Name_Pattern =>
1609 -- Attribute Config_Body_File_Name_Pattern
1612 Lang_Index.Config.Config_Body_Pattern :=
1613 Element.Value.Value;
1615 when Name_Config_Spec_File_Name =>
1617 -- Attribute Config_Spec_File_Name (<language>)
1619 Lang_Index.Config.Config_Spec :=
1620 Element.Value.Value;
1622 when Name_Config_Spec_File_Name_Pattern =>
1624 -- Attribute Config_Spec_File_Name_Pattern
1627 Lang_Index.Config.Config_Spec_Pattern :=
1628 Element.Value.Value;
1630 when Name_Config_File_Unique =>
1632 -- Attribute Config_File_Unique (<language>)
1635 Lang_Index.Config.Config_File_Unique :=
1637 (Get_Name_String (Element.Value.Value));
1639 when Constraint_Error =>
1643 "illegal value for Config_File_Unique",
1644 Element.Value.Location);
1653 Element_Id := Element.Next;
1656 Current_Array_Id := Current_Array.Next;
1658 end Process_Compiler;
1660 --------------------
1661 -- Process_Naming --
1662 --------------------
1664 procedure Process_Naming (Attributes : Variable_Id) is
1665 Attribute_Id : Variable_Id;
1666 Attribute : Variable;
1669 -- Process non associated array attribute from package Naming
1671 Attribute_Id := Attributes;
1672 while Attribute_Id /= No_Variable loop
1673 Attribute := In_Tree.Variable_Elements.Table (Attribute_Id);
1675 if not Attribute.Value.Default then
1676 if Attribute.Name = Name_Separate_Suffix then
1678 -- Attribute Separate_Suffix
1680 Get_Name_String (Attribute.Value.Value);
1681 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
1682 Separate_Suffix := Name_Find;
1684 elsif Attribute.Name = Name_Casing then
1690 Value (Get_Name_String (Attribute.Value.Value));
1693 when Constraint_Error =>
1697 "invalid value for Casing",
1698 Attribute.Value.Location);
1701 elsif Attribute.Name = Name_Dot_Replacement then
1703 -- Attribute Dot_Replacement
1705 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1710 Attribute_Id := Attribute.Next;
1714 procedure Process_Naming (Arrays : Array_Id) is
1715 Current_Array_Id : Array_Id;
1716 Current_Array : Array_Data;
1717 Element_Id : Array_Element_Id;
1718 Element : Array_Element;
1720 -- Process the associative array attribute of package Naming
1722 Current_Array_Id := Arrays;
1723 while Current_Array_Id /= No_Array loop
1724 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1726 Element_Id := Current_Array.Value;
1727 while Element_Id /= No_Array_Element loop
1728 Element := In_Tree.Array_Elements.Table (Element_Id);
1730 -- Get the name of the language
1732 Lang_Index := Get_Language_From_Name
1733 (Project, Get_Name_String (Element.Index));
1735 if Lang_Index /= No_Language_Index then
1736 case Current_Array.Name is
1737 when Name_Spec_Suffix | Name_Specification_Suffix =>
1739 -- Attribute Spec_Suffix (<language>)
1741 Get_Name_String (Element.Value.Value);
1742 Canonical_Case_File_Name
1743 (Name_Buffer (1 .. Name_Len));
1744 Lang_Index.Config.Naming_Data.Spec_Suffix :=
1747 when Name_Implementation_Suffix | Name_Body_Suffix =>
1749 Get_Name_String (Element.Value.Value);
1750 Canonical_Case_File_Name
1751 (Name_Buffer (1 .. Name_Len));
1753 -- Attribute Body_Suffix (<language>)
1755 Lang_Index.Config.Naming_Data.Body_Suffix :=
1757 Lang_Index.Config.Naming_Data.Separate_Suffix :=
1758 Lang_Index.Config.Naming_Data.Body_Suffix;
1765 Element_Id := Element.Next;
1768 Current_Array_Id := Current_Array.Next;
1772 --------------------
1773 -- Process_Linker --
1774 --------------------
1776 procedure Process_Linker (Attributes : Variable_Id) is
1777 Attribute_Id : Variable_Id;
1778 Attribute : Variable;
1781 -- Process non associated array attribute from package Linker
1783 Attribute_Id := Attributes;
1784 while Attribute_Id /= No_Variable loop
1786 In_Tree.Variable_Elements.Table (Attribute_Id);
1788 if not Attribute.Value.Default then
1789 if Attribute.Name = Name_Driver then
1791 -- Attribute Linker'Driver: the default linker to use
1793 Project.Config.Linker :=
1794 Path_Name_Type (Attribute.Value.Value);
1796 -- Linker'Driver is also used to link shared libraries
1797 -- if the obsolescent attribute Library_GCC has not been
1800 if Project.Config.Shared_Lib_Driver = No_File then
1801 Project.Config.Shared_Lib_Driver :=
1802 File_Name_Type (Attribute.Value.Value);
1805 elsif Attribute.Name = Name_Required_Switches then
1807 -- Attribute Required_Switches: the minimum
1808 -- options to use when invoking the linker
1810 Put (Into_List => Project.Config.Minimum_Linker_Options,
1811 From_List => Attribute.Value.Values,
1812 In_Tree => In_Tree);
1814 elsif Attribute.Name = Name_Map_File_Option then
1815 Project.Config.Map_File_Option := Attribute.Value.Value;
1817 elsif Attribute.Name = Name_Max_Command_Line_Length then
1819 Project.Config.Max_Command_Line_Length :=
1820 Natural'Value (Get_Name_String
1821 (Attribute.Value.Value));
1824 when Constraint_Error =>
1828 "value must be positive or equal to 0",
1829 Attribute.Value.Location);
1832 elsif Attribute.Name = Name_Response_File_Format then
1837 Get_Name_String (Attribute.Value.Value);
1838 To_Lower (Name_Buffer (1 .. Name_Len));
1841 if Name = Name_None then
1842 Project.Config.Resp_File_Format := None;
1844 elsif Name = Name_Gnu then
1845 Project.Config.Resp_File_Format := GNU;
1847 elsif Name = Name_Object_List then
1848 Project.Config.Resp_File_Format := Object_List;
1850 elsif Name = Name_Option_List then
1851 Project.Config.Resp_File_Format := Option_List;
1857 "illegal response file format",
1858 Attribute.Value.Location);
1862 elsif Attribute.Name = Name_Response_File_Switches then
1863 Put (Into_List => Project.Config.Resp_File_Options,
1864 From_List => Attribute.Value.Values,
1865 In_Tree => In_Tree);
1869 Attribute_Id := Attribute.Next;
1873 -- Start of processing for Process_Packages
1876 Packages := Project.Decl.Packages;
1877 while Packages /= No_Package loop
1878 Element := In_Tree.Packages.Table (Packages);
1880 case Element.Name is
1883 -- Process attributes of package Binder
1885 Process_Binder (Element.Decl.Arrays);
1887 when Name_Builder =>
1889 -- Process attributes of package Builder
1891 Process_Builder (Element.Decl.Attributes);
1893 when Name_Compiler =>
1895 -- Process attributes of package Compiler
1897 Process_Compiler (Element.Decl.Arrays);
1901 -- Process attributes of package Linker
1903 Process_Linker (Element.Decl.Attributes);
1907 -- Process attributes of package Naming
1909 Process_Naming (Element.Decl.Attributes);
1910 Process_Naming (Element.Decl.Arrays);
1916 Packages := Element.Next;
1918 end Process_Packages;
1920 ---------------------------------------------
1921 -- Process_Project_Level_Simple_Attributes --
1922 ---------------------------------------------
1924 procedure Process_Project_Level_Simple_Attributes is
1925 Attribute_Id : Variable_Id;
1926 Attribute : Variable;
1927 List : String_List_Id;
1930 -- Process non associated array attribute at project level
1932 Attribute_Id := Project.Decl.Attributes;
1933 while Attribute_Id /= No_Variable loop
1935 In_Tree.Variable_Elements.Table (Attribute_Id);
1937 if not Attribute.Value.Default then
1938 if Attribute.Name = Name_Target then
1940 -- Attribute Target: the target specified
1942 Project.Config.Target := Attribute.Value.Value;
1944 elsif Attribute.Name = Name_Library_Builder then
1946 -- Attribute Library_Builder: the application to invoke
1947 -- to build libraries.
1949 Project.Config.Library_Builder :=
1950 Path_Name_Type (Attribute.Value.Value);
1952 elsif Attribute.Name = Name_Archive_Builder then
1954 -- Attribute Archive_Builder: the archive builder
1955 -- (usually "ar") and its minimum options (usually "cr").
1957 List := Attribute.Value.Values;
1959 if List = Nil_String then
1963 "archive builder cannot be null",
1964 Attribute.Value.Location);
1967 Put (Into_List => Project.Config.Archive_Builder,
1969 In_Tree => In_Tree);
1971 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1973 -- Attribute Archive_Builder: the archive builder
1974 -- (usually "ar") and its minimum options (usually "cr").
1976 List := Attribute.Value.Values;
1978 if List /= Nil_String then
1981 Project.Config.Archive_Builder_Append_Option,
1983 In_Tree => In_Tree);
1986 elsif Attribute.Name = Name_Archive_Indexer then
1988 -- Attribute Archive_Indexer: the optional archive
1989 -- indexer (usually "ranlib") with its minimum options
1992 List := Attribute.Value.Values;
1994 if List = Nil_String then
1998 "archive indexer cannot be null",
1999 Attribute.Value.Location);
2002 Put (Into_List => Project.Config.Archive_Indexer,
2004 In_Tree => In_Tree);
2006 elsif Attribute.Name = Name_Library_Partial_Linker then
2008 -- Attribute Library_Partial_Linker: the optional linker
2009 -- driver with its minimum options, to partially link
2012 List := Attribute.Value.Values;
2014 if List = Nil_String then
2018 "partial linker cannot be null",
2019 Attribute.Value.Location);
2022 Put (Into_List => Project.Config.Lib_Partial_Linker,
2024 In_Tree => In_Tree);
2026 elsif Attribute.Name = Name_Library_GCC then
2027 Project.Config.Shared_Lib_Driver :=
2028 File_Name_Type (Attribute.Value.Value);
2032 "?Library_'G'C'C is an obsolescent attribute, " &
2033 "use Linker''Driver instead",
2034 Attribute.Value.Location);
2036 elsif Attribute.Name = Name_Archive_Suffix then
2037 Project.Config.Archive_Suffix :=
2038 File_Name_Type (Attribute.Value.Value);
2040 elsif Attribute.Name = Name_Linker_Executable_Option then
2042 -- Attribute Linker_Executable_Option: optional options
2043 -- to specify an executable name. Defaults to "-o".
2045 List := Attribute.Value.Values;
2047 if List = Nil_String then
2051 "linker executable option cannot be null",
2052 Attribute.Value.Location);
2055 Put (Into_List => Project.Config.Linker_Executable_Option,
2057 In_Tree => In_Tree);
2059 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2061 -- Attribute Linker_Lib_Dir_Option: optional options
2062 -- to specify a library search directory. Defaults to
2065 Get_Name_String (Attribute.Value.Value);
2067 if Name_Len = 0 then
2071 "linker library directory option cannot be empty",
2072 Attribute.Value.Location);
2075 Project.Config.Linker_Lib_Dir_Option :=
2076 Attribute.Value.Value;
2078 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2080 -- Attribute Linker_Lib_Name_Option: optional options
2081 -- to specify the name of a library to be linked in.
2082 -- Defaults to "-l".
2084 Get_Name_String (Attribute.Value.Value);
2086 if Name_Len = 0 then
2090 "linker library name option cannot be empty",
2091 Attribute.Value.Location);
2094 Project.Config.Linker_Lib_Name_Option :=
2095 Attribute.Value.Value;
2097 elsif Attribute.Name = Name_Run_Path_Option then
2099 -- Attribute Run_Path_Option: optional options to
2100 -- specify a path for libraries.
2102 List := Attribute.Value.Values;
2104 if List /= Nil_String then
2105 Put (Into_List => Project.Config.Run_Path_Option,
2107 In_Tree => In_Tree);
2110 elsif Attribute.Name = Name_Separate_Run_Path_Options then
2112 pragma Unsuppress (All_Checks);
2114 Project.Config.Separate_Run_Path_Options :=
2115 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2117 when Constraint_Error =>
2121 "invalid value """ &
2122 Get_Name_String (Attribute.Value.Value) &
2123 """ for Separate_Run_Path_Options",
2124 Attribute.Value.Location);
2127 elsif Attribute.Name = Name_Library_Support then
2129 pragma Unsuppress (All_Checks);
2131 Project.Config.Lib_Support :=
2132 Library_Support'Value (Get_Name_String
2133 (Attribute.Value.Value));
2135 when Constraint_Error =>
2139 "invalid value """ &
2140 Get_Name_String (Attribute.Value.Value) &
2141 """ for Library_Support",
2142 Attribute.Value.Location);
2145 elsif Attribute.Name = Name_Shared_Library_Prefix then
2146 Project.Config.Shared_Lib_Prefix :=
2147 File_Name_Type (Attribute.Value.Value);
2149 elsif Attribute.Name = Name_Shared_Library_Suffix then
2150 Project.Config.Shared_Lib_Suffix :=
2151 File_Name_Type (Attribute.Value.Value);
2153 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2155 pragma Unsuppress (All_Checks);
2157 Project.Config.Symbolic_Link_Supported :=
2158 Boolean'Value (Get_Name_String
2159 (Attribute.Value.Value));
2161 when Constraint_Error =>
2166 & Get_Name_String (Attribute.Value.Value)
2167 & """ for Symbolic_Link_Supported",
2168 Attribute.Value.Location);
2172 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2175 pragma Unsuppress (All_Checks);
2177 Project.Config.Lib_Maj_Min_Id_Supported :=
2178 Boolean'Value (Get_Name_String
2179 (Attribute.Value.Value));
2181 when Constraint_Error =>
2185 "invalid value """ &
2186 Get_Name_String (Attribute.Value.Value) &
2187 """ for Library_Major_Minor_Id_Supported",
2188 Attribute.Value.Location);
2191 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2193 pragma Unsuppress (All_Checks);
2195 Project.Config.Auto_Init_Supported :=
2196 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2198 when Constraint_Error =>
2203 & Get_Name_String (Attribute.Value.Value)
2204 & """ for Library_Auto_Init_Supported",
2205 Attribute.Value.Location);
2208 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2209 List := Attribute.Value.Values;
2211 if List /= Nil_String then
2212 Put (Into_List => Project.Config.Shared_Lib_Min_Options,
2214 In_Tree => In_Tree);
2217 elsif Attribute.Name = Name_Library_Version_Switches then
2218 List := Attribute.Value.Values;
2220 if List /= Nil_String then
2221 Put (Into_List => Project.Config.Lib_Version_Options,
2223 In_Tree => In_Tree);
2228 Attribute_Id := Attribute.Next;
2230 end Process_Project_Level_Simple_Attributes;
2232 --------------------------------------------
2233 -- Process_Project_Level_Array_Attributes --
2234 --------------------------------------------
2236 procedure Process_Project_Level_Array_Attributes is
2237 Current_Array_Id : Array_Id;
2238 Current_Array : Array_Data;
2239 Element_Id : Array_Element_Id;
2240 Element : Array_Element;
2241 List : String_List_Id;
2244 -- Process the associative array attributes at project level
2246 Current_Array_Id := Project.Decl.Arrays;
2247 while Current_Array_Id /= No_Array loop
2248 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2250 Element_Id := Current_Array.Value;
2251 while Element_Id /= No_Array_Element loop
2252 Element := In_Tree.Array_Elements.Table (Element_Id);
2254 -- Get the name of the language
2257 Get_Language_From_Name
2258 (Project, Get_Name_String (Element.Index));
2260 if Lang_Index /= No_Language_Index then
2261 case Current_Array.Name is
2262 when Name_Inherit_Source_Path =>
2263 List := Element.Value.Values;
2265 if List /= Nil_String then
2268 Lang_Index.Config.Include_Compatible_Languages,
2271 Lower_Case => True);
2274 when Name_Toolchain_Description =>
2276 -- Attribute Toolchain_Description (<language>)
2278 Lang_Index.Config.Toolchain_Description :=
2279 Element.Value.Value;
2281 when Name_Toolchain_Version =>
2283 -- Attribute Toolchain_Version (<language>)
2285 Lang_Index.Config.Toolchain_Version :=
2286 Element.Value.Value;
2288 when Name_Runtime_Library_Dir =>
2290 -- Attribute Runtime_Library_Dir (<language>)
2292 Lang_Index.Config.Runtime_Library_Dir :=
2293 Element.Value.Value;
2295 when Name_Runtime_Source_Dir =>
2297 -- Attribute Runtime_Library_Dir (<language>)
2299 Lang_Index.Config.Runtime_Source_Dir :=
2300 Element.Value.Value;
2302 when Name_Object_Generated =>
2304 pragma Unsuppress (All_Checks);
2310 (Get_Name_String (Element.Value.Value));
2312 Lang_Index.Config.Object_Generated := Value;
2314 -- If no object is generated, no object may be
2318 Lang_Index.Config.Objects_Linked := False;
2322 when Constraint_Error =>
2327 & Get_Name_String (Element.Value.Value)
2328 & """ for Object_Generated",
2329 Element.Value.Location);
2332 when Name_Objects_Linked =>
2334 pragma Unsuppress (All_Checks);
2340 (Get_Name_String (Element.Value.Value));
2342 -- No change if Object_Generated is False, as this
2343 -- forces Objects_Linked to be False too.
2345 if Lang_Index.Config.Object_Generated then
2346 Lang_Index.Config.Objects_Linked := Value;
2350 when Constraint_Error =>
2355 & Get_Name_String (Element.Value.Value)
2356 & """ for Objects_Linked",
2357 Element.Value.Location);
2364 Element_Id := Element.Next;
2367 Current_Array_Id := Current_Array.Next;
2369 end Process_Project_Level_Array_Attributes;
2372 Process_Project_Level_Simple_Attributes;
2373 Process_Project_Level_Array_Attributes;
2376 -- For unit based languages, set Casing, Dot_Replacement and
2377 -- Separate_Suffix in Naming_Data.
2379 Lang_Index := Project.Languages;
2380 while Lang_Index /= No_Language_Index loop
2381 if Lang_Index.Name = Name_Ada then
2382 Lang_Index.Config.Naming_Data.Casing := Casing;
2383 Lang_Index.Config.Naming_Data.Dot_Replacement := Dot_Replacement;
2385 if Separate_Suffix /= No_File then
2386 Lang_Index.Config.Naming_Data.Separate_Suffix :=
2393 Lang_Index := Lang_Index.Next;
2396 -- Give empty names to various prefixes/suffixes, if they have not
2397 -- been specified in the configuration.
2399 if Project.Config.Archive_Suffix = No_File then
2400 Project.Config.Archive_Suffix := Empty_File;
2403 if Project.Config.Shared_Lib_Prefix = No_File then
2404 Project.Config.Shared_Lib_Prefix := Empty_File;
2407 if Project.Config.Shared_Lib_Suffix = No_File then
2408 Project.Config.Shared_Lib_Suffix := Empty_File;
2411 Lang_Index := Project.Languages;
2412 while Lang_Index /= No_Language_Index loop
2413 -- For all languages, Compiler_Driver needs to be specified. This is
2414 -- only needed if we do intend to compile (not in GPS for instance).
2416 if Compiler_Driver_Mandatory
2417 and then Lang_Index.Config.Compiler_Driver = No_File
2419 Error_Msg_Name_1 := Lang_Index.Display_Name;
2423 "?no compiler specified for language %%" &
2424 ", ignoring all its sources",
2427 if Lang_Index = Project.Languages then
2428 Project.Languages := Lang_Index.Next;
2430 Prev_Index.Next := Lang_Index.Next;
2433 elsif Lang_Index.Name = Name_Ada then
2434 Prev_Index := Lang_Index;
2436 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2437 -- Body_Suffix need to be specified.
2439 if Lang_Index.Config.Naming_Data.Dot_Replacement = No_File then
2443 "Dot_Replacement not specified for Ada",
2447 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File then
2451 "Spec_Suffix not specified for Ada",
2455 if Lang_Index.Config.Naming_Data.Body_Suffix = No_File then
2459 "Body_Suffix not specified for Ada",
2464 Prev_Index := Lang_Index;
2466 -- For file based languages, either Spec_Suffix or Body_Suffix
2467 -- need to be specified.
2469 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File and then
2470 Lang_Index.Config.Naming_Data.Body_Suffix = No_File
2472 Error_Msg_Name_1 := Lang_Index.Display_Name;
2476 "no suffixes specified for %%",
2481 Lang_Index := Lang_Index.Next;
2483 end Check_Configuration;
2485 -------------------------------
2486 -- Check_If_Externally_Built --
2487 -------------------------------
2489 procedure Check_If_Externally_Built
2490 (Project : Project_Id;
2491 In_Tree : Project_Tree_Ref)
2493 Externally_Built : constant Variable_Value :=
2495 (Name_Externally_Built,
2496 Project.Decl.Attributes, In_Tree);
2499 if not Externally_Built.Default then
2500 Get_Name_String (Externally_Built.Value);
2501 To_Lower (Name_Buffer (1 .. Name_Len));
2503 if Name_Buffer (1 .. Name_Len) = "true" then
2504 Project.Externally_Built := True;
2506 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2507 Error_Msg (Project, In_Tree,
2508 "Externally_Built may only be true or false",
2509 Externally_Built.Location);
2513 -- A virtual project extending an externally built project is itself
2514 -- externally built.
2516 if Project.Virtual and then Project.Extends /= No_Project then
2517 Project.Externally_Built := Project.Extends.Externally_Built;
2520 if Current_Verbosity = High then
2521 Write_Str ("Project is ");
2523 if not Project.Externally_Built then
2527 Write_Line ("externally built.");
2529 end Check_If_Externally_Built;
2531 ----------------------
2532 -- Check_Interfaces --
2533 ----------------------
2535 procedure Check_Interfaces
2536 (Project : Project_Id;
2537 In_Tree : Project_Tree_Ref)
2539 Interfaces : constant Prj.Variable_Value :=
2541 (Snames.Name_Interfaces,
2542 Project.Decl.Attributes,
2545 List : String_List_Id;
2546 Element : String_Element;
2547 Name : File_Name_Type;
2548 Iter : Source_Iterator;
2550 Project_2 : Project_Id;
2554 if not Interfaces.Default then
2556 -- Set In_Interfaces to False for all sources. It will be set to True
2557 -- later for the sources in the Interfaces list.
2559 Project_2 := Project;
2560 while Project_2 /= No_Project loop
2561 Iter := For_Each_Source (In_Tree, Project_2);
2564 Source := Prj.Element (Iter);
2565 exit when Source = No_Source;
2566 Source.In_Interfaces := False;
2570 Project_2 := Project_2.Extends;
2573 List := Interfaces.Values;
2574 while List /= Nil_String loop
2575 Element := In_Tree.String_Elements.Table (List);
2576 Name := Canonical_Case_File_Name (Element.Value);
2578 Project_2 := Project;
2580 while Project_2 /= No_Project loop
2581 Iter := For_Each_Source (In_Tree, Project_2);
2584 Source := Prj.Element (Iter);
2585 exit when Source = No_Source;
2587 if Source.File = Name then
2588 if not Source.Locally_Removed then
2589 Source.In_Interfaces := True;
2590 Source.Declared_In_Interfaces := True;
2592 Other := Other_Part (Source);
2594 if Other /= No_Source then
2595 Other.In_Interfaces := True;
2596 Other.Declared_In_Interfaces := True;
2599 if Current_Verbosity = High then
2600 Write_Str (" interface: ");
2601 Write_Line (Get_Name_String (Source.Path.Name));
2611 Project_2 := Project_2.Extends;
2614 if Source = No_Source then
2615 Error_Msg_File_1 := File_Name_Type (Element.Value);
2616 Error_Msg_Name_1 := Project.Name;
2621 "{ cannot be an interface of project %% "
2622 & "as it is not one of its sources",
2626 List := Element.Next;
2629 Project.Interfaces_Defined := True;
2631 elsif Project.Extends /= No_Project then
2632 Project.Interfaces_Defined := Project.Extends.Interfaces_Defined;
2634 if Project.Interfaces_Defined then
2635 Iter := For_Each_Source (In_Tree, Project);
2637 Source := Prj.Element (Iter);
2638 exit when Source = No_Source;
2640 if not Source.Declared_In_Interfaces then
2641 Source.In_Interfaces := False;
2648 end Check_Interfaces;
2650 ------------------------------------
2651 -- Check_And_Normalize_Unit_Names --
2652 ------------------------------------
2654 procedure Check_And_Normalize_Unit_Names
2655 (Project : Project_Id;
2656 In_Tree : Project_Tree_Ref;
2657 List : Array_Element_Id;
2658 Debug_Name : String)
2660 Current : Array_Element_Id;
2661 Element : Array_Element;
2662 Unit_Name : Name_Id;
2665 if Current_Verbosity = High then
2666 Write_Line (" Checking unit names in " & Debug_Name);
2670 while Current /= No_Array_Element loop
2671 Element := In_Tree.Array_Elements.Table (Current);
2672 Element.Value.Value :=
2673 Name_Id (Canonical_Case_File_Name (Element.Value.Value));
2675 -- Check that it contains a valid unit name
2677 Get_Name_String (Element.Index);
2678 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2680 if Unit_Name = No_Name then
2681 Err_Vars.Error_Msg_Name_1 := Element.Index;
2684 "%% is not a valid unit name.",
2685 Element.Value.Location);
2688 if Current_Verbosity = High then
2689 Write_Str (" for unit: ");
2690 Write_Line (Get_Name_String (Unit_Name));
2693 Element.Index := Unit_Name;
2694 In_Tree.Array_Elements.Table (Current) := Element;
2697 Current := Element.Next;
2699 end Check_And_Normalize_Unit_Names;
2701 --------------------------
2702 -- Check_Package_Naming --
2703 --------------------------
2705 procedure Check_Package_Naming
2706 (Project : Project_Id;
2707 In_Tree : Project_Tree_Ref;
2708 Is_Config_File : Boolean;
2709 Bodies : out Array_Element_Id;
2710 Specs : out Array_Element_Id)
2712 Naming_Id : constant Package_Id :=
2713 Util.Value_Of (Name_Naming, Project.Decl.Packages, In_Tree);
2714 Naming : Package_Element;
2716 Ada_Body_Suffix_Loc : Source_Ptr := No_Location;
2717 Ada_Spec_Suffix_Loc : Source_Ptr := No_Location;
2719 procedure Check_Naming_Ada_Only;
2720 -- Does Check_Naming_Schemes processing in Ada_Only mode.
2721 -- If there is a package Naming, puts in Data.Naming the contents of
2724 procedure Check_Naming_Multi_Lang;
2725 -- Does Check_Naming_Schemes processing for Multi_Language mode
2727 procedure Check_Common
2728 (Dot_Replacement : in out File_Name_Type;
2729 Casing : in out Casing_Type;
2730 Casing_Defined : out Boolean;
2731 Separate_Suffix : in out File_Name_Type;
2732 Sep_Suffix_Loc : out Source_Ptr);
2733 -- Check attributes common to Ada_Only and Multi_Lang modes
2735 procedure Process_Exceptions_File_Based
2736 (Lang_Id : Language_Ptr;
2737 Kind : Source_Kind);
2738 procedure Process_Exceptions_Unit_Based
2739 (Lang_Id : Language_Ptr;
2740 Kind : Source_Kind);
2741 -- In Multi_Lang mode, process the naming exceptions for the two types
2742 -- of languages we can have.
2744 procedure Initialize_Naming_Data;
2745 -- Initialize internal naming data for the various languages
2751 procedure Check_Common
2752 (Dot_Replacement : in out File_Name_Type;
2753 Casing : in out Casing_Type;
2754 Casing_Defined : out Boolean;
2755 Separate_Suffix : in out File_Name_Type;
2756 Sep_Suffix_Loc : out Source_Ptr)
2758 Dot_Repl : constant Variable_Value :=
2760 (Name_Dot_Replacement,
2761 Naming.Decl.Attributes,
2763 Casing_String : constant Variable_Value :=
2766 Naming.Decl.Attributes,
2768 Sep_Suffix : constant Variable_Value :=
2770 (Name_Separate_Suffix,
2771 Naming.Decl.Attributes,
2773 Dot_Repl_Loc : Source_Ptr;
2776 Sep_Suffix_Loc := No_Location;
2778 if not Dot_Repl.Default then
2780 (Dot_Repl.Kind = Single, "Dot_Replacement is not a string");
2782 if Length_Of_Name (Dot_Repl.Value) = 0 then
2785 "Dot_Replacement cannot be empty",
2789 Dot_Replacement := Canonical_Case_File_Name (Dot_Repl.Value);
2790 Dot_Repl_Loc := Dot_Repl.Location;
2793 Repl : constant String := Get_Name_String (Dot_Replacement);
2796 -- Dot_Replacement cannot
2798 -- - start or end with an alphanumeric
2799 -- - be a single '_'
2800 -- - start with an '_' followed by an alphanumeric
2801 -- - contain a '.' except if it is "."
2804 or else Is_Alphanumeric (Repl (Repl'First))
2805 or else Is_Alphanumeric (Repl (Repl'Last))
2806 or else (Repl (Repl'First) = '_'
2810 Is_Alphanumeric (Repl (Repl'First + 1))))
2811 or else (Repl'Length > 1
2813 Index (Source => Repl, Pattern => ".") /= 0)
2818 """ is illegal for Dot_Replacement.",
2824 if Dot_Replacement /= No_File then
2826 ("Dot_Replacement", Get_Name_String (Dot_Replacement));
2829 Casing_Defined := False;
2831 if not Casing_String.Default then
2833 (Casing_String.Kind = Single, "Casing is not a string");
2836 Casing_Image : constant String :=
2837 Get_Name_String (Casing_String.Value);
2839 if Casing_Image'Length = 0 then
2842 "Casing cannot be an empty string",
2843 Casing_String.Location);
2846 Casing := Value (Casing_Image);
2847 Casing_Defined := True;
2850 when Constraint_Error =>
2851 Name_Len := Casing_Image'Length;
2852 Name_Buffer (1 .. Name_Len) := Casing_Image;
2853 Err_Vars.Error_Msg_Name_1 := Name_Find;
2856 "%% is not a correct Casing",
2857 Casing_String.Location);
2861 Write_Attr ("Casing", Image (Casing));
2863 if not Sep_Suffix.Default then
2864 if Length_Of_Name (Sep_Suffix.Value) = 0 then
2867 "Separate_Suffix cannot be empty",
2868 Sep_Suffix.Location);
2871 Separate_Suffix := Canonical_Case_File_Name (Sep_Suffix.Value);
2872 Sep_Suffix_Loc := Sep_Suffix.Location;
2874 if Is_Illegal_Suffix (Separate_Suffix, Dot_Replacement) then
2875 Err_Vars.Error_Msg_File_1 := Separate_Suffix;
2878 "{ is illegal for Separate_Suffix",
2879 Sep_Suffix.Location);
2884 if Separate_Suffix /= No_File then
2886 ("Separate_Suffix", Get_Name_String (Separate_Suffix));
2890 -----------------------------------
2891 -- Process_Exceptions_File_Based --
2892 -----------------------------------
2894 procedure Process_Exceptions_File_Based
2895 (Lang_Id : Language_Ptr;
2898 Lang : constant Name_Id := Lang_Id.Name;
2899 Exceptions : Array_Element_Id;
2900 Exception_List : Variable_Value;
2901 Element_Id : String_List_Id;
2902 Element : String_Element;
2903 File_Name : File_Name_Type;
2905 Iter : Source_Iterator;
2912 (Name_Implementation_Exceptions,
2913 In_Arrays => Naming.Decl.Arrays,
2914 In_Tree => In_Tree);
2919 (Name_Specification_Exceptions,
2920 In_Arrays => Naming.Decl.Arrays,
2921 In_Tree => In_Tree);
2924 Exception_List := Value_Of
2926 In_Array => Exceptions,
2927 In_Tree => In_Tree);
2929 if Exception_List /= Nil_Variable_Value then
2930 Element_Id := Exception_List.Values;
2931 while Element_Id /= Nil_String loop
2932 Element := In_Tree.String_Elements.Table (Element_Id);
2933 File_Name := Canonical_Case_File_Name (Element.Value);
2935 Iter := For_Each_Source (In_Tree, Project);
2937 Source := Prj.Element (Iter);
2938 exit when Source = No_Source or else Source.File = File_Name;
2942 if Source = No_Source then
2949 File_Name => File_Name,
2950 Display_File => File_Name_Type (Element.Value),
2951 Naming_Exception => True);
2954 -- Check if the file name is already recorded for another
2955 -- language or another kind.
2957 if Source.Language /= Lang_Id then
2961 "the same file cannot be a source of two languages",
2964 elsif Source.Kind /= Kind then
2968 "the same file cannot be a source and a template",
2972 -- If the file is already recorded for the same
2973 -- language and the same kind, it means that the file
2974 -- name appears several times in the *_Exceptions
2975 -- attribute; so there is nothing to do.
2978 Element_Id := Element.Next;
2981 end Process_Exceptions_File_Based;
2983 -----------------------------------
2984 -- Process_Exceptions_Unit_Based --
2985 -----------------------------------
2987 procedure Process_Exceptions_Unit_Based
2988 (Lang_Id : Language_Ptr;
2991 Lang : constant Name_Id := Lang_Id.Name;
2992 Exceptions : Array_Element_Id;
2993 Element : Array_Element;
2996 File_Name : File_Name_Type;
2998 Source_To_Replace : Source_Id := No_Source;
2999 Other_Project : Project_Id;
3000 Iter : Source_Iterator;
3005 Exceptions := Value_Of
3007 In_Arrays => Naming.Decl.Arrays,
3008 In_Tree => In_Tree);
3010 if Exceptions = No_Array_Element then
3013 (Name_Implementation,
3014 In_Arrays => Naming.Decl.Arrays,
3015 In_Tree => In_Tree);
3022 In_Arrays => Naming.Decl.Arrays,
3023 In_Tree => In_Tree);
3025 if Exceptions = No_Array_Element then
3026 Exceptions := Value_Of
3028 In_Arrays => Naming.Decl.Arrays,
3029 In_Tree => In_Tree);
3033 while Exceptions /= No_Array_Element loop
3034 Element := In_Tree.Array_Elements.Table (Exceptions);
3035 File_Name := Canonical_Case_File_Name (Element.Value.Value);
3037 Get_Name_String (Element.Index);
3038 To_Lower (Name_Buffer (1 .. Name_Len));
3040 Index := Element.Value.Index;
3042 -- For Ada, check if it is a valid unit name
3044 if Lang = Name_Ada then
3045 Get_Name_String (Element.Index);
3046 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
3048 if Unit = No_Name then
3049 Err_Vars.Error_Msg_Name_1 := Element.Index;
3052 "%% is not a valid unit name.",
3053 Element.Value.Location);
3057 if Unit /= No_Name then
3059 -- Check if the source already exists
3060 -- ??? In Ada_Only mode (Record_Unit), we use a htable for
3063 Source_To_Replace := No_Source;
3064 Iter := For_Each_Source (In_Tree);
3067 Source := Prj.Element (Iter);
3068 exit when Source = No_Source
3069 or else (Source.Unit /= null
3070 and then Source.Unit.Name = Unit
3071 and then Source.Index = Index);
3075 if Source /= No_Source then
3076 if Source.Kind /= Kind then
3079 Source := Prj.Element (Iter);
3081 exit when Source = No_Source
3082 or else (Source.Unit /= null
3083 and then Source.Unit.Name = Unit
3084 and then Source.Index = Index);
3088 if Source /= No_Source then
3089 Other_Project := Source.Project;
3091 if Is_Extending (Project, Other_Project) then
3092 Source_To_Replace := Source;
3093 Source := No_Source;
3096 Error_Msg_Name_1 := Unit;
3097 Error_Msg_Name_2 := Other_Project.Name;
3101 "%% is already a source of project %%",
3102 Element.Value.Location);
3107 if Source = No_Source then
3114 File_Name => File_Name,
3115 Display_File => File_Name_Type (Element.Value.Value),
3118 Naming_Exception => True,
3119 Source_To_Replace => Source_To_Replace);
3123 Exceptions := Element.Next;
3125 end Process_Exceptions_Unit_Based;
3127 ---------------------------
3128 -- Check_Naming_Ada_Only --
3129 ---------------------------
3131 procedure Check_Naming_Ada_Only is
3132 Ada : constant Language_Ptr :=
3133 Get_Language_From_Name (Project, "ada");
3135 Casing_Defined : Boolean;
3136 Sep_Suffix_Loc : Source_Ptr;
3139 -- If no language, then nothing to do
3146 Data : Lang_Naming_Data renames Ada.Config.Naming_Data;
3149 -- The default value of separate suffix should be the same as the
3150 -- body suffix, so we need to compute that first.
3152 Data.Separate_Suffix := Data.Body_Suffix;
3153 Write_Attr ("Body_Suffix", Get_Name_String (Data.Body_Suffix));
3155 -- We'll need the dot replacement below, so compute it now
3158 (Dot_Replacement => Data.Dot_Replacement,
3159 Casing => Data.Casing,
3160 Casing_Defined => Casing_Defined,
3161 Separate_Suffix => Data.Separate_Suffix,
3162 Sep_Suffix_Loc => Sep_Suffix_Loc);
3164 Bodies := Util.Value_Of (Name_Body, Naming.Decl.Arrays, In_Tree);
3166 if Bodies /= No_Array_Element then
3167 Check_And_Normalize_Unit_Names
3168 (Project, In_Tree, Bodies, "Naming.Bodies");
3171 Specs := Util.Value_Of (Name_Spec, Naming.Decl.Arrays, In_Tree);
3173 if Specs /= No_Array_Element then
3174 Check_And_Normalize_Unit_Names
3175 (Project, In_Tree, Specs, "Naming.Specs");
3178 -- Check Spec_Suffix
3180 if Is_Illegal_Suffix (Data.Spec_Suffix, Data.Dot_Replacement) then
3181 Err_Vars.Error_Msg_File_1 := Data.Spec_Suffix;
3184 "{ is illegal for Spec_Suffix",
3185 Ada_Spec_Suffix_Loc);
3188 Write_Attr ("Spec_Suffix", Get_Name_String (Data.Spec_Suffix));
3190 -- Check Body_Suffix
3192 if Is_Illegal_Suffix (Data.Body_Suffix, Data.Dot_Replacement) then
3193 Err_Vars.Error_Msg_File_1 := Data.Body_Suffix;
3196 "{ is illegal for Body_Suffix",
3197 Ada_Body_Suffix_Loc);
3200 -- Spec_Suffix cannot be equal to Body_Suffix or Separate_Suffix,
3201 -- since that would cause a clear ambiguity. Note that we do allow
3202 -- a Spec_Suffix to have the same termination as one of these,
3203 -- which causes a potential ambiguity, but we resolve that my
3204 -- matching the longest possible suffix.
3206 if Data.Spec_Suffix = Data.Body_Suffix then
3210 & Get_Name_String (Data.Body_Suffix)
3211 & """) cannot be the same as Spec_Suffix.",
3212 Ada_Body_Suffix_Loc);
3215 if Data.Body_Suffix /= Data.Separate_Suffix
3216 and then Data.Spec_Suffix = Data.Separate_Suffix
3220 "Separate_Suffix ("""
3221 & Get_Name_String (Data.Separate_Suffix)
3222 & """) cannot be the same as Spec_Suffix.",
3226 end Check_Naming_Ada_Only;
3228 -----------------------------
3229 -- Check_Naming_Multi_Lang --
3230 -----------------------------
3232 procedure Check_Naming_Multi_Lang is
3233 Dot_Replacement : File_Name_Type := No_File;
3234 Separate_Suffix : File_Name_Type := No_File;
3235 Casing : Casing_Type := All_Lower_Case;
3236 Casing_Defined : Boolean;
3237 Lang_Id : Language_Ptr;
3238 Sep_Suffix_Loc : Source_Ptr;
3239 Suffix : Variable_Value;
3244 (Dot_Replacement => Dot_Replacement,
3246 Casing_Defined => Casing_Defined,
3247 Separate_Suffix => Separate_Suffix,
3248 Sep_Suffix_Loc => Sep_Suffix_Loc);
3250 -- For all unit based languages, if any, set the specified value
3251 -- of Dot_Replacement, Casing and/or Separate_Suffix. Do not
3252 -- systematically overwrite, since the defaults come from the
3253 -- configuration file
3255 if Dot_Replacement /= No_File
3256 or else Casing_Defined
3257 or else Separate_Suffix /= No_File
3259 Lang_Id := Project.Languages;
3260 while Lang_Id /= No_Language_Index loop
3261 if Lang_Id.Config.Kind = Unit_Based then
3262 if Dot_Replacement /= No_File then
3263 Lang_Id.Config.Naming_Data.Dot_Replacement :=
3267 if Casing_Defined then
3268 Lang_Id.Config.Naming_Data.Casing := Casing;
3271 if Separate_Suffix /= No_File then
3272 Lang_Id.Config.Naming_Data.Separate_Suffix :=
3277 Lang_Id := Lang_Id.Next;
3281 -- Next, get the spec and body suffixes
3283 Lang_Id := Project.Languages;
3284 while Lang_Id /= No_Language_Index loop
3285 Lang := Lang_Id.Name;
3291 Attribute_Or_Array_Name => Name_Spec_Suffix,
3292 In_Package => Naming_Id,
3293 In_Tree => In_Tree);
3295 if Suffix = Nil_Variable_Value then
3298 Attribute_Or_Array_Name => Name_Spec_Suffix,
3299 In_Package => Naming_Id,
3300 In_Tree => In_Tree);
3303 if Suffix /= Nil_Variable_Value then
3304 Lang_Id.Config.Naming_Data.Spec_Suffix :=
3305 File_Name_Type (Suffix.Value);
3312 Attribute_Or_Array_Name => Name_Body_Suffix,
3313 In_Package => Naming_Id,
3314 In_Tree => In_Tree);
3316 if Suffix = Nil_Variable_Value then
3319 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3320 In_Package => Naming_Id,
3321 In_Tree => In_Tree);
3324 if Suffix /= Nil_Variable_Value then
3325 Lang_Id.Config.Naming_Data.Body_Suffix :=
3326 File_Name_Type (Suffix.Value);
3329 -- ??? As opposed to what is done in Check_Naming_Ada_Only,
3330 -- we do not check whether spec_suffix=body_suffix, which
3331 -- should be illegal. Best would be to share this code into
3332 -- Check_Common, but we access the attributes from the project
3333 -- files slightly differently apparently.
3335 Lang_Id := Lang_Id.Next;
3338 -- Get the naming exceptions for all languages
3340 for Kind in Spec .. Impl loop
3341 Lang_Id := Project.Languages;
3342 while Lang_Id /= No_Language_Index loop
3343 case Lang_Id.Config.Kind is
3345 Process_Exceptions_File_Based (Lang_Id, Kind);
3348 Process_Exceptions_Unit_Based (Lang_Id, Kind);
3351 Lang_Id := Lang_Id.Next;
3354 end Check_Naming_Multi_Lang;
3356 ----------------------------
3357 -- Initialize_Naming_Data --
3358 ----------------------------
3360 procedure Initialize_Naming_Data is
3361 Specs : Array_Element_Id :=
3367 Impls : Array_Element_Id :=
3373 Lang : Language_Ptr;
3374 Lang_Name : Name_Id;
3375 Value : Variable_Value;
3376 Extended : Project_Id;
3379 -- At this stage, the project already contains the default extensions
3380 -- for the various languages. We now merge those suffixes read in the
3381 -- user project, and they override the default.
3383 while Specs /= No_Array_Element loop
3384 Lang_Name := In_Tree.Array_Elements.Table (Specs).Index;
3385 Lang := Get_Language_From_Name
3386 (Project, Name => Get_Name_String (Lang_Name));
3388 -- An extending project inherits its parent projects' languages
3389 -- so if needed we should create entries for those languages
3392 Extended := Project.Extends;
3394 while Extended /= null loop
3395 Lang := Get_Language_From_Name
3396 (Extended, Name => Get_Name_String (Lang_Name));
3397 exit when Lang /= null;
3399 Extended := Extended.Extends;
3402 if Lang /= null then
3403 Lang := new Language_Data'(Lang.all);
3404 Lang.First_Source := null;
3405 Lang.Next := Project.Languages;
3406 Project.Languages := Lang;
3410 -- If the language was not found in project or the projects it
3414 if Current_Verbosity = High then
3416 ("Ignoring spec naming data for "
3417 & Get_Name_String (Lang_Name)
3418 & " since language is not defined for this project");
3421 Value := In_Tree.Array_Elements.Table (Specs).Value;
3423 if Lang.Name = Name_Ada then
3424 Ada_Spec_Suffix_Loc := Value.Location;
3427 if Value.Kind = Single then
3428 Lang.Config.Naming_Data.Spec_Suffix :=
3429 Canonical_Case_File_Name (Value.Value);
3433 Specs := In_Tree.Array_Elements.Table (Specs).Next;
3436 while Impls /= No_Array_Element loop
3437 Lang_Name := In_Tree.Array_Elements.Table (Impls).Index;
3438 Lang := Get_Language_From_Name
3439 (Project, Name => Get_Name_String (Lang_Name));
3442 if Current_Verbosity = High then
3444 ("Ignoring impl naming data for "
3445 & Get_Name_String (Lang_Name)
3446 & " since language is not defined for this project");
3449 Value := In_Tree.Array_Elements.Table (Impls).Value;
3451 if Lang.Name = Name_Ada then
3452 Ada_Body_Suffix_Loc := Value.Location;
3455 if Value.Kind = Single then
3456 Lang.Config.Naming_Data.Body_Suffix :=
3457 Canonical_Case_File_Name (Value.Value);
3461 Impls := In_Tree.Array_Elements.Table (Impls).Next;
3463 end Initialize_Naming_Data;
3465 -- Start of processing for Check_Naming_Schemes
3468 Specs := No_Array_Element;
3469 Bodies := No_Array_Element;
3471 -- No Naming package or parsing a configuration file? nothing to do
3473 if Naming_Id /= No_Package and not Is_Config_File then
3474 Naming := In_Tree.Packages.Table (Naming_Id);
3476 if Current_Verbosity = High then
3477 Write_Line ("Checking package Naming for project "
3478 & Get_Name_String (Project.Name));
3481 Initialize_Naming_Data;
3485 Check_Naming_Ada_Only;
3486 when Multi_Language =>
3487 Check_Naming_Multi_Lang;
3490 end Check_Package_Naming;
3492 ------------------------------
3493 -- Check_Library_Attributes --
3494 ------------------------------
3496 procedure Check_Library_Attributes
3497 (Project : Project_Id;
3498 In_Tree : Project_Tree_Ref)
3500 Attributes : constant Prj.Variable_Id := Project.Decl.Attributes;
3502 Lib_Dir : constant Prj.Variable_Value :=
3504 (Snames.Name_Library_Dir, Attributes, In_Tree);
3506 Lib_Name : constant Prj.Variable_Value :=
3508 (Snames.Name_Library_Name, Attributes, In_Tree);
3510 Lib_Version : constant Prj.Variable_Value :=
3512 (Snames.Name_Library_Version, Attributes, In_Tree);
3514 Lib_ALI_Dir : constant Prj.Variable_Value :=
3516 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3518 Lib_GCC : constant Prj.Variable_Value :=
3520 (Snames.Name_Library_GCC, Attributes, In_Tree);
3522 The_Lib_Kind : constant Prj.Variable_Value :=
3524 (Snames.Name_Library_Kind, Attributes, In_Tree);
3526 Imported_Project_List : Project_List;
3528 Continuation : String_Access := No_Continuation_String'Access;
3530 Support_For_Libraries : Library_Support;
3532 Library_Directory_Present : Boolean;
3534 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3535 -- Check if an imported or extended project if also a library project
3541 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3543 Iter : Source_Iterator;
3546 if Proj /= No_Project then
3547 if not Proj.Library then
3549 -- The only not library projects that are OK are those that
3550 -- have no sources. However, header files from non-Ada
3551 -- languages are OK, as there is nothing to compile.
3553 Iter := For_Each_Source (In_Tree, Proj);
3555 Src_Id := Prj.Element (Iter);
3556 exit when Src_Id = No_Source
3557 or else Src_Id.Language.Config.Kind /= File_Based
3558 or else Src_Id.Kind /= Spec;
3562 if Src_Id /= No_Source then
3563 Error_Msg_Name_1 := Project.Name;
3564 Error_Msg_Name_2 := Proj.Name;
3567 if Project.Library_Kind /= Static then
3571 "shared library project %% cannot extend " &
3572 "project %% that is not a library project",
3574 Continuation := Continuation_String'Access;
3577 elsif (not Unchecked_Shared_Lib_Imports)
3578 and then Project.Library_Kind /= Static
3583 "shared library project %% cannot import project %% " &
3584 "that is not a shared library project",
3586 Continuation := Continuation_String'Access;
3590 elsif Project.Library_Kind /= Static and then
3591 Proj.Library_Kind = Static
3593 Error_Msg_Name_1 := Project.Name;
3594 Error_Msg_Name_2 := Proj.Name;
3600 "shared library project %% cannot extend static " &
3601 "library project %%",
3603 Continuation := Continuation_String'Access;
3605 elsif not Unchecked_Shared_Lib_Imports then
3609 "shared library project %% cannot import static " &
3610 "library project %%",
3612 Continuation := Continuation_String'Access;
3619 Dir_Exists : Boolean;
3621 -- Start of processing for Check_Library_Attributes
3624 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3626 -- Special case of extending project
3628 if Project.Extends /= No_Project then
3630 -- If the project extended is a library project, we inherit the
3631 -- library name, if it is not redefined; we check that the library
3632 -- directory is specified.
3634 if Project.Extends.Library then
3635 if Project.Qualifier = Standard then
3638 "a standard project cannot extend a library project",
3642 if Lib_Name.Default then
3643 Project.Library_Name := Project.Extends.Library_Name;
3646 if Lib_Dir.Default then
3647 if not Project.Virtual then
3650 "a project extending a library project must " &
3651 "specify an attribute Library_Dir",
3655 -- For a virtual project extending a library project,
3656 -- inherit library directory.
3658 Project.Library_Dir := Project.Extends.Library_Dir;
3659 Library_Directory_Present := True;
3666 pragma Assert (Lib_Name.Kind = Single);
3668 if Lib_Name.Value = Empty_String then
3669 if Current_Verbosity = High
3670 and then Project.Library_Name = No_Name
3672 Write_Line ("No library name");
3676 -- There is no restriction on the syntax of library names
3678 Project.Library_Name := Lib_Name.Value;
3681 if Project.Library_Name /= No_Name then
3682 if Current_Verbosity = High then
3684 ("Library name", Get_Name_String (Project.Library_Name));
3687 pragma Assert (Lib_Dir.Kind = Single);
3689 if not Library_Directory_Present then
3690 if Current_Verbosity = High then
3691 Write_Line ("No library directory");
3695 -- Find path name (unless inherited), check that it is a directory
3697 if Project.Library_Dir = No_Path_Information then
3701 File_Name_Type (Lib_Dir.Value),
3702 Path => Project.Library_Dir,
3703 Dir_Exists => Dir_Exists,
3704 Create => "library",
3705 Must_Exist => False,
3706 Location => Lib_Dir.Location,
3707 Externally_Built => Project.Externally_Built);
3713 (Project.Library_Dir.Display_Name));
3716 if not Dir_Exists then
3717 -- Get the absolute name of the library directory that
3718 -- does not exist, to report an error.
3720 Err_Vars.Error_Msg_File_1 :=
3721 File_Name_Type (Project.Library_Dir.Display_Name);
3724 "library directory { does not exist",
3727 -- The library directory cannot be the same as the Object
3730 elsif Project.Library_Dir.Name = Project.Object_Directory.Name then
3733 "library directory cannot be the same " &
3734 "as object directory",
3736 Project.Library_Dir := No_Path_Information;
3740 OK : Boolean := True;
3741 Dirs_Id : String_List_Id;
3742 Dir_Elem : String_Element;
3746 -- The library directory cannot be the same as a source
3747 -- directory of the current project.
3749 Dirs_Id := Project.Source_Dirs;
3750 while Dirs_Id /= Nil_String loop
3751 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3752 Dirs_Id := Dir_Elem.Next;
3754 if Project.Library_Dir.Name =
3755 Path_Name_Type (Dir_Elem.Value)
3757 Err_Vars.Error_Msg_File_1 :=
3758 File_Name_Type (Dir_Elem.Value);
3761 "library directory cannot be the same " &
3762 "as source directory {",
3771 -- The library directory cannot be the same as a source
3772 -- directory of another project either.
3774 Pid := In_Tree.Projects;
3776 exit Project_Loop when Pid = null;
3778 if Pid.Project /= Project then
3779 Dirs_Id := Pid.Project.Source_Dirs;
3781 Dir_Loop : while Dirs_Id /= Nil_String loop
3783 In_Tree.String_Elements.Table (Dirs_Id);
3784 Dirs_Id := Dir_Elem.Next;
3786 if Project.Library_Dir.Name =
3787 Path_Name_Type (Dir_Elem.Value)
3789 Err_Vars.Error_Msg_File_1 :=
3790 File_Name_Type (Dir_Elem.Value);
3791 Err_Vars.Error_Msg_Name_1 := Pid.Project.Name;
3795 "library directory cannot be the same " &
3796 "as source directory { of project %%",
3805 end loop Project_Loop;
3809 Project.Library_Dir := No_Path_Information;
3811 elsif Current_Verbosity = High then
3813 -- Display the Library directory in high verbosity
3816 ("Library directory",
3817 Get_Name_String (Project.Library_Dir.Display_Name));
3826 Project.Library_Dir /= No_Path_Information
3827 and then Project.Library_Name /= No_Name;
3829 if Project.Extends = No_Project then
3830 case Project.Qualifier is
3832 if Project.Library then
3835 "a standard project cannot be a library project",
3840 if not Project.Library then
3841 if Project.Library_Dir = No_Path_Information then
3844 "\attribute Library_Dir not declared",
3848 if Project.Library_Name = No_Name then
3851 "\attribute Library_Name not declared",
3862 if Project.Library then
3863 if Get_Mode = Multi_Language then
3864 Support_For_Libraries := Project.Config.Lib_Support;
3867 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3870 if Support_For_Libraries = Prj.None then
3873 "?libraries are not supported on this platform",
3875 Project.Library := False;
3878 if Lib_ALI_Dir.Value = Empty_String then
3879 if Current_Verbosity = High then
3880 Write_Line ("No library ALI directory specified");
3883 Project.Library_ALI_Dir := Project.Library_Dir;
3886 -- Find path name, check that it is a directory
3891 File_Name_Type (Lib_ALI_Dir.Value),
3892 Path => Project.Library_ALI_Dir,
3893 Create => "library ALI",
3894 Dir_Exists => Dir_Exists,
3895 Must_Exist => False,
3896 Location => Lib_ALI_Dir.Location,
3897 Externally_Built => Project.Externally_Built);
3899 if not Dir_Exists then
3900 -- Get the absolute name of the library ALI directory that
3901 -- does not exist, to report an error.
3903 Err_Vars.Error_Msg_File_1 :=
3904 File_Name_Type (Project.Library_ALI_Dir.Display_Name);
3907 "library 'A'L'I directory { does not exist",
3908 Lib_ALI_Dir.Location);
3911 if Project.Library_ALI_Dir /= Project.Library_Dir then
3913 -- The library ALI directory cannot be the same as the
3914 -- Object directory.
3916 if Project.Library_ALI_Dir = Project.Object_Directory then
3919 "library 'A'L'I directory cannot be the same " &
3920 "as object directory",
3921 Lib_ALI_Dir.Location);
3922 Project.Library_ALI_Dir := No_Path_Information;
3926 OK : Boolean := True;
3927 Dirs_Id : String_List_Id;
3928 Dir_Elem : String_Element;
3932 -- The library ALI directory cannot be the same as
3933 -- a source directory of the current project.
3935 Dirs_Id := Project.Source_Dirs;
3936 while Dirs_Id /= Nil_String loop
3937 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3938 Dirs_Id := Dir_Elem.Next;
3940 if Project.Library_ALI_Dir.Name =
3941 Path_Name_Type (Dir_Elem.Value)
3943 Err_Vars.Error_Msg_File_1 :=
3944 File_Name_Type (Dir_Elem.Value);
3947 "library 'A'L'I directory cannot be " &
3948 "the same as source directory {",
3949 Lib_ALI_Dir.Location);
3957 -- The library ALI directory cannot be the same as
3958 -- a source directory of another project either.
3960 Pid := In_Tree.Projects;
3961 ALI_Project_Loop : loop
3962 exit ALI_Project_Loop when Pid = null;
3964 if Pid.Project /= Project then
3965 Dirs_Id := Pid.Project.Source_Dirs;
3968 while Dirs_Id /= Nil_String loop
3970 In_Tree.String_Elements.Table (Dirs_Id);
3971 Dirs_Id := Dir_Elem.Next;
3973 if Project.Library_ALI_Dir.Name =
3974 Path_Name_Type (Dir_Elem.Value)
3976 Err_Vars.Error_Msg_File_1 :=
3977 File_Name_Type (Dir_Elem.Value);
3978 Err_Vars.Error_Msg_Name_1 :=
3983 "library 'A'L'I directory cannot " &
3984 "be the same as source directory " &
3986 Lib_ALI_Dir.Location);
3988 exit ALI_Project_Loop;
3990 end loop ALI_Dir_Loop;
3993 end loop ALI_Project_Loop;
3997 Project.Library_ALI_Dir := No_Path_Information;
3999 elsif Current_Verbosity = High then
4001 -- Display the Library ALI directory in high
4007 (Project.Library_ALI_Dir.Display_Name));
4014 pragma Assert (Lib_Version.Kind = Single);
4016 if Lib_Version.Value = Empty_String then
4017 if Current_Verbosity = High then
4018 Write_Line ("No library version specified");
4022 Project.Lib_Internal_Name := Lib_Version.Value;
4025 pragma Assert (The_Lib_Kind.Kind = Single);
4027 if The_Lib_Kind.Value = Empty_String then
4028 if Current_Verbosity = High then
4029 Write_Line ("No library kind specified");
4033 Get_Name_String (The_Lib_Kind.Value);
4036 Kind_Name : constant String :=
4037 To_Lower (Name_Buffer (1 .. Name_Len));
4039 OK : Boolean := True;
4042 if Kind_Name = "static" then
4043 Project.Library_Kind := Static;
4045 elsif Kind_Name = "dynamic" then
4046 Project.Library_Kind := Dynamic;
4048 elsif Kind_Name = "relocatable" then
4049 Project.Library_Kind := Relocatable;
4054 "illegal value for Library_Kind",
4055 The_Lib_Kind.Location);
4059 if Current_Verbosity = High and then OK then
4060 Write_Attr ("Library kind", Kind_Name);
4063 if Project.Library_Kind /= Static then
4064 if Support_For_Libraries = Prj.Static_Only then
4067 "only static libraries are supported " &
4069 The_Lib_Kind.Location);
4070 Project.Library := False;
4073 -- Check if (obsolescent) attribute Library_GCC or
4074 -- Linker'Driver is declared.
4076 if Lib_GCC.Value /= Empty_String then
4080 "?Library_'G'C'C is an obsolescent attribute, " &
4081 "use Linker''Driver instead",
4083 Project.Config.Shared_Lib_Driver :=
4084 File_Name_Type (Lib_GCC.Value);
4088 Linker : constant Package_Id :=
4091 Project.Decl.Packages,
4093 Driver : constant Variable_Value :=
4096 Attribute_Or_Array_Name =>
4098 In_Package => Linker,
4103 if Driver /= Nil_Variable_Value
4104 and then Driver.Value /= Empty_String
4106 Project.Config.Shared_Lib_Driver :=
4107 File_Name_Type (Driver.Value);
4116 if Project.Library then
4117 if Current_Verbosity = High then
4118 Write_Line ("This is a library project file");
4121 if Get_Mode = Multi_Language then
4122 Check_Library (Project.Extends, Extends => True);
4124 Imported_Project_List := Project.Imported_Projects;
4125 while Imported_Project_List /= null loop
4127 (Imported_Project_List.Project,
4129 Imported_Project_List := Imported_Project_List.Next;
4137 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4138 -- Warn if they are declared, as it is a common error to think that
4139 -- library are "linked" with Linker switches.
4141 if Project.Library then
4143 Linker_Package_Id : constant Package_Id :=
4146 Project.Decl.Packages, In_Tree);
4147 Linker_Package : Package_Element;
4148 Switches : Array_Element_Id := No_Array_Element;
4151 if Linker_Package_Id /= No_Package then
4152 Linker_Package := In_Tree.Packages.Table (Linker_Package_Id);
4156 (Name => Name_Switches,
4157 In_Arrays => Linker_Package.Decl.Arrays,
4158 In_Tree => In_Tree);
4160 if Switches = No_Array_Element then
4163 (Name => Name_Default_Switches,
4164 In_Arrays => Linker_Package.Decl.Arrays,
4165 In_Tree => In_Tree);
4168 if Switches /= No_Array_Element then
4171 "?Linker switches not taken into account in library " &
4179 if Project.Extends /= No_Project then
4180 Project.Extends.Library := False;
4182 end Check_Library_Attributes;
4184 ---------------------------------
4185 -- Check_Programming_Languages --
4186 ---------------------------------
4188 procedure Check_Programming_Languages
4189 (In_Tree : Project_Tree_Ref;
4190 Project : Project_Id)
4192 Languages : Variable_Value := Nil_Variable_Value;
4193 Def_Lang : Variable_Value := Nil_Variable_Value;
4194 Def_Lang_Id : Name_Id;
4196 procedure Add_Language (Name, Display_Name : Name_Id);
4197 -- Add a new language to the list of languages for the project.
4198 -- Nothing is done if the language has already been defined
4200 procedure Add_Language (Name, Display_Name : Name_Id) is
4201 Lang : Language_Ptr := Project.Languages;
4203 while Lang /= No_Language_Index loop
4204 if Name = Lang.Name then
4211 Lang := new Language_Data'(No_Language_Data);
4212 Lang.Next := Project.Languages;
4213 Project.Languages := Lang;
4215 Lang.Display_Name := Display_Name;
4217 if Name = Name_Ada then
4218 Lang.Config.Kind := Unit_Based;
4219 Lang.Config.Dependency_Kind := ALI_File;
4221 if Get_Mode = Ada_Only then
4222 -- Create a default config for Ada (since there is no
4223 -- configuration file to create it for us)
4224 -- ??? We should do as GPS does and create a dummy config
4227 Lang.Config.Naming_Data :=
4228 (Dot_Replacement => File_Name_Type
4229 (First_Name_Id + Character'Pos ('-')),
4230 Casing => All_Lower_Case,
4231 Separate_Suffix => Default_Ada_Body_Suffix,
4232 Spec_Suffix => Default_Ada_Spec_Suffix,
4233 Body_Suffix => Default_Ada_Body_Suffix);
4237 Lang.Config.Kind := File_Based;
4241 -- Start of processing for Check_Programming_Languages
4244 Project.Languages := null;
4246 Prj.Util.Value_Of (Name_Languages, Project.Decl.Attributes, In_Tree);
4249 (Name_Default_Language, Project.Decl.Attributes, In_Tree);
4251 -- Shouldn't these be set to False by default, and only set to True when
4252 -- we actually find some source file???
4254 if Project.Source_Dirs /= Nil_String then
4256 -- Check if languages are specified in this project
4258 if Languages.Default then
4260 -- In Ada_Only mode, the default language is Ada
4262 if Get_Mode = Ada_Only then
4263 Def_Lang_Id := Name_Ada;
4266 -- Fail if there is no default language defined
4268 if Def_Lang.Default then
4269 if not Default_Language_Is_Ada then
4273 "no languages defined for this project",
4275 Def_Lang_Id := No_Name;
4278 Def_Lang_Id := Name_Ada;
4282 Get_Name_String (Def_Lang.Value);
4283 To_Lower (Name_Buffer (1 .. Name_Len));
4284 Def_Lang_Id := Name_Find;
4288 if Def_Lang_Id /= No_Name then
4289 Get_Name_String (Def_Lang_Id);
4290 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4292 (Name => Def_Lang_Id,
4293 Display_Name => Name_Find);
4298 Current : String_List_Id := Languages.Values;
4299 Element : String_Element;
4302 -- If there are no languages declared, there are no sources
4304 if Current = Nil_String then
4305 Project.Source_Dirs := Nil_String;
4307 if Project.Qualifier = Standard then
4311 "a standard project must have at least one language",
4312 Languages.Location);
4316 -- Look through all the languages specified in attribute
4319 while Current /= Nil_String loop
4320 Element := In_Tree.String_Elements.Table (Current);
4321 Get_Name_String (Element.Value);
4322 To_Lower (Name_Buffer (1 .. Name_Len));
4326 Display_Name => Element.Value);
4328 Current := Element.Next;
4334 end Check_Programming_Languages;
4340 function Check_Project
4342 Root_Project : Project_Id;
4343 Extending : Boolean) return Boolean
4348 if P = Root_Project then
4351 elsif Extending then
4352 Prj := Root_Project;
4353 while Prj.Extends /= No_Project loop
4354 if P = Prj.Extends then
4365 -------------------------------
4366 -- Check_Stand_Alone_Library --
4367 -------------------------------
4369 procedure Check_Stand_Alone_Library
4370 (Project : Project_Id;
4371 In_Tree : Project_Tree_Ref;
4372 Current_Dir : String;
4373 Extending : Boolean)
4375 Lib_Interfaces : constant Prj.Variable_Value :=
4377 (Snames.Name_Library_Interface,
4378 Project.Decl.Attributes,
4381 Lib_Auto_Init : constant Prj.Variable_Value :=
4383 (Snames.Name_Library_Auto_Init,
4384 Project.Decl.Attributes,
4387 Lib_Src_Dir : constant Prj.Variable_Value :=
4389 (Snames.Name_Library_Src_Dir,
4390 Project.Decl.Attributes,
4393 Lib_Symbol_File : constant Prj.Variable_Value :=
4395 (Snames.Name_Library_Symbol_File,
4396 Project.Decl.Attributes,
4399 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4401 (Snames.Name_Library_Symbol_Policy,
4402 Project.Decl.Attributes,
4405 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4407 (Snames.Name_Library_Reference_Symbol_File,
4408 Project.Decl.Attributes,
4411 Auto_Init_Supported : Boolean;
4412 OK : Boolean := True;
4414 Next_Proj : Project_Id;
4415 Iter : Source_Iterator;
4418 if Get_Mode = Multi_Language then
4419 Auto_Init_Supported := Project.Config.Auto_Init_Supported;
4421 Auto_Init_Supported :=
4422 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4425 pragma Assert (Lib_Interfaces.Kind = List);
4427 -- It is a stand-alone library project file if attribute
4428 -- Library_Interface is defined.
4430 if not Lib_Interfaces.Default then
4431 SAL_Library : declare
4432 Interfaces : String_List_Id := Lib_Interfaces.Values;
4433 Interface_ALIs : String_List_Id := Nil_String;
4437 procedure Add_ALI_For (Source : File_Name_Type);
4438 -- Add an ALI file name to the list of Interface ALIs
4444 procedure Add_ALI_For (Source : File_Name_Type) is
4446 Get_Name_String (Source);
4449 ALI : constant String :=
4450 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4451 ALI_Name_Id : Name_Id;
4454 Name_Len := ALI'Length;
4455 Name_Buffer (1 .. Name_Len) := ALI;
4456 ALI_Name_Id := Name_Find;
4458 String_Element_Table.Increment_Last
4459 (In_Tree.String_Elements);
4460 In_Tree.String_Elements.Table
4461 (String_Element_Table.Last
4462 (In_Tree.String_Elements)) :=
4463 (Value => ALI_Name_Id,
4465 Display_Value => ALI_Name_Id,
4467 In_Tree.String_Elements.Table
4468 (Interfaces).Location,
4470 Next => Interface_ALIs);
4471 Interface_ALIs := String_Element_Table.Last
4472 (In_Tree.String_Elements);
4476 -- Start of processing for SAL_Library
4479 Project.Standalone_Library := True;
4481 -- Library_Interface cannot be an empty list
4483 if Interfaces = Nil_String then
4486 "Library_Interface cannot be an empty list",
4487 Lib_Interfaces.Location);
4490 -- Process each unit name specified in the attribute
4491 -- Library_Interface.
4493 while Interfaces /= Nil_String loop
4495 (In_Tree.String_Elements.Table (Interfaces).Value);
4496 To_Lower (Name_Buffer (1 .. Name_Len));
4498 if Name_Len = 0 then
4501 "an interface cannot be an empty string",
4502 In_Tree.String_Elements.Table (Interfaces).Location);
4506 Error_Msg_Name_1 := Unit;
4508 if Get_Mode = Ada_Only then
4509 UData := Units_Htable.Get (In_Tree.Units_HT, Unit);
4511 if UData = No_Unit_Index then
4515 In_Tree.String_Elements.Table
4516 (Interfaces).Location);
4519 -- Check that the unit is part of the project
4521 if UData.File_Names (Impl) /= null
4522 and then not UData.File_Names (Impl).Locally_Removed
4525 (UData.File_Names (Impl).Project,
4528 -- There is a body for this unit. If there is
4529 -- no spec, we need to check that it is not a
4532 if UData.File_Names (Spec) = null then
4534 Src_Ind : Source_File_Index;
4538 Sinput.P.Load_Project_File
4539 (Get_Name_String (UData.File_Names
4542 if Sinput.P.Source_File_Is_Subunit
4547 "%% is a subunit; " &
4548 "it cannot be an interface",
4550 String_Elements.Table
4551 (Interfaces).Location);
4556 -- The unit is not a subunit, so we add the
4557 -- ALI file for its body to the Interface ALIs.
4560 (UData.File_Names (Impl).File);
4565 "%% is not an unit of this project",
4566 In_Tree.String_Elements.Table
4567 (Interfaces).Location);
4570 elsif UData.File_Names (Spec) /= null
4571 and then not UData.File_Names (Spec).Locally_Removed
4572 and then Check_Project
4573 (UData.File_Names (Spec).Project,
4577 -- The unit is part of the project, it has a spec,
4578 -- but no body. We add the ALI for its spec to the
4582 (UData.File_Names (Spec).File);
4587 "%% is not an unit of this project",
4588 In_Tree.String_Elements.Table
4589 (Interfaces).Location);
4594 -- Multi_Language mode
4596 Next_Proj := Project.Extends;
4597 Iter := For_Each_Source (In_Tree, Project);
4599 while Prj.Element (Iter) /= No_Source
4601 (Prj.Element (Iter).Unit = null
4602 or else Prj.Element (Iter).Unit.Name /= Unit)
4607 Source := Prj.Element (Iter);
4608 exit when Source /= No_Source
4609 or else Next_Proj = No_Project;
4611 Iter := For_Each_Source (In_Tree, Next_Proj);
4612 Next_Proj := Next_Proj.Extends;
4615 if Source /= No_Source then
4616 if Source.Kind = Sep then
4617 Source := No_Source;
4618 elsif Source.Kind = Spec
4619 and then Other_Part (Source) /= No_Source
4621 Source := Other_Part (Source);
4625 if Source /= No_Source then
4626 if Source.Project /= Project
4627 and then not Is_Extending (Project, Source.Project)
4629 Source := No_Source;
4633 if Source = No_Source then
4636 "%% is not an unit of this project",
4637 In_Tree.String_Elements.Table
4638 (Interfaces).Location);
4641 if Source.Kind = Spec
4642 and then Other_Part (Source) /= No_Source
4644 Source := Other_Part (Source);
4647 String_Element_Table.Increment_Last
4648 (In_Tree.String_Elements);
4650 In_Tree.String_Elements.Table
4651 (String_Element_Table.Last
4652 (In_Tree.String_Elements)) :=
4653 (Value => Name_Id (Source.Dep_Name),
4655 Display_Value => Name_Id (Source.Dep_Name),
4657 In_Tree.String_Elements.Table
4658 (Interfaces).Location,
4660 Next => Interface_ALIs);
4663 String_Element_Table.Last (In_Tree.String_Elements);
4671 In_Tree.String_Elements.Table (Interfaces).Next;
4674 -- Put the list of Interface ALIs in the project data
4676 Project.Lib_Interface_ALIs := Interface_ALIs;
4678 -- Check value of attribute Library_Auto_Init and set
4679 -- Lib_Auto_Init accordingly.
4681 if Lib_Auto_Init.Default then
4683 -- If no attribute Library_Auto_Init is declared, then set auto
4684 -- init only if it is supported.
4686 Project.Lib_Auto_Init := Auto_Init_Supported;
4689 Get_Name_String (Lib_Auto_Init.Value);
4690 To_Lower (Name_Buffer (1 .. Name_Len));
4692 if Name_Buffer (1 .. Name_Len) = "false" then
4693 Project.Lib_Auto_Init := False;
4695 elsif Name_Buffer (1 .. Name_Len) = "true" then
4696 if Auto_Init_Supported then
4697 Project.Lib_Auto_Init := True;
4700 -- Library_Auto_Init cannot be "true" if auto init is not
4705 "library auto init not supported " &
4707 Lib_Auto_Init.Location);
4713 "invalid value for attribute Library_Auto_Init",
4714 Lib_Auto_Init.Location);
4719 -- If attribute Library_Src_Dir is defined and not the empty string,
4720 -- check if the directory exist and is not the object directory or
4721 -- one of the source directories. This is the directory where copies
4722 -- of the interface sources will be copied. Note that this directory
4723 -- may be the library directory.
4725 if Lib_Src_Dir.Value /= Empty_String then
4727 Dir_Id : constant File_Name_Type :=
4728 File_Name_Type (Lib_Src_Dir.Value);
4729 Dir_Exists : Boolean;
4736 Path => Project.Library_Src_Dir,
4737 Dir_Exists => Dir_Exists,
4738 Must_Exist => False,
4739 Create => "library source copy",
4740 Location => Lib_Src_Dir.Location,
4741 Externally_Built => Project.Externally_Built);
4743 -- If directory does not exist, report an error
4745 if not Dir_Exists then
4746 -- Get the absolute name of the library directory that does
4747 -- not exist, to report an error.
4749 Err_Vars.Error_Msg_File_1 :=
4750 File_Name_Type (Project.Library_Src_Dir.Display_Name);
4753 "Directory { does not exist",
4754 Lib_Src_Dir.Location);
4756 -- Report error if it is the same as the object directory
4758 elsif Project.Library_Src_Dir = Project.Object_Directory then
4761 "directory to copy interfaces cannot be " &
4762 "the object directory",
4763 Lib_Src_Dir.Location);
4764 Project.Library_Src_Dir := No_Path_Information;
4768 Src_Dirs : String_List_Id;
4769 Src_Dir : String_Element;
4773 -- Interface copy directory cannot be one of the source
4774 -- directory of the current project.
4776 Src_Dirs := Project.Source_Dirs;
4777 while Src_Dirs /= Nil_String loop
4778 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
4780 -- Report error if it is one of the source directories
4782 if Project.Library_Src_Dir.Name =
4783 Path_Name_Type (Src_Dir.Value)
4787 "directory to copy interfaces cannot " &
4788 "be one of the source directories",
4789 Lib_Src_Dir.Location);
4790 Project.Library_Src_Dir := No_Path_Information;
4794 Src_Dirs := Src_Dir.Next;
4797 if Project.Library_Src_Dir /= No_Path_Information then
4799 -- It cannot be a source directory of any other
4802 Pid := In_Tree.Projects;
4804 exit Project_Loop when Pid = null;
4806 Src_Dirs := Pid.Project.Source_Dirs;
4807 Dir_Loop : while Src_Dirs /= Nil_String loop
4809 In_Tree.String_Elements.Table (Src_Dirs);
4811 -- Report error if it is one of the source
4814 if Project.Library_Src_Dir.Name =
4815 Path_Name_Type (Src_Dir.Value)
4818 File_Name_Type (Src_Dir.Value);
4819 Error_Msg_Name_1 := Pid.Project.Name;
4822 "directory to copy interfaces cannot " &
4823 "be the same as source directory { of " &
4825 Lib_Src_Dir.Location);
4826 Project.Library_Src_Dir :=
4827 No_Path_Information;
4831 Src_Dirs := Src_Dir.Next;
4835 end loop Project_Loop;
4839 -- In high verbosity, if there is a valid Library_Src_Dir,
4840 -- display its path name.
4842 if Project.Library_Src_Dir /= No_Path_Information
4843 and then Current_Verbosity = High
4846 ("Directory to copy interfaces",
4847 Get_Name_String (Project.Library_Src_Dir.Name));
4853 -- Check the symbol related attributes
4855 -- First, the symbol policy
4857 if not Lib_Symbol_Policy.Default then
4859 Value : constant String :=
4861 (Get_Name_String (Lib_Symbol_Policy.Value));
4864 -- Symbol policy must hove one of a limited number of values
4866 if Value = "autonomous" or else Value = "default" then
4867 Project.Symbol_Data.Symbol_Policy := Autonomous;
4869 elsif Value = "compliant" then
4870 Project.Symbol_Data.Symbol_Policy := Compliant;
4872 elsif Value = "controlled" then
4873 Project.Symbol_Data.Symbol_Policy := Controlled;
4875 elsif Value = "restricted" then
4876 Project.Symbol_Data.Symbol_Policy := Restricted;
4878 elsif Value = "direct" then
4879 Project.Symbol_Data.Symbol_Policy := Direct;
4884 "illegal value for Library_Symbol_Policy",
4885 Lib_Symbol_Policy.Location);
4890 -- If attribute Library_Symbol_File is not specified, symbol policy
4891 -- cannot be Restricted.
4893 if Lib_Symbol_File.Default then
4894 if Project.Symbol_Data.Symbol_Policy = Restricted then
4897 "Library_Symbol_File needs to be defined when " &
4898 "symbol policy is Restricted",
4899 Lib_Symbol_Policy.Location);
4903 -- Library_Symbol_File is defined
4905 Project.Symbol_Data.Symbol_File :=
4906 Path_Name_Type (Lib_Symbol_File.Value);
4908 Get_Name_String (Lib_Symbol_File.Value);
4910 if Name_Len = 0 then
4913 "symbol file name cannot be an empty string",
4914 Lib_Symbol_File.Location);
4917 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
4920 for J in 1 .. Name_Len loop
4921 if Name_Buffer (J) = '/'
4922 or else Name_Buffer (J) = Directory_Separator
4931 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
4934 "symbol file name { is illegal. " &
4935 "Name cannot include directory info.",
4936 Lib_Symbol_File.Location);
4941 -- If attribute Library_Reference_Symbol_File is not defined,
4942 -- symbol policy cannot be Compliant or Controlled.
4944 if Lib_Ref_Symbol_File.Default then
4945 if Project.Symbol_Data.Symbol_Policy = Compliant
4946 or else Project.Symbol_Data.Symbol_Policy = Controlled
4950 "a reference symbol file needs to be defined",
4951 Lib_Symbol_Policy.Location);
4955 -- Library_Reference_Symbol_File is defined, check file exists
4957 Project.Symbol_Data.Reference :=
4958 Path_Name_Type (Lib_Ref_Symbol_File.Value);
4960 Get_Name_String (Lib_Ref_Symbol_File.Value);
4962 if Name_Len = 0 then
4965 "reference symbol file name cannot be an empty string",
4966 Lib_Symbol_File.Location);
4969 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
4971 Add_Str_To_Name_Buffer
4972 (Get_Name_String (Project.Directory.Name));
4973 Add_Char_To_Name_Buffer (Directory_Separator);
4974 Add_Str_To_Name_Buffer
4975 (Get_Name_String (Lib_Ref_Symbol_File.Value));
4976 Project.Symbol_Data.Reference := Name_Find;
4979 if not Is_Regular_File
4980 (Get_Name_String (Project.Symbol_Data.Reference))
4983 File_Name_Type (Lib_Ref_Symbol_File.Value);
4985 -- For controlled and direct symbol policies, it is an error
4986 -- if the reference symbol file does not exist. For other
4987 -- symbol policies, this is just a warning
4990 Project.Symbol_Data.Symbol_Policy /= Controlled
4991 and then Project.Symbol_Data.Symbol_Policy /= Direct;
4995 "<library reference symbol file { does not exist",
4996 Lib_Ref_Symbol_File.Location);
4998 -- In addition in the non-controlled case, if symbol policy
4999 -- is Compliant, it is changed to Autonomous, because there
5000 -- is no reference to check against, and we don't want to
5001 -- fail in this case.
5003 if Project.Symbol_Data.Symbol_Policy /= Controlled then
5004 if Project.Symbol_Data.Symbol_Policy = Compliant then
5005 Project.Symbol_Data.Symbol_Policy := Autonomous;
5010 -- If both the reference symbol file and the symbol file are
5011 -- defined, then check that they are not the same file.
5013 if Project.Symbol_Data.Symbol_File /= No_Path then
5014 Get_Name_String (Project.Symbol_Data.Symbol_File);
5016 if Name_Len > 0 then
5018 Symb_Path : constant String :=
5021 (Project.Object_Directory.Name) &
5022 Directory_Separator &
5023 Name_Buffer (1 .. Name_Len),
5024 Directory => Current_Dir,
5026 Opt.Follow_Links_For_Files);
5027 Ref_Path : constant String :=
5030 (Project.Symbol_Data.Reference),
5031 Directory => Current_Dir,
5033 Opt.Follow_Links_For_Files);
5035 if Symb_Path = Ref_Path then
5038 "library reference symbol file and library" &
5039 " symbol file cannot be the same file",
5040 Lib_Ref_Symbol_File.Location);
5048 end Check_Stand_Alone_Library;
5050 ----------------------------
5051 -- Compute_Directory_Last --
5052 ----------------------------
5054 function Compute_Directory_Last (Dir : String) return Natural is
5057 and then (Dir (Dir'Last - 1) = Directory_Separator
5058 or else Dir (Dir'Last - 1) = '/')
5060 return Dir'Last - 1;
5064 end Compute_Directory_Last;
5071 (Project : Project_Id;
5072 In_Tree : Project_Tree_Ref;
5074 Flag_Location : Source_Ptr)
5076 Real_Location : Source_Ptr := Flag_Location;
5077 Error_Buffer : String (1 .. 5_000);
5078 Error_Last : Natural := 0;
5079 Name_Number : Natural := 0;
5080 File_Number : Natural := 0;
5081 First : Positive := Msg'First;
5084 procedure Add (C : Character);
5085 -- Add a character to the buffer
5087 procedure Add (S : String);
5088 -- Add a string to the buffer
5091 -- Add a name to the buffer
5094 -- Add a file name to the buffer
5100 procedure Add (C : Character) is
5102 Error_Last := Error_Last + 1;
5103 Error_Buffer (Error_Last) := C;
5106 procedure Add (S : String) is
5108 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5109 Error_Last := Error_Last + S'Length;
5116 procedure Add_File is
5117 File : File_Name_Type;
5121 File_Number := File_Number + 1;
5125 File := Err_Vars.Error_Msg_File_1;
5127 File := Err_Vars.Error_Msg_File_2;
5129 File := Err_Vars.Error_Msg_File_3;
5134 Get_Name_String (File);
5135 Add (Name_Buffer (1 .. Name_Len));
5143 procedure Add_Name is
5148 Name_Number := Name_Number + 1;
5152 Name := Err_Vars.Error_Msg_Name_1;
5154 Name := Err_Vars.Error_Msg_Name_2;
5156 Name := Err_Vars.Error_Msg_Name_3;
5161 Get_Name_String (Name);
5162 Add (Name_Buffer (1 .. Name_Len));
5166 -- Start of processing for Error_Msg
5169 -- If location of error is unknown, use the location of the project
5171 if Real_Location = No_Location then
5172 Real_Location := Project.Location;
5175 if Error_Report = null then
5176 Prj.Err.Error_Msg (Msg, Real_Location);
5180 -- Ignore continuation character
5182 if Msg (First) = '\' then
5186 -- Warning character is always the first one in this package
5187 -- this is an undocumented kludge???
5189 if Msg (First) = '?' then
5193 elsif Msg (First) = '<' then
5196 if Err_Vars.Error_Msg_Warn then
5202 while Index <= Msg'Last loop
5203 if Msg (Index) = '{' then
5206 elsif Msg (Index) = '%' then
5207 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5219 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5222 --------------------------------
5223 -- Free_Ada_Naming_Exceptions --
5224 --------------------------------
5226 procedure Free_Ada_Naming_Exceptions is
5228 Ada_Naming_Exception_Table.Set_Last (0);
5229 Ada_Naming_Exceptions.Reset;
5230 Reverse_Ada_Naming_Exceptions.Reset;
5231 end Free_Ada_Naming_Exceptions;
5233 ---------------------
5234 -- Get_Directories --
5235 ---------------------
5237 procedure Get_Directories
5238 (Project : Project_Id;
5239 In_Tree : Project_Tree_Ref;
5240 Current_Dir : String)
5242 Object_Dir : constant Variable_Value :=
5244 (Name_Object_Dir, Project.Decl.Attributes, In_Tree);
5246 Exec_Dir : constant Variable_Value :=
5248 (Name_Exec_Dir, Project.Decl.Attributes, In_Tree);
5250 Source_Dirs : constant Variable_Value :=
5252 (Name_Source_Dirs, Project.Decl.Attributes, In_Tree);
5254 Excluded_Source_Dirs : constant Variable_Value :=
5256 (Name_Excluded_Source_Dirs,
5257 Project.Decl.Attributes,
5260 Source_Files : constant Variable_Value :=
5262 (Name_Source_Files, Project.Decl.Attributes, In_Tree);
5264 Last_Source_Dir : String_List_Id := Nil_String;
5266 Languages : constant Variable_Value :=
5268 (Name_Languages, Project.Decl.Attributes, In_Tree);
5270 procedure Find_Source_Dirs
5271 (From : File_Name_Type;
5272 Location : Source_Ptr;
5273 Removed : Boolean := False);
5274 -- Find one or several source directories, and add (or remove, if
5275 -- Removed is True) them to list of source directories of the project.
5277 ----------------------
5278 -- Find_Source_Dirs --
5279 ----------------------
5281 procedure Find_Source_Dirs
5282 (From : File_Name_Type;
5283 Location : Source_Ptr;
5284 Removed : Boolean := False)
5286 Directory : constant String := Get_Name_String (From);
5287 Element : String_Element;
5289 procedure Recursive_Find_Dirs (Path : Name_Id);
5290 -- Find all the subdirectories (recursively) of Path and add them
5291 -- to the list of source directories of the project.
5293 -------------------------
5294 -- Recursive_Find_Dirs --
5295 -------------------------
5297 procedure Recursive_Find_Dirs (Path : Name_Id) is
5299 Name : String (1 .. 250);
5301 List : String_List_Id;
5302 Prev : String_List_Id;
5303 Element : String_Element;
5304 Found : Boolean := False;
5306 Non_Canonical_Path : Name_Id := No_Name;
5307 Canonical_Path : Name_Id := No_Name;
5309 The_Path : constant String :=
5311 (Get_Name_String (Path),
5312 Directory => Current_Dir,
5313 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5314 Directory_Separator;
5316 The_Path_Last : constant Natural :=
5317 Compute_Directory_Last (The_Path);
5320 Name_Len := The_Path_Last - The_Path'First + 1;
5321 Name_Buffer (1 .. Name_Len) :=
5322 The_Path (The_Path'First .. The_Path_Last);
5323 Non_Canonical_Path := Name_Find;
5325 Name_Id (Canonical_Case_File_Name (Non_Canonical_Path));
5327 -- To avoid processing the same directory several times, check
5328 -- if the directory is already in Recursive_Dirs. If it is, then
5329 -- there is nothing to do, just return. If it is not, put it there
5330 -- and continue recursive processing.
5333 if Recursive_Dirs.Get (Canonical_Path) then
5336 Recursive_Dirs.Set (Canonical_Path, True);
5340 -- Check if directory is already in list
5342 List := Project.Source_Dirs;
5344 while List /= Nil_String loop
5345 Element := In_Tree.String_Elements.Table (List);
5347 if Element.Value /= No_Name then
5348 Found := Element.Value = Canonical_Path;
5353 List := Element.Next;
5356 -- If directory is not already in list, put it there
5358 if (not Removed) and (not Found) then
5359 if Current_Verbosity = High then
5361 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5364 String_Element_Table.Increment_Last
5365 (In_Tree.String_Elements);
5367 (Value => Canonical_Path,
5368 Display_Value => Non_Canonical_Path,
5369 Location => No_Location,
5374 -- Case of first source directory
5376 if Last_Source_Dir = Nil_String then
5377 Project.Source_Dirs := String_Element_Table.Last
5378 (In_Tree.String_Elements);
5380 -- Here we already have source directories
5383 -- Link the previous last to the new one
5385 In_Tree.String_Elements.Table
5386 (Last_Source_Dir).Next :=
5387 String_Element_Table.Last
5388 (In_Tree.String_Elements);
5391 -- And register this source directory as the new last
5393 Last_Source_Dir := String_Element_Table.Last
5394 (In_Tree.String_Elements);
5395 In_Tree.String_Elements.Table (Last_Source_Dir) :=
5398 elsif Removed and Found then
5399 if Prev = Nil_String then
5400 Project.Source_Dirs :=
5401 In_Tree.String_Elements.Table (List).Next;
5403 In_Tree.String_Elements.Table (Prev).Next :=
5404 In_Tree.String_Elements.Table (List).Next;
5408 -- Now look for subdirectories. We do that even when this
5409 -- directory is already in the list, because some of its
5410 -- subdirectories may not be in the list yet.
5412 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5415 Read (Dir, Name, Last);
5418 if Name (1 .. Last) /= "."
5419 and then Name (1 .. Last) /= ".."
5421 -- Avoid . and .. directories
5423 if Current_Verbosity = High then
5424 Write_Str (" Checking ");
5425 Write_Line (Name (1 .. Last));
5429 Path_Name : constant String :=
5431 (Name => Name (1 .. Last),
5433 The_Path (The_Path'First .. The_Path_Last),
5434 Resolve_Links => Opt.Follow_Links_For_Dirs,
5435 Case_Sensitive => True);
5438 if Is_Directory (Path_Name) then
5439 -- We have found a new subdirectory, call self
5441 Name_Len := Path_Name'Length;
5442 Name_Buffer (1 .. Name_Len) := Path_Name;
5443 Recursive_Find_Dirs (Name_Find);
5452 when Directory_Error =>
5454 end Recursive_Find_Dirs;
5456 -- Start of processing for Find_Source_Dirs
5459 if Current_Verbosity = High and then not Removed then
5460 Write_Str ("Find_Source_Dirs (""");
5461 Write_Str (Directory);
5465 -- First, check if we are looking for a directory tree, indicated
5466 -- by "/**" at the end.
5468 if Directory'Length >= 3
5469 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5470 and then (Directory (Directory'Last - 2) = '/'
5472 Directory (Directory'Last - 2) = Directory_Separator)
5475 Project.Known_Order_Of_Source_Dirs := False;
5478 Name_Len := Directory'Length - 3;
5480 if Name_Len = 0 then
5482 -- Case of "/**": all directories in file system
5485 Name_Buffer (1) := Directory (Directory'First);
5488 Name_Buffer (1 .. Name_Len) :=
5489 Directory (Directory'First .. Directory'Last - 3);
5492 if Current_Verbosity = High then
5493 Write_Str ("Looking for all subdirectories of """);
5494 Write_Str (Name_Buffer (1 .. Name_Len));
5499 Base_Dir : constant File_Name_Type := Name_Find;
5500 Root_Dir : constant String :=
5502 (Name => Get_Name_String (Base_Dir),
5505 (Project.Directory.Display_Name),
5506 Resolve_Links => False,
5507 Case_Sensitive => True);
5510 if Root_Dir'Length = 0 then
5511 Err_Vars.Error_Msg_File_1 := Base_Dir;
5513 if Location = No_Location then
5516 "{ is not a valid directory.",
5521 "{ is not a valid directory.",
5526 -- We have an existing directory, we register it and all of
5527 -- its subdirectories.
5529 if Current_Verbosity = High then
5530 Write_Line ("Looking for source directories:");
5533 Name_Len := Root_Dir'Length;
5534 Name_Buffer (1 .. Name_Len) := Root_Dir;
5535 Recursive_Find_Dirs (Name_Find);
5537 if Current_Verbosity = High then
5538 Write_Line ("End of looking for source directories.");
5543 -- We have a single directory
5547 Path_Name : Path_Information;
5548 List : String_List_Id;
5549 Prev : String_List_Id;
5550 Dir_Exists : Boolean;
5554 (Project => Project,
5558 Dir_Exists => Dir_Exists,
5559 Must_Exist => False);
5561 if not Dir_Exists then
5562 Err_Vars.Error_Msg_File_1 := From;
5564 if Location = No_Location then
5567 "{ is not a valid directory",
5572 "{ is not a valid directory",
5578 Path : constant String :=
5579 Get_Name_String (Path_Name.Name) &
5580 Directory_Separator;
5581 Last_Path : constant Natural :=
5582 Compute_Directory_Last (Path);
5584 Display_Path : constant String :=
5586 (Path_Name.Display_Name) &
5587 Directory_Separator;
5588 Last_Display_Path : constant Natural :=
5589 Compute_Directory_Last
5591 Display_Path_Id : Name_Id;
5595 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
5596 Path_Id := Name_Find;
5598 Add_Str_To_Name_Buffer
5600 (Display_Path'First .. Last_Display_Path));
5601 Display_Path_Id := Name_Find;
5605 -- As it is an existing directory, we add it to the
5606 -- list of directories.
5608 String_Element_Table.Increment_Last
5609 (In_Tree.String_Elements);
5613 Display_Value => Display_Path_Id,
5614 Location => No_Location,
5616 Next => Nil_String);
5618 if Last_Source_Dir = Nil_String then
5620 -- This is the first source directory
5622 Project.Source_Dirs := String_Element_Table.Last
5623 (In_Tree.String_Elements);
5626 -- We already have source directories, link the
5627 -- previous last to the new one.
5629 In_Tree.String_Elements.Table
5630 (Last_Source_Dir).Next :=
5631 String_Element_Table.Last
5632 (In_Tree.String_Elements);
5635 -- And register this source directory as the new last
5637 Last_Source_Dir := String_Element_Table.Last
5638 (In_Tree.String_Elements);
5639 In_Tree.String_Elements.Table
5640 (Last_Source_Dir) := Element;
5643 -- Remove source dir, if present
5647 -- Look for source dir in current list
5649 List := Project.Source_Dirs;
5650 while List /= Nil_String loop
5651 Element := In_Tree.String_Elements.Table (List);
5652 exit when Element.Value = Path_Id;
5654 List := Element.Next;
5657 if List /= Nil_String then
5658 -- Source dir was found, remove it from the list
5660 if Prev = Nil_String then
5661 Project.Source_Dirs :=
5662 In_Tree.String_Elements.Table (List).Next;
5665 In_Tree.String_Elements.Table (Prev).Next :=
5666 In_Tree.String_Elements.Table (List).Next;
5674 end Find_Source_Dirs;
5676 -- Start of processing for Get_Directories
5678 Dir_Exists : Boolean;
5681 if Current_Verbosity = High then
5682 Write_Line ("Starting to look for directories");
5685 -- Set the object directory to its default which may be nil, if there
5686 -- is no sources in the project.
5688 if (((not Source_Files.Default)
5689 and then Source_Files.Values = Nil_String)
5691 ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
5693 ((not Languages.Default) and then Languages.Values = Nil_String))
5694 and then Project.Extends = No_Project
5696 Project.Object_Directory := No_Path_Information;
5698 Project.Object_Directory := Project.Directory;
5701 -- Check the object directory
5703 if Object_Dir.Value /= Empty_String then
5704 Get_Name_String (Object_Dir.Value);
5706 if Name_Len = 0 then
5709 "Object_Dir cannot be empty",
5710 Object_Dir.Location);
5713 -- We check that the specified object directory does exist.
5714 -- However, even when it doesn't exist, we set it to a default
5715 -- value. This is for the benefit of tools that recover from
5716 -- errors; for example, these tools could create the non existent
5718 -- We always return an absolute directory name though
5723 File_Name_Type (Object_Dir.Value),
5724 Path => Project.Object_Directory,
5726 Dir_Exists => Dir_Exists,
5727 Location => Object_Dir.Location,
5728 Must_Exist => False,
5729 Externally_Built => Project.Externally_Built);
5732 and then not Project.Externally_Built
5734 -- The object directory does not exist, report an error if
5735 -- the project is not externally built.
5737 Err_Vars.Error_Msg_File_1 :=
5738 File_Name_Type (Object_Dir.Value);
5741 "object directory { not found",
5746 elsif Project.Object_Directory /= No_Path_Information
5747 and then Subdirs /= null
5750 Name_Buffer (1) := '.';
5755 Path => Project.Object_Directory,
5757 Dir_Exists => Dir_Exists,
5758 Location => Object_Dir.Location,
5759 Externally_Built => Project.Externally_Built);
5762 if Current_Verbosity = High then
5763 if Project.Object_Directory = No_Path_Information then
5764 Write_Line ("No object directory");
5767 ("Object directory",
5768 Get_Name_String (Project.Object_Directory.Display_Name));
5772 -- Check the exec directory
5774 -- We set the object directory to its default
5776 Project.Exec_Directory := Project.Object_Directory;
5778 if Exec_Dir.Value /= Empty_String then
5779 Get_Name_String (Exec_Dir.Value);
5781 if Name_Len = 0 then
5784 "Exec_Dir cannot be empty",
5788 -- We check that the specified exec directory does exist
5793 File_Name_Type (Exec_Dir.Value),
5794 Path => Project.Exec_Directory,
5795 Dir_Exists => Dir_Exists,
5797 Location => Exec_Dir.Location,
5798 Externally_Built => Project.Externally_Built);
5800 if not Dir_Exists then
5801 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
5804 "exec directory { not found",
5810 if Current_Verbosity = High then
5811 if Project.Exec_Directory = No_Path_Information then
5812 Write_Line ("No exec directory");
5814 Write_Str ("Exec directory: """);
5815 Write_Str (Get_Name_String (Project.Exec_Directory.Display_Name));
5820 -- Look for the source directories
5822 if Current_Verbosity = High then
5823 Write_Line ("Starting to look for source directories");
5826 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
5828 if (not Source_Files.Default) and then
5829 Source_Files.Values = Nil_String
5831 Project.Source_Dirs := Nil_String;
5833 if Project.Qualifier = Standard then
5837 "a standard project cannot have no sources",
5838 Source_Files.Location);
5841 elsif Source_Dirs.Default then
5843 -- No Source_Dirs specified: the single source directory is the one
5844 -- containing the project file
5846 String_Element_Table.Append (In_Tree.String_Elements,
5847 (Value => Name_Id (Project.Directory.Name),
5848 Display_Value => Name_Id (Project.Directory.Display_Name),
5849 Location => No_Location,
5853 Project.Source_Dirs := String_Element_Table.Last
5854 (In_Tree.String_Elements);
5856 if Current_Verbosity = High then
5858 ("Default source directory",
5859 Get_Name_String (Project.Directory.Display_Name));
5862 elsif Source_Dirs.Values = Nil_String then
5863 if Project.Qualifier = Standard then
5867 "a standard project cannot have no source directories",
5868 Source_Dirs.Location);
5871 Project.Source_Dirs := Nil_String;
5875 Source_Dir : String_List_Id;
5876 Element : String_Element;
5879 -- Process the source directories for each element of the list
5881 Source_Dir := Source_Dirs.Values;
5882 while Source_Dir /= Nil_String loop
5883 Element := In_Tree.String_Elements.Table (Source_Dir);
5885 (File_Name_Type (Element.Value), Element.Location);
5886 Source_Dir := Element.Next;
5891 if not Excluded_Source_Dirs.Default
5892 and then Excluded_Source_Dirs.Values /= Nil_String
5895 Source_Dir : String_List_Id;
5896 Element : String_Element;
5899 -- Process the source directories for each element of the list
5901 Source_Dir := Excluded_Source_Dirs.Values;
5902 while Source_Dir /= Nil_String loop
5903 Element := In_Tree.String_Elements.Table (Source_Dir);
5905 (File_Name_Type (Element.Value),
5908 Source_Dir := Element.Next;
5913 if Current_Verbosity = High then
5914 Write_Line ("Putting source directories in canonical cases");
5918 Current : String_List_Id := Project.Source_Dirs;
5919 Element : String_Element;
5922 while Current /= Nil_String loop
5923 Element := In_Tree.String_Elements.Table (Current);
5924 if Element.Value /= No_Name then
5926 Name_Id (Canonical_Case_File_Name (Name_Id (Element.Value)));
5927 In_Tree.String_Elements.Table (Current) := Element;
5930 Current := Element.Next;
5933 end Get_Directories;
5940 (Project : Project_Id;
5941 In_Tree : Project_Tree_Ref)
5943 Mains : constant Variable_Value :=
5944 Prj.Util.Value_Of (Name_Main, Project.Decl.Attributes, In_Tree);
5945 List : String_List_Id;
5946 Elem : String_Element;
5949 Project.Mains := Mains.Values;
5951 -- If no Mains were specified, and if we are an extending project,
5952 -- inherit the Mains from the project we are extending.
5954 if Mains.Default then
5955 if not Project.Library and then Project.Extends /= No_Project then
5956 Project.Mains := Project.Extends.Mains;
5959 -- In a library project file, Main cannot be specified
5961 elsif Project.Library then
5964 "a library project file cannot have Main specified",
5968 List := Mains.Values;
5969 while List /= Nil_String loop
5970 Elem := In_Tree.String_Elements.Table (List);
5972 if Length_Of_Name (Elem.Value) = 0 then
5975 "?a main cannot have an empty name",
5985 ---------------------------
5986 -- Get_Sources_From_File --
5987 ---------------------------
5989 procedure Get_Sources_From_File
5991 Location : Source_Ptr;
5992 Project : Project_Id;
5993 In_Tree : Project_Tree_Ref)
5995 File : Prj.Util.Text_File;
5996 Line : String (1 .. 250);
5998 Source_Name : File_Name_Type;
5999 Name_Loc : Name_Location;
6002 if Get_Mode = Ada_Only then
6006 if Current_Verbosity = High then
6007 Write_Str ("Opening """);
6014 Prj.Util.Open (File, Path);
6016 if not Prj.Util.Is_Valid (File) then
6017 Error_Msg (Project, In_Tree, "file does not exist", Location);
6020 -- Read the lines one by one
6022 while not Prj.Util.End_Of_File (File) loop
6023 Prj.Util.Get_Line (File, Line, Last);
6025 -- A non empty, non comment line should contain a file name
6028 and then (Last = 1 or else Line (1 .. 2) /= "--")
6031 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6032 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6033 Source_Name := Name_Find;
6035 -- Check that there is no directory information
6037 for J in 1 .. Last loop
6038 if Line (J) = '/' or else Line (J) = Directory_Separator then
6039 Error_Msg_File_1 := Source_Name;
6043 "file name cannot include directory information ({)",
6049 Name_Loc := Source_Names.Get (Source_Name);
6051 if Name_Loc = No_Name_Location then
6053 (Name => Source_Name,
6054 Location => Location,
6055 Source => No_Source,
6060 Source_Names.Set (Source_Name, Name_Loc);
6064 Prj.Util.Close (File);
6067 end Get_Sources_From_File;
6069 -----------------------
6070 -- Compute_Unit_Name --
6071 -----------------------
6073 procedure Compute_Unit_Name
6074 (File_Name : File_Name_Type;
6075 Naming : Lang_Naming_Data;
6076 Kind : out Source_Kind;
6078 In_Tree : Project_Tree_Ref)
6080 Filename : constant String := Get_Name_String (File_Name);
6081 Last : Integer := Filename'Last;
6082 Sep_Len : constant Integer :=
6083 Integer (Length_Of_Name (Naming.Separate_Suffix));
6084 Body_Len : constant Integer :=
6085 Integer (Length_Of_Name (Naming.Body_Suffix));
6086 Spec_Len : constant Integer :=
6087 Integer (Length_Of_Name (Naming.Spec_Suffix));
6089 Standard_GNAT : constant Boolean :=
6090 Naming.Spec_Suffix = Default_Ada_Spec_Suffix
6092 Naming.Body_Suffix = Default_Ada_Body_Suffix;
6094 Unit_Except : Unit_Exception;
6095 Masked : Boolean := False;
6101 if Naming.Dot_Replacement = No_File then
6102 if Current_Verbosity = High then
6103 Write_Line (" No dot_replacement specified");
6109 -- Choose the longest suffix that matches. If there are several matches,
6110 -- give priority to specs, then bodies, then separates.
6112 if Naming.Separate_Suffix /= Naming.Body_Suffix
6113 and then Suffix_Matches (Filename, Naming.Separate_Suffix)
6115 Last := Filename'Last - Sep_Len;
6119 if Filename'Last - Body_Len <= Last
6120 and then Suffix_Matches (Filename, Naming.Body_Suffix)
6122 Last := Natural'Min (Last, Filename'Last - Body_Len);
6126 if Filename'Last - Spec_Len <= Last
6127 and then Suffix_Matches (Filename, Naming.Spec_Suffix)
6129 Last := Natural'Min (Last, Filename'Last - Spec_Len);
6133 if Last = Filename'Last then
6134 if Current_Verbosity = High then
6135 Write_Line (" No matching suffix");
6141 -- Check that the casing matches
6143 if File_Names_Case_Sensitive then
6144 case Naming.Casing is
6145 when All_Lower_Case =>
6146 for J in Filename'First .. Last loop
6147 if Is_Letter (Filename (J))
6148 and then not Is_Lower (Filename (J))
6150 if Current_Verbosity = High then
6151 Write_Line (" Invalid casing");
6158 when All_Upper_Case =>
6159 for J in Filename'First .. Last loop
6160 if Is_Letter (Filename (J))
6161 and then not Is_Upper (Filename (J))
6163 if Current_Verbosity = High then
6164 Write_Line (" Invalid casing");
6171 when Mixed_Case | Unknown =>
6176 -- If Dot_Replacement is not a single dot, then there should not
6177 -- be any dot in the name.
6180 Dot_Repl : constant String :=
6181 Get_Name_String (Naming.Dot_Replacement);
6184 if Dot_Repl /= "." then
6185 for Index in Filename'First .. Last loop
6186 if Filename (Index) = '.' then
6187 if Current_Verbosity = High then
6188 Write_Line (" Invalid name, contains dot");
6195 Replace_Into_Name_Buffer
6196 (Filename (Filename'First .. Last), Dot_Repl, '.');
6199 Name_Len := Last - Filename'First + 1;
6200 Name_Buffer (1 .. Name_Len) := Filename (Filename'First .. Last);
6202 (Source => Name_Buffer (1 .. Name_Len),
6203 Mapping => Lower_Case_Map);
6207 -- In the standard GNAT naming scheme, check for special cases: children
6208 -- or separates of A, G, I or S, and run time sources.
6210 if Standard_GNAT and then Name_Len >= 3 then
6212 S1 : constant Character := Name_Buffer (1);
6213 S2 : constant Character := Name_Buffer (2);
6214 S3 : constant Character := Name_Buffer (3);
6222 -- Children or separates of packages A, G, I or S. These names
6223 -- are x__ ... or x~... (where x is a, g, i, or s). Both
6224 -- versions (x__... and x~...) are allowed in all platforms,
6225 -- because it is not possible to know the platform before
6226 -- processing of the project files.
6228 if S2 = '_' and then S3 = '_' then
6229 Name_Buffer (2) := '.';
6230 Name_Buffer (3 .. Name_Len - 1) :=
6231 Name_Buffer (4 .. Name_Len);
6232 Name_Len := Name_Len - 1;
6235 Name_Buffer (2) := '.';
6239 -- If it is potentially a run time source, disable filling
6240 -- of the mapping file to avoid warnings.
6242 Set_Mapping_File_Initial_State_To_Empty (In_Tree);
6248 -- Name_Buffer contains the name of the the unit in lower-cases. Check
6249 -- that this is a valid unit name
6251 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
6253 -- If there is a naming exception for the same unit, the file is not
6254 -- a source for the unit. Currently, this only applies in multi_lang
6255 -- mode, since Unit_Exceptions is no set in ada_only mode.
6257 if Unit /= No_Name then
6258 Unit_Except := Unit_Exceptions.Get (Unit);
6261 Masked := Unit_Except.Spec /= No_File
6263 Unit_Except.Spec /= File_Name;
6265 Masked := Unit_Except.Impl /= No_File
6267 Unit_Except.Impl /= File_Name;
6271 if Current_Verbosity = High then
6272 Write_Str (" """ & Filename & """ contains the ");
6275 Write_Str ("spec of a unit found in """);
6276 Write_Str (Get_Name_String (Unit_Except.Spec));
6278 Write_Str ("body of a unit found in """);
6279 Write_Str (Get_Name_String (Unit_Except.Impl));
6282 Write_Line (""" (ignored)");
6290 and then Current_Verbosity = High
6293 when Spec => Write_Str (" spec of ");
6294 when Impl => Write_Str (" body of ");
6295 when Sep => Write_Str (" sep of ");
6298 Write_Line (Get_Name_String (Unit));
6300 end Compute_Unit_Name;
6307 (In_Tree : Project_Tree_Ref;
6308 Canonical_File_Name : File_Name_Type;
6309 Project : Project_Id;
6310 Exception_Id : out Ada_Naming_Exception_Id;
6311 Unit_Name : out Name_Id;
6312 Unit_Kind : out Spec_Or_Body)
6314 Info_Id : Ada_Naming_Exception_Id :=
6315 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6316 VMS_Name : File_Name_Type;
6318 Lang : Language_Ptr;
6321 if Info_Id = No_Ada_Naming_Exception
6322 and then Hostparm.OpenVMS
6324 VMS_Name := Canonical_File_Name;
6325 Get_Name_String (VMS_Name);
6327 if Name_Buffer (Name_Len) = '.' then
6328 Name_Len := Name_Len - 1;
6329 VMS_Name := Name_Find;
6332 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6335 if Info_Id /= No_Ada_Naming_Exception then
6336 Exception_Id := Info_Id;
6337 Unit_Name := No_Name;
6341 Exception_Id := No_Ada_Naming_Exception;
6342 Lang := Get_Language_From_Name (Project, "ada");
6345 Unit_Name := No_Name;
6349 (File_Name => Canonical_File_Name,
6350 Naming => Lang.Config.Naming_Data,
6353 In_Tree => In_Tree);
6356 when Spec => Unit_Kind := Spec;
6357 when Impl | Sep => Unit_Kind := Impl;
6367 function Hash (Unit : Unit_Info) return Header_Num is
6369 return Header_Num (Unit.Unit mod 2048);
6372 -----------------------
6373 -- Is_Illegal_Suffix --
6374 -----------------------
6376 function Is_Illegal_Suffix
6377 (Suffix : File_Name_Type;
6378 Dot_Replacement : File_Name_Type) return Boolean
6380 Suffix_Str : constant String := Get_Name_String (Suffix);
6383 if Suffix_Str'Length = 0 then
6385 elsif Index (Suffix_Str, ".") = 0 then
6389 -- Case of dot replacement is a single dot, and first character of
6390 -- suffix is also a dot.
6392 if Get_Name_String (Dot_Replacement) = "."
6393 and then Suffix_Str (Suffix_Str'First) = '.'
6395 for Index in Suffix_Str'First + 1 .. Suffix_Str'Last loop
6397 -- Case of following dot
6399 if Suffix_Str (Index) = '.' then
6401 -- It is illegal to have a letter following the initial dot
6403 return Is_Letter (Suffix_Str (Suffix_Str'First + 1));
6409 end Is_Illegal_Suffix;
6411 ----------------------
6412 -- Locate_Directory --
6413 ----------------------
6415 procedure Locate_Directory
6416 (Project : Project_Id;
6417 In_Tree : Project_Tree_Ref;
6418 Name : File_Name_Type;
6419 Path : out Path_Information;
6420 Dir_Exists : out Boolean;
6421 Create : String := "";
6422 Location : Source_Ptr := No_Location;
6423 Must_Exist : Boolean := True;
6424 Externally_Built : Boolean := False)
6426 Parent : constant Path_Name_Type :=
6427 Project.Directory.Display_Name;
6428 The_Parent : constant String :=
6429 Get_Name_String (Parent) & Directory_Separator;
6430 The_Parent_Last : constant Natural :=
6431 Compute_Directory_Last (The_Parent);
6432 Full_Name : File_Name_Type;
6433 The_Name : File_Name_Type;
6436 Get_Name_String (Name);
6438 -- Add Subdirs.all if it is a directory that may be created and
6439 -- Subdirs is not null;
6441 if Create /= "" and then Subdirs /= null then
6442 if Name_Buffer (Name_Len) /= Directory_Separator then
6443 Add_Char_To_Name_Buffer (Directory_Separator);
6446 Add_Str_To_Name_Buffer (Subdirs.all);
6449 -- Convert '/' to directory separator (for Windows)
6451 for J in 1 .. Name_Len loop
6452 if Name_Buffer (J) = '/' then
6453 Name_Buffer (J) := Directory_Separator;
6457 The_Name := Name_Find;
6459 if Current_Verbosity = High then
6460 Write_Str ("Locate_Directory (""");
6461 Write_Str (Get_Name_String (The_Name));
6462 Write_Str (""", """);
6463 Write_Str (The_Parent);
6467 Path := No_Path_Information;
6468 Dir_Exists := False;
6470 if Is_Absolute_Path (Get_Name_String (The_Name)) then
6471 Full_Name := The_Name;
6475 Add_Str_To_Name_Buffer
6476 (The_Parent (The_Parent'First .. The_Parent_Last));
6477 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
6478 Full_Name := Name_Find;
6482 Full_Path_Name : String_Access :=
6483 new String'(Get_Name_String (Full_Name));
6486 if (Setup_Projects or else Subdirs /= null)
6487 and then Create'Length > 0
6489 if not Is_Directory (Full_Path_Name.all) then
6491 -- If project is externally built, do not create a subdir,
6492 -- use the specified directory, without the subdir.
6494 if Externally_Built then
6495 if Is_Absolute_Path (Get_Name_String (Name)) then
6496 Get_Name_String (Name);
6500 Add_Str_To_Name_Buffer
6501 (The_Parent (The_Parent'First .. The_Parent_Last));
6502 Add_Str_To_Name_Buffer (Get_Name_String (Name));
6505 Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
6509 Create_Path (Full_Path_Name.all);
6511 if not Quiet_Output then
6513 Write_Str (" directory """);
6514 Write_Str (Full_Path_Name.all);
6515 Write_Str (""" created for project ");
6516 Write_Line (Get_Name_String (Project.Name));
6523 "could not create " & Create &
6524 " directory " & Full_Path_Name.all,
6531 Dir_Exists := Is_Directory (Full_Path_Name.all);
6533 if not Must_Exist or else Dir_Exists then
6535 Normed : constant String :=
6537 (Full_Path_Name.all,
6539 The_Parent (The_Parent'First .. The_Parent_Last),
6540 Resolve_Links => False,
6541 Case_Sensitive => True);
6543 Canonical_Path : constant String :=
6548 (The_Parent'First .. The_Parent_Last),
6550 Opt.Follow_Links_For_Dirs,
6551 Case_Sensitive => False);
6554 Name_Len := Normed'Length;
6555 Name_Buffer (1 .. Name_Len) := Normed;
6556 Path.Display_Name := Name_Find;
6558 Name_Len := Canonical_Path'Length;
6559 Name_Buffer (1 .. Name_Len) := Canonical_Path;
6560 Path.Name := Name_Find;
6564 Free (Full_Path_Name);
6566 end Locate_Directory;
6568 ---------------------------
6569 -- Find_Excluded_Sources --
6570 ---------------------------
6572 procedure Find_Excluded_Sources
6573 (Project : Project_Id;
6574 In_Tree : Project_Tree_Ref)
6576 Excluded_Source_List_File : constant Variable_Value :=
6578 (Name_Excluded_Source_List_File,
6579 Project.Decl.Attributes,
6582 Excluded_Sources : Variable_Value := Util.Value_Of
6583 (Name_Excluded_Source_Files,
6584 Project.Decl.Attributes,
6587 Current : String_List_Id;
6588 Element : String_Element;
6589 Location : Source_Ptr;
6590 Name : File_Name_Type;
6591 File : Prj.Util.Text_File;
6592 Line : String (1 .. 300);
6594 Locally_Removed : Boolean := False;
6597 -- If Excluded_Source_Files is not declared, check
6598 -- Locally_Removed_Files.
6600 if Excluded_Sources.Default then
6601 Locally_Removed := True;
6604 (Name_Locally_Removed_Files, Project.Decl.Attributes, In_Tree);
6607 Excluded_Sources_Htable.Reset;
6609 -- If there are excluded sources, put them in the table
6611 if not Excluded_Sources.Default then
6612 if not Excluded_Source_List_File.Default then
6613 if Locally_Removed then
6616 "?both attributes Locally_Removed_Files and " &
6617 "Excluded_Source_List_File are present",
6618 Excluded_Source_List_File.Location);
6622 "?both attributes Excluded_Source_Files and " &
6623 "Excluded_Source_List_File are present",
6624 Excluded_Source_List_File.Location);
6628 Current := Excluded_Sources.Values;
6629 while Current /= Nil_String loop
6630 Element := In_Tree.String_Elements.Table (Current);
6631 Name := Canonical_Case_File_Name (Element.Value);
6633 -- If the element has no location, then use the location of
6634 -- Excluded_Sources to report possible errors.
6636 if Element.Location = No_Location then
6637 Location := Excluded_Sources.Location;
6639 Location := Element.Location;
6642 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
6643 Current := Element.Next;
6646 elsif not Excluded_Source_List_File.Default then
6647 Location := Excluded_Source_List_File.Location;
6650 Source_File_Path_Name : constant String :=
6653 (Excluded_Source_List_File.Value),
6654 Project.Directory.Name);
6657 if Source_File_Path_Name'Length = 0 then
6658 Err_Vars.Error_Msg_File_1 :=
6659 File_Name_Type (Excluded_Source_List_File.Value);
6662 "file with excluded sources { does not exist",
6663 Excluded_Source_List_File.Location);
6668 Prj.Util.Open (File, Source_File_Path_Name);
6670 if not Prj.Util.Is_Valid (File) then
6672 (Project, In_Tree, "file does not exist", Location);
6674 -- Read the lines one by one
6676 while not Prj.Util.End_Of_File (File) loop
6677 Prj.Util.Get_Line (File, Line, Last);
6679 -- Non empty, non comment line should contain a file name
6682 and then (Last = 1 or else Line (1 .. 2) /= "--")
6685 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6686 Canonical_Case_File_Name
6687 (Name_Buffer (1 .. Name_Len));
6690 -- Check that there is no directory information
6692 for J in 1 .. Last loop
6694 or else Line (J) = Directory_Separator
6696 Error_Msg_File_1 := Name;
6700 "file name cannot include " &
6701 "directory information ({)",
6707 Excluded_Sources_Htable.Set
6708 (Name, (Name, False, Location));
6712 Prj.Util.Close (File);
6717 end Find_Excluded_Sources;
6723 procedure Find_Sources
6724 (Project : Project_Id;
6725 In_Tree : Project_Tree_Ref;
6726 Proc_Data : in out Processing_Data;
6727 Allow_Duplicate_Basenames : Boolean)
6729 Sources : constant Variable_Value :=
6732 Project.Decl.Attributes,
6734 Source_List_File : constant Variable_Value :=
6736 (Name_Source_List_File,
6737 Project.Decl.Attributes,
6739 Name_Loc : Name_Location;
6741 Has_Explicit_Sources : Boolean;
6744 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
6746 (Source_List_File.Kind = Single,
6747 "Source_List_File is not a single string");
6749 -- If the user has specified a Source_Files attribute
6751 if not Sources.Default then
6752 if not Source_List_File.Default then
6755 "?both attributes source_files and " &
6756 "source_list_file are present",
6757 Source_List_File.Location);
6760 -- Sources is a list of file names
6763 Current : String_List_Id := Sources.Values;
6764 Element : String_Element;
6765 Location : Source_Ptr;
6766 Name : File_Name_Type;
6769 if Get_Mode = Multi_Language then
6770 if Current = Nil_String then
6771 Project.Languages := No_Language_Index;
6773 -- This project contains no source. For projects that don't
6774 -- extend other projects, this also means that there is no
6775 -- need for an object directory, if not specified.
6777 if Project.Extends = No_Project
6778 and then Project.Object_Directory = Project.Directory
6780 Project.Object_Directory := No_Path_Information;
6785 while Current /= Nil_String loop
6786 Element := In_Tree.String_Elements.Table (Current);
6787 Name := Canonical_Case_File_Name (Element.Value);
6788 Get_Name_String (Element.Value);
6790 -- If the element has no location, then use the location of
6791 -- Sources to report possible errors.
6793 if Element.Location = No_Location then
6794 Location := Sources.Location;
6796 Location := Element.Location;
6799 -- Check that there is no directory information
6801 for J in 1 .. Name_Len loop
6802 if Name_Buffer (J) = '/'
6803 or else Name_Buffer (J) = Directory_Separator
6805 Error_Msg_File_1 := Name;
6809 "file name cannot include directory " &
6816 -- In Multi_Language mode, check whether the file is already
6817 -- there: the same file name may be in the list. If the source
6818 -- is missing, the error will be on the first mention of the
6819 -- source file name.
6823 Name_Loc := No_Name_Location;
6824 when Multi_Language =>
6825 Name_Loc := Source_Names.Get (Name);
6828 if Name_Loc = No_Name_Location then
6831 Location => Location,
6832 Source => No_Source,
6835 Source_Names.Set (Name, Name_Loc);
6838 Current := Element.Next;
6841 Has_Explicit_Sources := True;
6844 -- If we have no Source_Files attribute, check the Source_List_File
6847 elsif not Source_List_File.Default then
6849 -- Source_List_File is the name of the file that contains the source
6853 Source_File_Path_Name : constant String :=
6855 (File_Name_Type (Source_List_File.Value),
6856 Project.Directory.Name);
6859 Has_Explicit_Sources := True;
6861 if Source_File_Path_Name'Length = 0 then
6862 Err_Vars.Error_Msg_File_1 :=
6863 File_Name_Type (Source_List_File.Value);
6866 "file with sources { does not exist",
6867 Source_List_File.Location);
6870 Get_Sources_From_File
6871 (Source_File_Path_Name, Source_List_File.Location,
6877 -- Neither Source_Files nor Source_List_File has been specified. Find
6878 -- all the files that satisfy the naming scheme in all the source
6881 Has_Explicit_Sources := False;
6884 if Get_Mode = Ada_Only then
6887 Explicit_Sources_Only => Has_Explicit_Sources,
6888 Proc_Data => Proc_Data);
6894 Sources.Default and then Source_List_File.Default,
6895 Allow_Duplicate_Basenames => Allow_Duplicate_Basenames);
6898 -- Check if all exceptions have been found. For Ada, it is an error if
6899 -- an exception is not found. For other language, the source is simply
6904 Iter : Source_Iterator;
6907 Iter := For_Each_Source (In_Tree, Project);
6909 Source := Prj.Element (Iter);
6910 exit when Source = No_Source;
6912 if Source.Naming_Exception
6913 and then Source.Path = No_Path_Information
6915 if Source.Unit /= No_Unit_Index then
6916 Error_Msg_Name_1 := Name_Id (Source.Display_File);
6917 Error_Msg_Name_2 := Name_Id (Source.Unit.Name);
6920 "source file %% for unit %% not found",
6924 Remove_Source (Source, No_Source);
6931 -- It is an error if a source file name in a source list or in a source
6932 -- list file is not found.
6934 if Has_Explicit_Sources then
6937 First_Error : Boolean;
6940 NL := Source_Names.Get_First;
6941 First_Error := True;
6942 while NL /= No_Name_Location loop
6943 if not NL.Found then
6944 Err_Vars.Error_Msg_File_1 := NL.Name;
6949 "source file { not found",
6951 First_Error := False;
6956 "\source file { not found",
6961 NL := Source_Names.Get_Next;
6966 if Get_Mode = Ada_Only
6967 and then Project.Extends = No_Project
6969 -- We should have found at least one source, if not report an error
6971 if not Has_Ada_Sources (Project) then
6973 (Project, "Ada", In_Tree, Source_List_File.Location);
6982 procedure Initialize (Proc_Data : in out Processing_Data) is
6984 Files_Htable.Reset (Proc_Data.Units);
6991 procedure Free (Proc_Data : in out Processing_Data) is
6993 Files_Htable.Reset (Proc_Data.Units);
6996 ----------------------
6997 -- Find_Ada_Sources --
6998 ----------------------
7000 procedure Find_Ada_Sources
7001 (Project : Project_Id;
7002 In_Tree : Project_Tree_Ref;
7003 Explicit_Sources_Only : Boolean;
7004 Proc_Data : in out Processing_Data)
7006 Source_Dir : String_List_Id;
7007 Element : String_Element;
7009 Dir_Has_Source : Boolean := False;
7011 Ada_Language : Language_Ptr;
7014 if Current_Verbosity = High then
7015 Write_Line ("Looking for Ada sources:");
7018 Ada_Language := Project.Languages;
7019 while Ada_Language /= No_Language_Index
7020 and then Ada_Language.Name /= Name_Ada
7022 Ada_Language := Ada_Language.Next;
7025 -- We look in all source directories for the file names in the hash
7026 -- table Source_Names.
7028 Source_Dir := Project.Source_Dirs;
7029 while Source_Dir /= Nil_String loop
7030 Dir_Has_Source := False;
7031 Element := In_Tree.String_Elements.Table (Source_Dir);
7034 Dir_Path : constant String :=
7035 Get_Name_String (Element.Display_Value) &
7036 Directory_Separator;
7037 Dir_Last : constant Natural := Compute_Directory_Last (Dir_Path);
7040 if Current_Verbosity = High then
7041 Write_Line ("checking directory """ & Dir_Path & """");
7044 -- Look for all files in the current source directory
7046 Open (Dir, Dir_Path (Dir_Path'First .. Dir_Last));
7049 Read (Dir, Name_Buffer, Name_Len);
7050 exit when Name_Len = 0;
7052 if Current_Verbosity = High then
7053 Write_Line (" Checking " & Name_Buffer (1 .. Name_Len));
7057 Name : constant File_Name_Type := Name_Find;
7058 Canonical_Name : File_Name_Type;
7060 -- ??? We could probably optimize the following call: we
7061 -- need to resolve links only once for the directory itself,
7062 -- and then do a single call to readlink() for each file.
7063 -- Unfortunately that would require a change in
7064 -- Normalize_Pathname so that it has the option of not
7065 -- resolving links for its Directory parameter, only for
7068 Path : constant String :=
7070 (Name => Name_Buffer (1 .. Name_Len),
7071 Directory => Dir_Path (Dir_Path'First .. Dir_Last),
7072 Resolve_Links => Opt.Follow_Links_For_Files,
7073 Case_Sensitive => True); -- no case folding
7075 Path_Name : Path_Name_Type;
7076 To_Record : Boolean := False;
7077 Location : Source_Ptr;
7080 -- If the file was listed in the explicit list of sources,
7081 -- mark it as such (since we'll need to report an error when
7082 -- an explicit source was not found)
7084 if Explicit_Sources_Only then
7086 Canonical_Case_File_Name (Name_Id (Name));
7087 NL := Source_Names.Get (Canonical_Name);
7088 To_Record := NL /= No_Name_Location and then not NL.Found;
7092 Location := NL.Location;
7093 Source_Names.Set (Canonical_Name, NL);
7098 Location := No_Location;
7102 Name_Len := Path'Length;
7103 Name_Buffer (1 .. Name_Len) := Path;
7104 Path_Name := Name_Find;
7106 if Current_Verbosity = High then
7107 Write_Line (" recording " & Get_Name_String (Name));
7110 -- Register the source if it is an Ada compilation unit
7114 Path_Name => Path_Name,
7117 Proc_Data => Proc_Data,
7118 Ada_Language => Ada_Language,
7119 Location => Location,
7120 Source_Recorded => Dir_Has_Source);
7133 if Dir_Has_Source then
7134 In_Tree.String_Elements.Table (Source_Dir).Flag := True;
7137 Source_Dir := Element.Next;
7140 if Current_Verbosity = High then
7141 Write_Line ("End looking for sources");
7143 end Find_Ada_Sources;
7145 -------------------------------
7146 -- Check_File_Naming_Schemes --
7147 -------------------------------
7149 procedure Check_File_Naming_Schemes
7150 (In_Tree : Project_Tree_Ref;
7151 Project : Project_Id;
7152 File_Name : File_Name_Type;
7153 Alternate_Languages : out Language_List;
7154 Language : out Language_Ptr;
7155 Display_Language_Name : out Name_Id;
7157 Lang_Kind : out Language_Kind;
7158 Kind : out Source_Kind)
7160 Filename : constant String := Get_Name_String (File_Name);
7161 Config : Language_Config;
7162 Tmp_Lang : Language_Ptr;
7164 Header_File : Boolean := False;
7165 -- True if we found at least one language for which the file is a header
7166 -- In such a case, we search for all possible languages where this is
7167 -- also a header (C and C++ for instance), since the file might be used
7168 -- for several such languages.
7170 procedure Check_File_Based_Lang;
7171 -- Does the naming scheme test for file-based languages. For those,
7172 -- there is no Unit. Just check if the file name has the implementation
7173 -- or, if it is specified, the template suffix of the language.
7175 -- Returns True if the file belongs to the current language and we
7176 -- should stop searching for matching languages. Not that a given header
7177 -- file could belong to several languages (C and C++ for instance). Thus
7178 -- if we found a header we'll check whether it matches other languages.
7180 ---------------------------
7181 -- Check_File_Based_Lang --
7182 ---------------------------
7184 procedure Check_File_Based_Lang is
7187 and then Suffix_Matches (Filename, Config.Naming_Data.Body_Suffix)
7191 Language := Tmp_Lang;
7193 if Current_Verbosity = High then
7194 Write_Str (" implementation of language ");
7195 Write_Line (Get_Name_String (Display_Language_Name));
7198 elsif Suffix_Matches (Filename, Config.Naming_Data.Spec_Suffix) then
7199 if Current_Verbosity = High then
7200 Write_Str (" header of language ");
7201 Write_Line (Get_Name_String (Display_Language_Name));
7205 Alternate_Languages := new Language_List_Element'
7206 (Language => Language,
7207 Next => Alternate_Languages);
7210 Header_File := True;
7213 Language := Tmp_Lang;
7216 end Check_File_Based_Lang;
7218 -- Start of processing for Check_File_Naming_Schemes
7221 Language := No_Language_Index;
7222 Alternate_Languages := null;
7223 Display_Language_Name := No_Name;
7225 Lang_Kind := File_Based;
7228 Tmp_Lang := Project.Languages;
7229 while Tmp_Lang /= No_Language_Index loop
7230 if Current_Verbosity = High then
7232 (" Testing language "
7233 & Get_Name_String (Tmp_Lang.Name)
7234 & " Header_File=" & Header_File'Img);
7237 Display_Language_Name := Tmp_Lang.Display_Name;
7238 Config := Tmp_Lang.Config;
7239 Lang_Kind := Config.Kind;
7243 Check_File_Based_Lang;
7244 exit when Kind = Impl;
7248 -- We know it belongs to a least a file_based language, no
7249 -- need to check unit-based ones.
7251 if not Header_File then
7253 (File_Name => File_Name,
7254 Naming => Config.Naming_Data,
7257 In_Tree => In_Tree);
7259 if Unit /= No_Name then
7260 Language := Tmp_Lang;
7266 Tmp_Lang := Tmp_Lang.Next;
7269 if Language = No_Language_Index
7270 and then Current_Verbosity = High
7272 Write_Line (" not a source of any language");
7274 end Check_File_Naming_Schemes;
7280 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind) is
7282 -- If the file was previously already associated with a unit, change it
7284 if Source.Unit /= null
7285 and then Source.Kind in Spec_Or_Body
7286 and then Source.Unit.File_Names (Source.Kind) /= null
7288 -- If we had another file referencing the same unit (for instance it
7289 -- was in an extended project), that source file is in fact invisible
7290 -- from now on, and in particular doesn't belong to the same unit.
7292 if Source.Unit.File_Names (Source.Kind) /= Source then
7293 Source.Unit.File_Names (Source.Kind).Unit := No_Unit_Index;
7296 Source.Unit.File_Names (Source.Kind) := null;
7299 Source.Kind := Kind;
7301 if Source.Kind in Spec_Or_Body and then Source.Unit /= null then
7302 Source.Unit.File_Names (Source.Kind) := Source;
7310 procedure Check_File
7311 (Project : Project_Id;
7312 In_Tree : Project_Tree_Ref;
7313 Path : Path_Name_Type;
7314 File_Name : File_Name_Type;
7315 Display_File_Name : File_Name_Type;
7316 For_All_Sources : Boolean;
7317 Allow_Duplicate_Basenames : Boolean)
7319 Canonical_Path : constant Path_Name_Type :=
7321 (Canonical_Case_File_Name (Name_Id (Path)));
7323 Name_Loc : Name_Location := Source_Names.Get (File_Name);
7324 Check_Name : Boolean := False;
7325 Alternate_Languages : Language_List;
7326 Language : Language_Ptr;
7329 Src_Ind : Source_File_Index;
7331 Source_To_Replace : Source_Id := No_Source;
7332 Display_Language_Name : Name_Id;
7333 Lang_Kind : Language_Kind;
7334 Kind : Source_Kind := Spec;
7335 Iter : Source_Iterator;
7338 if Name_Loc = No_Name_Location then
7339 Check_Name := For_All_Sources;
7342 if Name_Loc.Found then
7343 -- Check if it is OK to have the same file name in several
7344 -- source directories.
7346 if not Project.Known_Order_Of_Source_Dirs then
7347 Error_Msg_File_1 := File_Name;
7350 "{ is found in several source directories",
7355 Name_Loc.Found := True;
7357 Source_Names.Set (File_Name, Name_Loc);
7359 if Name_Loc.Source = No_Source then
7363 -- ??? Issue: there could be several entries for the same
7364 -- source file in the list of sources, in case the file
7365 -- contains multiple units. We should share the data as much
7366 -- as possible, and more importantly set the path for all
7369 Name_Loc.Source.Path := (Canonical_Path, Path);
7371 Source_Paths_Htable.Set
7372 (In_Tree.Source_Paths_HT,
7376 -- Check if this is a subunit
7378 if Name_Loc.Source.Unit /= No_Unit_Index
7379 and then Name_Loc.Source.Kind = Impl
7381 Src_Ind := Sinput.P.Load_Project_File
7382 (Get_Name_String (Canonical_Path));
7384 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7385 Override_Kind (Name_Loc.Source, Sep);
7393 Check_File_Naming_Schemes
7394 (In_Tree => In_Tree,
7396 File_Name => File_Name,
7397 Alternate_Languages => Alternate_Languages,
7398 Language => Language,
7399 Display_Language_Name => Display_Language_Name,
7401 Lang_Kind => Lang_Kind,
7404 if Language = No_Language_Index then
7406 -- A file name in a list must be a source of a language
7408 if Name_Loc.Found then
7409 Error_Msg_File_1 := File_Name;
7413 "language unknown for {",
7418 -- Check if the same file name or unit is used in the prj tree
7420 Iter := For_Each_Source (In_Tree);
7423 Source := Prj.Element (Iter);
7424 exit when Source = No_Source;
7427 and then Source.Unit /= No_Unit_Index
7428 and then Source.Unit.Name = Unit
7430 ((Source.Kind = Spec and then Kind = Impl)
7432 (Source.Kind = Impl and then Kind = Spec))
7434 -- We found the "other_part (source)"
7438 elsif (Unit /= No_Name
7439 and then Source.Unit /= No_Unit_Index
7440 and then Source.Unit.Name = Unit
7444 (Source.Kind = Sep and then Kind = Impl)
7446 (Source.Kind = Impl and then Kind = Sep)))
7448 (Unit = No_Name and then Source.File = File_Name)
7450 -- Duplication of file/unit in same project is only
7451 -- allowed if order of source directories is known.
7453 if Project = Source.Project then
7454 if Unit = No_Name then
7455 if Allow_Duplicate_Basenames then
7457 elsif Project.Known_Order_Of_Source_Dirs then
7460 Error_Msg_File_1 := File_Name;
7462 (Project, In_Tree, "duplicate source file name {",
7468 if Project.Known_Order_Of_Source_Dirs then
7471 Error_Msg_Name_1 := Unit;
7473 (Project, In_Tree, "duplicate unit %%",
7479 -- Do not allow the same unit name in different projects,
7480 -- except if one is extending the other.
7482 -- For a file based language, the same file name replaces
7483 -- a file in a project being extended, but it is allowed
7484 -- to have the same file name in unrelated projects.
7486 elsif Is_Extending (Project, Source.Project) then
7487 Source_To_Replace := Source;
7489 elsif Unit /= No_Name
7490 and then not Source.Locally_Removed
7492 Error_Msg_Name_1 := Unit;
7495 "unit %% cannot belong to several projects",
7498 Error_Msg_Name_1 := Project.Name;
7499 Error_Msg_Name_2 := Name_Id (Path);
7501 (Project, In_Tree, "\ project %%, %%", No_Location);
7503 Error_Msg_Name_1 := Source.Project.Name;
7504 Error_Msg_Name_2 := Name_Id (Source.Path.Display_Name);
7506 (Project, In_Tree, "\ project %%, %%", No_Location);
7520 Lang_Id => Language,
7522 Alternate_Languages => Alternate_Languages,
7523 File_Name => File_Name,
7524 Display_File => Display_File_Name,
7526 Path => (Canonical_Path, Path),
7527 Source_To_Replace => Source_To_Replace);
7533 ------------------------
7534 -- Search_Directories --
7535 ------------------------
7537 procedure Search_Directories
7538 (Project : Project_Id;
7539 In_Tree : Project_Tree_Ref;
7540 For_All_Sources : Boolean;
7541 Allow_Duplicate_Basenames : Boolean)
7543 Source_Dir : String_List_Id;
7544 Element : String_Element;
7546 Name : String (1 .. 1_000);
7548 File_Name : File_Name_Type;
7549 Display_File_Name : File_Name_Type;
7552 if Current_Verbosity = High then
7553 Write_Line ("Looking for sources:");
7556 -- Loop through subdirectories
7558 Source_Dir := Project.Source_Dirs;
7559 while Source_Dir /= Nil_String loop
7561 Element := In_Tree.String_Elements.Table (Source_Dir);
7562 if Element.Value /= No_Name then
7563 Get_Name_String (Element.Display_Value);
7566 Source_Directory : constant String :=
7567 Name_Buffer (1 .. Name_Len) &
7568 Directory_Separator;
7570 Dir_Last : constant Natural :=
7571 Compute_Directory_Last
7575 if Current_Verbosity = High then
7576 Write_Attr ("Source_Dir", Source_Directory);
7579 -- We look to every entry in the source directory
7581 Open (Dir, Source_Directory);
7584 Read (Dir, Name, Last);
7588 -- ??? Duplicate system call here, we just did a
7589 -- a similar one. Maybe Ada.Directories would be more
7593 (Source_Directory & Name (1 .. Last))
7595 if Current_Verbosity = High then
7596 Write_Str (" Checking ");
7597 Write_Line (Name (1 .. Last));
7601 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
7602 Display_File_Name := Name_Find;
7604 if Osint.File_Names_Case_Sensitive then
7605 File_Name := Display_File_Name;
7607 Canonical_Case_File_Name
7608 (Name_Buffer (1 .. Name_Len));
7609 File_Name := Name_Find;
7613 Path_Name : constant String :=
7618 (Source_Directory'First ..
7621 Opt.Follow_Links_For_Files,
7622 Case_Sensitive => True);
7623 -- Case_Sensitive set True (no folding)
7625 Path : Path_Name_Type;
7627 Excluded_Sources_Htable.Get (File_Name);
7630 Name_Len := Path_Name'Length;
7631 Name_Buffer (1 .. Name_Len) := Path_Name;
7634 if FF /= No_File_Found then
7635 if not FF.Found then
7637 Excluded_Sources_Htable.Set (File_Name, FF);
7639 if Current_Verbosity = High then
7640 Write_Str (" excluded source """);
7641 Write_Str (Get_Name_String (File_Name));
7648 (Project => Project,
7651 File_Name => File_Name,
7652 Display_File_Name =>
7654 For_All_Sources => For_All_Sources,
7655 Allow_Duplicate_Basenames =>
7656 Allow_Duplicate_Basenames);
7667 when Directory_Error =>
7671 Source_Dir := Element.Next;
7674 if Current_Verbosity = High then
7675 Write_Line ("end Looking for sources.");
7677 end Search_Directories;
7679 ----------------------------
7680 -- Load_Naming_Exceptions --
7681 ----------------------------
7683 procedure Load_Naming_Exceptions
7684 (Project : Project_Id;
7685 In_Tree : Project_Tree_Ref)
7688 Iter : Source_Iterator;
7691 Unit_Exceptions.Reset;
7693 Iter := For_Each_Source (In_Tree, Project);
7695 Source := Prj.Element (Iter);
7696 exit when Source = No_Source;
7698 -- An excluded file cannot also be an exception file name
7700 if Excluded_Sources_Htable.Get (Source.File) /= No_File_Found then
7701 Error_Msg_File_1 := Source.File;
7704 "{ cannot be both excluded and an exception file name",
7708 if Current_Verbosity = High then
7709 Write_Str ("Naming exception: Putting source file ");
7710 Write_Str (Get_Name_String (Source.File));
7711 Write_Line (" in Source_Names");
7717 (Name => Source.File,
7718 Location => No_Location,
7720 Except => Source.Unit /= No_Unit_Index,
7723 -- If this is an Ada exception, record in table Unit_Exceptions
7725 if Source.Unit /= No_Unit_Index then
7727 Unit_Except : Unit_Exception :=
7728 Unit_Exceptions.Get (Source.Unit.Name);
7731 Unit_Except.Name := Source.Unit.Name;
7733 if Source.Kind = Spec then
7734 Unit_Except.Spec := Source.File;
7736 Unit_Except.Impl := Source.File;
7739 Unit_Exceptions.Set (Source.Unit.Name, Unit_Except);
7745 end Load_Naming_Exceptions;
7747 ----------------------
7748 -- Look_For_Sources --
7749 ----------------------
7751 procedure Look_For_Sources
7752 (Project : Project_Id;
7753 In_Tree : Project_Tree_Ref;
7754 Proc_Data : in out Processing_Data;
7755 Allow_Duplicate_Basenames : Boolean)
7757 Iter : Source_Iterator;
7759 procedure Process_Sources_In_Multi_Language_Mode;
7760 -- Find all source files when in multi language mode
7762 procedure Mark_Excluded_Sources;
7763 -- Mark as such the sources that are declared as excluded
7765 ---------------------------
7766 -- Mark_Excluded_Sources --
7767 ---------------------------
7769 procedure Mark_Excluded_Sources is
7770 Source : Source_Id := No_Source;
7772 Excluded : File_Found;
7775 Excluded := Excluded_Sources_Htable.Get_First;
7776 while Excluded /= No_File_Found loop
7779 -- ??? Don't we have a hash table to map files to Source_Id?
7780 -- ??? Why can't simply iterate over the sources of the current
7781 -- project, as opposed to the whole tree ?
7783 Iter := For_Each_Source (In_Tree);
7785 Source := Prj.Element (Iter);
7786 exit when Source = No_Source;
7788 if Source.File = Excluded.File then
7789 if Source.Project = Project
7790 or else Is_Extending (Project, Source.Project)
7793 Source.Locally_Removed := True;
7794 Source.In_Interfaces := False;
7796 if Current_Verbosity = High then
7797 Write_Str ("Removing file ");
7799 (Get_Name_String (Excluded.File)
7800 & " " & Get_Name_String (Source.Project.Name));
7806 "cannot remove a source from another project",
7810 -- We used to exit here, but in fact when a source is
7811 -- overridden in an extended project we have only marked the
7812 -- original source file if we stop here, not the one from
7813 -- the extended project.
7814 -- ??? We could exit (and thus be faster) if the loop could
7815 -- be done only on the current project, but this isn't
7816 -- compatible with the way gprbuild works with excluded
7817 -- sources apparently
7825 OK := OK or Excluded.Found;
7828 Err_Vars.Error_Msg_File_1 := Excluded.File;
7830 (Project, In_Tree, "unknown file {", Excluded.Location);
7833 Excluded := Excluded_Sources_Htable.Get_Next;
7835 end Mark_Excluded_Sources;
7837 --------------------------------------------
7838 -- Process_Sources_In_Multi_Language_Mode --
7839 --------------------------------------------
7841 procedure Process_Sources_In_Multi_Language_Mode is
7842 Iter : Source_Iterator;
7845 -- Check that two sources of this project do not have the same object
7848 Check_Object_File_Names : declare
7850 Source_Name : File_Name_Type;
7852 procedure Check_Object (Src : Source_Id);
7853 -- Check if object file name of the current source is already in
7854 -- hash table Object_File_Names. If it is, report an error. If it
7855 -- is not, put it there with the file name of the current source.
7861 procedure Check_Object (Src : Source_Id) is
7863 Source_Name := Object_File_Names.Get (Src.Object);
7865 if Source_Name /= No_File then
7866 Error_Msg_File_1 := Src.File;
7867 Error_Msg_File_2 := Source_Name;
7871 "{ and { have the same object file name",
7875 Object_File_Names.Set (Src.Object, Src.File);
7879 -- Start of processing for Check_Object_File_Names
7882 Object_File_Names.Reset;
7883 Iter := For_Each_Source (In_Tree);
7885 Src_Id := Prj.Element (Iter);
7886 exit when Src_Id = No_Source;
7888 if Is_Compilable (Src_Id)
7889 and then Src_Id.Language.Config.Object_Generated
7890 and then Is_Extending (Project, Src_Id.Project)
7892 if Src_Id.Unit = No_Unit_Index then
7893 if Src_Id.Kind = Impl then
7894 Check_Object (Src_Id);
7900 if Other_Part (Src_Id) = No_Source then
7901 Check_Object (Src_Id);
7908 if Other_Part (Src_Id) /= No_Source then
7909 Check_Object (Src_Id);
7912 -- Check if it is a subunit
7915 Src_Ind : constant Source_File_Index :=
7916 Sinput.P.Load_Project_File
7918 (Src_Id.Path.Name));
7920 if Sinput.P.Source_File_Is_Subunit
7923 Override_Kind (Src_Id, Sep);
7925 Check_Object (Src_Id);
7935 end Check_Object_File_Names;
7936 end Process_Sources_In_Multi_Language_Mode;
7938 -- Start of processing for Look_For_Sources
7942 Find_Excluded_Sources (Project, In_Tree);
7944 if (Get_Mode = Ada_Only and then Is_A_Language (Project, Name_Ada))
7945 or else (Get_Mode = Multi_Language
7946 and then Project.Languages /= No_Language_Index)
7948 if Get_Mode = Multi_Language then
7949 Load_Naming_Exceptions (Project, In_Tree);
7952 Find_Sources (Project, In_Tree, Proc_Data, Allow_Duplicate_Basenames);
7953 Mark_Excluded_Sources;
7955 if Get_Mode = Multi_Language then
7956 Process_Sources_In_Multi_Language_Mode;
7959 end Look_For_Sources;
7965 function Path_Name_Of
7966 (File_Name : File_Name_Type;
7967 Directory : Path_Name_Type) return String
7969 Result : String_Access;
7970 The_Directory : constant String := Get_Name_String (Directory);
7973 Get_Name_String (File_Name);
7976 (File_Name => Name_Buffer (1 .. Name_Len),
7977 Path => The_Directory);
7979 if Result = null then
7983 R : String := Result.all;
7986 Canonical_Case_File_Name (R);
7992 -----------------------------------
7993 -- Prepare_Ada_Naming_Exceptions --
7994 -----------------------------------
7996 procedure Prepare_Ada_Naming_Exceptions
7997 (List : Array_Element_Id;
7998 In_Tree : Project_Tree_Ref;
7999 Kind : Spec_Or_Body)
8001 Current : Array_Element_Id;
8002 Element : Array_Element;
8006 -- Traverse the list
8009 while Current /= No_Array_Element loop
8010 Element := In_Tree.Array_Elements.Table (Current);
8012 if Element.Index /= No_Name then
8015 Unit => Element.Index,
8016 Next => No_Ada_Naming_Exception);
8017 Reverse_Ada_Naming_Exceptions.Set
8018 (Unit, (Element.Value.Value, Element.Value.Index));
8020 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8021 Ada_Naming_Exception_Table.Increment_Last;
8022 Ada_Naming_Exception_Table.Table
8023 (Ada_Naming_Exception_Table.Last) := Unit;
8024 Ada_Naming_Exceptions.Set
8025 (File_Name_Type (Element.Value.Value),
8026 Ada_Naming_Exception_Table.Last);
8029 Current := Element.Next;
8031 end Prepare_Ada_Naming_Exceptions;
8033 -----------------------
8034 -- Record_Ada_Source --
8035 -----------------------
8037 procedure Record_Ada_Source
8038 (File_Name : File_Name_Type;
8039 Path_Name : Path_Name_Type;
8040 Project : Project_Id;
8041 In_Tree : Project_Tree_Ref;
8042 Proc_Data : in out Processing_Data;
8043 Ada_Language : Language_Ptr;
8044 Location : Source_Ptr;
8045 Source_Recorded : in out Boolean)
8047 Canonical_File : File_Name_Type;
8048 Canonical_Path : Path_Name_Type;
8050 File_Recorded : Boolean := False;
8051 -- True when at least one file has been recorded
8053 procedure Record_Unit
8054 (Unit_Name : Name_Id;
8055 Unit_Ind : Int := 0;
8056 Unit_Kind : Spec_Or_Body;
8057 Needs_Pragma : Boolean);
8058 -- Register of the units contained in the source file (there is in
8059 -- general a single such unit except when exceptions to the naming
8060 -- scheme indicate there are several such units)
8066 procedure Record_Unit
8067 (Unit_Name : Name_Id;
8068 Unit_Ind : Int := 0;
8069 Unit_Kind : Spec_Or_Body;
8070 Needs_Pragma : Boolean)
8072 UData : constant Unit_Index :=
8073 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
8074 -- ??? Add_Source will look it up again, can we do that only once ?
8077 To_Record : Boolean := False;
8078 The_Location : Source_Ptr := Location;
8079 Unit_Prj : Project_Id;
8082 if Current_Verbosity = High then
8083 Write_Str (" Putting ");
8084 Write_Str (Get_Name_String (Unit_Name));
8085 Write_Line (" in the unit list.");
8088 -- The unit is already in the list, but may be it is only the other
8089 -- unit kind (spec or body), or what is in the unit list is a unit of
8090 -- a project we are extending.
8092 if UData /= No_Unit_Index then
8093 if UData.File_Names (Unit_Kind) = null
8095 (UData.File_Names (Unit_Kind).File = Canonical_File
8096 and then UData.File_Names (Unit_Kind).Locally_Removed)
8097 or else Is_Extending
8098 (Project.Extends, UData.File_Names (Unit_Kind).Project)
8102 -- If the same file is already in the list, do not add it again
8104 elsif UData.File_Names (Unit_Kind).Project = Project
8106 (Project.Known_Order_Of_Source_Dirs
8108 UData.File_Names (Unit_Kind).Path.Name = Canonical_Path)
8112 -- Else, same unit but not same file => It is an error to have two
8113 -- units with the same name and the same kind (spec or body).
8116 if The_Location = No_Location then
8117 The_Location := Project.Location;
8120 Err_Vars.Error_Msg_Name_1 := Unit_Name;
8122 (Project, In_Tree, "duplicate unit %%", The_Location);
8124 Err_Vars.Error_Msg_Name_1 :=
8125 UData.File_Names (Unit_Kind).Project.Name;
8126 Err_Vars.Error_Msg_File_1 :=
8127 File_Name_Type (UData.File_Names (Unit_Kind).Path.Name);
8130 "\ project file %%, {", The_Location);
8132 Err_Vars.Error_Msg_Name_1 := Project.Name;
8133 Err_Vars.Error_Msg_File_1 := File_Name_Type (Canonical_Path);
8135 (Project, In_Tree, "\ project file %%, {", The_Location);
8140 -- It is a new unit, create a new record
8143 -- First, check if there is no other unit with this file name in
8144 -- another project. If it is, report error but note we do that
8145 -- only for the first unit in the source file.
8147 Unit_Prj := Files_Htable.Get (Proc_Data.Units, Canonical_File);
8149 if not File_Recorded
8150 and then Unit_Prj /= No_Project
8152 Error_Msg_File_1 := File_Name;
8153 Error_Msg_Name_1 := Unit_Prj.Name;
8156 "{ is already a source of project %%",
8165 Files_Htable.Set (Proc_Data.Units, Canonical_File, Project);
8170 Lang_Id => Ada_Language,
8171 File_Name => Canonical_File,
8172 Display_File => File_Name,
8174 Path => (Canonical_Path, Path_Name),
8175 Naming_Exception => Needs_Pragma,
8178 Source_Recorded := True;
8182 Exception_Id : Ada_Naming_Exception_Id;
8183 Unit_Name : Name_Id;
8184 Unit_Kind : Spec_Or_Body;
8185 Unit_Ind : Int := 0;
8187 Name_Index : Name_And_Index;
8188 Except_Name : Name_And_Index := No_Name_And_Index;
8189 Needs_Pragma : Boolean;
8192 Canonical_File := Canonical_Case_File_Name (Name_Id (File_Name));
8194 Path_Name_Type (Canonical_Case_File_Name (Name_Id (Path_Name)));
8196 -- Check the naming scheme to get extra file properties
8199 (In_Tree => In_Tree,
8200 Canonical_File_Name => Canonical_File,
8202 Exception_Id => Exception_Id,
8203 Unit_Name => Unit_Name,
8204 Unit_Kind => Unit_Kind);
8206 Needs_Pragma := Exception_Id /= No_Ada_Naming_Exception;
8208 if Exception_Id = No_Ada_Naming_Exception
8209 and then Unit_Name = No_Name
8211 if Current_Verbosity = High then
8213 Write_Str (Get_Name_String (Canonical_File));
8214 Write_Line (""" is not a valid source file name (ignored).");
8219 -- Check to see if the source has been hidden by an exception,
8220 -- but only if it is not an exception.
8222 if not Needs_Pragma then
8224 Reverse_Ada_Naming_Exceptions.Get
8225 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
8227 if Except_Name /= No_Name_And_Index then
8228 if Current_Verbosity = High then
8230 Write_Str (Get_Name_String (Canonical_File));
8231 Write_Str (""" contains a unit that is found in """);
8232 Write_Str (Get_Name_String (Except_Name.Name));
8233 Write_Line (""" (ignored).");
8236 -- The file is not included in the source of the project since it
8237 -- is hidden by the exception. So, nothing else to do.
8243 -- The following loop registers the unit in the appropriate table. It
8244 -- will be executed multiple times when the file is a multi-unit file,
8245 -- in which case Exception_Id initially points to the first file and
8246 -- then to each other unit in the file.
8249 if Exception_Id /= No_Ada_Naming_Exception then
8250 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
8251 Exception_Id := Info.Next;
8252 Info.Next := No_Ada_Naming_Exception;
8253 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
8255 Unit_Name := Info.Unit;
8256 Unit_Ind := Name_Index.Index;
8257 Unit_Kind := Info.Kind;
8260 Record_Unit (Unit_Name, Unit_Ind, Unit_Kind, Needs_Pragma);
8261 File_Recorded := True;
8263 exit when Exception_Id = No_Ada_Naming_Exception;
8265 end Record_Ada_Source;
8271 procedure Remove_Source
8273 Replaced_By : Source_Id)
8278 if Current_Verbosity = High then
8279 Write_Str ("Removing source ");
8280 Write_Line (Get_Name_String (Id.File));
8283 if Replaced_By /= No_Source then
8284 Id.Replaced_By := Replaced_By;
8285 Replaced_By.Declared_In_Interfaces := Id.Declared_In_Interfaces;
8288 Id.In_Interfaces := False;
8289 Id.Locally_Removed := True;
8291 -- ??? Should we remove the source from the unit ? The file is not used,
8292 -- so probably should not be referenced from the unit. On the other hand
8293 -- it might give useful additional info
8294 -- if Id.Unit /= null then
8295 -- Id.Unit.File_Names (Id.Kind) := null;
8298 Source := Id.Language.First_Source;
8301 Id.Language.First_Source := Id.Next_In_Lang;
8304 while Source.Next_In_Lang /= Id loop
8305 Source := Source.Next_In_Lang;
8308 Source.Next_In_Lang := Id.Next_In_Lang;
8312 -----------------------
8313 -- Report_No_Sources --
8314 -----------------------
8316 procedure Report_No_Sources
8317 (Project : Project_Id;
8319 In_Tree : Project_Tree_Ref;
8320 Location : Source_Ptr;
8321 Continuation : Boolean := False)
8324 case When_No_Sources is
8328 when Warning | Error =>
8330 Msg : constant String :=
8333 " sources in this project";
8336 Error_Msg_Warn := When_No_Sources = Warning;
8338 if Continuation then
8339 Error_Msg (Project, In_Tree, "\" & Msg, Location);
8341 Error_Msg (Project, In_Tree, Msg, Location);
8345 end Report_No_Sources;
8347 ----------------------
8348 -- Show_Source_Dirs --
8349 ----------------------
8351 procedure Show_Source_Dirs
8352 (Project : Project_Id;
8353 In_Tree : Project_Tree_Ref)
8355 Current : String_List_Id;
8356 Element : String_Element;
8359 Write_Line ("Source_Dirs:");
8361 Current := Project.Source_Dirs;
8362 while Current /= Nil_String loop
8363 Element := In_Tree.String_Elements.Table (Current);
8365 Write_Line (Get_Name_String (Element.Value));
8366 Current := Element.Next;
8369 Write_Line ("end Source_Dirs.");
8370 end Show_Source_Dirs;
8372 -------------------------
8373 -- Warn_If_Not_Sources --
8374 -------------------------
8376 -- comments needed in this body ???
8378 procedure Warn_If_Not_Sources
8379 (Project : Project_Id;
8380 In_Tree : Project_Tree_Ref;
8381 Conventions : Array_Element_Id;
8383 Extending : Boolean)
8385 Conv : Array_Element_Id;
8387 The_Unit_Data : Unit_Index;
8388 Location : Source_Ptr;
8391 Conv := Conventions;
8392 while Conv /= No_Array_Element loop
8393 Unit := In_Tree.Array_Elements.Table (Conv).Index;
8394 Error_Msg_Name_1 := Unit;
8395 Get_Name_String (Unit);
8396 To_Lower (Name_Buffer (1 .. Name_Len));
8398 The_Unit_Data := Units_Htable.Get (In_Tree.Units_HT, Unit);
8399 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
8401 if The_Unit_Data = No_Unit_Index then
8402 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
8406 In_Tree.Array_Elements.Table (Conv).Value.Value;
8409 if not Check_Project
8410 (The_Unit_Data.File_Names (Spec).Project,
8415 "?source of spec of unit %% (%%)" &
8416 " not found in this project",
8421 if The_Unit_Data.File_Names (Impl) = null
8422 or else not Check_Project
8423 (The_Unit_Data.File_Names (Impl).Project,
8428 "?source of body of unit %% (%%)" &
8429 " not found in this project",
8435 Conv := In_Tree.Array_Elements.Table (Conv).Next;
8437 end Warn_If_Not_Sources;