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 -- More documentation needed on what unit exceptions are about ???
99 type Unit_Exception is record
101 Spec : File_Name_Type;
102 Impl : File_Name_Type;
104 -- Record special naming schemes for Ada units (name of spec file and name
105 -- of implementation file).
107 No_Unit_Exception : constant Unit_Exception :=
112 package Unit_Exceptions is new GNAT.HTable.Simple_HTable
113 (Header_Num => Header_Num,
114 Element => Unit_Exception,
115 No_Element => No_Unit_Exception,
119 -- Hash table to store the unit exceptions.
120 -- ??? Seems to be used only by the multi_lang mode
121 -- ??? Should not be a global array, but stored in the project_data
123 package Recursive_Dirs is new GNAT.HTable.Simple_HTable
124 (Header_Num => Header_Num,
130 -- Hash table to store recursive source directories, to avoid looking
131 -- several times, and to avoid cycles that may be introduced by symbolic
134 type Ada_Naming_Exception_Id is new Nat;
135 No_Ada_Naming_Exception : constant Ada_Naming_Exception_Id := 0;
137 type Unit_Info is record
140 Next : Ada_Naming_Exception_Id := No_Ada_Naming_Exception;
144 package Ada_Naming_Exception_Table is new Table.Table
145 (Table_Component_Type => Unit_Info,
146 Table_Index_Type => Ada_Naming_Exception_Id,
147 Table_Low_Bound => 1,
149 Table_Increment => 100,
150 Table_Name => "Prj.Nmsc.Ada_Naming_Exception_Table");
152 package Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
153 (Header_Num => Header_Num,
154 Element => Ada_Naming_Exception_Id,
155 No_Element => No_Ada_Naming_Exception,
156 Key => File_Name_Type,
159 -- A hash table to store naming exceptions for Ada. For each file name
160 -- there is one or several unit in table Ada_Naming_Exception_Table.
161 -- ??? This is for ada_only mode, we should be able to merge with
162 -- Unit_Exceptions table, used by multi_lang mode.
164 package Object_File_Names is new GNAT.HTable.Simple_HTable
165 (Header_Num => Header_Num,
166 Element => File_Name_Type,
167 No_Element => No_File,
168 Key => File_Name_Type,
171 -- A hash table to store the object file names for a project, to check that
172 -- two different sources have different object file names.
174 type File_Found is record
175 File : File_Name_Type := No_File;
176 Found : Boolean := False;
177 Location : Source_Ptr := No_Location;
179 No_File_Found : constant File_Found := (No_File, False, No_Location);
180 -- Comments needed ???
182 package Excluded_Sources_Htable is new GNAT.HTable.Simple_HTable
183 (Header_Num => Header_Num,
184 Element => File_Found,
185 No_Element => No_File_Found,
186 Key => File_Name_Type,
189 -- A hash table to store the excluded files, if any. This is filled by
190 -- Find_Excluded_Sources below.
192 procedure Find_Excluded_Sources
193 (Project : Project_Id;
194 In_Tree : Project_Tree_Ref);
195 -- Find the list of files that should not be considered as source files
196 -- for this project. Sets the list in the Excluded_Sources_Htable.
198 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind);
199 -- Override the reference kind for a source file. This properly updates
200 -- the unit data if necessary.
202 function Hash (Unit : Unit_Info) return Header_Num;
204 type Name_And_Index is record
205 Name : Name_Id := No_Name;
208 No_Name_And_Index : constant Name_And_Index :=
209 (Name => No_Name, Index => 0);
210 -- Name of a unit, and its index inside the source file. The first unit has
211 -- index 1 (see doc for pragma Source_File_Name), but the index might be
212 -- set to 0 when the source file contains a single unit.
214 package Reverse_Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
215 (Header_Num => Header_Num,
216 Element => Name_And_Index,
217 No_Element => No_Name_And_Index,
221 -- A table to check if a unit with an exceptional name will hide a source
222 -- with a file name following the naming convention.
224 procedure Load_Naming_Exceptions
225 (Project : Project_Id;
226 In_Tree : Project_Tree_Ref);
227 -- All source files in Data.First_Source are considered as naming
228 -- exceptions, and copied into the Source_Names and Unit_Exceptions tables
233 In_Tree : Project_Tree_Ref;
234 Project : Project_Id;
235 Lang_Id : Language_Ptr;
237 File_Name : File_Name_Type;
238 Display_File : File_Name_Type;
239 Naming_Exception : Boolean := False;
240 Path : Path_Information := No_Path_Information;
241 Alternate_Languages : Language_List := null;
242 Unit : Name_Id := No_Name;
244 Source_To_Replace : Source_Id := No_Source);
245 -- Add a new source to the different lists: list of all sources in the
246 -- project tree, list of source of a project and list of sources of a
249 -- If Path is specified, the file is also added to Source_Paths_HT.
250 -- If Source_To_Replace is specified, it points to the source in the
251 -- extended project that the new file is overriding.
253 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type;
254 -- Same as Osint.Canonical_Case_File_Name but applies to Name_Id.
255 -- This alters Name_Buffer
257 function Suffix_Matches
259 Suffix : File_Name_Type) return Boolean;
260 -- True if the file name ends with the given suffix. Always returns False
261 -- if Suffix is No_Name.
263 procedure Replace_Into_Name_Buffer
266 Replacement : Character);
267 -- Copy Str into Name_Buffer, replacing Pattern with Replacement. Str is
268 -- converted to lower-case at the same time.
270 function ALI_File_Name (Source : String) return String;
271 -- Return the ALI file name corresponding to a source
273 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
274 -- Check that a name is a valid Ada unit name
276 procedure Check_Package_Naming
277 (Project : Project_Id;
278 In_Tree : Project_Tree_Ref;
279 Is_Config_File : Boolean;
280 Bodies : out Array_Element_Id;
281 Specs : out Array_Element_Id);
282 -- Check the naming scheme part of Data, and initialize the naming scheme
283 -- data in the config of the various languages.
284 -- Is_Config_File should be True if Project is a config file (.cgpr)
285 -- This also returns the naming scheme exceptions for unit-based
286 -- languages (Bodies and Specs are associative arrays mapping individual
287 -- unit names to source file names).
289 procedure Check_Configuration
290 (Project : Project_Id;
291 In_Tree : Project_Tree_Ref;
292 Compiler_Driver_Mandatory : Boolean);
293 -- Check the configuration attributes for the project
294 -- If Compiler_Driver_Mandatory is true, then a Compiler.Driver attribute
295 -- for each language must be defined, or we will not look for its source
298 procedure Check_If_Externally_Built
299 (Project : Project_Id;
300 In_Tree : Project_Tree_Ref);
301 -- Check attribute Externally_Built of project Project in project tree
302 -- In_Tree and modify its data Data if it has the value "true".
304 procedure Check_Interfaces
305 (Project : Project_Id;
306 In_Tree : Project_Tree_Ref);
307 -- If a list of sources is specified in attribute Interfaces, set
308 -- In_Interfaces only for the sources specified in the list.
310 procedure Check_Library_Attributes
311 (Project : Project_Id;
312 In_Tree : Project_Tree_Ref);
313 -- Check the library attributes of project Project in project tree In_Tree
314 -- and modify its data Data accordingly.
315 -- Current_Dir should represent the current directory, and is passed for
316 -- efficiency to avoid system calls to recompute it.
318 procedure Check_Programming_Languages
319 (In_Tree : Project_Tree_Ref;
320 Project : Project_Id);
321 -- Check attribute Languages for the project with data Data in project
322 -- tree In_Tree and set the components of Data for all the programming
323 -- languages indicated in attribute Languages, if any.
325 function Check_Project
327 Root_Project : Project_Id;
328 Extending : Boolean) return Boolean;
329 -- Returns True if P is Root_Project or, if Extending is True, a project
330 -- extended by Root_Project.
332 procedure Check_Stand_Alone_Library
333 (Project : Project_Id;
334 In_Tree : Project_Tree_Ref;
335 Current_Dir : String;
336 Extending : Boolean);
337 -- Check if project Project in project tree In_Tree is a Stand-Alone
338 -- Library project, and modify its data Data accordingly if it is one.
339 -- Current_Dir should represent the current directory, and is passed for
340 -- efficiency to avoid system calls to recompute it.
342 procedure Check_And_Normalize_Unit_Names
343 (Project : Project_Id;
344 In_Tree : Project_Tree_Ref;
345 List : Array_Element_Id;
346 Debug_Name : String);
347 -- Check that a list of unit names contains only valid names. Casing
348 -- is normalized where appropriate.
349 -- Debug_Name is the name representing the list, and is used for debug
352 procedure Find_Ada_Sources
353 (Project : Project_Id;
354 In_Tree : Project_Tree_Ref;
355 Explicit_Sources_Only : Boolean;
356 Proc_Data : in out Processing_Data);
357 -- Find all Ada sources by traversing all source directories. If
358 -- Explicit_Sources_Only is True, then the sources found must belong to
359 -- the list of sources specified explicitly in the project file. If
360 -- Explicit_Sources_Only is False, then all sources matching the naming
361 -- scheme are recorded.
363 function Compute_Directory_Last (Dir : String) return Natural;
364 -- Return the index of the last significant character in Dir. This is used
365 -- to avoid duplicate '/' (slash) characters at the end of directory names.
368 (Project : Project_Id;
369 In_Tree : Project_Tree_Ref;
371 Flag_Location : Source_Ptr);
372 -- Output an error message. If Error_Report is null, simply call
373 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
376 procedure Search_Directories
377 (Project : Project_Id;
378 In_Tree : Project_Tree_Ref;
379 For_All_Sources : Boolean;
380 Allow_Duplicate_Basenames : Boolean);
381 -- Search the source directories to find the sources. If For_All_Sources is
382 -- True, check each regular file name against the naming schemes of the
383 -- different languages. Otherwise consider only the file names in the hash
384 -- table Source_Names. If Allow_Duplicate_Basenames, then files with the
385 -- same base names are authorized within a project for source-based
386 -- languages (never for unit based languages)
389 (Project : Project_Id;
390 In_Tree : Project_Tree_Ref;
391 Path : Path_Name_Type;
392 File_Name : File_Name_Type;
393 Display_File_Name : File_Name_Type;
394 For_All_Sources : Boolean;
395 Allow_Duplicate_Basenames : Boolean);
396 -- Check if file File_Name is a valid source of the project. This is used
397 -- in multi-language mode only. When the file matches one of the naming
398 -- schemes, it is added to various htables through Add_Source and to
399 -- Source_Paths_Htable.
401 -- Name is the name of the candidate file. It hasn't been normalized yet
402 -- and is the direct result of readdir().
404 -- File_Name is the same as Name, but has been normalized.
405 -- Display_File_Name, however, has not been normalized.
407 -- Source_Directory is the directory in which the file
408 -- was found. It hasn't been normalized (nor has had links resolved).
409 -- It should not end with a directory separator, to avoid duplicates
412 -- If For_All_Sources is True, then all possible file names are analyzed
413 -- otherwise only those currently set in the Source_Names htable.
415 -- If Allow_Duplicate_Basenames, then files with the same base names are
416 -- authorized within a project for source-based languages (never for unit
419 procedure Check_File_Naming_Schemes
420 (In_Tree : Project_Tree_Ref;
421 Project : Project_Id;
422 File_Name : File_Name_Type;
423 Alternate_Languages : out Language_List;
424 Language : out Language_Ptr;
425 Display_Language_Name : out Name_Id;
427 Lang_Kind : out Language_Kind;
428 Kind : out Source_Kind);
429 -- Check if the file name File_Name conforms to one of the naming
430 -- schemes of the project.
432 -- If the file does not match one of the naming schemes, set Language
433 -- to No_Language_Index.
435 -- Filename is the name of the file being investigated. It has been
436 -- normalized (case-folded). File_Name is the same value.
438 procedure Free_Ada_Naming_Exceptions;
439 -- Free the internal hash tables used for checking naming exceptions
441 procedure Get_Directories
442 (Project : Project_Id;
443 In_Tree : Project_Tree_Ref;
444 Current_Dir : String);
445 -- Get the object directory, the exec directory and the source directories
448 -- Current_Dir should represent the current directory, and is passed for
449 -- efficiency to avoid system calls to recompute it.
452 (Project : Project_Id;
453 In_Tree : Project_Tree_Ref);
454 -- Get the mains of a project from attribute Main, if it exists, and put
455 -- them in the project data.
457 procedure Get_Sources_From_File
459 Location : Source_Ptr;
460 Project : Project_Id;
461 In_Tree : Project_Tree_Ref);
462 -- Get the list of sources from a text file and put them in hash table
465 procedure Find_Sources
466 (Project : Project_Id;
467 In_Tree : Project_Tree_Ref;
468 Proc_Data : in out Processing_Data;
469 Allow_Duplicate_Basenames : Boolean);
470 -- Process the Source_Files and Source_List_File attributes, and store
471 -- the list of source files into the Source_Names htable.
472 -- When these attributes are not defined, find all files matching the
473 -- naming schemes in the source directories.
474 -- If Allow_Duplicate_Basenames, then files with the same base names are
475 -- authorized within a project for source-based languages (never for unit
478 procedure Compute_Unit_Name
479 (File_Name : File_Name_Type;
480 Naming : Lang_Naming_Data;
481 Kind : out Source_Kind;
483 In_Tree : Project_Tree_Ref);
484 -- Check whether the file matches the naming scheme. If it does,
485 -- compute its unit name. If Unit is set to No_Name on exit, none of the
486 -- other out parameters are relevant.
489 (In_Tree : Project_Tree_Ref;
490 Canonical_File_Name : File_Name_Type;
491 Project : Project_Id;
492 Exception_Id : out Ada_Naming_Exception_Id;
493 Unit_Name : out Name_Id;
494 Unit_Kind : out Spec_Or_Body);
495 -- Find out, from a file name, the unit name, the unit kind and if a
496 -- specific SFN pragma is needed. If the file name corresponds to no unit,
497 -- then Unit_Name will be No_Name. If the file is a multi-unit source or an
498 -- exception to the naming scheme, then Exception_Id is set to the unit or
499 -- units that the source contains, and the other information are not set.
501 function Is_Illegal_Suffix
502 (Suffix : File_Name_Type;
503 Dot_Replacement : File_Name_Type) return Boolean;
504 -- Returns True if the string Suffix cannot be used as a spec suffix, a
505 -- body suffix or a separate suffix.
507 procedure Locate_Directory
508 (Project : Project_Id;
509 In_Tree : Project_Tree_Ref;
510 Name : File_Name_Type;
511 Path : out Path_Information;
512 Dir_Exists : out Boolean;
513 Create : String := "";
514 Location : Source_Ptr := No_Location;
515 Must_Exist : Boolean := True;
516 Externally_Built : Boolean := False);
517 -- Locate a directory. Name is the directory name.
518 -- Relative paths are resolved relative to the project's directory.
519 -- If the directory does not exist and Setup_Projects
520 -- is True and Create is a non null string, an attempt is made to create
522 -- If the directory does not exist, it is either created if Setup_Projects
523 -- is False (and then returned), or simply returned without checking for
524 -- its existence (if Must_Exist is False) or No_Path_Information is
525 -- returned. In all cases, Dir_Exists indicates whether the directory now
528 -- Create is also used for debugging traces to show which path we are
531 procedure Look_For_Sources
532 (Project : Project_Id;
533 In_Tree : Project_Tree_Ref;
534 Proc_Data : in out Processing_Data;
535 Allow_Duplicate_Basenames : Boolean);
536 -- Find all the sources of project Project in project tree In_Tree and
537 -- update its Data accordingly. This assumes that Data.First_Source has
538 -- been initialized with the list of excluded sources and special naming
539 -- exceptions. If Allow_Duplicate_Basenames, then files with the same base
540 -- names are authorized within a project for source-based languages (never
541 -- for unit based languages)
543 function Path_Name_Of
544 (File_Name : File_Name_Type;
545 Directory : Path_Name_Type) return String;
546 -- Returns the path name of a (non project) file. Returns an empty string
547 -- if file cannot be found.
549 procedure Prepare_Ada_Naming_Exceptions
550 (List : Array_Element_Id;
551 In_Tree : Project_Tree_Ref;
552 Kind : Spec_Or_Body);
553 -- Prepare the internal hash tables used for checking naming exceptions
554 -- for Ada. Insert all elements of List in the tables.
556 procedure Record_Ada_Source
557 (File_Name : File_Name_Type;
558 Path_Name : Path_Name_Type;
559 Project : Project_Id;
560 In_Tree : Project_Tree_Ref;
561 Proc_Data : in out Processing_Data;
562 Ada_Language : Language_Ptr;
563 Location : Source_Ptr;
564 Source_Recorded : in out Boolean);
565 -- Put a unit in the list of units of a project, if the file name
566 -- corresponds to a valid unit name. Ada_Language is a pointer to the
567 -- Language_Data for "Ada" in Project.
569 procedure Remove_Source
571 Replaced_By : Source_Id);
574 procedure Report_No_Sources
575 (Project : Project_Id;
577 In_Tree : Project_Tree_Ref;
578 Location : Source_Ptr;
579 Continuation : Boolean := False);
580 -- Report an error or a warning depending on the value of When_No_Sources
581 -- when there are no sources for language Lang_Name.
583 procedure Show_Source_Dirs
584 (Project : Project_Id; In_Tree : Project_Tree_Ref);
585 -- List all the source directories of a project
587 procedure Warn_If_Not_Sources
588 (Project : Project_Id;
589 In_Tree : Project_Tree_Ref;
590 Conventions : Array_Element_Id;
592 Extending : Boolean);
593 -- Check that individual naming conventions apply to immediate sources of
594 -- the project. If not, issue a warning.
596 procedure Write_Attr (Name, Value : String);
597 -- Debug print a value for a specific property. Does nothing when not in
600 ------------------------------
601 -- Replace_Into_Name_Buffer --
602 ------------------------------
604 procedure Replace_Into_Name_Buffer
607 Replacement : Character)
609 Max : constant Integer := Str'Last - Pattern'Length + 1;
616 while J <= Str'Last loop
617 Name_Len := Name_Len + 1;
620 and then Str (J .. J + Pattern'Length - 1) = Pattern
622 Name_Buffer (Name_Len) := Replacement;
623 J := J + Pattern'Length;
626 Name_Buffer (Name_Len) := GNAT.Case_Util.To_Lower (Str (J));
630 end Replace_Into_Name_Buffer;
636 function Suffix_Matches
638 Suffix : File_Name_Type) return Boolean
640 Min_Prefix_Length : Natural := 0;
642 if Suffix = No_File or else Suffix = Empty_File then
647 Suf : constant String := Get_Name_String (Suffix);
650 -- The file name must end with the suffix (which is not an extension)
651 -- For instance a suffix "configure.in" must match a file with the
652 -- same name. To avoid dummy cases, though, a suffix starting with
653 -- '.' requires a file that is at least one character longer ('.cpp'
654 -- should not match a file with the same name)
656 if Suf (Suf'First) = '.' then
657 Min_Prefix_Length := 1;
660 return Filename'Length >= Suf'Length + Min_Prefix_Length
662 (Filename'Last - Suf'Length + 1 .. Filename'Last) = Suf;
670 procedure Write_Attr (Name, Value : String) is
672 if Current_Verbosity = High then
673 Write_Str (" " & Name & " = """);
686 In_Tree : Project_Tree_Ref;
687 Project : Project_Id;
688 Lang_Id : Language_Ptr;
690 File_Name : File_Name_Type;
691 Display_File : File_Name_Type;
692 Naming_Exception : Boolean := False;
693 Path : Path_Information := No_Path_Information;
694 Alternate_Languages : Language_List := null;
695 Unit : Name_Id := No_Name;
697 Source_To_Replace : Source_Id := No_Source)
699 Config : constant Language_Config := Lang_Id.Config;
703 Id := new Source_Data;
705 if Current_Verbosity = High then
706 Write_Str ("Adding source File: ");
707 Write_Str (Get_Name_String (File_Name));
709 if Lang_Id.Config.Kind = Unit_Based then
710 Write_Str (" Unit: ");
711 -- ??? in gprclean, it seems we sometimes pass an empty Unit name
712 -- (see test extended_projects)
713 if Unit /= No_Name then
714 Write_Str (Get_Name_String (Unit));
716 Write_Str (" Kind: ");
717 Write_Str (Source_Kind'Image (Kind));
723 Id.Project := Project;
724 Id.Language := Lang_Id;
726 Id.Alternate_Languages := Alternate_Languages;
728 -- Add the source id to the Unit_Sources_HT hash table, if the unit name
731 if Unit /= No_Name then
732 Unit_Sources_Htable.Set (In_Tree.Unit_Sources_HT, Unit, Id);
734 -- ??? Record_Unit has already fetched that earlier, so this isn't
735 -- the most efficient way. But we can't really pass a parameter since
736 -- Process_Exceptions_Unit_Based and Check_File haven't looked it up.
738 UData := Units_Htable.Get (In_Tree.Units_HT, Unit);
740 if UData = No_Unit_Index then
741 UData := new Unit_Data;
743 Units_Htable.Set (In_Tree.Units_HT, Unit, UData);
748 -- Note that this updates Unit information as well
750 Override_Kind (Id, Kind);
754 Id.File := File_Name;
755 Id.Display_File := Display_File;
756 Id.Dep_Name := Dependency_Name
757 (File_Name, Lang_Id.Config.Dependency_Kind);
758 Id.Naming_Exception := Naming_Exception;
760 if Is_Compilable (Id) and then Config.Object_Generated then
761 Id.Object := Object_Name (File_Name, Config.Object_File_Suffix);
762 Id.Switches := Switches_Name (File_Name);
765 if Path /= No_Path_Information then
767 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path.Name, Id);
770 -- Add the source to the language list
772 Id.Next_In_Lang := Lang_Id.First_Source;
773 Lang_Id.First_Source := Id;
775 if Source_To_Replace /= No_Source then
776 Remove_Source (Source_To_Replace, Id);
784 function ALI_File_Name (Source : String) return String is
786 -- If the source name has extension, replace it with the ALI suffix
788 for Index in reverse Source'First + 1 .. Source'Last loop
789 if Source (Index) = '.' then
790 return Source (Source'First .. Index - 1) & ALI_Suffix;
794 -- If no dot, or if it is the first character, just add the ALI suffix
796 return Source & ALI_Suffix;
799 ------------------------------
800 -- Canonical_Case_File_Name --
801 ------------------------------
803 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type is
805 if Osint.File_Names_Case_Sensitive then
806 return File_Name_Type (Name);
808 Get_Name_String (Name);
809 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
812 end Canonical_Case_File_Name;
819 (Project : Project_Id;
820 In_Tree : Project_Tree_Ref;
821 Report_Error : Put_Line_Access;
822 When_No_Sources : Error_Warning;
823 Current_Dir : String;
824 Proc_Data : in out Processing_Data;
825 Is_Config_File : Boolean;
826 Compiler_Driver_Mandatory : Boolean;
827 Allow_Duplicate_Basenames : Boolean)
829 Specs : Array_Element_Id;
830 Bodies : Array_Element_Id;
831 Extending : Boolean := False;
834 Nmsc.When_No_Sources := When_No_Sources;
835 Error_Report := Report_Error;
837 Recursive_Dirs.Reset;
839 Check_If_Externally_Built (Project, In_Tree);
841 -- Object, exec and source directories
843 Get_Directories (Project, In_Tree, Current_Dir);
845 -- Get the programming languages
847 Check_Programming_Languages (In_Tree, Project);
849 if Project.Qualifier = Dry
850 and then Project.Source_Dirs /= Nil_String
853 Source_Dirs : constant Variable_Value :=
856 Project.Decl.Attributes, In_Tree);
857 Source_Files : constant Variable_Value :=
860 Project.Decl.Attributes, In_Tree);
861 Source_List_File : constant Variable_Value :=
863 (Name_Source_List_File,
864 Project.Decl.Attributes, In_Tree);
865 Languages : constant Variable_Value :=
868 Project.Decl.Attributes, In_Tree);
871 if Source_Dirs.Values = Nil_String
872 and then Source_Files.Values = Nil_String
873 and then Languages.Values = Nil_String
874 and then Source_List_File.Default
876 Project.Source_Dirs := Nil_String;
881 "at least one of Source_Files, Source_Dirs or Languages " &
882 "must be declared empty for an abstract project",
888 -- Check configuration in multi language mode
890 if Must_Check_Configuration then
893 Compiler_Driver_Mandatory => Compiler_Driver_Mandatory);
896 -- Library attributes
898 Check_Library_Attributes (Project, In_Tree);
900 if Current_Verbosity = High then
901 Show_Source_Dirs (Project, In_Tree);
904 Extending := Project.Extends /= No_Project;
906 Check_Package_Naming (Project, In_Tree, Is_Config_File, Bodies, Specs);
908 if Get_Mode = Ada_Only then
909 Prepare_Ada_Naming_Exceptions (Bodies, In_Tree, Impl);
910 Prepare_Ada_Naming_Exceptions (Specs, In_Tree, Spec);
915 if Project.Source_Dirs /= Nil_String then
917 (Project, In_Tree, Proc_Data, Allow_Duplicate_Basenames);
919 if Get_Mode = Ada_Only then
921 -- Check that all individual naming conventions apply to sources
922 -- of this project file.
925 (Project, In_Tree, Bodies,
927 Extending => Extending);
929 (Project, In_Tree, Specs,
931 Extending => Extending);
933 elsif Get_Mode = Multi_Language and then
934 (not Project.Externally_Built) and then
938 Language : Language_Ptr;
940 Alt_Lang : Language_List;
941 Continuation : Boolean := False;
942 Iter : Source_Iterator;
945 Language := Project.Languages;
946 while Language /= No_Language_Index loop
948 -- If there are no sources for this language, check whether
949 -- there are sources for which this is an alternate
952 if Language.First_Source = No_Source then
953 Iter := For_Each_Source (In_Tree => In_Tree,
956 Source := Element (Iter);
957 exit Source_Loop when Source = No_Source
958 or else Source.Language = Language;
960 Alt_Lang := Source.Alternate_Languages;
961 while Alt_Lang /= null loop
962 exit Source_Loop when Alt_Lang.Language = Language;
963 Alt_Lang := Alt_Lang.Next;
967 end loop Source_Loop;
969 if Source = No_Source then
972 Get_Name_String (Language.Display_Name),
976 Continuation := True;
980 Language := Language.Next;
986 if Get_Mode = Multi_Language then
988 -- If a list of sources is specified in attribute Interfaces, set
989 -- In_Interfaces only for the sources specified in the list.
991 Check_Interfaces (Project, In_Tree);
994 -- If it is a library project file, check if it is a standalone library
996 if Project.Library then
997 Check_Stand_Alone_Library
998 (Project, In_Tree, Current_Dir, Extending);
1001 -- Put the list of Mains, if any, in the project data
1003 Get_Mains (Project, In_Tree);
1005 Free_Ada_Naming_Exceptions;
1008 --------------------
1009 -- Check_Ada_Name --
1010 --------------------
1012 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
1013 The_Name : String := Name;
1014 Real_Name : Name_Id;
1015 Need_Letter : Boolean := True;
1016 Last_Underscore : Boolean := False;
1017 OK : Boolean := The_Name'Length > 0;
1020 function Is_Reserved (Name : Name_Id) return Boolean;
1021 function Is_Reserved (S : String) return Boolean;
1022 -- Check that the given name is not an Ada 95 reserved word. The reason
1023 -- for the Ada 95 here is that we do not want to exclude the case of an
1024 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
1025 -- name would be rejected anyway by the compiler. That means there is no
1026 -- requirement that the project file parser reject this.
1032 function Is_Reserved (S : String) return Boolean is
1035 Add_Str_To_Name_Buffer (S);
1036 return Is_Reserved (Name_Find);
1043 function Is_Reserved (Name : Name_Id) return Boolean is
1045 if Get_Name_Table_Byte (Name) /= 0
1046 and then Name /= Name_Project
1047 and then Name /= Name_Extends
1048 and then Name /= Name_External
1049 and then Name not in Ada_2005_Reserved_Words
1053 if Current_Verbosity = High then
1054 Write_Str (The_Name);
1055 Write_Line (" is an Ada reserved word.");
1065 -- Start of processing for Check_Ada_Name
1068 To_Lower (The_Name);
1070 Name_Len := The_Name'Length;
1071 Name_Buffer (1 .. Name_Len) := The_Name;
1073 -- Special cases of children of packages A, G, I and S on VMS
1075 if OpenVMS_On_Target
1076 and then Name_Len > 3
1077 and then Name_Buffer (2 .. 3) = "__"
1079 ((Name_Buffer (1) = 'a') or else
1080 (Name_Buffer (1) = 'g') or else
1081 (Name_Buffer (1) = 'i') or else
1082 (Name_Buffer (1) = 's'))
1084 Name_Buffer (2) := '.';
1085 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
1086 Name_Len := Name_Len - 1;
1089 Real_Name := Name_Find;
1091 if Is_Reserved (Real_Name) then
1095 First := The_Name'First;
1097 for Index in The_Name'Range loop
1100 -- We need a letter (at the beginning, and following a dot),
1101 -- but we don't have one.
1103 if Is_Letter (The_Name (Index)) then
1104 Need_Letter := False;
1109 if Current_Verbosity = High then
1110 Write_Int (Types.Int (Index));
1112 Write_Char (The_Name (Index));
1113 Write_Line ("' is not a letter.");
1119 elsif Last_Underscore
1120 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
1122 -- Two underscores are illegal, and a dot cannot follow
1127 if Current_Verbosity = High then
1128 Write_Int (Types.Int (Index));
1130 Write_Char (The_Name (Index));
1131 Write_Line ("' is illegal here.");
1136 elsif The_Name (Index) = '.' then
1138 -- First, check if the name before the dot is not a reserved word
1139 if Is_Reserved (The_Name (First .. Index - 1)) then
1145 -- We need a letter after a dot
1147 Need_Letter := True;
1149 elsif The_Name (Index) = '_' then
1150 Last_Underscore := True;
1153 -- We need an letter or a digit
1155 Last_Underscore := False;
1157 if not Is_Alphanumeric (The_Name (Index)) then
1160 if Current_Verbosity = High then
1161 Write_Int (Types.Int (Index));
1163 Write_Char (The_Name (Index));
1164 Write_Line ("' is not alphanumeric.");
1172 -- Cannot end with an underscore or a dot
1174 OK := OK and then not Need_Letter and then not Last_Underscore;
1177 if First /= Name'First and then
1178 Is_Reserved (The_Name (First .. The_Name'Last))
1186 -- Signal a problem with No_Name
1192 -------------------------
1193 -- Check_Configuration --
1194 -------------------------
1196 procedure Check_Configuration
1197 (Project : Project_Id;
1198 In_Tree : Project_Tree_Ref;
1199 Compiler_Driver_Mandatory : Boolean)
1201 Dot_Replacement : File_Name_Type := No_File;
1202 Casing : Casing_Type := All_Lower_Case;
1203 Separate_Suffix : File_Name_Type := No_File;
1205 Lang_Index : Language_Ptr := No_Language_Index;
1206 -- The index of the language data being checked
1208 Prev_Index : Language_Ptr := No_Language_Index;
1209 -- The index of the previous language
1211 procedure Process_Project_Level_Simple_Attributes;
1212 -- Process the simple attributes at the project level
1214 procedure Process_Project_Level_Array_Attributes;
1215 -- Process the associate array attributes at the project level
1217 procedure Process_Packages;
1218 -- Read the packages of the project
1220 ----------------------
1221 -- Process_Packages --
1222 ----------------------
1224 procedure Process_Packages is
1225 Packages : Package_Id;
1226 Element : Package_Element;
1228 procedure Process_Binder (Arrays : Array_Id);
1229 -- Process the associate array attributes of package Binder
1231 procedure Process_Builder (Attributes : Variable_Id);
1232 -- Process the simple attributes of package Builder
1234 procedure Process_Compiler (Arrays : Array_Id);
1235 -- Process the associate array attributes of package Compiler
1237 procedure Process_Naming (Attributes : Variable_Id);
1238 -- Process the simple attributes of package Naming
1240 procedure Process_Naming (Arrays : Array_Id);
1241 -- Process the associate array attributes of package Naming
1243 procedure Process_Linker (Attributes : Variable_Id);
1244 -- Process the simple attributes of package Linker of a
1245 -- configuration project.
1247 --------------------
1248 -- Process_Binder --
1249 --------------------
1251 procedure Process_Binder (Arrays : Array_Id) is
1252 Current_Array_Id : Array_Id;
1253 Current_Array : Array_Data;
1254 Element_Id : Array_Element_Id;
1255 Element : Array_Element;
1258 -- Process the associative array attribute of package Binder
1260 Current_Array_Id := Arrays;
1261 while Current_Array_Id /= No_Array loop
1262 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1264 Element_Id := Current_Array.Value;
1265 while Element_Id /= No_Array_Element loop
1266 Element := In_Tree.Array_Elements.Table (Element_Id);
1268 if Element.Index /= All_Other_Names then
1270 -- Get the name of the language
1273 Get_Language_From_Name
1274 (Project, Get_Name_String (Element.Index));
1276 if Lang_Index /= No_Language_Index then
1277 case Current_Array.Name is
1280 -- Attribute Driver (<language>)
1282 Lang_Index.Config.Binder_Driver :=
1283 File_Name_Type (Element.Value.Value);
1285 when Name_Required_Switches =>
1288 Lang_Index.Config.Binder_Required_Switches,
1289 From_List => Element.Value.Values,
1290 In_Tree => In_Tree);
1294 -- Attribute Prefix (<language>)
1296 Lang_Index.Config.Binder_Prefix :=
1297 Element.Value.Value;
1299 when Name_Objects_Path =>
1301 -- Attribute Objects_Path (<language>)
1303 Lang_Index.Config.Objects_Path :=
1304 Element.Value.Value;
1306 when Name_Objects_Path_File =>
1308 -- Attribute Objects_Path (<language>)
1310 Lang_Index.Config.Objects_Path_File :=
1311 Element.Value.Value;
1319 Element_Id := Element.Next;
1322 Current_Array_Id := Current_Array.Next;
1326 ---------------------
1327 -- Process_Builder --
1328 ---------------------
1330 procedure Process_Builder (Attributes : Variable_Id) is
1331 Attribute_Id : Variable_Id;
1332 Attribute : Variable;
1335 -- Process non associated array attribute from package Builder
1337 Attribute_Id := Attributes;
1338 while Attribute_Id /= No_Variable loop
1340 In_Tree.Variable_Elements.Table (Attribute_Id);
1342 if not Attribute.Value.Default then
1343 if Attribute.Name = Name_Executable_Suffix then
1345 -- Attribute Executable_Suffix: the suffix of the
1348 Project.Config.Executable_Suffix :=
1349 Attribute.Value.Value;
1353 Attribute_Id := Attribute.Next;
1355 end Process_Builder;
1357 ----------------------
1358 -- Process_Compiler --
1359 ----------------------
1361 procedure Process_Compiler (Arrays : Array_Id) is
1362 Current_Array_Id : Array_Id;
1363 Current_Array : Array_Data;
1364 Element_Id : Array_Element_Id;
1365 Element : Array_Element;
1366 List : String_List_Id;
1369 -- Process the associative array attribute of package Compiler
1371 Current_Array_Id := Arrays;
1372 while Current_Array_Id /= No_Array loop
1373 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1375 Element_Id := Current_Array.Value;
1376 while Element_Id /= No_Array_Element loop
1377 Element := In_Tree.Array_Elements.Table (Element_Id);
1379 if Element.Index /= All_Other_Names then
1381 -- Get the name of the language
1383 Lang_Index := Get_Language_From_Name
1384 (Project, Get_Name_String (Element.Index));
1386 if Lang_Index /= No_Language_Index then
1387 case Current_Array.Name is
1388 when Name_Dependency_Switches =>
1390 -- Attribute Dependency_Switches (<language>)
1392 if Lang_Index.Config.Dependency_Kind = None then
1393 Lang_Index.Config.Dependency_Kind := Makefile;
1396 List := Element.Value.Values;
1398 if List /= Nil_String then
1400 Lang_Index.Config.Dependency_Option,
1402 In_Tree => In_Tree);
1405 when Name_Dependency_Driver =>
1407 -- Attribute Dependency_Driver (<language>)
1409 if Lang_Index.Config.Dependency_Kind = None then
1410 Lang_Index.Config.Dependency_Kind := Makefile;
1413 List := Element.Value.Values;
1415 if List /= Nil_String then
1417 Lang_Index.Config.Compute_Dependency,
1419 In_Tree => In_Tree);
1422 when Name_Include_Switches =>
1424 -- Attribute Include_Switches (<language>)
1426 List := Element.Value.Values;
1428 if List = Nil_String then
1432 "include option cannot be null",
1433 Element.Value.Location);
1437 Lang_Index.Config.Include_Option,
1439 In_Tree => In_Tree);
1441 when Name_Include_Path =>
1443 -- Attribute Include_Path (<language>)
1445 Lang_Index.Config.Include_Path :=
1446 Element.Value.Value;
1448 when Name_Include_Path_File =>
1450 -- Attribute Include_Path_File (<language>)
1452 Lang_Index.Config.Include_Path_File :=
1453 Element.Value.Value;
1457 -- Attribute Driver (<language>)
1459 Lang_Index.Config.Compiler_Driver :=
1460 File_Name_Type (Element.Value.Value);
1462 when Name_Required_Switches |
1463 Name_Leading_Required_Switches =>
1466 Compiler_Leading_Required_Switches,
1467 From_List => Element.Value.Values,
1468 In_Tree => In_Tree);
1470 when Name_Trailing_Required_Switches =>
1473 Compiler_Trailing_Required_Switches,
1474 From_List => Element.Value.Values,
1475 In_Tree => In_Tree);
1477 when Name_Path_Syntax =>
1479 Lang_Index.Config.Path_Syntax :=
1480 Path_Syntax_Kind'Value
1481 (Get_Name_String (Element.Value.Value));
1484 when Constraint_Error =>
1488 "invalid value for Path_Syntax",
1489 Element.Value.Location);
1492 when Name_Object_File_Suffix =>
1493 if Get_Name_String (Element.Value.Value) = "" then
1496 "object file suffix cannot be empty",
1497 Element.Value.Location);
1500 Lang_Index.Config.Object_File_Suffix :=
1501 Element.Value.Value;
1504 when Name_Object_File_Switches =>
1506 Lang_Index.Config.Object_File_Switches,
1507 From_List => Element.Value.Values,
1508 In_Tree => In_Tree);
1510 when Name_Pic_Option =>
1512 -- Attribute Compiler_Pic_Option (<language>)
1514 List := Element.Value.Values;
1516 if List = Nil_String then
1520 "compiler PIC option cannot be null",
1521 Element.Value.Location);
1525 Lang_Index.Config.Compilation_PIC_Option,
1527 In_Tree => In_Tree);
1529 when Name_Mapping_File_Switches =>
1531 -- Attribute Mapping_File_Switches (<language>)
1533 List := Element.Value.Values;
1535 if List = Nil_String then
1539 "mapping file switches cannot be null",
1540 Element.Value.Location);
1544 Lang_Index.Config.Mapping_File_Switches,
1546 In_Tree => In_Tree);
1548 when Name_Mapping_Spec_Suffix =>
1550 -- Attribute Mapping_Spec_Suffix (<language>)
1552 Lang_Index.Config.Mapping_Spec_Suffix :=
1553 File_Name_Type (Element.Value.Value);
1555 when Name_Mapping_Body_Suffix =>
1557 -- Attribute Mapping_Body_Suffix (<language>)
1559 Lang_Index.Config.Mapping_Body_Suffix :=
1560 File_Name_Type (Element.Value.Value);
1562 when Name_Config_File_Switches =>
1564 -- Attribute Config_File_Switches (<language>)
1566 List := Element.Value.Values;
1568 if List = Nil_String then
1572 "config file switches cannot be null",
1573 Element.Value.Location);
1577 Lang_Index.Config.Config_File_Switches,
1579 In_Tree => In_Tree);
1581 when Name_Objects_Path =>
1583 -- Attribute Objects_Path (<language>)
1585 Lang_Index.Config.Objects_Path :=
1586 Element.Value.Value;
1588 when Name_Objects_Path_File =>
1590 -- Attribute Objects_Path_File (<language>)
1592 Lang_Index.Config.Objects_Path_File :=
1593 Element.Value.Value;
1595 when Name_Config_Body_File_Name =>
1597 -- Attribute Config_Body_File_Name (<language>)
1599 Lang_Index.Config.Config_Body :=
1600 Element.Value.Value;
1602 when Name_Config_Body_File_Name_Pattern =>
1604 -- Attribute Config_Body_File_Name_Pattern
1607 Lang_Index.Config.Config_Body_Pattern :=
1608 Element.Value.Value;
1610 when Name_Config_Spec_File_Name =>
1612 -- Attribute Config_Spec_File_Name (<language>)
1614 Lang_Index.Config.Config_Spec :=
1615 Element.Value.Value;
1617 when Name_Config_Spec_File_Name_Pattern =>
1619 -- Attribute Config_Spec_File_Name_Pattern
1622 Lang_Index.Config.Config_Spec_Pattern :=
1623 Element.Value.Value;
1625 when Name_Config_File_Unique =>
1627 -- Attribute Config_File_Unique (<language>)
1630 Lang_Index.Config.Config_File_Unique :=
1632 (Get_Name_String (Element.Value.Value));
1634 when Constraint_Error =>
1638 "illegal value for Config_File_Unique",
1639 Element.Value.Location);
1648 Element_Id := Element.Next;
1651 Current_Array_Id := Current_Array.Next;
1653 end Process_Compiler;
1655 --------------------
1656 -- Process_Naming --
1657 --------------------
1659 procedure Process_Naming (Attributes : Variable_Id) is
1660 Attribute_Id : Variable_Id;
1661 Attribute : Variable;
1664 -- Process non associated array attribute from package Naming
1666 Attribute_Id := Attributes;
1667 while Attribute_Id /= No_Variable loop
1668 Attribute := In_Tree.Variable_Elements.Table (Attribute_Id);
1670 if not Attribute.Value.Default then
1671 if Attribute.Name = Name_Separate_Suffix then
1673 -- Attribute Separate_Suffix
1675 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1677 elsif Attribute.Name = Name_Casing then
1683 Value (Get_Name_String (Attribute.Value.Value));
1686 when Constraint_Error =>
1690 "invalid value for Casing",
1691 Attribute.Value.Location);
1694 elsif Attribute.Name = Name_Dot_Replacement then
1696 -- Attribute Dot_Replacement
1698 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1703 Attribute_Id := Attribute.Next;
1707 procedure Process_Naming (Arrays : Array_Id) is
1708 Current_Array_Id : Array_Id;
1709 Current_Array : Array_Data;
1710 Element_Id : Array_Element_Id;
1711 Element : Array_Element;
1713 -- Process the associative array attribute of package Naming
1715 Current_Array_Id := Arrays;
1716 while Current_Array_Id /= No_Array loop
1717 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1719 Element_Id := Current_Array.Value;
1720 while Element_Id /= No_Array_Element loop
1721 Element := In_Tree.Array_Elements.Table (Element_Id);
1723 -- Get the name of the language
1725 Lang_Index := Get_Language_From_Name
1726 (Project, Get_Name_String (Element.Index));
1728 if Lang_Index /= No_Language_Index then
1729 case Current_Array.Name is
1730 when Name_Spec_Suffix | Name_Specification_Suffix =>
1732 -- Attribute Spec_Suffix (<language>)
1734 Lang_Index.Config.Naming_Data.Spec_Suffix :=
1735 File_Name_Type (Element.Value.Value);
1737 when Name_Implementation_Suffix | Name_Body_Suffix =>
1739 -- Attribute Body_Suffix (<language>)
1741 Lang_Index.Config.Naming_Data.Body_Suffix :=
1742 File_Name_Type (Element.Value.Value);
1744 Lang_Index.Config.Naming_Data.Separate_Suffix :=
1745 File_Name_Type (Element.Value.Value);
1752 Element_Id := Element.Next;
1755 Current_Array_Id := Current_Array.Next;
1759 --------------------
1760 -- Process_Linker --
1761 --------------------
1763 procedure Process_Linker (Attributes : Variable_Id) is
1764 Attribute_Id : Variable_Id;
1765 Attribute : Variable;
1768 -- Process non associated array attribute from package Linker
1770 Attribute_Id := Attributes;
1771 while Attribute_Id /= No_Variable loop
1773 In_Tree.Variable_Elements.Table (Attribute_Id);
1775 if not Attribute.Value.Default then
1776 if Attribute.Name = Name_Driver then
1778 -- Attribute Linker'Driver: the default linker to use
1780 Project.Config.Linker :=
1781 Path_Name_Type (Attribute.Value.Value);
1783 -- Linker'Driver is also used to link shared libraries
1784 -- if the obsolescent attribute Library_GCC has not been
1787 if Project.Config.Shared_Lib_Driver = No_File then
1788 Project.Config.Shared_Lib_Driver :=
1789 File_Name_Type (Attribute.Value.Value);
1792 elsif Attribute.Name = Name_Required_Switches then
1794 -- Attribute Required_Switches: the minimum
1795 -- options to use when invoking the linker
1797 Put (Into_List => Project.Config.Minimum_Linker_Options,
1798 From_List => Attribute.Value.Values,
1799 In_Tree => In_Tree);
1801 elsif Attribute.Name = Name_Map_File_Option then
1802 Project.Config.Map_File_Option := Attribute.Value.Value;
1804 elsif Attribute.Name = Name_Max_Command_Line_Length then
1806 Project.Config.Max_Command_Line_Length :=
1807 Natural'Value (Get_Name_String
1808 (Attribute.Value.Value));
1811 when Constraint_Error =>
1815 "value must be positive or equal to 0",
1816 Attribute.Value.Location);
1819 elsif Attribute.Name = Name_Response_File_Format then
1824 Get_Name_String (Attribute.Value.Value);
1825 To_Lower (Name_Buffer (1 .. Name_Len));
1828 if Name = Name_None then
1829 Project.Config.Resp_File_Format := None;
1831 elsif Name = Name_Gnu then
1832 Project.Config.Resp_File_Format := GNU;
1834 elsif Name = Name_Object_List then
1835 Project.Config.Resp_File_Format := Object_List;
1837 elsif Name = Name_Option_List then
1838 Project.Config.Resp_File_Format := Option_List;
1844 "illegal response file format",
1845 Attribute.Value.Location);
1849 elsif Attribute.Name = Name_Response_File_Switches then
1850 Put (Into_List => Project.Config.Resp_File_Options,
1851 From_List => Attribute.Value.Values,
1852 In_Tree => In_Tree);
1856 Attribute_Id := Attribute.Next;
1860 -- Start of processing for Process_Packages
1863 Packages := Project.Decl.Packages;
1864 while Packages /= No_Package loop
1865 Element := In_Tree.Packages.Table (Packages);
1867 case Element.Name is
1870 -- Process attributes of package Binder
1872 Process_Binder (Element.Decl.Arrays);
1874 when Name_Builder =>
1876 -- Process attributes of package Builder
1878 Process_Builder (Element.Decl.Attributes);
1880 when Name_Compiler =>
1882 -- Process attributes of package Compiler
1884 Process_Compiler (Element.Decl.Arrays);
1888 -- Process attributes of package Linker
1890 Process_Linker (Element.Decl.Attributes);
1894 -- Process attributes of package Naming
1896 Process_Naming (Element.Decl.Attributes);
1897 Process_Naming (Element.Decl.Arrays);
1903 Packages := Element.Next;
1905 end Process_Packages;
1907 ---------------------------------------------
1908 -- Process_Project_Level_Simple_Attributes --
1909 ---------------------------------------------
1911 procedure Process_Project_Level_Simple_Attributes is
1912 Attribute_Id : Variable_Id;
1913 Attribute : Variable;
1914 List : String_List_Id;
1917 -- Process non associated array attribute at project level
1919 Attribute_Id := Project.Decl.Attributes;
1920 while Attribute_Id /= No_Variable loop
1922 In_Tree.Variable_Elements.Table (Attribute_Id);
1924 if not Attribute.Value.Default then
1925 if Attribute.Name = Name_Target then
1927 -- Attribute Target: the target specified
1929 Project.Config.Target := Attribute.Value.Value;
1931 elsif Attribute.Name = Name_Library_Builder then
1933 -- Attribute Library_Builder: the application to invoke
1934 -- to build libraries.
1936 Project.Config.Library_Builder :=
1937 Path_Name_Type (Attribute.Value.Value);
1939 elsif Attribute.Name = Name_Archive_Builder then
1941 -- Attribute Archive_Builder: the archive builder
1942 -- (usually "ar") and its minimum options (usually "cr").
1944 List := Attribute.Value.Values;
1946 if List = Nil_String then
1950 "archive builder cannot be null",
1951 Attribute.Value.Location);
1954 Put (Into_List => Project.Config.Archive_Builder,
1956 In_Tree => In_Tree);
1958 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1960 -- Attribute Archive_Builder: the archive builder
1961 -- (usually "ar") and its minimum options (usually "cr").
1963 List := Attribute.Value.Values;
1965 if List /= Nil_String then
1968 Project.Config.Archive_Builder_Append_Option,
1970 In_Tree => In_Tree);
1973 elsif Attribute.Name = Name_Archive_Indexer then
1975 -- Attribute Archive_Indexer: the optional archive
1976 -- indexer (usually "ranlib") with its minimum options
1979 List := Attribute.Value.Values;
1981 if List = Nil_String then
1985 "archive indexer cannot be null",
1986 Attribute.Value.Location);
1989 Put (Into_List => Project.Config.Archive_Indexer,
1991 In_Tree => In_Tree);
1993 elsif Attribute.Name = Name_Library_Partial_Linker then
1995 -- Attribute Library_Partial_Linker: the optional linker
1996 -- driver with its minimum options, to partially link
1999 List := Attribute.Value.Values;
2001 if List = Nil_String then
2005 "partial linker cannot be null",
2006 Attribute.Value.Location);
2009 Put (Into_List => Project.Config.Lib_Partial_Linker,
2011 In_Tree => In_Tree);
2013 elsif Attribute.Name = Name_Library_GCC then
2014 Project.Config.Shared_Lib_Driver :=
2015 File_Name_Type (Attribute.Value.Value);
2019 "?Library_'G'C'C is an obsolescent attribute, " &
2020 "use Linker''Driver instead",
2021 Attribute.Value.Location);
2023 elsif Attribute.Name = Name_Archive_Suffix then
2024 Project.Config.Archive_Suffix :=
2025 File_Name_Type (Attribute.Value.Value);
2027 elsif Attribute.Name = Name_Linker_Executable_Option then
2029 -- Attribute Linker_Executable_Option: optional options
2030 -- to specify an executable name. Defaults to "-o".
2032 List := Attribute.Value.Values;
2034 if List = Nil_String then
2038 "linker executable option cannot be null",
2039 Attribute.Value.Location);
2042 Put (Into_List => Project.Config.Linker_Executable_Option,
2044 In_Tree => In_Tree);
2046 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2048 -- Attribute Linker_Lib_Dir_Option: optional options
2049 -- to specify a library search directory. Defaults to
2052 Get_Name_String (Attribute.Value.Value);
2054 if Name_Len = 0 then
2058 "linker library directory option cannot be empty",
2059 Attribute.Value.Location);
2062 Project.Config.Linker_Lib_Dir_Option :=
2063 Attribute.Value.Value;
2065 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2067 -- Attribute Linker_Lib_Name_Option: optional options
2068 -- to specify the name of a library to be linked in.
2069 -- Defaults to "-l".
2071 Get_Name_String (Attribute.Value.Value);
2073 if Name_Len = 0 then
2077 "linker library name option cannot be empty",
2078 Attribute.Value.Location);
2081 Project.Config.Linker_Lib_Name_Option :=
2082 Attribute.Value.Value;
2084 elsif Attribute.Name = Name_Run_Path_Option then
2086 -- Attribute Run_Path_Option: optional options to
2087 -- specify a path for libraries.
2089 List := Attribute.Value.Values;
2091 if List /= Nil_String then
2092 Put (Into_List => Project.Config.Run_Path_Option,
2094 In_Tree => In_Tree);
2097 elsif Attribute.Name = Name_Separate_Run_Path_Options then
2099 pragma Unsuppress (All_Checks);
2101 Project.Config.Separate_Run_Path_Options :=
2102 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2104 when Constraint_Error =>
2108 "invalid value """ &
2109 Get_Name_String (Attribute.Value.Value) &
2110 """ for Separate_Run_Path_Options",
2111 Attribute.Value.Location);
2114 elsif Attribute.Name = Name_Library_Support then
2116 pragma Unsuppress (All_Checks);
2118 Project.Config.Lib_Support :=
2119 Library_Support'Value (Get_Name_String
2120 (Attribute.Value.Value));
2122 when Constraint_Error =>
2126 "invalid value """ &
2127 Get_Name_String (Attribute.Value.Value) &
2128 """ for Library_Support",
2129 Attribute.Value.Location);
2132 elsif Attribute.Name = Name_Shared_Library_Prefix then
2133 Project.Config.Shared_Lib_Prefix :=
2134 File_Name_Type (Attribute.Value.Value);
2136 elsif Attribute.Name = Name_Shared_Library_Suffix then
2137 Project.Config.Shared_Lib_Suffix :=
2138 File_Name_Type (Attribute.Value.Value);
2140 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2142 pragma Unsuppress (All_Checks);
2144 Project.Config.Symbolic_Link_Supported :=
2145 Boolean'Value (Get_Name_String
2146 (Attribute.Value.Value));
2148 when Constraint_Error =>
2153 & Get_Name_String (Attribute.Value.Value)
2154 & """ for Symbolic_Link_Supported",
2155 Attribute.Value.Location);
2159 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2162 pragma Unsuppress (All_Checks);
2164 Project.Config.Lib_Maj_Min_Id_Supported :=
2165 Boolean'Value (Get_Name_String
2166 (Attribute.Value.Value));
2168 when Constraint_Error =>
2172 "invalid value """ &
2173 Get_Name_String (Attribute.Value.Value) &
2174 """ for Library_Major_Minor_Id_Supported",
2175 Attribute.Value.Location);
2178 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2180 pragma Unsuppress (All_Checks);
2182 Project.Config.Auto_Init_Supported :=
2183 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2185 when Constraint_Error =>
2190 & Get_Name_String (Attribute.Value.Value)
2191 & """ for Library_Auto_Init_Supported",
2192 Attribute.Value.Location);
2195 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2196 List := Attribute.Value.Values;
2198 if List /= Nil_String then
2199 Put (Into_List => Project.Config.Shared_Lib_Min_Options,
2201 In_Tree => In_Tree);
2204 elsif Attribute.Name = Name_Library_Version_Switches then
2205 List := Attribute.Value.Values;
2207 if List /= Nil_String then
2208 Put (Into_List => Project.Config.Lib_Version_Options,
2210 In_Tree => In_Tree);
2215 Attribute_Id := Attribute.Next;
2217 end Process_Project_Level_Simple_Attributes;
2219 --------------------------------------------
2220 -- Process_Project_Level_Array_Attributes --
2221 --------------------------------------------
2223 procedure Process_Project_Level_Array_Attributes is
2224 Current_Array_Id : Array_Id;
2225 Current_Array : Array_Data;
2226 Element_Id : Array_Element_Id;
2227 Element : Array_Element;
2228 List : String_List_Id;
2231 -- Process the associative array attributes at project level
2233 Current_Array_Id := Project.Decl.Arrays;
2234 while Current_Array_Id /= No_Array loop
2235 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2237 Element_Id := Current_Array.Value;
2238 while Element_Id /= No_Array_Element loop
2239 Element := In_Tree.Array_Elements.Table (Element_Id);
2241 -- Get the name of the language
2244 Get_Language_From_Name
2245 (Project, Get_Name_String (Element.Index));
2247 if Lang_Index /= No_Language_Index then
2248 case Current_Array.Name is
2249 when Name_Inherit_Source_Path =>
2250 List := Element.Value.Values;
2252 if List /= Nil_String then
2255 Lang_Index.Config.Include_Compatible_Languages,
2258 Lower_Case => True);
2261 when Name_Toolchain_Description =>
2263 -- Attribute Toolchain_Description (<language>)
2265 Lang_Index.Config.Toolchain_Description :=
2266 Element.Value.Value;
2268 when Name_Toolchain_Version =>
2270 -- Attribute Toolchain_Version (<language>)
2272 Lang_Index.Config.Toolchain_Version :=
2273 Element.Value.Value;
2275 when Name_Runtime_Library_Dir =>
2277 -- Attribute Runtime_Library_Dir (<language>)
2279 Lang_Index.Config.Runtime_Library_Dir :=
2280 Element.Value.Value;
2282 when Name_Runtime_Source_Dir =>
2284 -- Attribute Runtime_Library_Dir (<language>)
2286 Lang_Index.Config.Runtime_Source_Dir :=
2287 Element.Value.Value;
2289 when Name_Object_Generated =>
2291 pragma Unsuppress (All_Checks);
2297 (Get_Name_String (Element.Value.Value));
2299 Lang_Index.Config.Object_Generated := Value;
2301 -- If no object is generated, no object may be
2305 Lang_Index.Config.Objects_Linked := False;
2309 when Constraint_Error =>
2314 & Get_Name_String (Element.Value.Value)
2315 & """ for Object_Generated",
2316 Element.Value.Location);
2319 when Name_Objects_Linked =>
2321 pragma Unsuppress (All_Checks);
2327 (Get_Name_String (Element.Value.Value));
2329 -- No change if Object_Generated is False, as this
2330 -- forces Objects_Linked to be False too.
2332 if Lang_Index.Config.Object_Generated then
2333 Lang_Index.Config.Objects_Linked := Value;
2337 when Constraint_Error =>
2342 & Get_Name_String (Element.Value.Value)
2343 & """ for Objects_Linked",
2344 Element.Value.Location);
2351 Element_Id := Element.Next;
2354 Current_Array_Id := Current_Array.Next;
2356 end Process_Project_Level_Array_Attributes;
2359 Process_Project_Level_Simple_Attributes;
2360 Process_Project_Level_Array_Attributes;
2363 -- For unit based languages, set Casing, Dot_Replacement and
2364 -- Separate_Suffix in Naming_Data.
2366 Lang_Index := Project.Languages;
2367 while Lang_Index /= No_Language_Index loop
2368 if Lang_Index.Name = Name_Ada then
2369 Lang_Index.Config.Naming_Data.Casing := Casing;
2370 Lang_Index.Config.Naming_Data.Dot_Replacement := Dot_Replacement;
2372 if Separate_Suffix /= No_File then
2373 Lang_Index.Config.Naming_Data.Separate_Suffix :=
2380 Lang_Index := Lang_Index.Next;
2383 -- Give empty names to various prefixes/suffixes, if they have not
2384 -- been specified in the configuration.
2386 if Project.Config.Archive_Suffix = No_File then
2387 Project.Config.Archive_Suffix := Empty_File;
2390 if Project.Config.Shared_Lib_Prefix = No_File then
2391 Project.Config.Shared_Lib_Prefix := Empty_File;
2394 if Project.Config.Shared_Lib_Suffix = No_File then
2395 Project.Config.Shared_Lib_Suffix := Empty_File;
2398 Lang_Index := Project.Languages;
2399 while Lang_Index /= No_Language_Index loop
2400 -- For all languages, Compiler_Driver needs to be specified. This is
2401 -- only necessary if we do intend to compile (not in GPS for
2404 if Compiler_Driver_Mandatory
2405 and then Lang_Index.Config.Compiler_Driver = No_File
2407 Error_Msg_Name_1 := Lang_Index.Display_Name;
2411 "?no compiler specified for language %%" &
2412 ", ignoring all its sources",
2415 if Lang_Index = Project.Languages then
2416 Project.Languages := Lang_Index.Next;
2418 Prev_Index.Next := Lang_Index.Next;
2421 elsif Lang_Index.Name = Name_Ada then
2422 Prev_Index := Lang_Index;
2424 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2425 -- Body_Suffix need to be specified.
2427 if Lang_Index.Config.Naming_Data.Dot_Replacement = No_File then
2431 "Dot_Replacement not specified for Ada",
2435 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File then
2439 "Spec_Suffix not specified for Ada",
2443 if Lang_Index.Config.Naming_Data.Body_Suffix = No_File then
2447 "Body_Suffix not specified for Ada",
2452 Prev_Index := Lang_Index;
2454 -- For file based languages, either Spec_Suffix or Body_Suffix
2455 -- need to be specified.
2457 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File and then
2458 Lang_Index.Config.Naming_Data.Body_Suffix = No_File
2460 Error_Msg_Name_1 := Lang_Index.Display_Name;
2464 "no suffixes specified for %%",
2469 Lang_Index := Lang_Index.Next;
2471 end Check_Configuration;
2473 -------------------------------
2474 -- Check_If_Externally_Built --
2475 -------------------------------
2477 procedure Check_If_Externally_Built
2478 (Project : Project_Id;
2479 In_Tree : Project_Tree_Ref)
2481 Externally_Built : constant Variable_Value :=
2483 (Name_Externally_Built,
2484 Project.Decl.Attributes, In_Tree);
2487 if not Externally_Built.Default then
2488 Get_Name_String (Externally_Built.Value);
2489 To_Lower (Name_Buffer (1 .. Name_Len));
2491 if Name_Buffer (1 .. Name_Len) = "true" then
2492 Project.Externally_Built := True;
2494 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2495 Error_Msg (Project, In_Tree,
2496 "Externally_Built may only be true or false",
2497 Externally_Built.Location);
2501 -- A virtual project extending an externally built project is itself
2502 -- externally built.
2504 if Project.Virtual and then Project.Extends /= No_Project then
2505 Project.Externally_Built := Project.Extends.Externally_Built;
2508 if Current_Verbosity = High then
2509 Write_Str ("Project is ");
2511 if not Project.Externally_Built then
2515 Write_Line ("externally built.");
2517 end Check_If_Externally_Built;
2519 ----------------------
2520 -- Check_Interfaces --
2521 ----------------------
2523 procedure Check_Interfaces
2524 (Project : Project_Id;
2525 In_Tree : Project_Tree_Ref)
2527 Interfaces : constant Prj.Variable_Value :=
2529 (Snames.Name_Interfaces,
2530 Project.Decl.Attributes,
2533 List : String_List_Id;
2534 Element : String_Element;
2535 Name : File_Name_Type;
2536 Iter : Source_Iterator;
2538 Project_2 : Project_Id;
2542 if not Interfaces.Default then
2544 -- Set In_Interfaces to False for all sources. It will be set to True
2545 -- later for the sources in the Interfaces list.
2547 Project_2 := Project;
2548 while Project_2 /= No_Project loop
2549 Iter := For_Each_Source (In_Tree, Project_2);
2552 Source := Prj.Element (Iter);
2553 exit when Source = No_Source;
2554 Source.In_Interfaces := False;
2558 Project_2 := Project_2.Extends;
2561 List := Interfaces.Values;
2562 while List /= Nil_String loop
2563 Element := In_Tree.String_Elements.Table (List);
2564 Name := Canonical_Case_File_Name (Element.Value);
2566 Project_2 := Project;
2568 while Project_2 /= No_Project loop
2569 Iter := For_Each_Source (In_Tree, Project_2);
2572 Source := Prj.Element (Iter);
2573 exit when Source = No_Source;
2575 if Source.File = Name then
2576 if not Source.Locally_Removed then
2577 Source.In_Interfaces := True;
2578 Source.Declared_In_Interfaces := True;
2580 Other := Other_Part (Source);
2582 if Other /= No_Source then
2583 Other.In_Interfaces := True;
2584 Other.Declared_In_Interfaces := True;
2587 if Current_Verbosity = High then
2588 Write_Str (" interface: ");
2589 Write_Line (Get_Name_String (Source.Path.Name));
2599 Project_2 := Project_2.Extends;
2602 if Source = No_Source then
2603 Error_Msg_File_1 := File_Name_Type (Element.Value);
2604 Error_Msg_Name_1 := Project.Name;
2609 "{ cannot be an interface of project %% "
2610 & "as it is not one of its sources",
2614 List := Element.Next;
2617 Project.Interfaces_Defined := True;
2619 elsif Project.Extends /= No_Project then
2620 Project.Interfaces_Defined := Project.Extends.Interfaces_Defined;
2622 if Project.Interfaces_Defined then
2623 Iter := For_Each_Source (In_Tree, Project);
2625 Source := Prj.Element (Iter);
2626 exit when Source = No_Source;
2628 if not Source.Declared_In_Interfaces then
2629 Source.In_Interfaces := False;
2636 end Check_Interfaces;
2638 ------------------------------------
2639 -- Check_And_Normalize_Unit_Names --
2640 ------------------------------------
2642 procedure Check_And_Normalize_Unit_Names
2643 (Project : Project_Id;
2644 In_Tree : Project_Tree_Ref;
2645 List : Array_Element_Id;
2646 Debug_Name : String)
2648 Current : Array_Element_Id;
2649 Element : Array_Element;
2650 Unit_Name : Name_Id;
2653 if Current_Verbosity = High then
2654 Write_Line (" Checking unit names in " & Debug_Name);
2658 while Current /= No_Array_Element loop
2659 Element := In_Tree.Array_Elements.Table (Current);
2660 Element.Value.Value :=
2661 Name_Id (Canonical_Case_File_Name (Element.Value.Value));
2663 -- Check that it contains a valid unit name
2665 Get_Name_String (Element.Index);
2666 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2668 if Unit_Name = No_Name then
2669 Err_Vars.Error_Msg_Name_1 := Element.Index;
2672 "%% is not a valid unit name.",
2673 Element.Value.Location);
2676 if Current_Verbosity = High then
2677 Write_Str (" for unit: ");
2678 Write_Line (Get_Name_String (Unit_Name));
2681 Element.Index := Unit_Name;
2682 In_Tree.Array_Elements.Table (Current) := Element;
2685 Current := Element.Next;
2687 end Check_And_Normalize_Unit_Names;
2689 --------------------------
2690 -- Check_Package_Naming --
2691 --------------------------
2693 procedure Check_Package_Naming
2694 (Project : Project_Id;
2695 In_Tree : Project_Tree_Ref;
2696 Is_Config_File : Boolean;
2697 Bodies : out Array_Element_Id;
2698 Specs : out Array_Element_Id)
2700 Naming_Id : constant Package_Id :=
2701 Util.Value_Of (Name_Naming, Project.Decl.Packages, In_Tree);
2702 Naming : Package_Element;
2704 Ada_Body_Suffix_Loc : Source_Ptr := No_Location;
2705 Ada_Spec_Suffix_Loc : Source_Ptr := No_Location;
2707 procedure Check_Naming_Ada_Only;
2708 -- Does Check_Naming_Schemes processing in Ada_Only mode.
2709 -- If there is a package Naming, puts in Data.Naming the contents of
2712 procedure Check_Naming_Multi_Lang;
2713 -- Does Check_Naming_Schemes processing for Multi_Language mode
2715 procedure Check_Common
2716 (Dot_Replacement : in out File_Name_Type;
2717 Casing : in out Casing_Type;
2718 Casing_Defined : out Boolean;
2719 Separate_Suffix : in out File_Name_Type;
2720 Sep_Suffix_Loc : out Source_Ptr);
2721 -- Check attributes common to Ada_Only and Multi_Lang modes
2723 procedure Process_Exceptions_File_Based
2724 (Lang_Id : Language_Ptr;
2725 Kind : Source_Kind);
2726 procedure Process_Exceptions_Unit_Based
2727 (Lang_Id : Language_Ptr;
2728 Kind : Source_Kind);
2729 -- In Multi_Lang mode, process the naming exceptions for the two types
2730 -- of languages we can have.
2732 procedure Initialize_Naming_Data;
2733 -- Initialize internal naming data for the various languages
2739 procedure Check_Common
2740 (Dot_Replacement : in out File_Name_Type;
2741 Casing : in out Casing_Type;
2742 Casing_Defined : out Boolean;
2743 Separate_Suffix : in out File_Name_Type;
2744 Sep_Suffix_Loc : out Source_Ptr)
2746 Dot_Repl : constant Variable_Value :=
2748 (Name_Dot_Replacement,
2749 Naming.Decl.Attributes,
2751 Casing_String : constant Variable_Value :=
2754 Naming.Decl.Attributes,
2756 Sep_Suffix : constant Variable_Value :=
2758 (Name_Separate_Suffix,
2759 Naming.Decl.Attributes,
2761 Dot_Repl_Loc : Source_Ptr;
2764 Sep_Suffix_Loc := No_Location;
2766 if not Dot_Repl.Default then
2768 (Dot_Repl.Kind = Single, "Dot_Replacement is not a string");
2770 if Length_Of_Name (Dot_Repl.Value) = 0 then
2773 "Dot_Replacement cannot be empty",
2777 Dot_Replacement := Canonical_Case_File_Name (Dot_Repl.Value);
2778 Dot_Repl_Loc := Dot_Repl.Location;
2781 Repl : constant String := Get_Name_String (Dot_Replacement);
2784 -- Dot_Replacement cannot
2786 -- - start or end with an alphanumeric
2787 -- - be a single '_'
2788 -- - start with an '_' followed by an alphanumeric
2789 -- - contain a '.' except if it is "."
2792 or else Is_Alphanumeric (Repl (Repl'First))
2793 or else Is_Alphanumeric (Repl (Repl'Last))
2794 or else (Repl (Repl'First) = '_'
2798 Is_Alphanumeric (Repl (Repl'First + 1))))
2799 or else (Repl'Length > 1
2801 Index (Source => Repl, Pattern => ".") /= 0)
2806 """ is illegal for Dot_Replacement.",
2812 if Dot_Replacement /= No_File then
2814 ("Dot_Replacement", Get_Name_String (Dot_Replacement));
2817 Casing_Defined := False;
2819 if not Casing_String.Default then
2821 (Casing_String.Kind = Single, "Casing is not a string");
2824 Casing_Image : constant String :=
2825 Get_Name_String (Casing_String.Value);
2827 if Casing_Image'Length = 0 then
2830 "Casing cannot be an empty string",
2831 Casing_String.Location);
2834 Casing := Value (Casing_Image);
2835 Casing_Defined := True;
2838 when Constraint_Error =>
2839 Name_Len := Casing_Image'Length;
2840 Name_Buffer (1 .. Name_Len) := Casing_Image;
2841 Err_Vars.Error_Msg_Name_1 := Name_Find;
2844 "%% is not a correct Casing",
2845 Casing_String.Location);
2849 Write_Attr ("Casing", Image (Casing));
2851 if not Sep_Suffix.Default then
2852 if Length_Of_Name (Sep_Suffix.Value) = 0 then
2855 "Separate_Suffix cannot be empty",
2856 Sep_Suffix.Location);
2859 Separate_Suffix := Canonical_Case_File_Name (Sep_Suffix.Value);
2860 Sep_Suffix_Loc := Sep_Suffix.Location;
2862 if Is_Illegal_Suffix (Separate_Suffix, Dot_Replacement) then
2863 Err_Vars.Error_Msg_File_1 := Separate_Suffix;
2866 "{ is illegal for Separate_Suffix",
2867 Sep_Suffix.Location);
2872 if Separate_Suffix /= No_File then
2874 ("Separate_Suffix", Get_Name_String (Separate_Suffix));
2878 -----------------------------------
2879 -- Process_Exceptions_File_Based --
2880 -----------------------------------
2882 procedure Process_Exceptions_File_Based
2883 (Lang_Id : Language_Ptr;
2886 Lang : constant Name_Id := Lang_Id.Name;
2887 Exceptions : Array_Element_Id;
2888 Exception_List : Variable_Value;
2889 Element_Id : String_List_Id;
2890 Element : String_Element;
2891 File_Name : File_Name_Type;
2893 Iter : Source_Iterator;
2900 (Name_Implementation_Exceptions,
2901 In_Arrays => Naming.Decl.Arrays,
2902 In_Tree => In_Tree);
2907 (Name_Specification_Exceptions,
2908 In_Arrays => Naming.Decl.Arrays,
2909 In_Tree => In_Tree);
2912 Exception_List := Value_Of
2914 In_Array => Exceptions,
2915 In_Tree => In_Tree);
2917 if Exception_List /= Nil_Variable_Value then
2918 Element_Id := Exception_List.Values;
2919 while Element_Id /= Nil_String loop
2920 Element := In_Tree.String_Elements.Table (Element_Id);
2921 File_Name := Canonical_Case_File_Name (Element.Value);
2923 Iter := For_Each_Source (In_Tree, Project);
2925 Source := Prj.Element (Iter);
2926 exit when Source = No_Source or else Source.File = File_Name;
2930 if Source = No_Source then
2937 File_Name => File_Name,
2938 Display_File => File_Name_Type (Element.Value),
2939 Naming_Exception => True);
2942 -- Check if the file name is already recorded for another
2943 -- language or another kind.
2945 if Source.Language /= Lang_Id then
2949 "the same file cannot be a source of two languages",
2952 elsif Source.Kind /= Kind then
2956 "the same file cannot be a source and a template",
2960 -- If the file is already recorded for the same
2961 -- language and the same kind, it means that the file
2962 -- name appears several times in the *_Exceptions
2963 -- attribute; so there is nothing to do.
2966 Element_Id := Element.Next;
2969 end Process_Exceptions_File_Based;
2971 -----------------------------------
2972 -- Process_Exceptions_Unit_Based --
2973 -----------------------------------
2975 procedure Process_Exceptions_Unit_Based
2976 (Lang_Id : Language_Ptr;
2979 Lang : constant Name_Id := Lang_Id.Name;
2980 Exceptions : Array_Element_Id;
2981 Element : Array_Element;
2984 File_Name : File_Name_Type;
2986 Source_To_Replace : Source_Id := No_Source;
2987 Other_Project : Project_Id;
2988 Iter : Source_Iterator;
2993 Exceptions := Value_Of
2995 In_Arrays => Naming.Decl.Arrays,
2996 In_Tree => In_Tree);
2998 if Exceptions = No_Array_Element then
3001 (Name_Implementation,
3002 In_Arrays => Naming.Decl.Arrays,
3003 In_Tree => In_Tree);
3010 In_Arrays => Naming.Decl.Arrays,
3011 In_Tree => In_Tree);
3013 if Exceptions = No_Array_Element then
3014 Exceptions := Value_Of
3016 In_Arrays => Naming.Decl.Arrays,
3017 In_Tree => In_Tree);
3021 while Exceptions /= No_Array_Element loop
3022 Element := In_Tree.Array_Elements.Table (Exceptions);
3023 File_Name := Canonical_Case_File_Name (Element.Value.Value);
3025 Get_Name_String (Element.Index);
3026 To_Lower (Name_Buffer (1 .. Name_Len));
3028 Index := Element.Value.Index;
3030 -- For Ada, check if it is a valid unit name
3032 if Lang = Name_Ada then
3033 Get_Name_String (Element.Index);
3034 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
3036 if Unit = No_Name then
3037 Err_Vars.Error_Msg_Name_1 := Element.Index;
3040 "%% is not a valid unit name.",
3041 Element.Value.Location);
3045 if Unit /= No_Name then
3047 -- Check if the source already exists
3048 -- ??? In Ada_Only mode (Record_Unit), we use a htable for
3051 Source_To_Replace := No_Source;
3052 Iter := For_Each_Source (In_Tree);
3055 Source := Prj.Element (Iter);
3056 exit when Source = No_Source
3057 or else (Source.Unit /= null
3058 and then Source.Unit.Name = Unit
3059 and then Source.Index = Index);
3063 if Source /= No_Source then
3064 if Source.Kind /= Kind then
3067 Source := Prj.Element (Iter);
3069 exit when Source = No_Source
3070 or else (Source.Unit /= null
3071 and then Source.Unit.Name = Unit
3072 and then Source.Index = Index);
3076 if Source /= No_Source then
3077 Other_Project := Source.Project;
3079 if Is_Extending (Project, Other_Project) then
3080 Source_To_Replace := Source;
3081 Source := No_Source;
3084 Error_Msg_Name_1 := Unit;
3085 Error_Msg_Name_2 := Other_Project.Name;
3089 "%% is already a source of project %%",
3090 Element.Value.Location);
3095 if Source = No_Source then
3102 File_Name => File_Name,
3103 Display_File => File_Name_Type (Element.Value.Value),
3106 Naming_Exception => True,
3107 Source_To_Replace => Source_To_Replace);
3111 Exceptions := Element.Next;
3113 end Process_Exceptions_Unit_Based;
3115 ---------------------------
3116 -- Check_Naming_Ada_Only --
3117 ---------------------------
3119 procedure Check_Naming_Ada_Only is
3120 Ada : constant Language_Ptr :=
3121 Get_Language_From_Name (Project, "ada");
3123 Casing_Defined : Boolean;
3124 Sep_Suffix_Loc : Source_Ptr;
3128 -- No language, thus nothing to do
3133 Data : Lang_Naming_Data renames Ada.Config.Naming_Data;
3135 -- The default value of separate suffix should be the same as the
3136 -- body suffix, so we need to compute that first.
3138 Data.Separate_Suffix := Data.Body_Suffix;
3139 Write_Attr ("Body_Suffix", Get_Name_String (Data.Body_Suffix));
3141 -- We'll need the dot replacement below, so compute it now
3144 (Dot_Replacement => Data.Dot_Replacement,
3145 Casing => Data.Casing,
3146 Casing_Defined => Casing_Defined,
3147 Separate_Suffix => Data.Separate_Suffix,
3148 Sep_Suffix_Loc => Sep_Suffix_Loc);
3150 Bodies := Util.Value_Of (Name_Body, Naming.Decl.Arrays, In_Tree);
3152 if Bodies /= No_Array_Element then
3153 Check_And_Normalize_Unit_Names
3154 (Project, In_Tree, Bodies, "Naming.Bodies");
3157 Specs := Util.Value_Of (Name_Spec, Naming.Decl.Arrays, In_Tree);
3159 if Specs /= No_Array_Element then
3160 Check_And_Normalize_Unit_Names
3161 (Project, In_Tree, Specs, "Naming.Specs");
3164 -- Check Spec_Suffix
3166 if Is_Illegal_Suffix (Data.Spec_Suffix, Data.Dot_Replacement) then
3167 Err_Vars.Error_Msg_File_1 := Data.Spec_Suffix;
3170 "{ is illegal for Spec_Suffix",
3171 Ada_Spec_Suffix_Loc);
3174 Write_Attr ("Spec_Suffix", Get_Name_String (Data.Spec_Suffix));
3176 -- Check Body_Suffix
3178 if Is_Illegal_Suffix (Data.Body_Suffix, Data.Dot_Replacement) then
3179 Err_Vars.Error_Msg_File_1 := Data.Body_Suffix;
3182 "{ is illegal for Body_Suffix",
3183 Ada_Body_Suffix_Loc);
3186 -- Spec_Suffix cannot be equal to Body_Suffix or Separate_Suffix,
3187 -- since that would cause a clear ambiguity. Note that we do allow
3188 -- a Spec_Suffix to have the same termination as one of these,
3189 -- which causes a potential ambiguity, but we resolve that my
3190 -- matching the longest possible suffix.
3192 if Data.Spec_Suffix = Data.Body_Suffix then
3196 Get_Name_String (Data.Body_Suffix) &
3197 """) cannot be the same as Spec_Suffix.",
3198 Ada_Body_Suffix_Loc);
3201 if Data.Body_Suffix /= Data.Separate_Suffix
3202 and then Data.Spec_Suffix = Data.Separate_Suffix
3206 "Separate_Suffix (""" &
3207 Get_Name_String (Data.Separate_Suffix) &
3208 """) cannot be the same as Spec_Suffix.",
3212 end Check_Naming_Ada_Only;
3214 -----------------------------
3215 -- Check_Naming_Multi_Lang --
3216 -----------------------------
3218 procedure Check_Naming_Multi_Lang is
3219 Dot_Replacement : File_Name_Type := No_File;
3220 Separate_Suffix : File_Name_Type := No_File;
3221 Casing : Casing_Type := All_Lower_Case;
3222 Casing_Defined : Boolean;
3223 Lang_Id : Language_Ptr;
3224 Sep_Suffix_Loc : Source_Ptr;
3225 Suffix : Variable_Value;
3230 (Dot_Replacement => Dot_Replacement,
3232 Casing_Defined => Casing_Defined,
3233 Separate_Suffix => Separate_Suffix,
3234 Sep_Suffix_Loc => Sep_Suffix_Loc);
3236 -- For all unit based languages, if any, set the specified
3237 -- value of Dot_Replacement, Casing and/or Separate_Suffix. Do not
3238 -- systematically overwrite, since the defaults come from the
3239 -- configuration file
3241 if Dot_Replacement /= No_File
3242 or else Casing_Defined
3243 or else Separate_Suffix /= No_File
3245 Lang_Id := Project.Languages;
3246 while Lang_Id /= No_Language_Index loop
3247 if Lang_Id.Config.Kind = Unit_Based then
3248 if Dot_Replacement /= No_File then
3249 Lang_Id.Config.Naming_Data.Dot_Replacement :=
3253 if Casing_Defined then
3254 Lang_Id.Config.Naming_Data.Casing := Casing;
3257 if Separate_Suffix /= No_File then
3258 Lang_Id.Config.Naming_Data.Separate_Suffix :=
3263 Lang_Id := Lang_Id.Next;
3267 -- Next, get the spec and body suffixes
3269 Lang_Id := Project.Languages;
3270 while Lang_Id /= No_Language_Index loop
3271 Lang := Lang_Id.Name;
3277 Attribute_Or_Array_Name => Name_Spec_Suffix,
3278 In_Package => Naming_Id,
3279 In_Tree => In_Tree);
3281 if Suffix = Nil_Variable_Value then
3284 Attribute_Or_Array_Name => Name_Spec_Suffix,
3285 In_Package => Naming_Id,
3286 In_Tree => In_Tree);
3289 if Suffix /= Nil_Variable_Value then
3290 Lang_Id.Config.Naming_Data.Spec_Suffix :=
3291 File_Name_Type (Suffix.Value);
3298 Attribute_Or_Array_Name => Name_Body_Suffix,
3299 In_Package => Naming_Id,
3300 In_Tree => In_Tree);
3302 if Suffix = Nil_Variable_Value then
3305 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3306 In_Package => Naming_Id,
3307 In_Tree => In_Tree);
3310 if Suffix /= Nil_Variable_Value then
3311 Lang_Id.Config.Naming_Data.Body_Suffix :=
3312 File_Name_Type (Suffix.Value);
3315 -- ??? As opposed to what is done in Check_Naming_Ada_Only,
3316 -- we do not check whether spec_suffix=body_suffix, which
3317 -- should be illegal. Best would be to share this code into
3318 -- Check_Common, but we access the attributes from the project
3319 -- files slightly differently apparently.
3321 Lang_Id := Lang_Id.Next;
3324 -- Get the naming exceptions for all languages
3326 for Kind in Spec .. Impl loop
3327 Lang_Id := Project.Languages;
3328 while Lang_Id /= No_Language_Index loop
3329 case Lang_Id.Config.Kind is
3331 Process_Exceptions_File_Based (Lang_Id, Kind);
3334 Process_Exceptions_Unit_Based (Lang_Id, Kind);
3337 Lang_Id := Lang_Id.Next;
3340 end Check_Naming_Multi_Lang;
3342 ----------------------------
3343 -- Initialize_Naming_Data --
3344 ----------------------------
3346 procedure Initialize_Naming_Data is
3347 Specs : Array_Element_Id :=
3352 Impls : Array_Element_Id :=
3357 Lang : Language_Ptr;
3358 Lang_Name : Name_Id;
3359 Value : Variable_Value;
3362 -- At this stage, the project already contains the default
3363 -- extensions for the various languages. We now merge those
3364 -- suffixes read in the user project, and they override the
3367 while Specs /= No_Array_Element loop
3368 Lang_Name := In_Tree.Array_Elements.Table (Specs).Index;
3369 Lang := Get_Language_From_Name
3370 (Project, Name => Get_Name_String (Lang_Name));
3373 if Current_Verbosity = High then
3375 ("Ignoring spec naming data for "
3376 & Get_Name_String (Lang_Name)
3377 & " since language is not defined for this project");
3380 Value := In_Tree.Array_Elements.Table (Specs).Value;
3382 if Lang.Name = Name_Ada then
3383 Ada_Spec_Suffix_Loc := Value.Location;
3386 if Value.Kind = Single then
3387 Lang.Config.Naming_Data.Spec_Suffix :=
3388 Canonical_Case_File_Name (Value.Value);
3392 Specs := In_Tree.Array_Elements.Table (Specs).Next;
3395 while Impls /= No_Array_Element loop
3396 Lang_Name := In_Tree.Array_Elements.Table (Impls).Index;
3397 Lang := Get_Language_From_Name
3398 (Project, Name => Get_Name_String (Lang_Name));
3401 if Current_Verbosity = High then
3403 ("Ignoring impl naming data for "
3404 & Get_Name_String (Lang_Name)
3405 & " since language is not defined for this project");
3408 Value := In_Tree.Array_Elements.Table (Impls).Value;
3410 if Lang.Name = Name_Ada then
3411 Ada_Body_Suffix_Loc := Value.Location;
3414 if Value.Kind = Single then
3415 Lang.Config.Naming_Data.Body_Suffix :=
3416 Canonical_Case_File_Name (Value.Value);
3420 Impls := In_Tree.Array_Elements.Table (Impls).Next;
3422 end Initialize_Naming_Data;
3424 -- Start of processing for Check_Naming_Schemes
3427 Specs := No_Array_Element;
3428 Bodies := No_Array_Element;
3430 -- No Naming package or parsing a configuration file? nothing to do
3432 if Naming_Id /= No_Package and not Is_Config_File then
3433 Naming := In_Tree.Packages.Table (Naming_Id);
3435 if Current_Verbosity = High then
3436 Write_Line ("Checking package Naming for project "
3437 & Get_Name_String (Project.Name));
3440 Initialize_Naming_Data;
3444 Check_Naming_Ada_Only;
3445 when Multi_Language =>
3446 Check_Naming_Multi_Lang;
3449 end Check_Package_Naming;
3451 ------------------------------
3452 -- Check_Library_Attributes --
3453 ------------------------------
3455 procedure Check_Library_Attributes
3456 (Project : Project_Id;
3457 In_Tree : Project_Tree_Ref)
3459 Attributes : constant Prj.Variable_Id := Project.Decl.Attributes;
3461 Lib_Dir : constant Prj.Variable_Value :=
3463 (Snames.Name_Library_Dir, Attributes, In_Tree);
3465 Lib_Name : constant Prj.Variable_Value :=
3467 (Snames.Name_Library_Name, Attributes, In_Tree);
3469 Lib_Version : constant Prj.Variable_Value :=
3471 (Snames.Name_Library_Version, Attributes, In_Tree);
3473 Lib_ALI_Dir : constant Prj.Variable_Value :=
3475 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3477 Lib_GCC : constant Prj.Variable_Value :=
3479 (Snames.Name_Library_GCC, Attributes, In_Tree);
3481 The_Lib_Kind : constant Prj.Variable_Value :=
3483 (Snames.Name_Library_Kind, Attributes, In_Tree);
3485 Imported_Project_List : Project_List;
3487 Continuation : String_Access := No_Continuation_String'Access;
3489 Support_For_Libraries : Library_Support;
3491 Library_Directory_Present : Boolean;
3493 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3494 -- Check if an imported or extended project if also a library project
3500 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3502 Iter : Source_Iterator;
3505 if Proj /= No_Project then
3506 if not Proj.Library then
3508 -- The only not library projects that are OK are those that
3509 -- have no sources. However, header files from non-Ada
3510 -- languages are OK, as there is nothing to compile.
3512 Iter := For_Each_Source (In_Tree, Proj);
3514 Src_Id := Prj.Element (Iter);
3515 exit when Src_Id = No_Source
3516 or else Src_Id.Language.Config.Kind /= File_Based
3517 or else Src_Id.Kind /= Spec;
3521 if Src_Id /= No_Source then
3522 Error_Msg_Name_1 := Project.Name;
3523 Error_Msg_Name_2 := Proj.Name;
3526 if Project.Library_Kind /= Static then
3530 "shared library project %% cannot extend " &
3531 "project %% that is not a library project",
3533 Continuation := Continuation_String'Access;
3536 elsif (not Unchecked_Shared_Lib_Imports)
3537 and then Project.Library_Kind /= Static
3542 "shared library project %% cannot import project %% " &
3543 "that is not a shared library project",
3545 Continuation := Continuation_String'Access;
3549 elsif Project.Library_Kind /= Static and then
3550 Proj.Library_Kind = Static
3552 Error_Msg_Name_1 := Project.Name;
3553 Error_Msg_Name_2 := Proj.Name;
3559 "shared library project %% cannot extend static " &
3560 "library project %%",
3562 Continuation := Continuation_String'Access;
3564 elsif not Unchecked_Shared_Lib_Imports then
3568 "shared library project %% cannot import static " &
3569 "library project %%",
3571 Continuation := Continuation_String'Access;
3578 Dir_Exists : Boolean;
3580 -- Start of processing for Check_Library_Attributes
3583 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3585 -- Special case of extending project
3587 if Project.Extends /= No_Project then
3589 -- If the project extended is a library project, we inherit the
3590 -- library name, if it is not redefined; we check that the library
3591 -- directory is specified.
3593 if Project.Extends.Library then
3594 if Project.Qualifier = Standard then
3597 "a standard project cannot extend a library project",
3601 if Lib_Name.Default then
3602 Project.Library_Name := Project.Extends.Library_Name;
3605 if Lib_Dir.Default then
3606 if not Project.Virtual then
3609 "a project extending a library project must " &
3610 "specify an attribute Library_Dir",
3614 -- For a virtual project extending a library project,
3615 -- inherit library directory.
3617 Project.Library_Dir := Project.Extends.Library_Dir;
3618 Library_Directory_Present := True;
3625 pragma Assert (Lib_Name.Kind = Single);
3627 if Lib_Name.Value = Empty_String then
3628 if Current_Verbosity = High
3629 and then Project.Library_Name = No_Name
3631 Write_Line ("No library name");
3635 -- There is no restriction on the syntax of library names
3637 Project.Library_Name := Lib_Name.Value;
3640 if Project.Library_Name /= No_Name then
3641 if Current_Verbosity = High then
3643 ("Library name", Get_Name_String (Project.Library_Name));
3646 pragma Assert (Lib_Dir.Kind = Single);
3648 if not Library_Directory_Present then
3649 if Current_Verbosity = High then
3650 Write_Line ("No library directory");
3654 -- Find path name (unless inherited), check that it is a directory
3656 if Project.Library_Dir = No_Path_Information then
3660 File_Name_Type (Lib_Dir.Value),
3661 Path => Project.Library_Dir,
3662 Dir_Exists => Dir_Exists,
3663 Create => "library",
3664 Must_Exist => False,
3665 Location => Lib_Dir.Location,
3666 Externally_Built => Project.Externally_Built);
3672 (Project.Library_Dir.Display_Name));
3675 if not Dir_Exists then
3676 -- Get the absolute name of the library directory that
3677 -- does not exist, to report an error.
3679 Err_Vars.Error_Msg_File_1 :=
3680 File_Name_Type (Project.Library_Dir.Display_Name);
3683 "library directory { does not exist",
3686 -- The library directory cannot be the same as the Object
3689 elsif Project.Library_Dir.Name = Project.Object_Directory.Name then
3692 "library directory cannot be the same " &
3693 "as object directory",
3695 Project.Library_Dir := No_Path_Information;
3699 OK : Boolean := True;
3700 Dirs_Id : String_List_Id;
3701 Dir_Elem : String_Element;
3705 -- The library directory cannot be the same as a source
3706 -- directory of the current project.
3708 Dirs_Id := Project.Source_Dirs;
3709 while Dirs_Id /= Nil_String loop
3710 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3711 Dirs_Id := Dir_Elem.Next;
3713 if Project.Library_Dir.Name =
3714 Path_Name_Type (Dir_Elem.Value)
3716 Err_Vars.Error_Msg_File_1 :=
3717 File_Name_Type (Dir_Elem.Value);
3720 "library directory cannot be the same " &
3721 "as source directory {",
3730 -- The library directory cannot be the same as a source
3731 -- directory of another project either.
3733 Pid := In_Tree.Projects;
3735 exit Project_Loop when Pid = null;
3737 if Pid.Project /= Project then
3738 Dirs_Id := Pid.Project.Source_Dirs;
3740 Dir_Loop : while Dirs_Id /= Nil_String loop
3742 In_Tree.String_Elements.Table (Dirs_Id);
3743 Dirs_Id := Dir_Elem.Next;
3745 if Project.Library_Dir.Name =
3746 Path_Name_Type (Dir_Elem.Value)
3748 Err_Vars.Error_Msg_File_1 :=
3749 File_Name_Type (Dir_Elem.Value);
3750 Err_Vars.Error_Msg_Name_1 := Pid.Project.Name;
3754 "library directory cannot be the same " &
3755 "as source directory { of project %%",
3764 end loop Project_Loop;
3768 Project.Library_Dir := No_Path_Information;
3770 elsif Current_Verbosity = High then
3772 -- Display the Library directory in high verbosity
3775 ("Library directory",
3776 Get_Name_String (Project.Library_Dir.Display_Name));
3785 Project.Library_Dir /= No_Path_Information
3786 and then Project.Library_Name /= No_Name;
3788 if Project.Extends = No_Project then
3789 case Project.Qualifier is
3791 if Project.Library then
3794 "a standard project cannot be a library project",
3799 if not Project.Library then
3800 if Project.Library_Dir = No_Path_Information then
3803 "\attribute Library_Dir not declared",
3807 if Project.Library_Name = No_Name then
3810 "\attribute Library_Name not declared",
3821 if Project.Library then
3822 if Get_Mode = Multi_Language then
3823 Support_For_Libraries := Project.Config.Lib_Support;
3826 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3829 if Support_For_Libraries = Prj.None then
3832 "?libraries are not supported on this platform",
3834 Project.Library := False;
3837 if Lib_ALI_Dir.Value = Empty_String then
3838 if Current_Verbosity = High then
3839 Write_Line ("No library ALI directory specified");
3842 Project.Library_ALI_Dir := Project.Library_Dir;
3845 -- Find path name, check that it is a directory
3850 File_Name_Type (Lib_ALI_Dir.Value),
3851 Path => Project.Library_ALI_Dir,
3852 Create => "library ALI",
3853 Dir_Exists => Dir_Exists,
3854 Must_Exist => False,
3855 Location => Lib_ALI_Dir.Location,
3856 Externally_Built => Project.Externally_Built);
3858 if not Dir_Exists then
3859 -- Get the absolute name of the library ALI directory that
3860 -- does not exist, to report an error.
3862 Err_Vars.Error_Msg_File_1 :=
3863 File_Name_Type (Project.Library_ALI_Dir.Display_Name);
3866 "library 'A'L'I directory { does not exist",
3867 Lib_ALI_Dir.Location);
3870 if Project.Library_ALI_Dir /= Project.Library_Dir then
3872 -- The library ALI directory cannot be the same as the
3873 -- Object directory.
3875 if Project.Library_ALI_Dir = Project.Object_Directory then
3878 "library 'A'L'I directory cannot be the same " &
3879 "as object directory",
3880 Lib_ALI_Dir.Location);
3881 Project.Library_ALI_Dir := No_Path_Information;
3885 OK : Boolean := True;
3886 Dirs_Id : String_List_Id;
3887 Dir_Elem : String_Element;
3891 -- The library ALI directory cannot be the same as
3892 -- a source directory of the current project.
3894 Dirs_Id := Project.Source_Dirs;
3895 while Dirs_Id /= Nil_String loop
3896 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3897 Dirs_Id := Dir_Elem.Next;
3899 if Project.Library_ALI_Dir.Name =
3900 Path_Name_Type (Dir_Elem.Value)
3902 Err_Vars.Error_Msg_File_1 :=
3903 File_Name_Type (Dir_Elem.Value);
3906 "library 'A'L'I directory cannot be " &
3907 "the same as source directory {",
3908 Lib_ALI_Dir.Location);
3916 -- The library ALI directory cannot be the same as
3917 -- a source directory of another project either.
3919 Pid := In_Tree.Projects;
3920 ALI_Project_Loop : loop
3921 exit ALI_Project_Loop when Pid = null;
3923 if Pid.Project /= Project then
3924 Dirs_Id := Pid.Project.Source_Dirs;
3927 while Dirs_Id /= Nil_String loop
3929 In_Tree.String_Elements.Table (Dirs_Id);
3930 Dirs_Id := Dir_Elem.Next;
3932 if Project.Library_ALI_Dir.Name =
3933 Path_Name_Type (Dir_Elem.Value)
3935 Err_Vars.Error_Msg_File_1 :=
3936 File_Name_Type (Dir_Elem.Value);
3937 Err_Vars.Error_Msg_Name_1 :=
3942 "library 'A'L'I directory cannot " &
3943 "be the same as source directory " &
3945 Lib_ALI_Dir.Location);
3947 exit ALI_Project_Loop;
3949 end loop ALI_Dir_Loop;
3952 end loop ALI_Project_Loop;
3956 Project.Library_ALI_Dir := No_Path_Information;
3958 elsif Current_Verbosity = High then
3960 -- Display the Library ALI directory in high
3966 (Project.Library_ALI_Dir.Display_Name));
3973 pragma Assert (Lib_Version.Kind = Single);
3975 if Lib_Version.Value = Empty_String then
3976 if Current_Verbosity = High then
3977 Write_Line ("No library version specified");
3981 Project.Lib_Internal_Name := Lib_Version.Value;
3984 pragma Assert (The_Lib_Kind.Kind = Single);
3986 if The_Lib_Kind.Value = Empty_String then
3987 if Current_Verbosity = High then
3988 Write_Line ("No library kind specified");
3992 Get_Name_String (The_Lib_Kind.Value);
3995 Kind_Name : constant String :=
3996 To_Lower (Name_Buffer (1 .. Name_Len));
3998 OK : Boolean := True;
4001 if Kind_Name = "static" then
4002 Project.Library_Kind := Static;
4004 elsif Kind_Name = "dynamic" then
4005 Project.Library_Kind := Dynamic;
4007 elsif Kind_Name = "relocatable" then
4008 Project.Library_Kind := Relocatable;
4013 "illegal value for Library_Kind",
4014 The_Lib_Kind.Location);
4018 if Current_Verbosity = High and then OK then
4019 Write_Attr ("Library kind", Kind_Name);
4022 if Project.Library_Kind /= Static then
4023 if Support_For_Libraries = Prj.Static_Only then
4026 "only static libraries are supported " &
4028 The_Lib_Kind.Location);
4029 Project.Library := False;
4032 -- Check if (obsolescent) attribute Library_GCC or
4033 -- Linker'Driver is declared.
4035 if Lib_GCC.Value /= Empty_String then
4039 "?Library_'G'C'C is an obsolescent attribute, " &
4040 "use Linker''Driver instead",
4042 Project.Config.Shared_Lib_Driver :=
4043 File_Name_Type (Lib_GCC.Value);
4047 Linker : constant Package_Id :=
4050 Project.Decl.Packages,
4052 Driver : constant Variable_Value :=
4055 Attribute_Or_Array_Name =>
4057 In_Package => Linker,
4062 if Driver /= Nil_Variable_Value
4063 and then Driver.Value /= Empty_String
4065 Project.Config.Shared_Lib_Driver :=
4066 File_Name_Type (Driver.Value);
4075 if Project.Library then
4076 if Current_Verbosity = High then
4077 Write_Line ("This is a library project file");
4080 if Get_Mode = Multi_Language then
4081 Check_Library (Project.Extends, Extends => True);
4083 Imported_Project_List := Project.Imported_Projects;
4084 while Imported_Project_List /= null loop
4086 (Imported_Project_List.Project,
4088 Imported_Project_List := Imported_Project_List.Next;
4096 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4097 -- Warn if they are declared, as it is a common error to think that
4098 -- library are "linked" with Linker switches.
4100 if Project.Library then
4102 Linker_Package_Id : constant Package_Id :=
4105 Project.Decl.Packages, In_Tree);
4106 Linker_Package : Package_Element;
4107 Switches : Array_Element_Id := No_Array_Element;
4110 if Linker_Package_Id /= No_Package then
4111 Linker_Package := In_Tree.Packages.Table (Linker_Package_Id);
4115 (Name => Name_Switches,
4116 In_Arrays => Linker_Package.Decl.Arrays,
4117 In_Tree => In_Tree);
4119 if Switches = No_Array_Element then
4122 (Name => Name_Default_Switches,
4123 In_Arrays => Linker_Package.Decl.Arrays,
4124 In_Tree => In_Tree);
4127 if Switches /= No_Array_Element then
4130 "?Linker switches not taken into account in library " &
4138 if Project.Extends /= No_Project then
4139 Project.Extends.Library := False;
4141 end Check_Library_Attributes;
4143 ---------------------------------
4144 -- Check_Programming_Languages --
4145 ---------------------------------
4147 procedure Check_Programming_Languages
4148 (In_Tree : Project_Tree_Ref;
4149 Project : Project_Id)
4151 Languages : Variable_Value := Nil_Variable_Value;
4152 Def_Lang : Variable_Value := Nil_Variable_Value;
4153 Def_Lang_Id : Name_Id;
4155 procedure Add_Language (Name, Display_Name : Name_Id);
4156 -- Add a new language to the list of languages for the project.
4157 -- Nothing is done if the language has already been defined
4159 procedure Add_Language (Name, Display_Name : Name_Id) is
4160 Lang : Language_Ptr := Project.Languages;
4162 while Lang /= No_Language_Index loop
4163 if Name = Lang.Name then
4170 Lang := new Language_Data'(No_Language_Data);
4171 Lang.Next := Project.Languages;
4172 Project.Languages := Lang;
4174 Lang.Display_Name := Display_Name;
4176 if Name = Name_Ada then
4177 Lang.Config.Kind := Unit_Based;
4178 Lang.Config.Dependency_Kind := ALI_File;
4180 if Get_Mode = Ada_Only then
4181 -- Create a default config for Ada (since there is no
4182 -- configuration file to create it for us)
4183 -- ??? We should do as GPS does and create a dummy config
4186 Lang.Config.Naming_Data :=
4187 (Dot_Replacement => File_Name_Type
4188 (First_Name_Id + Character'Pos ('-')),
4189 Casing => All_Lower_Case,
4190 Separate_Suffix => Default_Ada_Body_Suffix,
4191 Spec_Suffix => Default_Ada_Spec_Suffix,
4192 Body_Suffix => Default_Ada_Body_Suffix);
4196 Lang.Config.Kind := File_Based;
4201 Project.Languages := null;
4203 Prj.Util.Value_Of (Name_Languages, Project.Decl.Attributes, In_Tree);
4206 (Name_Default_Language, Project.Decl.Attributes, In_Tree);
4208 -- Shouldn't these be set to False by default, and only set to True when
4209 -- we actually find some source file???
4211 if Project.Source_Dirs /= Nil_String then
4213 -- Check if languages are specified in this project
4215 if Languages.Default then
4217 -- In Ada_Only mode, the default language is Ada
4219 if Get_Mode = Ada_Only then
4220 Def_Lang_Id := Name_Ada;
4223 -- Fail if there is no default language defined
4225 if Def_Lang.Default then
4226 if not Default_Language_Is_Ada then
4230 "no languages defined for this project",
4232 Def_Lang_Id := No_Name;
4234 Def_Lang_Id := Name_Ada;
4238 Get_Name_String (Def_Lang.Value);
4239 To_Lower (Name_Buffer (1 .. Name_Len));
4240 Def_Lang_Id := Name_Find;
4244 if Def_Lang_Id /= No_Name then
4245 Get_Name_String (Def_Lang_Id);
4246 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4248 (Name => Def_Lang_Id,
4249 Display_Name => Name_Find);
4254 Current : String_List_Id := Languages.Values;
4255 Element : String_Element;
4258 -- If there are no languages declared, there are no sources
4260 if Current = Nil_String then
4261 Project.Source_Dirs := Nil_String;
4263 if Project.Qualifier = Standard then
4267 "a standard project must have at least one language",
4268 Languages.Location);
4272 -- Look through all the languages specified in attribute
4275 while Current /= Nil_String loop
4276 Element := In_Tree.String_Elements.Table (Current);
4277 Get_Name_String (Element.Value);
4278 To_Lower (Name_Buffer (1 .. Name_Len));
4282 Display_Name => Element.Value);
4284 Current := Element.Next;
4290 end Check_Programming_Languages;
4296 function Check_Project
4298 Root_Project : Project_Id;
4299 Extending : Boolean) return Boolean
4303 if P = Root_Project then
4306 elsif Extending then
4307 Prj := Root_Project;
4308 while Prj.Extends /= No_Project loop
4309 if P = Prj.Extends then
4320 -------------------------------
4321 -- Check_Stand_Alone_Library --
4322 -------------------------------
4324 procedure Check_Stand_Alone_Library
4325 (Project : Project_Id;
4326 In_Tree : Project_Tree_Ref;
4327 Current_Dir : String;
4328 Extending : Boolean)
4330 Lib_Interfaces : constant Prj.Variable_Value :=
4332 (Snames.Name_Library_Interface,
4333 Project.Decl.Attributes,
4336 Lib_Auto_Init : constant Prj.Variable_Value :=
4338 (Snames.Name_Library_Auto_Init,
4339 Project.Decl.Attributes,
4342 Lib_Src_Dir : constant Prj.Variable_Value :=
4344 (Snames.Name_Library_Src_Dir,
4345 Project.Decl.Attributes,
4348 Lib_Symbol_File : constant Prj.Variable_Value :=
4350 (Snames.Name_Library_Symbol_File,
4351 Project.Decl.Attributes,
4354 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4356 (Snames.Name_Library_Symbol_Policy,
4357 Project.Decl.Attributes,
4360 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4362 (Snames.Name_Library_Reference_Symbol_File,
4363 Project.Decl.Attributes,
4366 Auto_Init_Supported : Boolean;
4367 OK : Boolean := True;
4369 Next_Proj : Project_Id;
4370 Iter : Source_Iterator;
4373 if Get_Mode = Multi_Language then
4374 Auto_Init_Supported := Project.Config.Auto_Init_Supported;
4376 Auto_Init_Supported :=
4377 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4380 pragma Assert (Lib_Interfaces.Kind = List);
4382 -- It is a stand-alone library project file if attribute
4383 -- Library_Interface is defined.
4385 if not Lib_Interfaces.Default then
4386 SAL_Library : declare
4387 Interfaces : String_List_Id := Lib_Interfaces.Values;
4388 Interface_ALIs : String_List_Id := Nil_String;
4392 procedure Add_ALI_For (Source : File_Name_Type);
4393 -- Add an ALI file name to the list of Interface ALIs
4399 procedure Add_ALI_For (Source : File_Name_Type) is
4401 Get_Name_String (Source);
4404 ALI : constant String :=
4405 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4406 ALI_Name_Id : Name_Id;
4409 Name_Len := ALI'Length;
4410 Name_Buffer (1 .. Name_Len) := ALI;
4411 ALI_Name_Id := Name_Find;
4413 String_Element_Table.Increment_Last
4414 (In_Tree.String_Elements);
4415 In_Tree.String_Elements.Table
4416 (String_Element_Table.Last
4417 (In_Tree.String_Elements)) :=
4418 (Value => ALI_Name_Id,
4420 Display_Value => ALI_Name_Id,
4422 In_Tree.String_Elements.Table
4423 (Interfaces).Location,
4425 Next => Interface_ALIs);
4426 Interface_ALIs := String_Element_Table.Last
4427 (In_Tree.String_Elements);
4431 -- Start of processing for SAL_Library
4434 Project.Standalone_Library := True;
4436 -- Library_Interface cannot be an empty list
4438 if Interfaces = Nil_String then
4441 "Library_Interface cannot be an empty list",
4442 Lib_Interfaces.Location);
4445 -- Process each unit name specified in the attribute
4446 -- Library_Interface.
4448 while Interfaces /= Nil_String loop
4450 (In_Tree.String_Elements.Table (Interfaces).Value);
4451 To_Lower (Name_Buffer (1 .. Name_Len));
4453 if Name_Len = 0 then
4456 "an interface cannot be an empty string",
4457 In_Tree.String_Elements.Table (Interfaces).Location);
4461 Error_Msg_Name_1 := Unit;
4463 if Get_Mode = Ada_Only then
4464 UData := Units_Htable.Get (In_Tree.Units_HT, Unit);
4466 if UData = No_Unit_Index then
4470 In_Tree.String_Elements.Table
4471 (Interfaces).Location);
4474 -- Check that the unit is part of the project
4476 if UData.File_Names (Impl) /= null
4477 and then not UData.File_Names (Impl).Locally_Removed
4480 (UData.File_Names (Impl).Project,
4483 -- There is a body for this unit. If there is
4484 -- no spec, we need to check that it is not a
4487 if UData.File_Names (Spec) = null then
4489 Src_Ind : Source_File_Index;
4493 Sinput.P.Load_Project_File
4494 (Get_Name_String (UData.File_Names
4497 if Sinput.P.Source_File_Is_Subunit
4502 "%% is a subunit; " &
4503 "it cannot be an interface",
4505 String_Elements.Table
4506 (Interfaces).Location);
4511 -- The unit is not a subunit, so we add the
4512 -- ALI file for its body to the Interface ALIs.
4515 (UData.File_Names (Impl).File);
4520 "%% is not an unit of this project",
4521 In_Tree.String_Elements.Table
4522 (Interfaces).Location);
4525 elsif UData.File_Names (Spec) /= null
4526 and then not UData.File_Names (Spec).Locally_Removed
4527 and then Check_Project
4528 (UData.File_Names (Spec).Project,
4532 -- The unit is part of the project, it has a spec,
4533 -- but no body. We add the ALI for its spec to the
4537 (UData.File_Names (Spec).File);
4542 "%% is not an unit of this project",
4543 In_Tree.String_Elements.Table
4544 (Interfaces).Location);
4549 -- Multi_Language mode
4551 Next_Proj := Project.Extends;
4552 Iter := For_Each_Source (In_Tree, Project);
4554 while Prj.Element (Iter) /= No_Source
4556 (Prj.Element (Iter).Unit = null
4557 or else Prj.Element (Iter).Unit.Name /= Unit)
4562 Source := Prj.Element (Iter);
4563 exit when Source /= No_Source
4564 or else Next_Proj = No_Project;
4566 Iter := For_Each_Source (In_Tree, Next_Proj);
4567 Next_Proj := Next_Proj.Extends;
4570 if Source /= No_Source then
4571 if Source.Kind = Sep then
4572 Source := No_Source;
4573 elsif Source.Kind = Spec
4574 and then Other_Part (Source) /= No_Source
4576 Source := Other_Part (Source);
4580 if Source /= No_Source then
4581 if Source.Project /= Project
4582 and then not Is_Extending (Project, Source.Project)
4584 Source := No_Source;
4588 if Source = No_Source then
4591 "%% is not an unit of this project",
4592 In_Tree.String_Elements.Table
4593 (Interfaces).Location);
4596 if Source.Kind = Spec
4597 and then Other_Part (Source) /= No_Source
4599 Source := Other_Part (Source);
4602 String_Element_Table.Increment_Last
4603 (In_Tree.String_Elements);
4605 In_Tree.String_Elements.Table
4606 (String_Element_Table.Last
4607 (In_Tree.String_Elements)) :=
4608 (Value => Name_Id (Source.Dep_Name),
4610 Display_Value => Name_Id (Source.Dep_Name),
4612 In_Tree.String_Elements.Table
4613 (Interfaces).Location,
4615 Next => Interface_ALIs);
4618 String_Element_Table.Last (In_Tree.String_Elements);
4626 In_Tree.String_Elements.Table (Interfaces).Next;
4629 -- Put the list of Interface ALIs in the project data
4631 Project.Lib_Interface_ALIs := Interface_ALIs;
4633 -- Check value of attribute Library_Auto_Init and set
4634 -- Lib_Auto_Init accordingly.
4636 if Lib_Auto_Init.Default then
4638 -- If no attribute Library_Auto_Init is declared, then set auto
4639 -- init only if it is supported.
4641 Project.Lib_Auto_Init := Auto_Init_Supported;
4644 Get_Name_String (Lib_Auto_Init.Value);
4645 To_Lower (Name_Buffer (1 .. Name_Len));
4647 if Name_Buffer (1 .. Name_Len) = "false" then
4648 Project.Lib_Auto_Init := False;
4650 elsif Name_Buffer (1 .. Name_Len) = "true" then
4651 if Auto_Init_Supported then
4652 Project.Lib_Auto_Init := True;
4655 -- Library_Auto_Init cannot be "true" if auto init is not
4660 "library auto init not supported " &
4662 Lib_Auto_Init.Location);
4668 "invalid value for attribute Library_Auto_Init",
4669 Lib_Auto_Init.Location);
4674 -- If attribute Library_Src_Dir is defined and not the empty string,
4675 -- check if the directory exist and is not the object directory or
4676 -- one of the source directories. This is the directory where copies
4677 -- of the interface sources will be copied. Note that this directory
4678 -- may be the library directory.
4680 if Lib_Src_Dir.Value /= Empty_String then
4682 Dir_Id : constant File_Name_Type :=
4683 File_Name_Type (Lib_Src_Dir.Value);
4684 Dir_Exists : Boolean;
4691 Path => Project.Library_Src_Dir,
4692 Dir_Exists => Dir_Exists,
4693 Must_Exist => False,
4694 Create => "library source copy",
4695 Location => Lib_Src_Dir.Location,
4696 Externally_Built => Project.Externally_Built);
4698 -- If directory does not exist, report an error
4700 if not Dir_Exists then
4701 -- Get the absolute name of the library directory that does
4702 -- not exist, to report an error.
4704 Err_Vars.Error_Msg_File_1 :=
4705 File_Name_Type (Project.Library_Src_Dir.Display_Name);
4708 "Directory { does not exist",
4709 Lib_Src_Dir.Location);
4711 -- Report error if it is the same as the object directory
4713 elsif Project.Library_Src_Dir = Project.Object_Directory then
4716 "directory to copy interfaces cannot be " &
4717 "the object directory",
4718 Lib_Src_Dir.Location);
4719 Project.Library_Src_Dir := No_Path_Information;
4723 Src_Dirs : String_List_Id;
4724 Src_Dir : String_Element;
4728 -- Interface copy directory cannot be one of the source
4729 -- directory of the current project.
4731 Src_Dirs := Project.Source_Dirs;
4732 while Src_Dirs /= Nil_String loop
4733 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
4735 -- Report error if it is one of the source directories
4737 if Project.Library_Src_Dir.Name =
4738 Path_Name_Type (Src_Dir.Value)
4742 "directory to copy interfaces cannot " &
4743 "be one of the source directories",
4744 Lib_Src_Dir.Location);
4745 Project.Library_Src_Dir := No_Path_Information;
4749 Src_Dirs := Src_Dir.Next;
4752 if Project.Library_Src_Dir /= No_Path_Information then
4754 -- It cannot be a source directory of any other
4757 Pid := In_Tree.Projects;
4759 exit Project_Loop when Pid = null;
4761 Src_Dirs := Pid.Project.Source_Dirs;
4762 Dir_Loop : while Src_Dirs /= Nil_String loop
4764 In_Tree.String_Elements.Table (Src_Dirs);
4766 -- Report error if it is one of the source
4769 if Project.Library_Src_Dir.Name =
4770 Path_Name_Type (Src_Dir.Value)
4773 File_Name_Type (Src_Dir.Value);
4774 Error_Msg_Name_1 := Pid.Project.Name;
4777 "directory to copy interfaces cannot " &
4778 "be the same as source directory { of " &
4780 Lib_Src_Dir.Location);
4781 Project.Library_Src_Dir :=
4782 No_Path_Information;
4786 Src_Dirs := Src_Dir.Next;
4790 end loop Project_Loop;
4794 -- In high verbosity, if there is a valid Library_Src_Dir,
4795 -- display its path name.
4797 if Project.Library_Src_Dir /= No_Path_Information
4798 and then Current_Verbosity = High
4801 ("Directory to copy interfaces",
4802 Get_Name_String (Project.Library_Src_Dir.Name));
4808 -- Check the symbol related attributes
4810 -- First, the symbol policy
4812 if not Lib_Symbol_Policy.Default then
4814 Value : constant String :=
4816 (Get_Name_String (Lib_Symbol_Policy.Value));
4819 -- Symbol policy must hove one of a limited number of values
4821 if Value = "autonomous" or else Value = "default" then
4822 Project.Symbol_Data.Symbol_Policy := Autonomous;
4824 elsif Value = "compliant" then
4825 Project.Symbol_Data.Symbol_Policy := Compliant;
4827 elsif Value = "controlled" then
4828 Project.Symbol_Data.Symbol_Policy := Controlled;
4830 elsif Value = "restricted" then
4831 Project.Symbol_Data.Symbol_Policy := Restricted;
4833 elsif Value = "direct" then
4834 Project.Symbol_Data.Symbol_Policy := Direct;
4839 "illegal value for Library_Symbol_Policy",
4840 Lib_Symbol_Policy.Location);
4845 -- If attribute Library_Symbol_File is not specified, symbol policy
4846 -- cannot be Restricted.
4848 if Lib_Symbol_File.Default then
4849 if Project.Symbol_Data.Symbol_Policy = Restricted then
4852 "Library_Symbol_File needs to be defined when " &
4853 "symbol policy is Restricted",
4854 Lib_Symbol_Policy.Location);
4858 -- Library_Symbol_File is defined
4860 Project.Symbol_Data.Symbol_File :=
4861 Path_Name_Type (Lib_Symbol_File.Value);
4863 Get_Name_String (Lib_Symbol_File.Value);
4865 if Name_Len = 0 then
4868 "symbol file name cannot be an empty string",
4869 Lib_Symbol_File.Location);
4872 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
4875 for J in 1 .. Name_Len loop
4876 if Name_Buffer (J) = '/'
4877 or else Name_Buffer (J) = Directory_Separator
4886 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
4889 "symbol file name { is illegal. " &
4890 "Name cannot include directory info.",
4891 Lib_Symbol_File.Location);
4896 -- If attribute Library_Reference_Symbol_File is not defined,
4897 -- symbol policy cannot be Compliant or Controlled.
4899 if Lib_Ref_Symbol_File.Default then
4900 if Project.Symbol_Data.Symbol_Policy = Compliant
4901 or else Project.Symbol_Data.Symbol_Policy = Controlled
4905 "a reference symbol file needs to be defined",
4906 Lib_Symbol_Policy.Location);
4910 -- Library_Reference_Symbol_File is defined, check file exists
4912 Project.Symbol_Data.Reference :=
4913 Path_Name_Type (Lib_Ref_Symbol_File.Value);
4915 Get_Name_String (Lib_Ref_Symbol_File.Value);
4917 if Name_Len = 0 then
4920 "reference symbol file name cannot be an empty string",
4921 Lib_Symbol_File.Location);
4924 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
4926 Add_Str_To_Name_Buffer
4927 (Get_Name_String (Project.Directory.Name));
4928 Add_Char_To_Name_Buffer (Directory_Separator);
4929 Add_Str_To_Name_Buffer
4930 (Get_Name_String (Lib_Ref_Symbol_File.Value));
4931 Project.Symbol_Data.Reference := Name_Find;
4934 if not Is_Regular_File
4935 (Get_Name_String (Project.Symbol_Data.Reference))
4938 File_Name_Type (Lib_Ref_Symbol_File.Value);
4940 -- For controlled and direct symbol policies, it is an error
4941 -- if the reference symbol file does not exist. For other
4942 -- symbol policies, this is just a warning
4945 Project.Symbol_Data.Symbol_Policy /= Controlled
4946 and then Project.Symbol_Data.Symbol_Policy /= Direct;
4950 "<library reference symbol file { does not exist",
4951 Lib_Ref_Symbol_File.Location);
4953 -- In addition in the non-controlled case, if symbol policy
4954 -- is Compliant, it is changed to Autonomous, because there
4955 -- is no reference to check against, and we don't want to
4956 -- fail in this case.
4958 if Project.Symbol_Data.Symbol_Policy /= Controlled then
4959 if Project.Symbol_Data.Symbol_Policy = Compliant then
4960 Project.Symbol_Data.Symbol_Policy := Autonomous;
4965 -- If both the reference symbol file and the symbol file are
4966 -- defined, then check that they are not the same file.
4968 if Project.Symbol_Data.Symbol_File /= No_Path then
4969 Get_Name_String (Project.Symbol_Data.Symbol_File);
4971 if Name_Len > 0 then
4973 Symb_Path : constant String :=
4976 (Project.Object_Directory.Name) &
4977 Directory_Separator &
4978 Name_Buffer (1 .. Name_Len),
4979 Directory => Current_Dir,
4981 Opt.Follow_Links_For_Files);
4982 Ref_Path : constant String :=
4985 (Project.Symbol_Data.Reference),
4986 Directory => Current_Dir,
4988 Opt.Follow_Links_For_Files);
4990 if Symb_Path = Ref_Path then
4993 "library reference symbol file and library" &
4994 " symbol file cannot be the same file",
4995 Lib_Ref_Symbol_File.Location);
5003 end Check_Stand_Alone_Library;
5005 ----------------------------
5006 -- Compute_Directory_Last --
5007 ----------------------------
5009 function Compute_Directory_Last (Dir : String) return Natural is
5012 and then (Dir (Dir'Last - 1) = Directory_Separator
5013 or else Dir (Dir'Last - 1) = '/')
5015 return Dir'Last - 1;
5019 end Compute_Directory_Last;
5026 (Project : Project_Id;
5027 In_Tree : Project_Tree_Ref;
5029 Flag_Location : Source_Ptr)
5031 Real_Location : Source_Ptr := Flag_Location;
5032 Error_Buffer : String (1 .. 5_000);
5033 Error_Last : Natural := 0;
5034 Name_Number : Natural := 0;
5035 File_Number : Natural := 0;
5036 First : Positive := Msg'First;
5039 procedure Add (C : Character);
5040 -- Add a character to the buffer
5042 procedure Add (S : String);
5043 -- Add a string to the buffer
5046 -- Add a name to the buffer
5049 -- Add a file name to the buffer
5055 procedure Add (C : Character) is
5057 Error_Last := Error_Last + 1;
5058 Error_Buffer (Error_Last) := C;
5061 procedure Add (S : String) is
5063 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5064 Error_Last := Error_Last + S'Length;
5071 procedure Add_File is
5072 File : File_Name_Type;
5076 File_Number := File_Number + 1;
5080 File := Err_Vars.Error_Msg_File_1;
5082 File := Err_Vars.Error_Msg_File_2;
5084 File := Err_Vars.Error_Msg_File_3;
5089 Get_Name_String (File);
5090 Add (Name_Buffer (1 .. Name_Len));
5098 procedure Add_Name is
5103 Name_Number := Name_Number + 1;
5107 Name := Err_Vars.Error_Msg_Name_1;
5109 Name := Err_Vars.Error_Msg_Name_2;
5111 Name := Err_Vars.Error_Msg_Name_3;
5116 Get_Name_String (Name);
5117 Add (Name_Buffer (1 .. Name_Len));
5121 -- Start of processing for Error_Msg
5124 -- If location of error is unknown, use the location of the project
5126 if Real_Location = No_Location then
5127 Real_Location := Project.Location;
5130 if Error_Report = null then
5131 Prj.Err.Error_Msg (Msg, Real_Location);
5135 -- Ignore continuation character
5137 if Msg (First) = '\' then
5141 -- Warning character is always the first one in this package
5142 -- this is an undocumented kludge???
5144 if Msg (First) = '?' then
5148 elsif Msg (First) = '<' then
5151 if Err_Vars.Error_Msg_Warn then
5157 while Index <= Msg'Last loop
5158 if Msg (Index) = '{' then
5161 elsif Msg (Index) = '%' then
5162 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5174 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5177 --------------------------------
5178 -- Free_Ada_Naming_Exceptions --
5179 --------------------------------
5181 procedure Free_Ada_Naming_Exceptions is
5183 Ada_Naming_Exception_Table.Set_Last (0);
5184 Ada_Naming_Exceptions.Reset;
5185 Reverse_Ada_Naming_Exceptions.Reset;
5186 end Free_Ada_Naming_Exceptions;
5188 ---------------------
5189 -- Get_Directories --
5190 ---------------------
5192 procedure Get_Directories
5193 (Project : Project_Id;
5194 In_Tree : Project_Tree_Ref;
5195 Current_Dir : String)
5197 Object_Dir : constant Variable_Value :=
5199 (Name_Object_Dir, Project.Decl.Attributes, In_Tree);
5201 Exec_Dir : constant Variable_Value :=
5203 (Name_Exec_Dir, Project.Decl.Attributes, In_Tree);
5205 Source_Dirs : constant Variable_Value :=
5207 (Name_Source_Dirs, Project.Decl.Attributes, In_Tree);
5209 Excluded_Source_Dirs : constant Variable_Value :=
5211 (Name_Excluded_Source_Dirs,
5212 Project.Decl.Attributes,
5215 Source_Files : constant Variable_Value :=
5217 (Name_Source_Files, Project.Decl.Attributes, In_Tree);
5219 Last_Source_Dir : String_List_Id := Nil_String;
5221 Languages : constant Variable_Value :=
5223 (Name_Languages, Project.Decl.Attributes, In_Tree);
5225 procedure Find_Source_Dirs
5226 (From : File_Name_Type;
5227 Location : Source_Ptr;
5228 Removed : Boolean := False);
5229 -- Find one or several source directories, and add (or remove, if
5230 -- Removed is True) them to list of source directories of the project.
5232 ----------------------
5233 -- Find_Source_Dirs --
5234 ----------------------
5236 procedure Find_Source_Dirs
5237 (From : File_Name_Type;
5238 Location : Source_Ptr;
5239 Removed : Boolean := False)
5241 Directory : constant String := Get_Name_String (From);
5242 Element : String_Element;
5244 procedure Recursive_Find_Dirs (Path : Name_Id);
5245 -- Find all the subdirectories (recursively) of Path and add them
5246 -- to the list of source directories of the project.
5248 -------------------------
5249 -- Recursive_Find_Dirs --
5250 -------------------------
5252 procedure Recursive_Find_Dirs (Path : Name_Id) is
5254 Name : String (1 .. 250);
5256 List : String_List_Id;
5257 Prev : String_List_Id;
5258 Element : String_Element;
5259 Found : Boolean := False;
5261 Non_Canonical_Path : Name_Id := No_Name;
5262 Canonical_Path : Name_Id := No_Name;
5264 The_Path : constant String :=
5266 (Get_Name_String (Path),
5267 Directory => Current_Dir,
5268 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5269 Directory_Separator;
5271 The_Path_Last : constant Natural :=
5272 Compute_Directory_Last (The_Path);
5275 Name_Len := The_Path_Last - The_Path'First + 1;
5276 Name_Buffer (1 .. Name_Len) :=
5277 The_Path (The_Path'First .. The_Path_Last);
5278 Non_Canonical_Path := Name_Find;
5280 Name_Id (Canonical_Case_File_Name (Non_Canonical_Path));
5282 -- To avoid processing the same directory several times, check
5283 -- if the directory is already in Recursive_Dirs. If it is, then
5284 -- there is nothing to do, just return. If it is not, put it there
5285 -- and continue recursive processing.
5288 if Recursive_Dirs.Get (Canonical_Path) then
5291 Recursive_Dirs.Set (Canonical_Path, True);
5295 -- Check if directory is already in list
5297 List := Project.Source_Dirs;
5299 while List /= Nil_String loop
5300 Element := In_Tree.String_Elements.Table (List);
5302 if Element.Value /= No_Name then
5303 Found := Element.Value = Canonical_Path;
5308 List := Element.Next;
5311 -- If directory is not already in list, put it there
5313 if (not Removed) and (not Found) then
5314 if Current_Verbosity = High then
5316 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5319 String_Element_Table.Increment_Last
5320 (In_Tree.String_Elements);
5322 (Value => Canonical_Path,
5323 Display_Value => Non_Canonical_Path,
5324 Location => No_Location,
5329 -- Case of first source directory
5331 if Last_Source_Dir = Nil_String then
5332 Project.Source_Dirs := String_Element_Table.Last
5333 (In_Tree.String_Elements);
5335 -- Here we already have source directories
5338 -- Link the previous last to the new one
5340 In_Tree.String_Elements.Table
5341 (Last_Source_Dir).Next :=
5342 String_Element_Table.Last
5343 (In_Tree.String_Elements);
5346 -- And register this source directory as the new last
5348 Last_Source_Dir := String_Element_Table.Last
5349 (In_Tree.String_Elements);
5350 In_Tree.String_Elements.Table (Last_Source_Dir) :=
5353 elsif Removed and Found then
5354 if Prev = Nil_String then
5355 Project.Source_Dirs :=
5356 In_Tree.String_Elements.Table (List).Next;
5358 In_Tree.String_Elements.Table (Prev).Next :=
5359 In_Tree.String_Elements.Table (List).Next;
5363 -- Now look for subdirectories. We do that even when this
5364 -- directory is already in the list, because some of its
5365 -- subdirectories may not be in the list yet.
5367 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5370 Read (Dir, Name, Last);
5373 if Name (1 .. Last) /= "."
5374 and then Name (1 .. Last) /= ".."
5376 -- Avoid . and .. directories
5378 if Current_Verbosity = High then
5379 Write_Str (" Checking ");
5380 Write_Line (Name (1 .. Last));
5384 Path_Name : constant String :=
5386 (Name => Name (1 .. Last),
5388 The_Path (The_Path'First .. The_Path_Last),
5389 Resolve_Links => Opt.Follow_Links_For_Dirs,
5390 Case_Sensitive => True);
5393 if Is_Directory (Path_Name) then
5394 -- We have found a new subdirectory, call self
5396 Name_Len := Path_Name'Length;
5397 Name_Buffer (1 .. Name_Len) := Path_Name;
5398 Recursive_Find_Dirs (Name_Find);
5407 when Directory_Error =>
5409 end Recursive_Find_Dirs;
5411 -- Start of processing for Find_Source_Dirs
5414 if Current_Verbosity = High and then not Removed then
5415 Write_Str ("Find_Source_Dirs (""");
5416 Write_Str (Directory);
5420 -- First, check if we are looking for a directory tree, indicated
5421 -- by "/**" at the end.
5423 if Directory'Length >= 3
5424 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5425 and then (Directory (Directory'Last - 2) = '/'
5427 Directory (Directory'Last - 2) = Directory_Separator)
5430 Project.Known_Order_Of_Source_Dirs := False;
5433 Name_Len := Directory'Length - 3;
5435 if Name_Len = 0 then
5437 -- Case of "/**": all directories in file system
5440 Name_Buffer (1) := Directory (Directory'First);
5443 Name_Buffer (1 .. Name_Len) :=
5444 Directory (Directory'First .. Directory'Last - 3);
5447 if Current_Verbosity = High then
5448 Write_Str ("Looking for all subdirectories of """);
5449 Write_Str (Name_Buffer (1 .. Name_Len));
5454 Base_Dir : constant File_Name_Type := Name_Find;
5455 Root_Dir : constant String :=
5457 (Name => Get_Name_String (Base_Dir),
5460 (Project.Directory.Display_Name),
5461 Resolve_Links => False,
5462 Case_Sensitive => True);
5465 if Root_Dir'Length = 0 then
5466 Err_Vars.Error_Msg_File_1 := Base_Dir;
5468 if Location = No_Location then
5471 "{ is not a valid directory.",
5476 "{ is not a valid directory.",
5481 -- We have an existing directory, we register it and all of
5482 -- its subdirectories.
5484 if Current_Verbosity = High then
5485 Write_Line ("Looking for source directories:");
5488 Name_Len := Root_Dir'Length;
5489 Name_Buffer (1 .. Name_Len) := Root_Dir;
5490 Recursive_Find_Dirs (Name_Find);
5492 if Current_Verbosity = High then
5493 Write_Line ("End of looking for source directories.");
5498 -- We have a single directory
5502 Path_Name : Path_Information;
5503 List : String_List_Id;
5504 Prev : String_List_Id;
5505 Dir_Exists : Boolean;
5509 (Project => Project,
5513 Dir_Exists => Dir_Exists,
5514 Must_Exist => False);
5516 if not Dir_Exists then
5517 Err_Vars.Error_Msg_File_1 := From;
5519 if Location = No_Location then
5522 "{ is not a valid directory",
5527 "{ is not a valid directory",
5533 Path : constant String :=
5534 Get_Name_String (Path_Name.Name) &
5535 Directory_Separator;
5536 Last_Path : constant Natural :=
5537 Compute_Directory_Last (Path);
5539 Display_Path : constant String :=
5541 (Path_Name.Display_Name) &
5542 Directory_Separator;
5543 Last_Display_Path : constant Natural :=
5544 Compute_Directory_Last
5546 Display_Path_Id : Name_Id;
5550 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
5551 Path_Id := Name_Find;
5553 Add_Str_To_Name_Buffer
5555 (Display_Path'First .. Last_Display_Path));
5556 Display_Path_Id := Name_Find;
5560 -- As it is an existing directory, we add it to the
5561 -- list of directories.
5563 String_Element_Table.Increment_Last
5564 (In_Tree.String_Elements);
5568 Display_Value => Display_Path_Id,
5569 Location => No_Location,
5571 Next => Nil_String);
5573 if Last_Source_Dir = Nil_String then
5575 -- This is the first source directory
5577 Project.Source_Dirs := String_Element_Table.Last
5578 (In_Tree.String_Elements);
5581 -- We already have source directories, link the
5582 -- previous last to the new one.
5584 In_Tree.String_Elements.Table
5585 (Last_Source_Dir).Next :=
5586 String_Element_Table.Last
5587 (In_Tree.String_Elements);
5590 -- And register this source directory as the new last
5592 Last_Source_Dir := String_Element_Table.Last
5593 (In_Tree.String_Elements);
5594 In_Tree.String_Elements.Table
5595 (Last_Source_Dir) := Element;
5598 -- Remove source dir, if present
5602 -- Look for source dir in current list
5604 List := Project.Source_Dirs;
5605 while List /= Nil_String loop
5606 Element := In_Tree.String_Elements.Table (List);
5607 exit when Element.Value = Path_Id;
5609 List := Element.Next;
5612 if List /= Nil_String then
5613 -- Source dir was found, remove it from the list
5615 if Prev = Nil_String then
5616 Project.Source_Dirs :=
5617 In_Tree.String_Elements.Table (List).Next;
5620 In_Tree.String_Elements.Table (Prev).Next :=
5621 In_Tree.String_Elements.Table (List).Next;
5629 end Find_Source_Dirs;
5631 -- Start of processing for Get_Directories
5633 Dir_Exists : Boolean;
5636 if Current_Verbosity = High then
5637 Write_Line ("Starting to look for directories");
5640 -- Set the object directory to its default which may be nil, if there
5641 -- is no sources in the project.
5643 if (((not Source_Files.Default)
5644 and then Source_Files.Values = Nil_String)
5646 ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
5648 ((not Languages.Default) and then Languages.Values = Nil_String))
5649 and then Project.Extends = No_Project
5651 Project.Object_Directory := No_Path_Information;
5653 Project.Object_Directory := Project.Directory;
5656 -- Check the object directory
5658 if Object_Dir.Value /= Empty_String then
5659 Get_Name_String (Object_Dir.Value);
5661 if Name_Len = 0 then
5664 "Object_Dir cannot be empty",
5665 Object_Dir.Location);
5668 -- We check that the specified object directory does exist.
5669 -- However, even when it doesn't exist, we set it to a default
5670 -- value. This is for the benefit of tools that recover from
5671 -- errors; for example, these tools could create the non existent
5673 -- We always return an absolute directory name though
5678 File_Name_Type (Object_Dir.Value),
5679 Path => Project.Object_Directory,
5681 Dir_Exists => Dir_Exists,
5682 Location => Object_Dir.Location,
5683 Must_Exist => False,
5684 Externally_Built => Project.Externally_Built);
5687 and then not Project.Externally_Built
5689 -- The object directory does not exist, report an error if
5690 -- the project is not externally built.
5692 Err_Vars.Error_Msg_File_1 :=
5693 File_Name_Type (Object_Dir.Value);
5696 "object directory { not found",
5701 elsif Project.Object_Directory /= No_Path_Information
5702 and then Subdirs /= null
5705 Name_Buffer (1) := '.';
5710 Path => Project.Object_Directory,
5712 Dir_Exists => Dir_Exists,
5713 Location => Object_Dir.Location,
5714 Externally_Built => Project.Externally_Built);
5717 if Current_Verbosity = High then
5718 if Project.Object_Directory = No_Path_Information then
5719 Write_Line ("No object directory");
5722 ("Object directory",
5723 Get_Name_String (Project.Object_Directory.Display_Name));
5727 -- Check the exec directory
5729 -- We set the object directory to its default
5731 Project.Exec_Directory := Project.Object_Directory;
5733 if Exec_Dir.Value /= Empty_String then
5734 Get_Name_String (Exec_Dir.Value);
5736 if Name_Len = 0 then
5739 "Exec_Dir cannot be empty",
5743 -- We check that the specified exec directory does exist
5748 File_Name_Type (Exec_Dir.Value),
5749 Path => Project.Exec_Directory,
5750 Dir_Exists => Dir_Exists,
5752 Location => Exec_Dir.Location,
5753 Externally_Built => Project.Externally_Built);
5755 if not Dir_Exists then
5756 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
5759 "exec directory { not found",
5765 if Current_Verbosity = High then
5766 if Project.Exec_Directory = No_Path_Information then
5767 Write_Line ("No exec directory");
5769 Write_Str ("Exec directory: """);
5770 Write_Str (Get_Name_String (Project.Exec_Directory.Display_Name));
5775 -- Look for the source directories
5777 if Current_Verbosity = High then
5778 Write_Line ("Starting to look for source directories");
5781 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
5783 if (not Source_Files.Default) and then
5784 Source_Files.Values = Nil_String
5786 Project.Source_Dirs := Nil_String;
5788 if Project.Qualifier = Standard then
5792 "a standard project cannot have no sources",
5793 Source_Files.Location);
5796 elsif Source_Dirs.Default then
5798 -- No Source_Dirs specified: the single source directory is the one
5799 -- containing the project file
5801 String_Element_Table.Append (In_Tree.String_Elements,
5802 (Value => Name_Id (Project.Directory.Name),
5803 Display_Value => Name_Id (Project.Directory.Display_Name),
5804 Location => No_Location,
5808 Project.Source_Dirs := String_Element_Table.Last
5809 (In_Tree.String_Elements);
5811 if Current_Verbosity = High then
5813 ("Default source directory",
5814 Get_Name_String (Project.Directory.Display_Name));
5817 elsif Source_Dirs.Values = Nil_String then
5818 if Project.Qualifier = Standard then
5822 "a standard project cannot have no source directories",
5823 Source_Dirs.Location);
5826 Project.Source_Dirs := Nil_String;
5830 Source_Dir : String_List_Id;
5831 Element : String_Element;
5834 -- Process the source directories for each element of the list
5836 Source_Dir := Source_Dirs.Values;
5837 while Source_Dir /= Nil_String loop
5838 Element := In_Tree.String_Elements.Table (Source_Dir);
5840 (File_Name_Type (Element.Value), Element.Location);
5841 Source_Dir := Element.Next;
5846 if not Excluded_Source_Dirs.Default
5847 and then Excluded_Source_Dirs.Values /= Nil_String
5850 Source_Dir : String_List_Id;
5851 Element : String_Element;
5854 -- Process the source directories for each element of the list
5856 Source_Dir := Excluded_Source_Dirs.Values;
5857 while Source_Dir /= Nil_String loop
5858 Element := In_Tree.String_Elements.Table (Source_Dir);
5860 (File_Name_Type (Element.Value),
5863 Source_Dir := Element.Next;
5868 if Current_Verbosity = High then
5869 Write_Line ("Putting source directories in canonical cases");
5873 Current : String_List_Id := Project.Source_Dirs;
5874 Element : String_Element;
5877 while Current /= Nil_String loop
5878 Element := In_Tree.String_Elements.Table (Current);
5879 if Element.Value /= No_Name then
5881 Name_Id (Canonical_Case_File_Name (Name_Id (Element.Value)));
5882 In_Tree.String_Elements.Table (Current) := Element;
5885 Current := Element.Next;
5888 end Get_Directories;
5895 (Project : Project_Id;
5896 In_Tree : Project_Tree_Ref)
5898 Mains : constant Variable_Value :=
5899 Prj.Util.Value_Of (Name_Main, Project.Decl.Attributes, In_Tree);
5900 List : String_List_Id;
5901 Elem : String_Element;
5904 Project.Mains := Mains.Values;
5906 -- If no Mains were specified, and if we are an extending project,
5907 -- inherit the Mains from the project we are extending.
5909 if Mains.Default then
5910 if not Project.Library and then Project.Extends /= No_Project then
5911 Project.Mains := Project.Extends.Mains;
5914 -- In a library project file, Main cannot be specified
5916 elsif Project.Library then
5919 "a library project file cannot have Main specified",
5923 List := Mains.Values;
5924 while List /= Nil_String loop
5925 Elem := In_Tree.String_Elements.Table (List);
5927 if Length_Of_Name (Elem.Value) = 0 then
5930 "?a main cannot have an empty name",
5940 ---------------------------
5941 -- Get_Sources_From_File --
5942 ---------------------------
5944 procedure Get_Sources_From_File
5946 Location : Source_Ptr;
5947 Project : Project_Id;
5948 In_Tree : Project_Tree_Ref)
5950 File : Prj.Util.Text_File;
5951 Line : String (1 .. 250);
5953 Source_Name : File_Name_Type;
5954 Name_Loc : Name_Location;
5957 if Get_Mode = Ada_Only then
5961 if Current_Verbosity = High then
5962 Write_Str ("Opening """);
5969 Prj.Util.Open (File, Path);
5971 if not Prj.Util.Is_Valid (File) then
5972 Error_Msg (Project, In_Tree, "file does not exist", Location);
5975 -- Read the lines one by one
5977 while not Prj.Util.End_Of_File (File) loop
5978 Prj.Util.Get_Line (File, Line, Last);
5980 -- A non empty, non comment line should contain a file name
5983 and then (Last = 1 or else Line (1 .. 2) /= "--")
5986 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
5987 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
5988 Source_Name := Name_Find;
5990 -- Check that there is no directory information
5992 for J in 1 .. Last loop
5993 if Line (J) = '/' or else Line (J) = Directory_Separator then
5994 Error_Msg_File_1 := Source_Name;
5998 "file name cannot include directory information ({)",
6004 Name_Loc := Source_Names.Get (Source_Name);
6006 if Name_Loc = No_Name_Location then
6008 (Name => Source_Name,
6009 Location => Location,
6010 Source => No_Source,
6015 Source_Names.Set (Source_Name, Name_Loc);
6019 Prj.Util.Close (File);
6022 end Get_Sources_From_File;
6024 -----------------------
6025 -- Compute_Unit_Name --
6026 -----------------------
6028 procedure Compute_Unit_Name
6029 (File_Name : File_Name_Type;
6030 Naming : Lang_Naming_Data;
6031 Kind : out Source_Kind;
6033 In_Tree : Project_Tree_Ref)
6035 Filename : constant String := Get_Name_String (File_Name);
6036 Last : Integer := Filename'Last;
6037 Sep_Len : constant Integer :=
6038 Integer (Length_Of_Name (Naming.Separate_Suffix));
6039 Body_Len : constant Integer :=
6040 Integer (Length_Of_Name (Naming.Body_Suffix));
6041 Spec_Len : constant Integer :=
6042 Integer (Length_Of_Name (Naming.Spec_Suffix));
6044 Standard_GNAT : constant Boolean :=
6045 Naming.Spec_Suffix = Default_Ada_Spec_Suffix
6047 Naming.Body_Suffix = Default_Ada_Body_Suffix;
6049 Unit_Except : Unit_Exception;
6050 Masked : Boolean := False;
6055 if Naming.Dot_Replacement = No_File then
6056 if Current_Verbosity = High then
6057 Write_Line (" No dot_replacement specified");
6062 -- Choose the longest suffix that matches. If there are several matches,
6063 -- give priority to specs, then bodies, then separates.
6065 if Naming.Separate_Suffix /= Naming.Body_Suffix
6066 and then Suffix_Matches (Filename, Naming.Separate_Suffix)
6068 Last := Filename'Last - Sep_Len;
6072 if Filename'Last - Body_Len <= Last
6073 and then Suffix_Matches (Filename, Naming.Body_Suffix)
6075 Last := Natural'Min (Last, Filename'Last - Body_Len);
6079 if Filename'Last - Spec_Len <= Last
6080 and then Suffix_Matches (Filename, Naming.Spec_Suffix)
6082 Last := Natural'Min (Last, Filename'Last - Spec_Len);
6086 if Last = Filename'Last then
6087 if Current_Verbosity = High then
6088 Write_Line (" No matching suffix");
6093 -- Check that the casing matches
6095 if File_Names_Case_Sensitive then
6096 case Naming.Casing is
6097 when All_Lower_Case =>
6098 for J in Filename'First .. Last loop
6099 if Is_Letter (Filename (J))
6100 and then not Is_Lower (Filename (J))
6102 if Current_Verbosity = High then
6103 Write_Line (" Invalid casing");
6109 when All_Upper_Case =>
6110 for J in Filename'First .. Last loop
6111 if Is_Letter (Filename (J))
6112 and then not Is_Upper (Filename (J))
6114 if Current_Verbosity = High then
6115 Write_Line (" Invalid casing");
6121 when Mixed_Case | Unknown =>
6126 -- If Dot_Replacement is not a single dot, then there should not
6127 -- be any dot in the name.
6130 Dot_Repl : constant String :=
6131 Get_Name_String (Naming.Dot_Replacement);
6134 if Dot_Repl /= "." then
6135 for Index in Filename'First .. Last loop
6136 if Filename (Index) = '.' then
6137 if Current_Verbosity = High then
6138 Write_Line (" Invalid name, contains dot");
6144 Replace_Into_Name_Buffer
6145 (Filename (Filename'First .. Last), Dot_Repl, '.');
6147 Name_Len := Last - Filename'First + 1;
6148 Name_Buffer (1 .. Name_Len) := Filename (Filename'First .. Last);
6150 (Source => Name_Buffer (1 .. Name_Len),
6151 Mapping => Lower_Case_Map);
6155 -- In the standard GNAT naming scheme, check for special cases: children
6156 -- or separates of A, G, I or S, and run time sources.
6158 if Standard_GNAT and then Name_Len >= 3 then
6160 S1 : constant Character := Name_Buffer (1);
6161 S2 : constant Character := Name_Buffer (2);
6162 S3 : constant Character := Name_Buffer (3);
6170 -- Children or separates of packages A, G, I or S. These names
6171 -- are x__ ... or x~... (where x is a, g, i, or s). Both
6172 -- versions (x__... and x~...) are allowed in all platforms,
6173 -- because it is not possible to know the platform before
6174 -- processing of the project files.
6176 if S2 = '_' and then S3 = '_' then
6177 Name_Buffer (2) := '.';
6178 Name_Buffer (3 .. Name_Len - 1) :=
6179 Name_Buffer (4 .. Name_Len);
6180 Name_Len := Name_Len - 1;
6183 Name_Buffer (2) := '.';
6187 -- If it is potentially a run time source, disable filling
6188 -- of the mapping file to avoid warnings.
6190 Set_Mapping_File_Initial_State_To_Empty (In_Tree);
6196 -- Name_Buffer contains the name of the the unit in lower-cases. Check
6197 -- that this is a valid unit name
6199 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
6201 -- If there is a naming exception for the same unit, the file is not
6202 -- a source for the unit. Currently, this only applies in multi_lang
6203 -- mode, since Unit_Exceptions is no set in ada_only mode.
6205 if Unit /= No_Name then
6206 Unit_Except := Unit_Exceptions.Get (Unit);
6209 Masked := Unit_Except.Spec /= No_File
6211 Unit_Except.Spec /= File_Name;
6213 Masked := Unit_Except.Impl /= No_File
6215 Unit_Except.Impl /= File_Name;
6219 if Current_Verbosity = High then
6220 Write_Str (" """ & Filename & """ contains the ");
6223 Write_Str ("spec of a unit found in """);
6224 Write_Str (Get_Name_String (Unit_Except.Spec));
6226 Write_Str ("body of a unit found in """);
6227 Write_Str (Get_Name_String (Unit_Except.Impl));
6230 Write_Line (""" (ignored)");
6238 and then Current_Verbosity = High
6241 when Spec => Write_Str (" spec of ");
6242 when Impl => Write_Str (" body of ");
6243 when Sep => Write_Str (" sep of ");
6246 Write_Line (Get_Name_String (Unit));
6248 end Compute_Unit_Name;
6255 (In_Tree : Project_Tree_Ref;
6256 Canonical_File_Name : File_Name_Type;
6257 Project : Project_Id;
6258 Exception_Id : out Ada_Naming_Exception_Id;
6259 Unit_Name : out Name_Id;
6260 Unit_Kind : out Spec_Or_Body)
6262 Info_Id : Ada_Naming_Exception_Id :=
6263 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6264 VMS_Name : File_Name_Type;
6266 Lang : Language_Ptr;
6269 if Info_Id = No_Ada_Naming_Exception
6270 and then Hostparm.OpenVMS
6272 VMS_Name := Canonical_File_Name;
6273 Get_Name_String (VMS_Name);
6275 if Name_Buffer (Name_Len) = '.' then
6276 Name_Len := Name_Len - 1;
6277 VMS_Name := Name_Find;
6280 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6283 if Info_Id /= No_Ada_Naming_Exception then
6284 Exception_Id := Info_Id;
6285 Unit_Name := No_Name;
6289 Exception_Id := No_Ada_Naming_Exception;
6290 Lang := Get_Language_From_Name (Project, "ada");
6293 Unit_Name := No_Name;
6297 (File_Name => Canonical_File_Name,
6298 Naming => Lang.Config.Naming_Data,
6301 In_Tree => In_Tree);
6304 when Spec => Unit_Kind := Spec;
6305 when Impl | Sep => Unit_Kind := Impl;
6315 function Hash (Unit : Unit_Info) return Header_Num is
6317 return Header_Num (Unit.Unit mod 2048);
6320 -----------------------
6321 -- Is_Illegal_Suffix --
6322 -----------------------
6324 function Is_Illegal_Suffix
6325 (Suffix : File_Name_Type;
6326 Dot_Replacement : File_Name_Type) return Boolean
6328 Suffix_Str : constant String := Get_Name_String (Suffix);
6331 if Suffix_Str'Length = 0 then
6333 elsif Index (Suffix_Str, ".") = 0 then
6337 -- Case of dot replacement is a single dot, and first character of
6338 -- suffix is also a dot.
6340 if Get_Name_String (Dot_Replacement) = "."
6341 and then Suffix_Str (Suffix_Str'First) = '.'
6343 for Index in Suffix_Str'First + 1 .. Suffix_Str'Last loop
6345 -- Case of following dot
6347 if Suffix_Str (Index) = '.' then
6349 -- It is illegal to have a letter following the initial dot
6351 return Is_Letter (Suffix_Str (Suffix_Str'First + 1));
6357 end Is_Illegal_Suffix;
6359 ----------------------
6360 -- Locate_Directory --
6361 ----------------------
6363 procedure Locate_Directory
6364 (Project : Project_Id;
6365 In_Tree : Project_Tree_Ref;
6366 Name : File_Name_Type;
6367 Path : out Path_Information;
6368 Dir_Exists : out Boolean;
6369 Create : String := "";
6370 Location : Source_Ptr := No_Location;
6371 Must_Exist : Boolean := True;
6372 Externally_Built : Boolean := False)
6374 Parent : constant Path_Name_Type :=
6375 Project.Directory.Display_Name;
6376 The_Parent : constant String :=
6377 Get_Name_String (Parent) & Directory_Separator;
6378 The_Parent_Last : constant Natural :=
6379 Compute_Directory_Last (The_Parent);
6380 Full_Name : File_Name_Type;
6381 The_Name : File_Name_Type;
6384 Get_Name_String (Name);
6386 -- Add Subdirs.all if it is a directory that may be created and
6387 -- Subdirs is not null;
6389 if Create /= "" and then Subdirs /= null then
6390 if Name_Buffer (Name_Len) /= Directory_Separator then
6391 Add_Char_To_Name_Buffer (Directory_Separator);
6394 Add_Str_To_Name_Buffer (Subdirs.all);
6397 -- Convert '/' to directory separator (for Windows)
6399 for J in 1 .. Name_Len loop
6400 if Name_Buffer (J) = '/' then
6401 Name_Buffer (J) := Directory_Separator;
6405 The_Name := Name_Find;
6407 if Current_Verbosity = High then
6408 Write_Str ("Locate_Directory (""");
6409 Write_Str (Get_Name_String (The_Name));
6410 Write_Str (""", """);
6411 Write_Str (The_Parent);
6415 Path := No_Path_Information;
6416 Dir_Exists := False;
6418 if Is_Absolute_Path (Get_Name_String (The_Name)) then
6419 Full_Name := The_Name;
6423 Add_Str_To_Name_Buffer
6424 (The_Parent (The_Parent'First .. The_Parent_Last));
6425 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
6426 Full_Name := Name_Find;
6430 Full_Path_Name : String_Access :=
6431 new String'(Get_Name_String (Full_Name));
6434 if (Setup_Projects or else Subdirs /= null)
6435 and then Create'Length > 0
6437 if not Is_Directory (Full_Path_Name.all) then
6439 -- If project is externally built, do not create a subdir,
6440 -- use the specified directory, without the subdir.
6442 if Externally_Built then
6443 if Is_Absolute_Path (Get_Name_String (Name)) then
6444 Get_Name_String (Name);
6448 Add_Str_To_Name_Buffer
6449 (The_Parent (The_Parent'First .. The_Parent_Last));
6450 Add_Str_To_Name_Buffer (Get_Name_String (Name));
6453 Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
6457 Create_Path (Full_Path_Name.all);
6459 if not Quiet_Output then
6461 Write_Str (" directory """);
6462 Write_Str (Full_Path_Name.all);
6463 Write_Str (""" created for project ");
6464 Write_Line (Get_Name_String (Project.Name));
6471 "could not create " & Create &
6472 " directory " & Full_Path_Name.all,
6479 Dir_Exists := Is_Directory (Full_Path_Name.all);
6481 if not Must_Exist or else Dir_Exists then
6483 Normed : constant String :=
6485 (Full_Path_Name.all,
6487 The_Parent (The_Parent'First .. The_Parent_Last),
6488 Resolve_Links => False,
6489 Case_Sensitive => True);
6491 Canonical_Path : constant String :=
6496 (The_Parent'First .. The_Parent_Last),
6498 Opt.Follow_Links_For_Dirs,
6499 Case_Sensitive => False);
6502 Name_Len := Normed'Length;
6503 Name_Buffer (1 .. Name_Len) := Normed;
6504 Path.Display_Name := Name_Find;
6506 Name_Len := Canonical_Path'Length;
6507 Name_Buffer (1 .. Name_Len) := Canonical_Path;
6508 Path.Name := Name_Find;
6512 Free (Full_Path_Name);
6514 end Locate_Directory;
6516 ---------------------------
6517 -- Find_Excluded_Sources --
6518 ---------------------------
6520 procedure Find_Excluded_Sources
6521 (Project : Project_Id;
6522 In_Tree : Project_Tree_Ref)
6524 Excluded_Source_List_File : constant Variable_Value :=
6526 (Name_Excluded_Source_List_File,
6527 Project.Decl.Attributes,
6530 Excluded_Sources : Variable_Value := Util.Value_Of
6531 (Name_Excluded_Source_Files,
6532 Project.Decl.Attributes,
6535 Current : String_List_Id;
6536 Element : String_Element;
6537 Location : Source_Ptr;
6538 Name : File_Name_Type;
6539 File : Prj.Util.Text_File;
6540 Line : String (1 .. 300);
6542 Locally_Removed : Boolean := False;
6545 -- If Excluded_Source_Files is not declared, check
6546 -- Locally_Removed_Files.
6548 if Excluded_Sources.Default then
6549 Locally_Removed := True;
6552 (Name_Locally_Removed_Files, Project.Decl.Attributes, In_Tree);
6555 Excluded_Sources_Htable.Reset;
6557 -- If there are excluded sources, put them in the table
6559 if not Excluded_Sources.Default then
6560 if not Excluded_Source_List_File.Default then
6561 if Locally_Removed then
6564 "?both attributes Locally_Removed_Files and " &
6565 "Excluded_Source_List_File are present",
6566 Excluded_Source_List_File.Location);
6570 "?both attributes Excluded_Source_Files and " &
6571 "Excluded_Source_List_File are present",
6572 Excluded_Source_List_File.Location);
6576 Current := Excluded_Sources.Values;
6577 while Current /= Nil_String loop
6578 Element := In_Tree.String_Elements.Table (Current);
6579 Name := Canonical_Case_File_Name (Element.Value);
6581 -- If the element has no location, then use the location of
6582 -- Excluded_Sources to report possible errors.
6584 if Element.Location = No_Location then
6585 Location := Excluded_Sources.Location;
6587 Location := Element.Location;
6590 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
6591 Current := Element.Next;
6594 elsif not Excluded_Source_List_File.Default then
6595 Location := Excluded_Source_List_File.Location;
6598 Source_File_Path_Name : constant String :=
6601 (Excluded_Source_List_File.Value),
6602 Project.Directory.Name);
6605 if Source_File_Path_Name'Length = 0 then
6606 Err_Vars.Error_Msg_File_1 :=
6607 File_Name_Type (Excluded_Source_List_File.Value);
6610 "file with excluded sources { does not exist",
6611 Excluded_Source_List_File.Location);
6616 Prj.Util.Open (File, Source_File_Path_Name);
6618 if not Prj.Util.Is_Valid (File) then
6620 (Project, In_Tree, "file does not exist", Location);
6622 -- Read the lines one by one
6624 while not Prj.Util.End_Of_File (File) loop
6625 Prj.Util.Get_Line (File, Line, Last);
6627 -- Non empty, non comment line should contain a file name
6630 and then (Last = 1 or else Line (1 .. 2) /= "--")
6633 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6634 Canonical_Case_File_Name
6635 (Name_Buffer (1 .. Name_Len));
6638 -- Check that there is no directory information
6640 for J in 1 .. Last loop
6642 or else Line (J) = Directory_Separator
6644 Error_Msg_File_1 := Name;
6648 "file name cannot include " &
6649 "directory information ({)",
6655 Excluded_Sources_Htable.Set
6656 (Name, (Name, False, Location));
6660 Prj.Util.Close (File);
6665 end Find_Excluded_Sources;
6671 procedure Find_Sources
6672 (Project : Project_Id;
6673 In_Tree : Project_Tree_Ref;
6674 Proc_Data : in out Processing_Data;
6675 Allow_Duplicate_Basenames : Boolean)
6677 Sources : constant Variable_Value :=
6680 Project.Decl.Attributes,
6682 Source_List_File : constant Variable_Value :=
6684 (Name_Source_List_File,
6685 Project.Decl.Attributes,
6687 Name_Loc : Name_Location;
6689 Has_Explicit_Sources : Boolean;
6692 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
6694 (Source_List_File.Kind = Single,
6695 "Source_List_File is not a single string");
6697 -- If the user has specified a Source_Files attribute
6699 if not Sources.Default then
6700 if not Source_List_File.Default then
6703 "?both attributes source_files and " &
6704 "source_list_file are present",
6705 Source_List_File.Location);
6708 -- Sources is a list of file names
6711 Current : String_List_Id := Sources.Values;
6712 Element : String_Element;
6713 Location : Source_Ptr;
6714 Name : File_Name_Type;
6717 if Get_Mode = Multi_Language then
6718 if Current = Nil_String then
6719 Project.Languages := No_Language_Index;
6721 -- This project contains no source. For projects that don't
6722 -- extend other projects, this also means that there is no
6723 -- need for an object directory, if not specified.
6725 if Project.Extends = No_Project
6726 and then Project.Object_Directory = Project.Directory
6728 Project.Object_Directory := No_Path_Information;
6733 while Current /= Nil_String loop
6734 Element := In_Tree.String_Elements.Table (Current);
6735 Name := Canonical_Case_File_Name (Element.Value);
6736 Get_Name_String (Element.Value);
6738 -- If the element has no location, then use the location of
6739 -- Sources to report possible errors.
6741 if Element.Location = No_Location then
6742 Location := Sources.Location;
6744 Location := Element.Location;
6747 -- Check that there is no directory information
6749 for J in 1 .. Name_Len loop
6750 if Name_Buffer (J) = '/'
6751 or else Name_Buffer (J) = Directory_Separator
6753 Error_Msg_File_1 := Name;
6757 "file name cannot include directory " &
6764 -- In Multi_Language mode, check whether the file is already
6765 -- there: the same file name may be in the list. If the source
6766 -- is missing, the error will be on the first mention of the
6767 -- source file name.
6771 Name_Loc := No_Name_Location;
6772 when Multi_Language =>
6773 Name_Loc := Source_Names.Get (Name);
6776 if Name_Loc = No_Name_Location then
6779 Location => Location,
6780 Source => No_Source,
6783 Source_Names.Set (Name, Name_Loc);
6786 Current := Element.Next;
6789 Has_Explicit_Sources := True;
6792 -- If we have no Source_Files attribute, check the Source_List_File
6795 elsif not Source_List_File.Default then
6797 -- Source_List_File is the name of the file that contains the source
6801 Source_File_Path_Name : constant String :=
6803 (File_Name_Type (Source_List_File.Value),
6804 Project.Directory.Name);
6807 Has_Explicit_Sources := True;
6809 if Source_File_Path_Name'Length = 0 then
6810 Err_Vars.Error_Msg_File_1 :=
6811 File_Name_Type (Source_List_File.Value);
6814 "file with sources { does not exist",
6815 Source_List_File.Location);
6818 Get_Sources_From_File
6819 (Source_File_Path_Name, Source_List_File.Location,
6825 -- Neither Source_Files nor Source_List_File has been specified. Find
6826 -- all the files that satisfy the naming scheme in all the source
6829 Has_Explicit_Sources := False;
6832 if Get_Mode = Ada_Only then
6835 Explicit_Sources_Only => Has_Explicit_Sources,
6836 Proc_Data => Proc_Data);
6842 Sources.Default and then Source_List_File.Default,
6843 Allow_Duplicate_Basenames => Allow_Duplicate_Basenames);
6846 -- Check if all exceptions have been found. For Ada, it is an error if
6847 -- an exception is not found. For other language, the source is simply
6852 Iter : Source_Iterator;
6855 Iter := For_Each_Source (In_Tree, Project);
6857 Source := Prj.Element (Iter);
6858 exit when Source = No_Source;
6860 if Source.Naming_Exception
6861 and then Source.Path = No_Path_Information
6863 if Source.Unit /= No_Unit_Index then
6864 Error_Msg_Name_1 := Name_Id (Source.Display_File);
6865 Error_Msg_Name_2 := Name_Id (Source.Unit.Name);
6868 "source file %% for unit %% not found",
6872 Remove_Source (Source, No_Source);
6879 -- It is an error if a source file name in a source list or in a source
6880 -- list file is not found.
6882 if Has_Explicit_Sources then
6885 First_Error : Boolean;
6888 NL := Source_Names.Get_First;
6889 First_Error := True;
6890 while NL /= No_Name_Location loop
6891 if not NL.Found then
6892 Err_Vars.Error_Msg_File_1 := NL.Name;
6897 "source file { not found",
6899 First_Error := False;
6904 "\source file { not found",
6909 NL := Source_Names.Get_Next;
6914 if Get_Mode = Ada_Only
6915 and then Project.Extends = No_Project
6917 -- We should have found at least one source, if not report an error
6919 if not Has_Ada_Sources (Project) then
6921 (Project, "Ada", In_Tree, Source_List_File.Location);
6930 procedure Initialize (Proc_Data : in out Processing_Data) is
6932 Files_Htable.Reset (Proc_Data.Units);
6939 procedure Free (Proc_Data : in out Processing_Data) is
6941 Files_Htable.Reset (Proc_Data.Units);
6944 ----------------------
6945 -- Find_Ada_Sources --
6946 ----------------------
6948 procedure Find_Ada_Sources
6949 (Project : Project_Id;
6950 In_Tree : Project_Tree_Ref;
6951 Explicit_Sources_Only : Boolean;
6952 Proc_Data : in out Processing_Data)
6954 Source_Dir : String_List_Id;
6955 Element : String_Element;
6957 Dir_Has_Source : Boolean := False;
6959 Ada_Language : Language_Ptr;
6962 if Current_Verbosity = High then
6963 Write_Line ("Looking for Ada sources:");
6966 Ada_Language := Project.Languages;
6967 while Ada_Language /= No_Language_Index
6968 and then Ada_Language.Name /= Name_Ada
6970 Ada_Language := Ada_Language.Next;
6973 -- We look in all source directories for the file names in the hash
6974 -- table Source_Names.
6976 Source_Dir := Project.Source_Dirs;
6977 while Source_Dir /= Nil_String loop
6978 Dir_Has_Source := False;
6979 Element := In_Tree.String_Elements.Table (Source_Dir);
6982 Dir_Path : constant String :=
6983 Get_Name_String (Element.Display_Value) &
6984 Directory_Separator;
6985 Dir_Last : constant Natural := Compute_Directory_Last (Dir_Path);
6988 if Current_Verbosity = High then
6989 Write_Line ("checking directory """ & Dir_Path & """");
6992 -- Look for all files in the current source directory
6994 Open (Dir, Dir_Path (Dir_Path'First .. Dir_Last));
6997 Read (Dir, Name_Buffer, Name_Len);
6998 exit when Name_Len = 0;
7000 if Current_Verbosity = High then
7001 Write_Line (" Checking " & Name_Buffer (1 .. Name_Len));
7005 Name : constant File_Name_Type := Name_Find;
7006 Canonical_Name : File_Name_Type;
7008 -- ??? We could probably optimize the following call: we
7009 -- need to resolve links only once for the directory itself,
7010 -- and then do a single call to readlink() for each file.
7011 -- Unfortunately that would require a change in
7012 -- Normalize_Pathname so that it has the option of not
7013 -- resolving links for its Directory parameter, only for
7016 Path : constant String :=
7018 (Name => Name_Buffer (1 .. Name_Len),
7019 Directory => Dir_Path (Dir_Path'First .. Dir_Last),
7020 Resolve_Links => Opt.Follow_Links_For_Files,
7021 Case_Sensitive => True); -- no case folding
7023 Path_Name : Path_Name_Type;
7024 To_Record : Boolean := False;
7025 Location : Source_Ptr;
7028 -- If the file was listed in the explicit list of sources,
7029 -- mark it as such (since we'll need to report an error when
7030 -- an explicit source was not found)
7032 if Explicit_Sources_Only then
7034 Canonical_Case_File_Name (Name_Id (Name));
7035 NL := Source_Names.Get (Canonical_Name);
7036 To_Record := NL /= No_Name_Location and then not NL.Found;
7040 Location := NL.Location;
7041 Source_Names.Set (Canonical_Name, NL);
7046 Location := No_Location;
7050 Name_Len := Path'Length;
7051 Name_Buffer (1 .. Name_Len) := Path;
7052 Path_Name := Name_Find;
7054 if Current_Verbosity = High then
7055 Write_Line (" recording " & Get_Name_String (Name));
7058 -- Register the source if it is an Ada compilation unit
7062 Path_Name => Path_Name,
7065 Proc_Data => Proc_Data,
7066 Ada_Language => Ada_Language,
7067 Location => Location,
7068 Source_Recorded => Dir_Has_Source);
7081 if Dir_Has_Source then
7082 In_Tree.String_Elements.Table (Source_Dir).Flag := True;
7085 Source_Dir := Element.Next;
7088 if Current_Verbosity = High then
7089 Write_Line ("End looking for sources");
7091 end Find_Ada_Sources;
7093 -------------------------------
7094 -- Check_File_Naming_Schemes --
7095 -------------------------------
7097 procedure Check_File_Naming_Schemes
7098 (In_Tree : Project_Tree_Ref;
7099 Project : Project_Id;
7100 File_Name : File_Name_Type;
7101 Alternate_Languages : out Language_List;
7102 Language : out Language_Ptr;
7103 Display_Language_Name : out Name_Id;
7105 Lang_Kind : out Language_Kind;
7106 Kind : out Source_Kind)
7108 Filename : constant String := Get_Name_String (File_Name);
7109 Config : Language_Config;
7110 Tmp_Lang : Language_Ptr;
7112 Header_File : Boolean := False;
7113 -- True if we found at least one language for which the file is a header
7114 -- In such a case, we search for all possible languages where this is
7115 -- also a header (C and C++ for instance), since the file might be used
7116 -- for several such languages.
7118 procedure Check_File_Based_Lang;
7119 -- Does the naming scheme test for file-based languages. For those,
7120 -- there is no Unit. Just check if the file name has the implementation
7121 -- or, if it is specified, the template suffix of the language.
7123 -- Returns True if the file belongs to the current language and we
7124 -- should stop searching for matching languages. Not that a given header
7125 -- file could belong to several languages (C and C++ for instance). Thus
7126 -- if we found a header we'll check whether it matches other languages.
7128 ---------------------------
7129 -- Check_File_Based_Lang --
7130 ---------------------------
7132 procedure Check_File_Based_Lang is
7135 and then Suffix_Matches (Filename, Config.Naming_Data.Body_Suffix)
7139 Language := Tmp_Lang;
7141 if Current_Verbosity = High then
7142 Write_Str (" implementation of language ");
7143 Write_Line (Get_Name_String (Display_Language_Name));
7146 elsif Suffix_Matches (Filename, Config.Naming_Data.Spec_Suffix) then
7147 if Current_Verbosity = High then
7148 Write_Str (" header of language ");
7149 Write_Line (Get_Name_String (Display_Language_Name));
7153 Alternate_Languages := new Language_List_Element'
7154 (Language => Language,
7155 Next => Alternate_Languages);
7158 Header_File := True;
7161 Language := Tmp_Lang;
7164 end Check_File_Based_Lang;
7166 -- Start of processing for Check_File_Naming_Schemes
7169 Language := No_Language_Index;
7170 Alternate_Languages := null;
7171 Display_Language_Name := No_Name;
7173 Lang_Kind := File_Based;
7176 Tmp_Lang := Project.Languages;
7177 while Tmp_Lang /= No_Language_Index loop
7178 if Current_Verbosity = High then
7180 (" Testing language "
7181 & Get_Name_String (Tmp_Lang.Name)
7182 & " Header_File=" & Header_File'Img);
7185 Display_Language_Name := Tmp_Lang.Display_Name;
7186 Config := Tmp_Lang.Config;
7187 Lang_Kind := Config.Kind;
7191 Check_File_Based_Lang;
7192 exit when Kind = Impl;
7196 -- We know it belongs to a least a file_based language, no
7197 -- need to check unit-based ones.
7199 if not Header_File then
7201 (File_Name => File_Name,
7202 Naming => Config.Naming_Data,
7205 In_Tree => In_Tree);
7207 if Unit /= No_Name then
7208 Language := Tmp_Lang;
7214 Tmp_Lang := Tmp_Lang.Next;
7217 if Language = No_Language_Index
7218 and then Current_Verbosity = High
7220 Write_Line (" not a source of any language");
7222 end Check_File_Naming_Schemes;
7228 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind) is
7230 -- If the file was previously already associated with a unit, change it
7232 if Source.Unit /= null
7233 and then Source.Kind in Spec_Or_Body
7234 and then Source.Unit.File_Names (Source.Kind) /= null
7236 -- If we had another file referencing the same unit (for instance it
7237 -- was in an extended project), that source file is in fact invisible
7238 -- from now on, and in particular doesn't belong to the same unit.
7240 if Source.Unit.File_Names (Source.Kind) /= Source then
7241 Source.Unit.File_Names (Source.Kind).Unit := No_Unit_Index;
7244 Source.Unit.File_Names (Source.Kind) := null;
7247 Source.Kind := Kind;
7249 if Source.Kind in Spec_Or_Body and then Source.Unit /= null then
7250 Source.Unit.File_Names (Source.Kind) := Source;
7258 procedure Check_File
7259 (Project : Project_Id;
7260 In_Tree : Project_Tree_Ref;
7261 Path : Path_Name_Type;
7262 File_Name : File_Name_Type;
7263 Display_File_Name : File_Name_Type;
7264 For_All_Sources : Boolean;
7265 Allow_Duplicate_Basenames : Boolean)
7267 Canonical_Path : constant Path_Name_Type :=
7269 (Canonical_Case_File_Name (Name_Id (Path)));
7271 Name_Loc : Name_Location := Source_Names.Get (File_Name);
7272 Check_Name : Boolean := False;
7273 Alternate_Languages : Language_List;
7274 Language : Language_Ptr;
7277 Src_Ind : Source_File_Index;
7279 Source_To_Replace : Source_Id := No_Source;
7280 Display_Language_Name : Name_Id;
7281 Lang_Kind : Language_Kind;
7282 Kind : Source_Kind := Spec;
7283 Iter : Source_Iterator;
7286 if Name_Loc = No_Name_Location then
7287 Check_Name := For_All_Sources;
7290 if Name_Loc.Found then
7292 -- Check if it is OK to have the same file name in several
7293 -- source directories.
7295 if not Project.Known_Order_Of_Source_Dirs then
7296 Error_Msg_File_1 := File_Name;
7299 "{ is found in several source directories",
7304 Name_Loc.Found := True;
7306 Source_Names.Set (File_Name, Name_Loc);
7308 if Name_Loc.Source = No_Source then
7312 Name_Loc.Source.Path := (Canonical_Path, Path);
7314 Source_Paths_Htable.Set
7315 (In_Tree.Source_Paths_HT,
7319 -- Check if this is a subunit
7321 if Name_Loc.Source.Unit /= No_Unit_Index
7322 and then Name_Loc.Source.Kind = Impl
7324 Src_Ind := Sinput.P.Load_Project_File
7325 (Get_Name_String (Canonical_Path));
7327 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7328 Override_Kind (Name_Loc.Source, Sep);
7336 Check_File_Naming_Schemes
7337 (In_Tree => In_Tree,
7339 File_Name => File_Name,
7340 Alternate_Languages => Alternate_Languages,
7341 Language => Language,
7342 Display_Language_Name => Display_Language_Name,
7344 Lang_Kind => Lang_Kind,
7347 if Language = No_Language_Index then
7349 -- A file name in a list must be a source of a language
7351 if Name_Loc.Found then
7352 Error_Msg_File_1 := File_Name;
7356 "language unknown for {",
7361 -- Check if the same file name or unit is used in the prj tree
7363 Iter := For_Each_Source (In_Tree);
7366 Source := Prj.Element (Iter);
7367 exit when Source = No_Source;
7370 and then Source.Unit /= No_Unit_Index
7371 and then Source.Unit.Name = Unit
7373 ((Source.Kind = Spec and then Kind = Impl)
7375 (Source.Kind = Impl and then Kind = Spec))
7377 -- We found the "other_part (source)"
7381 elsif (Unit /= No_Name
7382 and then Source.Unit /= No_Unit_Index
7383 and then Source.Unit.Name = Unit
7387 (Source.Kind = Sep and then Kind = Impl)
7389 (Source.Kind = Impl and then Kind = Sep)))
7391 (Unit = No_Name and then Source.File = File_Name)
7393 -- Duplication of file/unit in same project is only
7394 -- allowed if order of source directories is known.
7396 if Project = Source.Project then
7397 if Unit = No_Name then
7398 if Allow_Duplicate_Basenames then
7400 elsif Project.Known_Order_Of_Source_Dirs then
7403 Error_Msg_File_1 := File_Name;
7405 (Project, In_Tree, "duplicate source file name {",
7411 if Project.Known_Order_Of_Source_Dirs then
7414 Error_Msg_Name_1 := Unit;
7416 (Project, In_Tree, "duplicate unit %%",
7422 -- Do not allow the same unit name in different projects,
7423 -- except if one is extending the other.
7425 -- For a file based language, the same file name replaces
7426 -- a file in a project being extended, but it is allowed
7427 -- to have the same file name in unrelated projects.
7429 elsif Is_Extending (Project, Source.Project) then
7430 Source_To_Replace := Source;
7432 elsif Unit /= No_Name
7433 and then not Source.Locally_Removed
7435 Error_Msg_Name_1 := Unit;
7438 "unit %% cannot belong to several projects",
7441 Error_Msg_Name_1 := Project.Name;
7442 Error_Msg_Name_2 := Name_Id (Path);
7444 (Project, In_Tree, "\ project %%, %%", No_Location);
7446 Error_Msg_Name_1 := Source.Project.Name;
7447 Error_Msg_Name_2 := Name_Id (Source.Path.Display_Name);
7449 (Project, In_Tree, "\ project %%, %%", No_Location);
7463 Lang_Id => Language,
7465 Alternate_Languages => Alternate_Languages,
7466 File_Name => File_Name,
7467 Display_File => Display_File_Name,
7469 Path => (Canonical_Path, Path),
7470 Source_To_Replace => Source_To_Replace);
7476 ------------------------
7477 -- Search_Directories --
7478 ------------------------
7480 procedure Search_Directories
7481 (Project : Project_Id;
7482 In_Tree : Project_Tree_Ref;
7483 For_All_Sources : Boolean;
7484 Allow_Duplicate_Basenames : Boolean)
7486 Source_Dir : String_List_Id;
7487 Element : String_Element;
7489 Name : String (1 .. 1_000);
7491 File_Name : File_Name_Type;
7492 Display_File_Name : File_Name_Type;
7495 if Current_Verbosity = High then
7496 Write_Line ("Looking for sources:");
7499 -- Loop through subdirectories
7501 Source_Dir := Project.Source_Dirs;
7502 while Source_Dir /= Nil_String loop
7504 Element := In_Tree.String_Elements.Table (Source_Dir);
7505 if Element.Value /= No_Name then
7506 Get_Name_String (Element.Display_Value);
7509 Source_Directory : constant String :=
7510 Name_Buffer (1 .. Name_Len) &
7511 Directory_Separator;
7513 Dir_Last : constant Natural :=
7514 Compute_Directory_Last
7518 if Current_Verbosity = High then
7519 Write_Attr ("Source_Dir", Source_Directory);
7522 -- We look to every entry in the source directory
7524 Open (Dir, Source_Directory);
7527 Read (Dir, Name, Last);
7531 -- ??? Duplicate system call here, we just did a
7532 -- a similar one. Maybe Ada.Directories would be more
7536 (Source_Directory & Name (1 .. Last))
7538 if Current_Verbosity = High then
7539 Write_Str (" Checking ");
7540 Write_Line (Name (1 .. Last));
7544 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
7545 Display_File_Name := Name_Find;
7547 if Osint.File_Names_Case_Sensitive then
7548 File_Name := Display_File_Name;
7550 Canonical_Case_File_Name
7551 (Name_Buffer (1 .. Name_Len));
7552 File_Name := Name_Find;
7556 Path_Name : constant String :=
7561 (Source_Directory'First ..
7564 Opt.Follow_Links_For_Files,
7565 Case_Sensitive => True);
7566 -- Case_Sensitive set True (no folding)
7568 Path : Path_Name_Type;
7570 Excluded_Sources_Htable.Get (File_Name);
7573 Name_Len := Path_Name'Length;
7574 Name_Buffer (1 .. Name_Len) := Path_Name;
7577 if FF /= No_File_Found then
7578 if not FF.Found then
7580 Excluded_Sources_Htable.Set (File_Name, FF);
7582 if Current_Verbosity = High then
7583 Write_Str (" excluded source """);
7584 Write_Str (Get_Name_String (File_Name));
7591 (Project => Project,
7594 File_Name => File_Name,
7595 Display_File_Name =>
7597 For_All_Sources => For_All_Sources,
7598 Allow_Duplicate_Basenames =>
7599 Allow_Duplicate_Basenames);
7610 when Directory_Error =>
7614 Source_Dir := Element.Next;
7617 if Current_Verbosity = High then
7618 Write_Line ("end Looking for sources.");
7620 end Search_Directories;
7622 ----------------------------
7623 -- Load_Naming_Exceptions --
7624 ----------------------------
7626 procedure Load_Naming_Exceptions
7627 (Project : Project_Id;
7628 In_Tree : Project_Tree_Ref)
7631 Iter : Source_Iterator;
7634 Unit_Exceptions.Reset;
7636 Iter := For_Each_Source (In_Tree, Project);
7638 Source := Prj.Element (Iter);
7639 exit when Source = No_Source;
7641 -- An excluded file cannot also be an exception file name
7643 if Excluded_Sources_Htable.Get (Source.File) /= No_File_Found then
7644 Error_Msg_File_1 := Source.File;
7647 "{ cannot be both excluded and an exception file name",
7651 if Current_Verbosity = High then
7652 Write_Str ("Naming exception: Putting source file ");
7653 Write_Str (Get_Name_String (Source.File));
7654 Write_Line (" in Source_Names");
7660 (Name => Source.File,
7661 Location => No_Location,
7663 Except => Source.Unit /= No_Unit_Index,
7666 -- If this is an Ada exception, record in table Unit_Exceptions
7668 if Source.Unit /= No_Unit_Index then
7670 Unit_Except : Unit_Exception :=
7671 Unit_Exceptions.Get (Source.Unit.Name);
7674 Unit_Except.Name := Source.Unit.Name;
7676 if Source.Kind = Spec then
7677 Unit_Except.Spec := Source.File;
7679 Unit_Except.Impl := Source.File;
7682 Unit_Exceptions.Set (Source.Unit.Name, Unit_Except);
7688 end Load_Naming_Exceptions;
7690 ----------------------
7691 -- Look_For_Sources --
7692 ----------------------
7694 procedure Look_For_Sources
7695 (Project : Project_Id;
7696 In_Tree : Project_Tree_Ref;
7697 Proc_Data : in out Processing_Data;
7698 Allow_Duplicate_Basenames : Boolean)
7700 Iter : Source_Iterator;
7702 procedure Process_Sources_In_Multi_Language_Mode;
7703 -- Find all source files when in multi language mode
7705 procedure Mark_Excluded_Sources;
7706 -- Mark as such the sources that are declared as excluded
7708 ---------------------------
7709 -- Mark_Excluded_Sources --
7710 ---------------------------
7712 procedure Mark_Excluded_Sources is
7713 Source : Source_Id := No_Source;
7715 Excluded : File_Found;
7718 Excluded := Excluded_Sources_Htable.Get_First;
7719 while Excluded /= No_File_Found loop
7722 -- ??? Don't we have a hash table to map files to Source_Id?
7724 Iter := For_Each_Source (In_Tree);
7726 Source := Prj.Element (Iter);
7727 exit when Source = No_Source;
7729 if Source.File = Excluded.File then
7730 if Source.Project = Project
7731 or else Is_Extending (Project, Source.Project)
7734 Source.Locally_Removed := True;
7735 Source.In_Interfaces := False;
7737 if Current_Verbosity = High then
7738 Write_Str ("Removing file ");
7739 Write_Line (Get_Name_String (Excluded.File));
7745 "cannot remove a source from another project",
7755 OK := OK or Excluded.Found;
7758 Err_Vars.Error_Msg_File_1 := Excluded.File;
7760 (Project, In_Tree, "unknown file {", Excluded.Location);
7763 Excluded := Excluded_Sources_Htable.Get_Next;
7765 end Mark_Excluded_Sources;
7767 --------------------------------------------
7768 -- Process_Sources_In_Multi_Language_Mode --
7769 --------------------------------------------
7771 procedure Process_Sources_In_Multi_Language_Mode is
7772 Iter : Source_Iterator;
7775 -- Check that two sources of this project do not have the same object
7778 Check_Object_File_Names : declare
7780 Source_Name : File_Name_Type;
7782 procedure Check_Object (Src : Source_Id);
7783 -- Check if object file name of the current source is already in
7784 -- hash table Object_File_Names. If it is, report an error. If it
7785 -- is not, put it there with the file name of the current source.
7791 procedure Check_Object (Src : Source_Id) is
7793 Source_Name := Object_File_Names.Get (Src.Object);
7795 if Source_Name /= No_File then
7796 Error_Msg_File_1 := Src.File;
7797 Error_Msg_File_2 := Source_Name;
7801 "{ and { have the same object file name",
7805 Object_File_Names.Set (Src.Object, Src.File);
7809 -- Start of processing for Check_Object_File_Names
7812 Object_File_Names.Reset;
7813 Iter := For_Each_Source (In_Tree);
7815 Src_Id := Prj.Element (Iter);
7816 exit when Src_Id = No_Source;
7818 if Is_Compilable (Src_Id)
7819 and then Src_Id.Language.Config.Object_Generated
7820 and then Is_Extending (Project, Src_Id.Project)
7822 if Src_Id.Unit = No_Unit_Index then
7823 if Src_Id.Kind = Impl then
7824 Check_Object (Src_Id);
7830 if Other_Part (Src_Id) = No_Source then
7831 Check_Object (Src_Id);
7838 if Other_Part (Src_Id) /= No_Source then
7839 Check_Object (Src_Id);
7842 -- Check if it is a subunit
7845 Src_Ind : constant Source_File_Index :=
7846 Sinput.P.Load_Project_File
7848 (Src_Id.Path.Name));
7850 if Sinput.P.Source_File_Is_Subunit
7853 Override_Kind (Src_Id, Sep);
7855 Check_Object (Src_Id);
7865 end Check_Object_File_Names;
7866 end Process_Sources_In_Multi_Language_Mode;
7868 -- Start of processing for Look_For_Sources
7872 Find_Excluded_Sources (Project, In_Tree);
7874 if (Get_Mode = Ada_Only and then Is_A_Language (Project, Name_Ada))
7875 or else (Get_Mode = Multi_Language
7876 and then Project.Languages /= No_Language_Index)
7878 if Get_Mode = Multi_Language then
7879 Load_Naming_Exceptions (Project, In_Tree);
7882 Find_Sources (Project, In_Tree, Proc_Data, Allow_Duplicate_Basenames);
7883 Mark_Excluded_Sources;
7885 if Get_Mode = Multi_Language then
7886 Process_Sources_In_Multi_Language_Mode;
7889 end Look_For_Sources;
7895 function Path_Name_Of
7896 (File_Name : File_Name_Type;
7897 Directory : Path_Name_Type) return String
7899 Result : String_Access;
7900 The_Directory : constant String := Get_Name_String (Directory);
7903 Get_Name_String (File_Name);
7906 (File_Name => Name_Buffer (1 .. Name_Len),
7907 Path => The_Directory);
7909 if Result = null then
7913 R : String := Result.all;
7916 Canonical_Case_File_Name (R);
7922 -----------------------------------
7923 -- Prepare_Ada_Naming_Exceptions --
7924 -----------------------------------
7926 procedure Prepare_Ada_Naming_Exceptions
7927 (List : Array_Element_Id;
7928 In_Tree : Project_Tree_Ref;
7929 Kind : Spec_Or_Body)
7931 Current : Array_Element_Id;
7932 Element : Array_Element;
7936 -- Traverse the list
7939 while Current /= No_Array_Element loop
7940 Element := In_Tree.Array_Elements.Table (Current);
7942 if Element.Index /= No_Name then
7945 Unit => Element.Index,
7946 Next => No_Ada_Naming_Exception);
7947 Reverse_Ada_Naming_Exceptions.Set
7948 (Unit, (Element.Value.Value, Element.Value.Index));
7950 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
7951 Ada_Naming_Exception_Table.Increment_Last;
7952 Ada_Naming_Exception_Table.Table
7953 (Ada_Naming_Exception_Table.Last) := Unit;
7954 Ada_Naming_Exceptions.Set
7955 (File_Name_Type (Element.Value.Value),
7956 Ada_Naming_Exception_Table.Last);
7959 Current := Element.Next;
7961 end Prepare_Ada_Naming_Exceptions;
7963 -----------------------
7964 -- Record_Ada_Source --
7965 -----------------------
7967 procedure Record_Ada_Source
7968 (File_Name : File_Name_Type;
7969 Path_Name : Path_Name_Type;
7970 Project : Project_Id;
7971 In_Tree : Project_Tree_Ref;
7972 Proc_Data : in out Processing_Data;
7973 Ada_Language : Language_Ptr;
7974 Location : Source_Ptr;
7975 Source_Recorded : in out Boolean)
7977 Canonical_File : File_Name_Type;
7978 Canonical_Path : Path_Name_Type;
7980 File_Recorded : Boolean := False;
7981 -- True when at least one file has been recorded
7983 procedure Record_Unit
7984 (Unit_Name : Name_Id;
7985 Unit_Ind : Int := 0;
7986 Unit_Kind : Spec_Or_Body;
7987 Needs_Pragma : Boolean);
7988 -- Register of the units contained in the source file (there is in
7989 -- general a single such unit except when exceptions to the naming
7990 -- scheme indicate there are several such units)
7996 procedure Record_Unit
7997 (Unit_Name : Name_Id;
7998 Unit_Ind : Int := 0;
7999 Unit_Kind : Spec_Or_Body;
8000 Needs_Pragma : Boolean)
8002 UData : constant Unit_Index :=
8003 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
8004 -- ??? Add_Source will look it up again, can we do that only once ?
8007 To_Record : Boolean := False;
8008 The_Location : Source_Ptr := Location;
8009 Unit_Prj : Project_Id;
8012 if Current_Verbosity = High then
8013 Write_Str (" Putting ");
8014 Write_Str (Get_Name_String (Unit_Name));
8015 Write_Line (" in the unit list.");
8018 -- The unit is already in the list, but may be it is only the other
8019 -- unit kind (spec or body), or what is in the unit list is a unit of
8020 -- a project we are extending.
8022 if UData /= No_Unit_Index then
8023 if UData.File_Names (Unit_Kind) = null
8025 (UData.File_Names (Unit_Kind).File = Canonical_File
8026 and then UData.File_Names (Unit_Kind).Locally_Removed)
8027 or else Is_Extending
8028 (Project.Extends, UData.File_Names (Unit_Kind).Project)
8032 -- If the same file is already in the list, do not add it again
8034 elsif UData.File_Names (Unit_Kind).Project = Project
8036 (Project.Known_Order_Of_Source_Dirs
8038 UData.File_Names (Unit_Kind).Path.Name = Canonical_Path)
8042 -- Else, same unit but not same file => It is an error to have two
8043 -- units with the same name and the same kind (spec or body).
8046 if The_Location = No_Location then
8047 The_Location := Project.Location;
8050 Err_Vars.Error_Msg_Name_1 := Unit_Name;
8052 (Project, In_Tree, "duplicate unit %%", The_Location);
8054 Err_Vars.Error_Msg_Name_1 :=
8055 UData.File_Names (Unit_Kind).Project.Name;
8056 Err_Vars.Error_Msg_File_1 :=
8057 File_Name_Type (UData.File_Names (Unit_Kind).Path.Name);
8060 "\ project file %%, {", The_Location);
8062 Err_Vars.Error_Msg_Name_1 := Project.Name;
8063 Err_Vars.Error_Msg_File_1 := File_Name_Type (Canonical_Path);
8065 (Project, In_Tree, "\ project file %%, {", The_Location);
8070 -- It is a new unit, create a new record
8073 -- First, check if there is no other unit with this file name in
8074 -- another project. If it is, report error but note we do that
8075 -- only for the first unit in the source file.
8077 Unit_Prj := Files_Htable.Get (Proc_Data.Units, Canonical_File);
8079 if not File_Recorded
8080 and then Unit_Prj /= No_Project
8082 Error_Msg_File_1 := File_Name;
8083 Error_Msg_Name_1 := Unit_Prj.Name;
8086 "{ is already a source of project %%",
8095 Files_Htable.Set (Proc_Data.Units, Canonical_File, Project);
8100 Lang_Id => Ada_Language,
8101 File_Name => Canonical_File,
8102 Display_File => File_Name,
8104 Path => (Canonical_Path, Path_Name),
8105 Naming_Exception => Needs_Pragma,
8108 Source_Recorded := True;
8112 Exception_Id : Ada_Naming_Exception_Id;
8113 Unit_Name : Name_Id;
8114 Unit_Kind : Spec_Or_Body;
8115 Unit_Ind : Int := 0;
8117 Name_Index : Name_And_Index;
8118 Except_Name : Name_And_Index := No_Name_And_Index;
8119 Needs_Pragma : Boolean;
8122 Canonical_File := Canonical_Case_File_Name (Name_Id (File_Name));
8124 Path_Name_Type (Canonical_Case_File_Name (Name_Id (Path_Name)));
8126 -- Check the naming scheme to get extra file properties
8129 (In_Tree => In_Tree,
8130 Canonical_File_Name => Canonical_File,
8132 Exception_Id => Exception_Id,
8133 Unit_Name => Unit_Name,
8134 Unit_Kind => Unit_Kind);
8136 Needs_Pragma := Exception_Id /= No_Ada_Naming_Exception;
8138 if Exception_Id = No_Ada_Naming_Exception
8139 and then Unit_Name = No_Name
8141 if Current_Verbosity = High then
8143 Write_Str (Get_Name_String (Canonical_File));
8144 Write_Line (""" is not a valid source file name (ignored).");
8149 -- Check to see if the source has been hidden by an exception,
8150 -- but only if it is not an exception.
8152 if not Needs_Pragma then
8154 Reverse_Ada_Naming_Exceptions.Get
8155 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
8157 if Except_Name /= No_Name_And_Index then
8158 if Current_Verbosity = High then
8160 Write_Str (Get_Name_String (Canonical_File));
8161 Write_Str (""" contains a unit that is found in """);
8162 Write_Str (Get_Name_String (Except_Name.Name));
8163 Write_Line (""" (ignored).");
8166 -- The file is not included in the source of the project since it
8167 -- is hidden by the exception. So, nothing else to do.
8173 -- The following loop registers the unit in the appropriate table. It
8174 -- will be executed multiple times when the file is a multi-unit file,
8175 -- in which case Exception_Id initially points to the first file and
8176 -- then to each other unit in the file.
8179 if Exception_Id /= No_Ada_Naming_Exception then
8180 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
8181 Exception_Id := Info.Next;
8182 Info.Next := No_Ada_Naming_Exception;
8183 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
8185 Unit_Name := Info.Unit;
8186 Unit_Ind := Name_Index.Index;
8187 Unit_Kind := Info.Kind;
8190 Record_Unit (Unit_Name, Unit_Ind, Unit_Kind, Needs_Pragma);
8191 File_Recorded := True;
8193 exit when Exception_Id = No_Ada_Naming_Exception;
8195 end Record_Ada_Source;
8201 procedure Remove_Source
8203 Replaced_By : Source_Id)
8208 if Current_Verbosity = High then
8209 Write_Str ("Removing source ");
8210 Write_Line (Get_Name_String (Id.File));
8213 if Replaced_By /= No_Source then
8214 Id.Replaced_By := Replaced_By;
8215 Replaced_By.Declared_In_Interfaces := Id.Declared_In_Interfaces;
8218 Source := Id.Language.First_Source;
8221 Id.Language.First_Source := Id.Next_In_Lang;
8224 while Source.Next_In_Lang /= Id loop
8225 Source := Source.Next_In_Lang;
8228 Source.Next_In_Lang := Id.Next_In_Lang;
8232 -----------------------
8233 -- Report_No_Sources --
8234 -----------------------
8236 procedure Report_No_Sources
8237 (Project : Project_Id;
8239 In_Tree : Project_Tree_Ref;
8240 Location : Source_Ptr;
8241 Continuation : Boolean := False)
8244 case When_No_Sources is
8248 when Warning | Error =>
8250 Msg : constant String :=
8253 " sources in this project";
8256 Error_Msg_Warn := When_No_Sources = Warning;
8258 if Continuation then
8259 Error_Msg (Project, In_Tree, "\" & Msg, Location);
8261 Error_Msg (Project, In_Tree, Msg, Location);
8265 end Report_No_Sources;
8267 ----------------------
8268 -- Show_Source_Dirs --
8269 ----------------------
8271 procedure Show_Source_Dirs
8272 (Project : Project_Id;
8273 In_Tree : Project_Tree_Ref)
8275 Current : String_List_Id;
8276 Element : String_Element;
8279 Write_Line ("Source_Dirs:");
8281 Current := Project.Source_Dirs;
8282 while Current /= Nil_String loop
8283 Element := In_Tree.String_Elements.Table (Current);
8285 Write_Line (Get_Name_String (Element.Value));
8286 Current := Element.Next;
8289 Write_Line ("end Source_Dirs.");
8290 end Show_Source_Dirs;
8292 -------------------------
8293 -- Warn_If_Not_Sources --
8294 -------------------------
8296 -- comments needed in this body ???
8298 procedure Warn_If_Not_Sources
8299 (Project : Project_Id;
8300 In_Tree : Project_Tree_Ref;
8301 Conventions : Array_Element_Id;
8303 Extending : Boolean)
8305 Conv : Array_Element_Id;
8307 The_Unit_Data : Unit_Index;
8308 Location : Source_Ptr;
8311 Conv := Conventions;
8312 while Conv /= No_Array_Element loop
8313 Unit := In_Tree.Array_Elements.Table (Conv).Index;
8314 Error_Msg_Name_1 := Unit;
8315 Get_Name_String (Unit);
8316 To_Lower (Name_Buffer (1 .. Name_Len));
8318 The_Unit_Data := Units_Htable.Get (In_Tree.Units_HT, Unit);
8319 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
8321 if The_Unit_Data = No_Unit_Index then
8322 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
8326 In_Tree.Array_Elements.Table (Conv).Value.Value;
8329 if not Check_Project
8330 (The_Unit_Data.File_Names (Spec).Project,
8335 "?source of spec of unit %% (%%)" &
8336 " not found in this project",
8341 if The_Unit_Data.File_Names (Impl) = null
8342 or else not Check_Project
8343 (The_Unit_Data.File_Names (Impl).Project,
8348 "?source of body of unit %% (%%)" &
8349 " not found in this project",
8355 Conv := In_Tree.Array_Elements.Table (Conv).Next;
8357 end Warn_If_Not_Sources;