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_Naming_Schemes
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.
283 -- Is_Config_File should be True if Project is a config file (.cgpr)
284 -- This also returns the naming scheme exceptions for unit-based
285 -- languages (Bodies and Specs are associative arrays mapping individual
286 -- unit names to source file names).
288 procedure Check_Configuration
289 (Project : Project_Id;
290 In_Tree : Project_Tree_Ref;
291 Compiler_Driver_Mandatory : Boolean);
292 -- Check the configuration attributes for the project
293 -- If Compiler_Driver_Mandatory is true, then a Compiler.Driver attribute
294 -- for each language must be defined, or we will not look for its source
297 procedure Check_If_Externally_Built
298 (Project : Project_Id;
299 In_Tree : Project_Tree_Ref);
300 -- Check attribute Externally_Built of project Project in project tree
301 -- In_Tree and modify its data Data if it has the value "true".
303 procedure Check_Interfaces
304 (Project : Project_Id;
305 In_Tree : Project_Tree_Ref);
306 -- If a list of sources is specified in attribute Interfaces, set
307 -- In_Interfaces only for the sources specified in the list.
309 procedure Check_Library_Attributes
310 (Project : Project_Id;
311 In_Tree : Project_Tree_Ref);
312 -- Check the library attributes of project Project in project tree In_Tree
313 -- and modify its data Data accordingly.
314 -- Current_Dir should represent the current directory, and is passed for
315 -- efficiency to avoid system calls to recompute it.
317 procedure Check_Package_Naming
318 (Project : Project_Id;
319 In_Tree : Project_Tree_Ref);
320 -- Check package Naming of project Project in project tree In_Tree and
321 -- modify its data Data accordingly.
323 procedure Check_Programming_Languages
324 (In_Tree : Project_Tree_Ref;
325 Project : Project_Id);
326 -- Check attribute Languages for the project with data Data in project
327 -- tree In_Tree and set the components of Data for all the programming
328 -- languages indicated in attribute Languages, if any.
330 function Check_Project
332 Root_Project : Project_Id;
333 Extending : Boolean) return Boolean;
334 -- Returns True if P is Root_Project or, if Extending is True, a project
335 -- extended by Root_Project.
337 procedure Check_Stand_Alone_Library
338 (Project : Project_Id;
339 In_Tree : Project_Tree_Ref;
340 Current_Dir : String;
341 Extending : Boolean);
342 -- Check if project Project in project tree In_Tree is a Stand-Alone
343 -- Library project, and modify its data Data accordingly if it is one.
344 -- Current_Dir should represent the current directory, and is passed for
345 -- efficiency to avoid system calls to recompute it.
347 procedure Check_And_Normalize_Unit_Names
348 (Project : Project_Id;
349 In_Tree : Project_Tree_Ref;
350 List : Array_Element_Id;
351 Debug_Name : String);
352 -- Check that a list of unit names contains only valid names. Casing
353 -- is normalized where appropriate.
354 -- Debug_Name is the name representing the list, and is used for debug
357 procedure Find_Ada_Sources
358 (Project : Project_Id;
359 In_Tree : Project_Tree_Ref;
360 Explicit_Sources_Only : Boolean;
361 Proc_Data : in out Processing_Data);
362 -- Find all Ada sources by traversing all source directories. If
363 -- Explicit_Sources_Only is True, then the sources found must belong to
364 -- the list of sources specified explicitly in the project file. If
365 -- Explicit_Sources_Only is False, then all sources matching the naming
366 -- scheme are recorded.
368 function Compute_Directory_Last (Dir : String) return Natural;
369 -- Return the index of the last significant character in Dir. This is used
370 -- to avoid duplicate '/' (slash) characters at the end of directory names.
373 (Project : Project_Id;
374 In_Tree : Project_Tree_Ref;
376 Flag_Location : Source_Ptr);
377 -- Output an error message. If Error_Report is null, simply call
378 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
381 procedure Search_Directories
382 (Project : Project_Id;
383 In_Tree : Project_Tree_Ref;
384 For_All_Sources : Boolean;
385 Allow_Duplicate_Basenames : Boolean);
386 -- Search the source directories to find the sources. If For_All_Sources is
387 -- True, check each regular file name against the naming schemes of the
388 -- different languages. Otherwise consider only the file names in the hash
389 -- table Source_Names. If Allow_Duplicate_Basenames, then files with the
390 -- same base names are authorized within a project for source-based
391 -- languages (never for unit based languages)
394 (Project : Project_Id;
395 In_Tree : Project_Tree_Ref;
396 Path : Path_Name_Type;
397 File_Name : File_Name_Type;
398 Display_File_Name : File_Name_Type;
399 For_All_Sources : Boolean;
400 Allow_Duplicate_Basenames : Boolean);
401 -- Check if file File_Name is a valid source of the project. This is used
402 -- in multi-language mode only. When the file matches one of the naming
403 -- schemes, it is added to various htables through Add_Source and to
404 -- Source_Paths_Htable.
406 -- Name is the name of the candidate file. It hasn't been normalized yet
407 -- and is the direct result of readdir().
409 -- File_Name is the same as Name, but has been normalized.
410 -- Display_File_Name, however, has not been normalized.
412 -- Source_Directory is the directory in which the file
413 -- was found. It hasn't been normalized (nor has had links resolved).
414 -- It should not end with a directory separator, to avoid duplicates
417 -- If For_All_Sources is True, then all possible file names are analyzed
418 -- otherwise only those currently set in the Source_Names htable.
420 -- If Allow_Duplicate_Basenames, then files with the same base names are
421 -- authorized within a project for source-based languages (never for unit
424 procedure Check_File_Naming_Schemes
425 (In_Tree : Project_Tree_Ref;
426 Project : Project_Id;
427 File_Name : File_Name_Type;
428 Alternate_Languages : out Language_List;
429 Language : out Language_Ptr;
430 Display_Language_Name : out Name_Id;
432 Lang_Kind : out Language_Kind;
433 Kind : out Source_Kind);
434 -- Check if the file name File_Name conforms to one of the naming
435 -- schemes of the project.
437 -- If the file does not match one of the naming schemes, set Language
438 -- to No_Language_Index.
440 -- Filename is the name of the file being investigated. It has been
441 -- normalized (case-folded). File_Name is the same value.
443 procedure Free_Ada_Naming_Exceptions;
444 -- Free the internal hash tables used for checking naming exceptions
446 procedure Get_Directories
447 (Project : Project_Id;
448 In_Tree : Project_Tree_Ref;
449 Current_Dir : String);
450 -- Get the object directory, the exec directory and the source directories
453 -- Current_Dir should represent the current directory, and is passed for
454 -- efficiency to avoid system calls to recompute it.
457 (Project : Project_Id;
458 In_Tree : Project_Tree_Ref);
459 -- Get the mains of a project from attribute Main, if it exists, and put
460 -- them in the project data.
462 procedure Get_Sources_From_File
464 Location : Source_Ptr;
465 Project : Project_Id;
466 In_Tree : Project_Tree_Ref);
467 -- Get the list of sources from a text file and put them in hash table
470 procedure Find_Sources
471 (Project : Project_Id;
472 In_Tree : Project_Tree_Ref;
473 Proc_Data : in out Processing_Data;
474 Allow_Duplicate_Basenames : Boolean);
475 -- Process the Source_Files and Source_List_File attributes, and store
476 -- the list of source files into the Source_Names htable.
477 -- When these attributes are not defined, find all files matching the
478 -- naming schemes in the source directories.
479 -- If Allow_Duplicate_Basenames, then files with the same base names are
480 -- authorized within a project for source-based languages (never for unit
483 procedure Compute_Unit_Name
484 (File_Name : File_Name_Type;
485 Dot_Replacement : File_Name_Type;
486 Separate_Suffix : File_Name_Type;
487 Body_Suffix : File_Name_Type;
488 Spec_Suffix : File_Name_Type;
489 Casing : Casing_Type;
490 Kind : out Source_Kind;
492 In_Tree : Project_Tree_Ref);
493 -- Check whether the file matches the naming scheme. If it does,
494 -- compute its unit name. If Unit is set to No_Name on exit, none of the
495 -- other out parameters are relevant.
498 (In_Tree : Project_Tree_Ref;
499 Canonical_File_Name : File_Name_Type;
500 Naming : Naming_Data;
501 Exception_Id : out Ada_Naming_Exception_Id;
502 Unit_Name : out Name_Id;
503 Unit_Kind : out Spec_Or_Body);
504 -- Find out, from a file name, the unit name, the unit kind and if a
505 -- specific SFN pragma is needed. If the file name corresponds to no unit,
506 -- then Unit_Name will be No_Name. If the file is a multi-unit source or an
507 -- exception to the naming scheme, then Exception_Id is set to the unit or
508 -- units that the source contains, and the other information are not set.
510 function Is_Illegal_Suffix
511 (Suffix : File_Name_Type;
512 Dot_Replacement : File_Name_Type) return Boolean;
513 -- Returns True if the string Suffix cannot be used as a spec suffix, a
514 -- body suffix or a separate suffix.
516 procedure Locate_Directory
517 (Project : Project_Id;
518 In_Tree : Project_Tree_Ref;
519 Name : File_Name_Type;
520 Path : out Path_Information;
521 Dir_Exists : out Boolean;
522 Create : String := "";
523 Location : Source_Ptr := No_Location;
524 Must_Exist : Boolean := True;
525 Externally_Built : Boolean := False);
526 -- Locate a directory. Name is the directory name.
527 -- Relative paths are resolved relative to the project's directory.
528 -- If the directory does not exist and Setup_Projects
529 -- is True and Create is a non null string, an attempt is made to create
531 -- If the directory does not exist, it is either created if Setup_Projects
532 -- is False (and then returned), or simply returned without checking for
533 -- its existence (if Must_Exist is False) or No_Path_Information is
534 -- returned. In all cases, Dir_Exists indicates whether the directory now
537 -- Create is also used for debugging traces to show which path we are
540 procedure Look_For_Sources
541 (Project : Project_Id;
542 In_Tree : Project_Tree_Ref;
543 Proc_Data : in out Processing_Data;
544 Allow_Duplicate_Basenames : Boolean);
545 -- Find all the sources of project Project in project tree In_Tree and
546 -- update its Data accordingly. This assumes that Data.First_Source has
547 -- been initialized with the list of excluded sources and special naming
548 -- exceptions. If Allow_Duplicate_Basenames, then files with the same base
549 -- names are authorized within a project for source-based languages (never
550 -- for unit based languages)
552 function Path_Name_Of
553 (File_Name : File_Name_Type;
554 Directory : Path_Name_Type) return String;
555 -- Returns the path name of a (non project) file. Returns an empty string
556 -- if file cannot be found.
558 procedure Prepare_Ada_Naming_Exceptions
559 (List : Array_Element_Id;
560 In_Tree : Project_Tree_Ref;
561 Kind : Spec_Or_Body);
562 -- Prepare the internal hash tables used for checking naming exceptions
563 -- for Ada. Insert all elements of List in the tables.
565 procedure Record_Ada_Source
566 (File_Name : File_Name_Type;
567 Path_Name : Path_Name_Type;
568 Project : Project_Id;
569 In_Tree : Project_Tree_Ref;
570 Proc_Data : in out Processing_Data;
571 Ada_Language : Language_Ptr;
572 Location : Source_Ptr;
573 Source_Recorded : in out Boolean);
574 -- Put a unit in the list of units of a project, if the file name
575 -- corresponds to a valid unit name. Ada_Language is a pointer to the
576 -- Language_Data for "Ada" in Project.
578 procedure Remove_Source
580 Replaced_By : Source_Id);
583 procedure Report_No_Sources
584 (Project : Project_Id;
586 In_Tree : Project_Tree_Ref;
587 Location : Source_Ptr;
588 Continuation : Boolean := False);
589 -- Report an error or a warning depending on the value of When_No_Sources
590 -- when there are no sources for language Lang_Name.
592 procedure Show_Source_Dirs
593 (Project : Project_Id; In_Tree : Project_Tree_Ref);
594 -- List all the source directories of a project
596 procedure Warn_If_Not_Sources
597 (Project : Project_Id;
598 In_Tree : Project_Tree_Ref;
599 Conventions : Array_Element_Id;
601 Extending : Boolean);
602 -- Check that individual naming conventions apply to immediate sources of
603 -- the project. If not, issue a warning.
605 procedure Write_Attr (Name, Value : String);
606 -- Debug print a value for a specific property. Does nothing when not in
609 ------------------------------
610 -- Replace_Into_Name_Buffer --
611 ------------------------------
613 procedure Replace_Into_Name_Buffer
616 Replacement : Character)
618 Max : constant Integer := Str'Last - Pattern'Length + 1;
625 while J <= Str'Last loop
626 Name_Len := Name_Len + 1;
629 and then Str (J .. J + Pattern'Length - 1) = Pattern
631 Name_Buffer (Name_Len) := Replacement;
632 J := J + Pattern'Length;
635 Name_Buffer (Name_Len) := GNAT.Case_Util.To_Lower (Str (J));
639 end Replace_Into_Name_Buffer;
645 function Suffix_Matches
647 Suffix : File_Name_Type) return Boolean
649 Min_Prefix_Length : Natural := 0;
651 if Suffix = No_File or else Suffix = Empty_File then
656 Suf : constant String := Get_Name_String (Suffix);
659 -- The file name must end with the suffix (which is not an extension)
660 -- For instance a suffix "configure.in" must match a file with the
661 -- same name. To avoid dummy cases, though, a suffix starting with
662 -- '.' requires a file that is at least one character longer ('.cpp'
663 -- should not match a file with the same name)
665 if Suf (Suf'First) = '.' then
666 Min_Prefix_Length := 1;
669 return Filename'Length >= Suf'Length + Min_Prefix_Length
671 (Filename'Last - Suf'Length + 1 .. Filename'Last) = Suf;
679 procedure Write_Attr (Name, Value : String) is
681 if Current_Verbosity = High then
682 Write_Str (" " & Name & " = """);
695 In_Tree : Project_Tree_Ref;
696 Project : Project_Id;
697 Lang_Id : Language_Ptr;
699 File_Name : File_Name_Type;
700 Display_File : File_Name_Type;
701 Naming_Exception : Boolean := False;
702 Path : Path_Information := No_Path_Information;
703 Alternate_Languages : Language_List := null;
704 Unit : Name_Id := No_Name;
706 Source_To_Replace : Source_Id := No_Source)
708 Config : constant Language_Config := Lang_Id.Config;
712 Id := new Source_Data;
714 if Current_Verbosity = High then
715 Write_Str ("Adding source File: ");
716 Write_Str (Get_Name_String (File_Name));
718 if Lang_Id.Config.Kind = Unit_Based then
719 Write_Str (" Unit: ");
720 -- ??? in gprclean, it seems we sometimes pass an empty Unit name
721 -- (see test extended_projects)
722 if Unit /= No_Name then
723 Write_Str (Get_Name_String (Unit));
725 Write_Str (" Kind: ");
726 Write_Str (Source_Kind'Image (Kind));
732 Id.Project := Project;
733 Id.Language := Lang_Id;
735 Id.Alternate_Languages := Alternate_Languages;
737 -- Add the source id to the Unit_Sources_HT hash table, if the unit name
740 if Unit /= No_Name then
741 Unit_Sources_Htable.Set (In_Tree.Unit_Sources_HT, Unit, Id);
743 -- ??? Record_Unit has already fetched that earlier, so this isn't
744 -- the most efficient way. But we can't really pass a parameter since
745 -- Process_Exceptions_Unit_Based and Check_File haven't looked it up.
747 UData := Units_Htable.Get (In_Tree.Units_HT, Unit);
749 if UData = No_Unit_Index then
750 UData := new Unit_Data;
752 Units_Htable.Set (In_Tree.Units_HT, Unit, UData);
757 -- Note that this updates Unit information as well
759 Override_Kind (Id, Kind);
763 Id.File := File_Name;
764 Id.Display_File := Display_File;
765 Id.Dep_Name := Dependency_Name
766 (File_Name, Lang_Id.Config.Dependency_Kind);
767 Id.Naming_Exception := Naming_Exception;
769 if Is_Compilable (Id) and then Config.Object_Generated then
770 Id.Object := Object_Name (File_Name, Config.Object_File_Suffix);
771 Id.Switches := Switches_Name (File_Name);
774 if Path /= No_Path_Information then
776 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path.Name, Id);
779 -- Add the source to the language list
781 Id.Next_In_Lang := Lang_Id.First_Source;
782 Lang_Id.First_Source := Id;
784 if Source_To_Replace /= No_Source then
785 Remove_Source (Source_To_Replace, Id);
793 function ALI_File_Name (Source : String) return String is
795 -- If the source name has extension, replace it with the ALI suffix
797 for Index in reverse Source'First + 1 .. Source'Last loop
798 if Source (Index) = '.' then
799 return Source (Source'First .. Index - 1) & ALI_Suffix;
803 -- If no dot, or if it is the first character, just add the ALI suffix
805 return Source & ALI_Suffix;
808 ------------------------------
809 -- Canonical_Case_File_Name --
810 ------------------------------
812 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type is
814 if Osint.File_Names_Case_Sensitive then
815 return File_Name_Type (Name);
817 Get_Name_String (Name);
818 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
821 end Canonical_Case_File_Name;
828 (Project : Project_Id;
829 In_Tree : Project_Tree_Ref;
830 Report_Error : Put_Line_Access;
831 When_No_Sources : Error_Warning;
832 Current_Dir : String;
833 Proc_Data : in out Processing_Data;
834 Is_Config_File : Boolean;
835 Compiler_Driver_Mandatory : Boolean;
836 Allow_Duplicate_Basenames : Boolean)
838 Specs : Array_Element_Id;
839 Bodies : Array_Element_Id;
840 Extending : Boolean := False;
843 Nmsc.When_No_Sources := When_No_Sources;
844 Error_Report := Report_Error;
846 Recursive_Dirs.Reset;
848 Check_If_Externally_Built (Project, In_Tree);
850 -- Object, exec and source directories
852 Get_Directories (Project, In_Tree, Current_Dir);
854 -- Get the programming languages
856 Check_Programming_Languages (In_Tree, Project);
858 if Project.Qualifier = Dry
859 and then Project.Source_Dirs /= Nil_String
862 Source_Dirs : constant Variable_Value :=
865 Project.Decl.Attributes, In_Tree);
866 Source_Files : constant Variable_Value :=
869 Project.Decl.Attributes, In_Tree);
870 Source_List_File : constant Variable_Value :=
872 (Name_Source_List_File,
873 Project.Decl.Attributes, In_Tree);
874 Languages : constant Variable_Value :=
877 Project.Decl.Attributes, In_Tree);
880 if Source_Dirs.Values = Nil_String
881 and then Source_Files.Values = Nil_String
882 and then Languages.Values = Nil_String
883 and then Source_List_File.Default
885 Project.Source_Dirs := Nil_String;
890 "at least one of Source_Files, Source_Dirs or Languages " &
891 "must be declared empty for an abstract project",
897 -- Check configuration in multi language mode
899 if Must_Check_Configuration then
902 Compiler_Driver_Mandatory => Compiler_Driver_Mandatory);
905 -- Library attributes
907 Check_Library_Attributes (Project, In_Tree);
909 if Current_Verbosity = High then
910 Show_Source_Dirs (Project, In_Tree);
913 Check_Package_Naming (Project, In_Tree);
915 Extending := Project.Extends /= No_Project;
917 Check_Naming_Schemes (Project, In_Tree, Is_Config_File, Bodies, Specs);
919 if Get_Mode = Ada_Only then
920 Prepare_Ada_Naming_Exceptions (Bodies, In_Tree, Impl);
921 Prepare_Ada_Naming_Exceptions (Specs, In_Tree, Spec);
926 if Project.Source_Dirs /= Nil_String then
928 (Project, In_Tree, Proc_Data, Allow_Duplicate_Basenames);
930 if Get_Mode = Ada_Only then
932 -- Check that all individual naming conventions apply to sources
933 -- of this project file.
936 (Project, In_Tree, Bodies,
938 Extending => Extending);
940 (Project, In_Tree, Specs,
942 Extending => Extending);
944 elsif Get_Mode = Multi_Language and then
945 (not Project.Externally_Built) and then
949 Language : Language_Ptr;
951 Alt_Lang : Language_List;
952 Continuation : Boolean := False;
953 Iter : Source_Iterator;
956 Language := Project.Languages;
957 while Language /= No_Language_Index loop
959 -- If there are no sources for this language, check whether
960 -- there are sources for which this is an alternate
963 if Language.First_Source = No_Source then
964 Iter := For_Each_Source (In_Tree => In_Tree,
967 Source := Element (Iter);
968 exit Source_Loop when Source = No_Source
969 or else Source.Language = Language;
971 Alt_Lang := Source.Alternate_Languages;
972 while Alt_Lang /= null loop
973 exit Source_Loop when Alt_Lang.Language = Language;
974 Alt_Lang := Alt_Lang.Next;
978 end loop Source_Loop;
980 if Source = No_Source then
983 Get_Name_String (Language.Display_Name),
987 Continuation := True;
991 Language := Language.Next;
997 if Get_Mode = Multi_Language then
999 -- If a list of sources is specified in attribute Interfaces, set
1000 -- In_Interfaces only for the sources specified in the list.
1002 Check_Interfaces (Project, In_Tree);
1005 -- If it is a library project file, check if it is a standalone library
1007 if Project.Library then
1008 Check_Stand_Alone_Library
1009 (Project, In_Tree, Current_Dir, Extending);
1012 -- Put the list of Mains, if any, in the project data
1014 Get_Mains (Project, In_Tree);
1016 Free_Ada_Naming_Exceptions;
1019 --------------------
1020 -- Check_Ada_Name --
1021 --------------------
1023 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
1024 The_Name : String := Name;
1025 Real_Name : Name_Id;
1026 Need_Letter : Boolean := True;
1027 Last_Underscore : Boolean := False;
1028 OK : Boolean := The_Name'Length > 0;
1031 function Is_Reserved (Name : Name_Id) return Boolean;
1032 function Is_Reserved (S : String) return Boolean;
1033 -- Check that the given name is not an Ada 95 reserved word. The reason
1034 -- for the Ada 95 here is that we do not want to exclude the case of an
1035 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
1036 -- name would be rejected anyway by the compiler. That means there is no
1037 -- requirement that the project file parser reject this.
1043 function Is_Reserved (S : String) return Boolean is
1046 Add_Str_To_Name_Buffer (S);
1047 return Is_Reserved (Name_Find);
1054 function Is_Reserved (Name : Name_Id) return Boolean is
1056 if Get_Name_Table_Byte (Name) /= 0
1057 and then Name /= Name_Project
1058 and then Name /= Name_Extends
1059 and then Name /= Name_External
1060 and then Name not in Ada_2005_Reserved_Words
1064 if Current_Verbosity = High then
1065 Write_Str (The_Name);
1066 Write_Line (" is an Ada reserved word.");
1076 -- Start of processing for Check_Ada_Name
1079 To_Lower (The_Name);
1081 Name_Len := The_Name'Length;
1082 Name_Buffer (1 .. Name_Len) := The_Name;
1084 -- Special cases of children of packages A, G, I and S on VMS
1086 if OpenVMS_On_Target
1087 and then Name_Len > 3
1088 and then Name_Buffer (2 .. 3) = "__"
1090 ((Name_Buffer (1) = 'a') or else
1091 (Name_Buffer (1) = 'g') or else
1092 (Name_Buffer (1) = 'i') or else
1093 (Name_Buffer (1) = 's'))
1095 Name_Buffer (2) := '.';
1096 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
1097 Name_Len := Name_Len - 1;
1100 Real_Name := Name_Find;
1102 if Is_Reserved (Real_Name) then
1106 First := The_Name'First;
1108 for Index in The_Name'Range loop
1111 -- We need a letter (at the beginning, and following a dot),
1112 -- but we don't have one.
1114 if Is_Letter (The_Name (Index)) then
1115 Need_Letter := False;
1120 if Current_Verbosity = High then
1121 Write_Int (Types.Int (Index));
1123 Write_Char (The_Name (Index));
1124 Write_Line ("' is not a letter.");
1130 elsif Last_Underscore
1131 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
1133 -- Two underscores are illegal, and a dot cannot follow
1138 if Current_Verbosity = High then
1139 Write_Int (Types.Int (Index));
1141 Write_Char (The_Name (Index));
1142 Write_Line ("' is illegal here.");
1147 elsif The_Name (Index) = '.' then
1149 -- First, check if the name before the dot is not a reserved word
1150 if Is_Reserved (The_Name (First .. Index - 1)) then
1156 -- We need a letter after a dot
1158 Need_Letter := True;
1160 elsif The_Name (Index) = '_' then
1161 Last_Underscore := True;
1164 -- We need an letter or a digit
1166 Last_Underscore := False;
1168 if not Is_Alphanumeric (The_Name (Index)) then
1171 if Current_Verbosity = High then
1172 Write_Int (Types.Int (Index));
1174 Write_Char (The_Name (Index));
1175 Write_Line ("' is not alphanumeric.");
1183 -- Cannot end with an underscore or a dot
1185 OK := OK and then not Need_Letter and then not Last_Underscore;
1188 if First /= Name'First and then
1189 Is_Reserved (The_Name (First .. The_Name'Last))
1197 -- Signal a problem with No_Name
1203 -------------------------
1204 -- Check_Configuration --
1205 -------------------------
1207 procedure Check_Configuration
1208 (Project : Project_Id;
1209 In_Tree : Project_Tree_Ref;
1210 Compiler_Driver_Mandatory : Boolean)
1212 Dot_Replacement : File_Name_Type := No_File;
1213 Casing : Casing_Type := All_Lower_Case;
1214 Separate_Suffix : File_Name_Type := No_File;
1216 Lang_Index : Language_Ptr := No_Language_Index;
1217 -- The index of the language data being checked
1219 Prev_Index : Language_Ptr := No_Language_Index;
1220 -- The index of the previous language
1222 procedure Process_Project_Level_Simple_Attributes;
1223 -- Process the simple attributes at the project level
1225 procedure Process_Project_Level_Array_Attributes;
1226 -- Process the associate array attributes at the project level
1228 procedure Process_Packages;
1229 -- Read the packages of the project
1231 ----------------------
1232 -- Process_Packages --
1233 ----------------------
1235 procedure Process_Packages is
1236 Packages : Package_Id;
1237 Element : Package_Element;
1239 procedure Process_Binder (Arrays : Array_Id);
1240 -- Process the associate array attributes of package Binder
1242 procedure Process_Builder (Attributes : Variable_Id);
1243 -- Process the simple attributes of package Builder
1245 procedure Process_Compiler (Arrays : Array_Id);
1246 -- Process the associate array attributes of package Compiler
1248 procedure Process_Naming (Attributes : Variable_Id);
1249 -- Process the simple attributes of package Naming
1251 procedure Process_Naming (Arrays : Array_Id);
1252 -- Process the associate array attributes of package Naming
1254 procedure Process_Linker (Attributes : Variable_Id);
1255 -- Process the simple attributes of package Linker of a
1256 -- configuration project.
1258 --------------------
1259 -- Process_Binder --
1260 --------------------
1262 procedure Process_Binder (Arrays : Array_Id) is
1263 Current_Array_Id : Array_Id;
1264 Current_Array : Array_Data;
1265 Element_Id : Array_Element_Id;
1266 Element : Array_Element;
1269 -- Process the associative array attribute of package Binder
1271 Current_Array_Id := Arrays;
1272 while Current_Array_Id /= No_Array loop
1273 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1275 Element_Id := Current_Array.Value;
1276 while Element_Id /= No_Array_Element loop
1277 Element := In_Tree.Array_Elements.Table (Element_Id);
1279 if Element.Index /= All_Other_Names then
1281 -- Get the name of the language
1284 Get_Language_From_Name
1285 (Project, Get_Name_String (Element.Index));
1287 if Lang_Index /= No_Language_Index then
1288 case Current_Array.Name is
1291 -- Attribute Driver (<language>)
1293 Lang_Index.Config.Binder_Driver :=
1294 File_Name_Type (Element.Value.Value);
1296 when Name_Required_Switches =>
1299 Lang_Index.Config.Binder_Required_Switches,
1300 From_List => Element.Value.Values,
1301 In_Tree => In_Tree);
1305 -- Attribute Prefix (<language>)
1307 Lang_Index.Config.Binder_Prefix :=
1308 Element.Value.Value;
1310 when Name_Objects_Path =>
1312 -- Attribute Objects_Path (<language>)
1314 Lang_Index.Config.Objects_Path :=
1315 Element.Value.Value;
1317 when Name_Objects_Path_File =>
1319 -- Attribute Objects_Path (<language>)
1321 Lang_Index.Config.Objects_Path_File :=
1322 Element.Value.Value;
1330 Element_Id := Element.Next;
1333 Current_Array_Id := Current_Array.Next;
1337 ---------------------
1338 -- Process_Builder --
1339 ---------------------
1341 procedure Process_Builder (Attributes : Variable_Id) is
1342 Attribute_Id : Variable_Id;
1343 Attribute : Variable;
1346 -- Process non associated array attribute from package Builder
1348 Attribute_Id := Attributes;
1349 while Attribute_Id /= No_Variable loop
1351 In_Tree.Variable_Elements.Table (Attribute_Id);
1353 if not Attribute.Value.Default then
1354 if Attribute.Name = Name_Executable_Suffix then
1356 -- Attribute Executable_Suffix: the suffix of the
1359 Project.Config.Executable_Suffix :=
1360 Attribute.Value.Value;
1364 Attribute_Id := Attribute.Next;
1366 end Process_Builder;
1368 ----------------------
1369 -- Process_Compiler --
1370 ----------------------
1372 procedure Process_Compiler (Arrays : Array_Id) is
1373 Current_Array_Id : Array_Id;
1374 Current_Array : Array_Data;
1375 Element_Id : Array_Element_Id;
1376 Element : Array_Element;
1377 List : String_List_Id;
1380 -- Process the associative array attribute of package Compiler
1382 Current_Array_Id := Arrays;
1383 while Current_Array_Id /= No_Array loop
1384 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1386 Element_Id := Current_Array.Value;
1387 while Element_Id /= No_Array_Element loop
1388 Element := In_Tree.Array_Elements.Table (Element_Id);
1390 if Element.Index /= All_Other_Names then
1392 -- Get the name of the language
1394 Lang_Index := Get_Language_From_Name
1395 (Project, Get_Name_String (Element.Index));
1397 if Lang_Index /= No_Language_Index then
1398 case Current_Array.Name is
1399 when Name_Dependency_Switches =>
1401 -- Attribute Dependency_Switches (<language>)
1403 if Lang_Index.Config.Dependency_Kind = None then
1404 Lang_Index.Config.Dependency_Kind := Makefile;
1407 List := Element.Value.Values;
1409 if List /= Nil_String then
1411 Lang_Index.Config.Dependency_Option,
1413 In_Tree => In_Tree);
1416 when Name_Dependency_Driver =>
1418 -- Attribute Dependency_Driver (<language>)
1420 if Lang_Index.Config.Dependency_Kind = None then
1421 Lang_Index.Config.Dependency_Kind := Makefile;
1424 List := Element.Value.Values;
1426 if List /= Nil_String then
1428 Lang_Index.Config.Compute_Dependency,
1430 In_Tree => In_Tree);
1433 when Name_Include_Switches =>
1435 -- Attribute Include_Switches (<language>)
1437 List := Element.Value.Values;
1439 if List = Nil_String then
1443 "include option cannot be null",
1444 Element.Value.Location);
1448 Lang_Index.Config.Include_Option,
1450 In_Tree => In_Tree);
1452 when Name_Include_Path =>
1454 -- Attribute Include_Path (<language>)
1456 Lang_Index.Config.Include_Path :=
1457 Element.Value.Value;
1459 when Name_Include_Path_File =>
1461 -- Attribute Include_Path_File (<language>)
1463 Lang_Index.Config.Include_Path_File :=
1464 Element.Value.Value;
1468 -- Attribute Driver (<language>)
1470 Lang_Index.Config.Compiler_Driver :=
1471 File_Name_Type (Element.Value.Value);
1473 when Name_Required_Switches |
1474 Name_Leading_Required_Switches =>
1477 Compiler_Leading_Required_Switches,
1478 From_List => Element.Value.Values,
1479 In_Tree => In_Tree);
1481 when Name_Trailing_Required_Switches =>
1484 Compiler_Trailing_Required_Switches,
1485 From_List => Element.Value.Values,
1486 In_Tree => In_Tree);
1488 when Name_Path_Syntax =>
1490 Lang_Index.Config.Path_Syntax :=
1491 Path_Syntax_Kind'Value
1492 (Get_Name_String (Element.Value.Value));
1495 when Constraint_Error =>
1499 "invalid value for Path_Syntax",
1500 Element.Value.Location);
1503 when Name_Object_File_Suffix =>
1504 if Get_Name_String (Element.Value.Value) = "" then
1507 "object file suffix cannot be empty",
1508 Element.Value.Location);
1511 Lang_Index.Config.Object_File_Suffix :=
1512 Element.Value.Value;
1515 when Name_Object_File_Switches =>
1517 Lang_Index.Config.Object_File_Switches,
1518 From_List => Element.Value.Values,
1519 In_Tree => In_Tree);
1521 when Name_Pic_Option =>
1523 -- Attribute Compiler_Pic_Option (<language>)
1525 List := Element.Value.Values;
1527 if List = Nil_String then
1531 "compiler PIC option cannot be null",
1532 Element.Value.Location);
1536 Lang_Index.Config.Compilation_PIC_Option,
1538 In_Tree => In_Tree);
1540 when Name_Mapping_File_Switches =>
1542 -- Attribute Mapping_File_Switches (<language>)
1544 List := Element.Value.Values;
1546 if List = Nil_String then
1550 "mapping file switches cannot be null",
1551 Element.Value.Location);
1555 Lang_Index.Config.Mapping_File_Switches,
1557 In_Tree => In_Tree);
1559 when Name_Mapping_Spec_Suffix =>
1561 -- Attribute Mapping_Spec_Suffix (<language>)
1563 Lang_Index.Config.Mapping_Spec_Suffix :=
1564 File_Name_Type (Element.Value.Value);
1566 when Name_Mapping_Body_Suffix =>
1568 -- Attribute Mapping_Body_Suffix (<language>)
1570 Lang_Index.Config.Mapping_Body_Suffix :=
1571 File_Name_Type (Element.Value.Value);
1573 when Name_Config_File_Switches =>
1575 -- Attribute Config_File_Switches (<language>)
1577 List := Element.Value.Values;
1579 if List = Nil_String then
1583 "config file switches cannot be null",
1584 Element.Value.Location);
1588 Lang_Index.Config.Config_File_Switches,
1590 In_Tree => In_Tree);
1592 when Name_Objects_Path =>
1594 -- Attribute Objects_Path (<language>)
1596 Lang_Index.Config.Objects_Path :=
1597 Element.Value.Value;
1599 when Name_Objects_Path_File =>
1601 -- Attribute Objects_Path_File (<language>)
1603 Lang_Index.Config.Objects_Path_File :=
1604 Element.Value.Value;
1606 when Name_Config_Body_File_Name =>
1608 -- Attribute Config_Body_File_Name (<language>)
1610 Lang_Index.Config.Config_Body :=
1611 Element.Value.Value;
1613 when Name_Config_Body_File_Name_Pattern =>
1615 -- Attribute Config_Body_File_Name_Pattern
1618 Lang_Index.Config.Config_Body_Pattern :=
1619 Element.Value.Value;
1621 when Name_Config_Spec_File_Name =>
1623 -- Attribute Config_Spec_File_Name (<language>)
1625 Lang_Index.Config.Config_Spec :=
1626 Element.Value.Value;
1628 when Name_Config_Spec_File_Name_Pattern =>
1630 -- Attribute Config_Spec_File_Name_Pattern
1633 Lang_Index.Config.Config_Spec_Pattern :=
1634 Element.Value.Value;
1636 when Name_Config_File_Unique =>
1638 -- Attribute Config_File_Unique (<language>)
1641 Lang_Index.Config.Config_File_Unique :=
1643 (Get_Name_String (Element.Value.Value));
1645 when Constraint_Error =>
1649 "illegal value for Config_File_Unique",
1650 Element.Value.Location);
1659 Element_Id := Element.Next;
1662 Current_Array_Id := Current_Array.Next;
1664 end Process_Compiler;
1666 --------------------
1667 -- Process_Naming --
1668 --------------------
1670 procedure Process_Naming (Attributes : Variable_Id) is
1671 Attribute_Id : Variable_Id;
1672 Attribute : Variable;
1675 -- Process non associated array attribute from package Naming
1677 Attribute_Id := Attributes;
1678 while Attribute_Id /= No_Variable loop
1679 Attribute := In_Tree.Variable_Elements.Table (Attribute_Id);
1681 if not Attribute.Value.Default then
1682 if Attribute.Name = Name_Separate_Suffix then
1684 -- Attribute Separate_Suffix
1686 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1688 elsif Attribute.Name = Name_Casing then
1694 Value (Get_Name_String (Attribute.Value.Value));
1697 when Constraint_Error =>
1701 "invalid value for Casing",
1702 Attribute.Value.Location);
1705 elsif Attribute.Name = Name_Dot_Replacement then
1707 -- Attribute Dot_Replacement
1709 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1714 Attribute_Id := Attribute.Next;
1718 procedure Process_Naming (Arrays : Array_Id) is
1719 Current_Array_Id : Array_Id;
1720 Current_Array : Array_Data;
1721 Element_Id : Array_Element_Id;
1722 Element : Array_Element;
1724 -- Process the associative array attribute of package Naming
1726 Current_Array_Id := Arrays;
1727 while Current_Array_Id /= No_Array loop
1728 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1730 Element_Id := Current_Array.Value;
1731 while Element_Id /= No_Array_Element loop
1732 Element := In_Tree.Array_Elements.Table (Element_Id);
1734 -- Get the name of the language
1736 Lang_Index := Get_Language_From_Name
1737 (Project, Get_Name_String (Element.Index));
1739 if Lang_Index /= No_Language_Index then
1740 case Current_Array.Name is
1741 when Name_Spec_Suffix | Name_Specification_Suffix =>
1743 -- Attribute Spec_Suffix (<language>)
1745 Lang_Index.Config.Naming_Data.Spec_Suffix :=
1746 File_Name_Type (Element.Value.Value);
1748 when Name_Implementation_Suffix | Name_Body_Suffix =>
1750 -- Attribute Body_Suffix (<language>)
1752 Lang_Index.Config.Naming_Data.Body_Suffix :=
1753 File_Name_Type (Element.Value.Value);
1755 Lang_Index.Config.Naming_Data.Separate_Suffix :=
1756 File_Name_Type (Element.Value.Value);
1763 Element_Id := Element.Next;
1766 Current_Array_Id := Current_Array.Next;
1770 --------------------
1771 -- Process_Linker --
1772 --------------------
1774 procedure Process_Linker (Attributes : Variable_Id) is
1775 Attribute_Id : Variable_Id;
1776 Attribute : Variable;
1779 -- Process non associated array attribute from package Linker
1781 Attribute_Id := Attributes;
1782 while Attribute_Id /= No_Variable loop
1784 In_Tree.Variable_Elements.Table (Attribute_Id);
1786 if not Attribute.Value.Default then
1787 if Attribute.Name = Name_Driver then
1789 -- Attribute Linker'Driver: the default linker to use
1791 Project.Config.Linker :=
1792 Path_Name_Type (Attribute.Value.Value);
1794 -- Linker'Driver is also used to link shared libraries
1795 -- if the obsolescent attribute Library_GCC has not been
1798 if Project.Config.Shared_Lib_Driver = No_File then
1799 Project.Config.Shared_Lib_Driver :=
1800 File_Name_Type (Attribute.Value.Value);
1803 elsif Attribute.Name = Name_Required_Switches then
1805 -- Attribute Required_Switches: the minimum
1806 -- options to use when invoking the linker
1808 Put (Into_List => Project.Config.Minimum_Linker_Options,
1809 From_List => Attribute.Value.Values,
1810 In_Tree => In_Tree);
1812 elsif Attribute.Name = Name_Map_File_Option then
1813 Project.Config.Map_File_Option := Attribute.Value.Value;
1815 elsif Attribute.Name = Name_Max_Command_Line_Length then
1817 Project.Config.Max_Command_Line_Length :=
1818 Natural'Value (Get_Name_String
1819 (Attribute.Value.Value));
1822 when Constraint_Error =>
1826 "value must be positive or equal to 0",
1827 Attribute.Value.Location);
1830 elsif Attribute.Name = Name_Response_File_Format then
1835 Get_Name_String (Attribute.Value.Value);
1836 To_Lower (Name_Buffer (1 .. Name_Len));
1839 if Name = Name_None then
1840 Project.Config.Resp_File_Format := None;
1842 elsif Name = Name_Gnu then
1843 Project.Config.Resp_File_Format := GNU;
1845 elsif Name = Name_Object_List then
1846 Project.Config.Resp_File_Format := Object_List;
1848 elsif Name = Name_Option_List then
1849 Project.Config.Resp_File_Format := Option_List;
1855 "illegal response file format",
1856 Attribute.Value.Location);
1860 elsif Attribute.Name = Name_Response_File_Switches then
1861 Put (Into_List => Project.Config.Resp_File_Options,
1862 From_List => Attribute.Value.Values,
1863 In_Tree => In_Tree);
1867 Attribute_Id := Attribute.Next;
1871 -- Start of processing for Process_Packages
1874 Packages := Project.Decl.Packages;
1875 while Packages /= No_Package loop
1876 Element := In_Tree.Packages.Table (Packages);
1878 case Element.Name is
1881 -- Process attributes of package Binder
1883 Process_Binder (Element.Decl.Arrays);
1885 when Name_Builder =>
1887 -- Process attributes of package Builder
1889 Process_Builder (Element.Decl.Attributes);
1891 when Name_Compiler =>
1893 -- Process attributes of package Compiler
1895 Process_Compiler (Element.Decl.Arrays);
1899 -- Process attributes of package Linker
1901 Process_Linker (Element.Decl.Attributes);
1905 -- Process attributes of package Naming
1907 Process_Naming (Element.Decl.Attributes);
1908 Process_Naming (Element.Decl.Arrays);
1914 Packages := Element.Next;
1916 end Process_Packages;
1918 ---------------------------------------------
1919 -- Process_Project_Level_Simple_Attributes --
1920 ---------------------------------------------
1922 procedure Process_Project_Level_Simple_Attributes is
1923 Attribute_Id : Variable_Id;
1924 Attribute : Variable;
1925 List : String_List_Id;
1928 -- Process non associated array attribute at project level
1930 Attribute_Id := Project.Decl.Attributes;
1931 while Attribute_Id /= No_Variable loop
1933 In_Tree.Variable_Elements.Table (Attribute_Id);
1935 if not Attribute.Value.Default then
1936 if Attribute.Name = Name_Target then
1938 -- Attribute Target: the target specified
1940 Project.Config.Target := Attribute.Value.Value;
1942 elsif Attribute.Name = Name_Library_Builder then
1944 -- Attribute Library_Builder: the application to invoke
1945 -- to build libraries.
1947 Project.Config.Library_Builder :=
1948 Path_Name_Type (Attribute.Value.Value);
1950 elsif Attribute.Name = Name_Archive_Builder then
1952 -- Attribute Archive_Builder: the archive builder
1953 -- (usually "ar") and its minimum options (usually "cr").
1955 List := Attribute.Value.Values;
1957 if List = Nil_String then
1961 "archive builder cannot be null",
1962 Attribute.Value.Location);
1965 Put (Into_List => Project.Config.Archive_Builder,
1967 In_Tree => In_Tree);
1969 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1971 -- Attribute Archive_Builder: the archive builder
1972 -- (usually "ar") and its minimum options (usually "cr").
1974 List := Attribute.Value.Values;
1976 if List /= Nil_String then
1979 Project.Config.Archive_Builder_Append_Option,
1981 In_Tree => In_Tree);
1984 elsif Attribute.Name = Name_Archive_Indexer then
1986 -- Attribute Archive_Indexer: the optional archive
1987 -- indexer (usually "ranlib") with its minimum options
1990 List := Attribute.Value.Values;
1992 if List = Nil_String then
1996 "archive indexer cannot be null",
1997 Attribute.Value.Location);
2000 Put (Into_List => Project.Config.Archive_Indexer,
2002 In_Tree => In_Tree);
2004 elsif Attribute.Name = Name_Library_Partial_Linker then
2006 -- Attribute Library_Partial_Linker: the optional linker
2007 -- driver with its minimum options, to partially link
2010 List := Attribute.Value.Values;
2012 if List = Nil_String then
2016 "partial linker cannot be null",
2017 Attribute.Value.Location);
2020 Put (Into_List => Project.Config.Lib_Partial_Linker,
2022 In_Tree => In_Tree);
2024 elsif Attribute.Name = Name_Library_GCC then
2025 Project.Config.Shared_Lib_Driver :=
2026 File_Name_Type (Attribute.Value.Value);
2030 "?Library_'G'C'C is an obsolescent attribute, " &
2031 "use Linker''Driver instead",
2032 Attribute.Value.Location);
2034 elsif Attribute.Name = Name_Archive_Suffix then
2035 Project.Config.Archive_Suffix :=
2036 File_Name_Type (Attribute.Value.Value);
2038 elsif Attribute.Name = Name_Linker_Executable_Option then
2040 -- Attribute Linker_Executable_Option: optional options
2041 -- to specify an executable name. Defaults to "-o".
2043 List := Attribute.Value.Values;
2045 if List = Nil_String then
2049 "linker executable option cannot be null",
2050 Attribute.Value.Location);
2053 Put (Into_List => Project.Config.Linker_Executable_Option,
2055 In_Tree => In_Tree);
2057 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2059 -- Attribute Linker_Lib_Dir_Option: optional options
2060 -- to specify a library search directory. Defaults to
2063 Get_Name_String (Attribute.Value.Value);
2065 if Name_Len = 0 then
2069 "linker library directory option cannot be empty",
2070 Attribute.Value.Location);
2073 Project.Config.Linker_Lib_Dir_Option :=
2074 Attribute.Value.Value;
2076 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2078 -- Attribute Linker_Lib_Name_Option: optional options
2079 -- to specify the name of a library to be linked in.
2080 -- Defaults to "-l".
2082 Get_Name_String (Attribute.Value.Value);
2084 if Name_Len = 0 then
2088 "linker library name option cannot be empty",
2089 Attribute.Value.Location);
2092 Project.Config.Linker_Lib_Name_Option :=
2093 Attribute.Value.Value;
2095 elsif Attribute.Name = Name_Run_Path_Option then
2097 -- Attribute Run_Path_Option: optional options to
2098 -- specify a path for libraries.
2100 List := Attribute.Value.Values;
2102 if List /= Nil_String then
2103 Put (Into_List => Project.Config.Run_Path_Option,
2105 In_Tree => In_Tree);
2108 elsif Attribute.Name = Name_Separate_Run_Path_Options then
2110 pragma Unsuppress (All_Checks);
2112 Project.Config.Separate_Run_Path_Options :=
2113 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2115 when Constraint_Error =>
2119 "invalid value """ &
2120 Get_Name_String (Attribute.Value.Value) &
2121 """ for Separate_Run_Path_Options",
2122 Attribute.Value.Location);
2125 elsif Attribute.Name = Name_Library_Support then
2127 pragma Unsuppress (All_Checks);
2129 Project.Config.Lib_Support :=
2130 Library_Support'Value (Get_Name_String
2131 (Attribute.Value.Value));
2133 when Constraint_Error =>
2137 "invalid value """ &
2138 Get_Name_String (Attribute.Value.Value) &
2139 """ for Library_Support",
2140 Attribute.Value.Location);
2143 elsif Attribute.Name = Name_Shared_Library_Prefix then
2144 Project.Config.Shared_Lib_Prefix :=
2145 File_Name_Type (Attribute.Value.Value);
2147 elsif Attribute.Name = Name_Shared_Library_Suffix then
2148 Project.Config.Shared_Lib_Suffix :=
2149 File_Name_Type (Attribute.Value.Value);
2151 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2153 pragma Unsuppress (All_Checks);
2155 Project.Config.Symbolic_Link_Supported :=
2156 Boolean'Value (Get_Name_String
2157 (Attribute.Value.Value));
2159 when Constraint_Error =>
2164 & Get_Name_String (Attribute.Value.Value)
2165 & """ for Symbolic_Link_Supported",
2166 Attribute.Value.Location);
2170 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2173 pragma Unsuppress (All_Checks);
2175 Project.Config.Lib_Maj_Min_Id_Supported :=
2176 Boolean'Value (Get_Name_String
2177 (Attribute.Value.Value));
2179 when Constraint_Error =>
2183 "invalid value """ &
2184 Get_Name_String (Attribute.Value.Value) &
2185 """ for Library_Major_Minor_Id_Supported",
2186 Attribute.Value.Location);
2189 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2191 pragma Unsuppress (All_Checks);
2193 Project.Config.Auto_Init_Supported :=
2194 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2196 when Constraint_Error =>
2201 & Get_Name_String (Attribute.Value.Value)
2202 & """ for Library_Auto_Init_Supported",
2203 Attribute.Value.Location);
2206 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2207 List := Attribute.Value.Values;
2209 if List /= Nil_String then
2210 Put (Into_List => Project.Config.Shared_Lib_Min_Options,
2212 In_Tree => In_Tree);
2215 elsif Attribute.Name = Name_Library_Version_Switches then
2216 List := Attribute.Value.Values;
2218 if List /= Nil_String then
2219 Put (Into_List => Project.Config.Lib_Version_Options,
2221 In_Tree => In_Tree);
2226 Attribute_Id := Attribute.Next;
2228 end Process_Project_Level_Simple_Attributes;
2230 --------------------------------------------
2231 -- Process_Project_Level_Array_Attributes --
2232 --------------------------------------------
2234 procedure Process_Project_Level_Array_Attributes is
2235 Current_Array_Id : Array_Id;
2236 Current_Array : Array_Data;
2237 Element_Id : Array_Element_Id;
2238 Element : Array_Element;
2239 List : String_List_Id;
2242 -- Process the associative array attributes at project level
2244 Current_Array_Id := Project.Decl.Arrays;
2245 while Current_Array_Id /= No_Array loop
2246 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2248 Element_Id := Current_Array.Value;
2249 while Element_Id /= No_Array_Element loop
2250 Element := In_Tree.Array_Elements.Table (Element_Id);
2252 -- Get the name of the language
2255 Get_Language_From_Name
2256 (Project, Get_Name_String (Element.Index));
2258 if Lang_Index /= No_Language_Index then
2259 case Current_Array.Name is
2260 when Name_Inherit_Source_Path =>
2261 List := Element.Value.Values;
2263 if List /= Nil_String then
2266 Lang_Index.Config.Include_Compatible_Languages,
2269 Lower_Case => True);
2272 when Name_Toolchain_Description =>
2274 -- Attribute Toolchain_Description (<language>)
2276 Lang_Index.Config.Toolchain_Description :=
2277 Element.Value.Value;
2279 when Name_Toolchain_Version =>
2281 -- Attribute Toolchain_Version (<language>)
2283 Lang_Index.Config.Toolchain_Version :=
2284 Element.Value.Value;
2286 when Name_Runtime_Library_Dir =>
2288 -- Attribute Runtime_Library_Dir (<language>)
2290 Lang_Index.Config.Runtime_Library_Dir :=
2291 Element.Value.Value;
2293 when Name_Runtime_Source_Dir =>
2295 -- Attribute Runtime_Library_Dir (<language>)
2297 Lang_Index.Config.Runtime_Source_Dir :=
2298 Element.Value.Value;
2300 when Name_Object_Generated =>
2302 pragma Unsuppress (All_Checks);
2308 (Get_Name_String (Element.Value.Value));
2310 Lang_Index.Config.Object_Generated := Value;
2312 -- If no object is generated, no object may be
2316 Lang_Index.Config.Objects_Linked := False;
2320 when Constraint_Error =>
2325 & Get_Name_String (Element.Value.Value)
2326 & """ for Object_Generated",
2327 Element.Value.Location);
2330 when Name_Objects_Linked =>
2332 pragma Unsuppress (All_Checks);
2338 (Get_Name_String (Element.Value.Value));
2340 -- No change if Object_Generated is False, as this
2341 -- forces Objects_Linked to be False too.
2343 if Lang_Index.Config.Object_Generated then
2344 Lang_Index.Config.Objects_Linked := Value;
2348 when Constraint_Error =>
2353 & Get_Name_String (Element.Value.Value)
2354 & """ for Objects_Linked",
2355 Element.Value.Location);
2362 Element_Id := Element.Next;
2365 Current_Array_Id := Current_Array.Next;
2367 end Process_Project_Level_Array_Attributes;
2370 Process_Project_Level_Simple_Attributes;
2371 Process_Project_Level_Array_Attributes;
2374 -- For unit based languages, set Casing, Dot_Replacement and
2375 -- Separate_Suffix in Naming_Data.
2377 Lang_Index := Project.Languages;
2378 while Lang_Index /= No_Language_Index loop
2379 if Lang_Index.Name = Name_Ada then
2380 Lang_Index.Config.Naming_Data.Casing := Casing;
2381 Lang_Index.Config.Naming_Data.Dot_Replacement := Dot_Replacement;
2383 if Separate_Suffix /= No_File then
2384 Lang_Index.Config.Naming_Data.Separate_Suffix :=
2391 Lang_Index := Lang_Index.Next;
2394 -- Give empty names to various prefixes/suffixes, if they have not
2395 -- been specified in the configuration.
2397 if Project.Config.Archive_Suffix = No_File then
2398 Project.Config.Archive_Suffix := Empty_File;
2401 if Project.Config.Shared_Lib_Prefix = No_File then
2402 Project.Config.Shared_Lib_Prefix := Empty_File;
2405 if Project.Config.Shared_Lib_Suffix = No_File then
2406 Project.Config.Shared_Lib_Suffix := Empty_File;
2409 Lang_Index := Project.Languages;
2410 while Lang_Index /= No_Language_Index loop
2411 -- For all languages, Compiler_Driver needs to be specified. This is
2412 -- only necessary if we do intend to compiler (not in GPS for
2415 if Compiler_Driver_Mandatory
2416 and then Lang_Index.Config.Compiler_Driver = No_File
2418 Error_Msg_Name_1 := Lang_Index.Display_Name;
2422 "?no compiler specified for language %%" &
2423 ", ignoring all its sources",
2426 if Lang_Index = Project.Languages then
2427 Project.Languages := Lang_Index.Next;
2429 Prev_Index.Next := Lang_Index.Next;
2432 elsif Lang_Index.Name = Name_Ada then
2433 Prev_Index := Lang_Index;
2435 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2436 -- Body_Suffix need to be specified.
2438 if Lang_Index.Config.Naming_Data.Dot_Replacement = No_File then
2442 "Dot_Replacement not specified for Ada",
2446 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File then
2450 "Spec_Suffix not specified for Ada",
2454 if Lang_Index.Config.Naming_Data.Body_Suffix = No_File then
2458 "Body_Suffix not specified for Ada",
2463 Prev_Index := Lang_Index;
2465 -- For file based languages, either Spec_Suffix or Body_Suffix
2466 -- need to be specified.
2468 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File and then
2469 Lang_Index.Config.Naming_Data.Body_Suffix = No_File
2471 Error_Msg_Name_1 := Lang_Index.Display_Name;
2475 "no suffixes specified for %%",
2480 Lang_Index := Lang_Index.Next;
2482 end Check_Configuration;
2484 -------------------------------
2485 -- Check_If_Externally_Built --
2486 -------------------------------
2488 procedure Check_If_Externally_Built
2489 (Project : Project_Id;
2490 In_Tree : Project_Tree_Ref)
2492 Externally_Built : constant Variable_Value :=
2494 (Name_Externally_Built,
2495 Project.Decl.Attributes, In_Tree);
2498 if not Externally_Built.Default then
2499 Get_Name_String (Externally_Built.Value);
2500 To_Lower (Name_Buffer (1 .. Name_Len));
2502 if Name_Buffer (1 .. Name_Len) = "true" then
2503 Project.Externally_Built := True;
2505 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2506 Error_Msg (Project, In_Tree,
2507 "Externally_Built may only be true or false",
2508 Externally_Built.Location);
2512 -- A virtual project extending an externally built project is itself
2513 -- externally built.
2515 if Project.Virtual and then Project.Extends /= No_Project then
2516 Project.Externally_Built := Project.Extends.Externally_Built;
2519 if Current_Verbosity = High then
2520 Write_Str ("Project is ");
2522 if not Project.Externally_Built then
2526 Write_Line ("externally built.");
2528 end Check_If_Externally_Built;
2530 ----------------------
2531 -- Check_Interfaces --
2532 ----------------------
2534 procedure Check_Interfaces
2535 (Project : Project_Id;
2536 In_Tree : Project_Tree_Ref)
2538 Interfaces : constant Prj.Variable_Value :=
2540 (Snames.Name_Interfaces,
2541 Project.Decl.Attributes,
2544 List : String_List_Id;
2545 Element : String_Element;
2546 Name : File_Name_Type;
2547 Iter : Source_Iterator;
2549 Project_2 : Project_Id;
2553 if not Interfaces.Default then
2555 -- Set In_Interfaces to False for all sources. It will be set to True
2556 -- later for the sources in the Interfaces list.
2558 Project_2 := Project;
2559 while Project_2 /= No_Project loop
2560 Iter := For_Each_Source (In_Tree, Project_2);
2563 Source := Prj.Element (Iter);
2564 exit when Source = No_Source;
2565 Source.In_Interfaces := False;
2569 Project_2 := Project_2.Extends;
2572 List := Interfaces.Values;
2573 while List /= Nil_String loop
2574 Element := In_Tree.String_Elements.Table (List);
2575 Name := Canonical_Case_File_Name (Element.Value);
2577 Project_2 := Project;
2579 while Project_2 /= No_Project loop
2580 Iter := For_Each_Source (In_Tree, Project_2);
2583 Source := Prj.Element (Iter);
2584 exit when Source = No_Source;
2586 if Source.File = Name then
2587 if not Source.Locally_Removed then
2588 Source.In_Interfaces := True;
2589 Source.Declared_In_Interfaces := True;
2591 Other := Other_Part (Source);
2593 if Other /= No_Source then
2594 Other.In_Interfaces := True;
2595 Other.Declared_In_Interfaces := True;
2598 if Current_Verbosity = High then
2599 Write_Str (" interface: ");
2600 Write_Line (Get_Name_String (Source.Path.Name));
2610 Project_2 := Project_2.Extends;
2613 if Source = No_Source then
2614 Error_Msg_File_1 := File_Name_Type (Element.Value);
2615 Error_Msg_Name_1 := Project.Name;
2620 "{ cannot be an interface of project %% "
2621 & "as it is not one of its sources",
2625 List := Element.Next;
2628 Project.Interfaces_Defined := True;
2630 elsif Project.Extends /= No_Project then
2631 Project.Interfaces_Defined := Project.Extends.Interfaces_Defined;
2633 if Project.Interfaces_Defined then
2634 Iter := For_Each_Source (In_Tree, Project);
2636 Source := Prj.Element (Iter);
2637 exit when Source = No_Source;
2639 if not Source.Declared_In_Interfaces then
2640 Source.In_Interfaces := False;
2647 end Check_Interfaces;
2649 ------------------------------------
2650 -- Check_And_Normalize_Unit_Names --
2651 ------------------------------------
2653 procedure Check_And_Normalize_Unit_Names
2654 (Project : Project_Id;
2655 In_Tree : Project_Tree_Ref;
2656 List : Array_Element_Id;
2657 Debug_Name : String)
2659 Current : Array_Element_Id;
2660 Element : Array_Element;
2661 Unit_Name : Name_Id;
2664 if Current_Verbosity = High then
2665 Write_Line (" Checking unit names in " & Debug_Name);
2669 while Current /= No_Array_Element loop
2670 Element := In_Tree.Array_Elements.Table (Current);
2671 Element.Value.Value :=
2672 Name_Id (Canonical_Case_File_Name (Element.Value.Value));
2674 -- Check that it contains a valid unit name
2676 Get_Name_String (Element.Index);
2677 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2679 if Unit_Name = No_Name then
2680 Err_Vars.Error_Msg_Name_1 := Element.Index;
2683 "%% is not a valid unit name.",
2684 Element.Value.Location);
2687 if Current_Verbosity = High then
2688 Write_Str (" for unit: ");
2689 Write_Line (Get_Name_String (Unit_Name));
2692 Element.Index := Unit_Name;
2693 In_Tree.Array_Elements.Table (Current) := Element;
2696 Current := Element.Next;
2698 end Check_And_Normalize_Unit_Names;
2700 --------------------------
2701 -- Check_Naming_Schemes --
2702 --------------------------
2704 procedure Check_Naming_Schemes
2705 (Project : Project_Id;
2706 In_Tree : Project_Tree_Ref;
2707 Is_Config_File : Boolean;
2708 Bodies : out Array_Element_Id;
2709 Specs : out Array_Element_Id)
2711 Naming_Id : constant Package_Id :=
2712 Util.Value_Of (Name_Naming, Project.Decl.Packages, In_Tree);
2713 Naming : Package_Element;
2715 procedure Check_Naming_Ada_Only;
2716 -- Does Check_Naming_Schemes processing in Ada_Only mode.
2717 -- If there is a package Naming, puts in Data.Naming the contents of
2720 procedure Check_Naming_Multi_Lang;
2721 -- Does Check_Naming_Schemes processing for Multi_Language mode
2723 procedure Check_Common
2724 (Dot_Replacement : in out File_Name_Type;
2725 Casing : in out Casing_Type;
2726 Casing_Defined : out Boolean;
2727 Separate_Suffix : in out File_Name_Type;
2728 Sep_Suffix_Loc : out Source_Ptr);
2729 -- Check attributes common to Ada_Only and Multi_Lang modes
2731 procedure Process_Exceptions_File_Based
2732 (Lang_Id : Language_Ptr;
2733 Kind : Source_Kind);
2734 procedure Process_Exceptions_Unit_Based
2735 (Lang_Id : Language_Ptr;
2736 Kind : Source_Kind);
2737 -- In Multi_Lang mode, process the naming exceptions for the two types
2738 -- of languages we can have.
2744 procedure Check_Common
2745 (Dot_Replacement : in out File_Name_Type;
2746 Casing : in out Casing_Type;
2747 Casing_Defined : out Boolean;
2748 Separate_Suffix : in out File_Name_Type;
2749 Sep_Suffix_Loc : out Source_Ptr)
2751 Dot_Repl : constant Variable_Value :=
2753 (Name_Dot_Replacement,
2754 Naming.Decl.Attributes,
2756 Casing_String : constant Variable_Value :=
2759 Naming.Decl.Attributes,
2761 Sep_Suffix : constant Variable_Value :=
2763 (Name_Separate_Suffix,
2764 Naming.Decl.Attributes,
2766 Dot_Repl_Loc : Source_Ptr;
2769 Sep_Suffix_Loc := No_Location;
2771 if not Dot_Repl.Default then
2773 (Dot_Repl.Kind = Single, "Dot_Replacement is not a string");
2775 if Length_Of_Name (Dot_Repl.Value) = 0 then
2778 "Dot_Replacement cannot be empty",
2782 Dot_Replacement := Canonical_Case_File_Name (Dot_Repl.Value);
2783 Dot_Repl_Loc := Dot_Repl.Location;
2786 Repl : constant String := Get_Name_String (Dot_Replacement);
2789 -- Dot_Replacement cannot
2791 -- - start or end with an alphanumeric
2792 -- - be a single '_'
2793 -- - start with an '_' followed by an alphanumeric
2794 -- - contain a '.' except if it is "."
2797 or else Is_Alphanumeric (Repl (Repl'First))
2798 or else Is_Alphanumeric (Repl (Repl'Last))
2799 or else (Repl (Repl'First) = '_'
2803 Is_Alphanumeric (Repl (Repl'First + 1))))
2804 or else (Repl'Length > 1
2806 Index (Source => Repl, Pattern => ".") /= 0)
2811 """ is illegal for Dot_Replacement.",
2817 if Dot_Replacement /= No_File then
2819 ("Dot_Replacement", Get_Name_String (Dot_Replacement));
2822 Casing_Defined := False;
2824 if not Casing_String.Default then
2826 (Casing_String.Kind = Single, "Casing is not a string");
2829 Casing_Image : constant String :=
2830 Get_Name_String (Casing_String.Value);
2832 if Casing_Image'Length = 0 then
2835 "Casing cannot be an empty string",
2836 Casing_String.Location);
2839 Casing := Value (Casing_Image);
2840 Casing_Defined := True;
2843 when Constraint_Error =>
2844 Name_Len := Casing_Image'Length;
2845 Name_Buffer (1 .. Name_Len) := Casing_Image;
2846 Err_Vars.Error_Msg_Name_1 := Name_Find;
2849 "%% is not a correct Casing",
2850 Casing_String.Location);
2854 Write_Attr ("Casing", Image (Casing));
2856 if not Sep_Suffix.Default then
2857 if Length_Of_Name (Sep_Suffix.Value) = 0 then
2860 "Separate_Suffix cannot be empty",
2861 Sep_Suffix.Location);
2864 Separate_Suffix := Canonical_Case_File_Name (Sep_Suffix.Value);
2865 Sep_Suffix_Loc := Sep_Suffix.Location;
2867 if Is_Illegal_Suffix (Separate_Suffix, Dot_Replacement) then
2868 Err_Vars.Error_Msg_File_1 := Separate_Suffix;
2871 "{ is illegal for Separate_Suffix",
2872 Sep_Suffix.Location);
2877 if Separate_Suffix /= No_File then
2879 ("Separate_Suffix", Get_Name_String (Separate_Suffix));
2883 -----------------------------------
2884 -- Process_Exceptions_File_Based --
2885 -----------------------------------
2887 procedure Process_Exceptions_File_Based
2888 (Lang_Id : Language_Ptr;
2891 Lang : constant Name_Id := Lang_Id.Name;
2892 Exceptions : Array_Element_Id;
2893 Exception_List : Variable_Value;
2894 Element_Id : String_List_Id;
2895 Element : String_Element;
2896 File_Name : File_Name_Type;
2898 Iter : Source_Iterator;
2905 (Name_Implementation_Exceptions,
2906 In_Arrays => Naming.Decl.Arrays,
2907 In_Tree => In_Tree);
2912 (Name_Specification_Exceptions,
2913 In_Arrays => Naming.Decl.Arrays,
2914 In_Tree => In_Tree);
2917 Exception_List := Value_Of
2919 In_Array => Exceptions,
2920 In_Tree => In_Tree);
2922 if Exception_List /= Nil_Variable_Value then
2923 Element_Id := Exception_List.Values;
2924 while Element_Id /= Nil_String loop
2925 Element := In_Tree.String_Elements.Table (Element_Id);
2926 File_Name := Canonical_Case_File_Name (Element.Value);
2928 Iter := For_Each_Source (In_Tree, Project);
2930 Source := Prj.Element (Iter);
2931 exit when Source = No_Source or else Source.File = File_Name;
2935 if Source = No_Source then
2942 File_Name => File_Name,
2943 Display_File => File_Name_Type (Element.Value),
2944 Naming_Exception => True);
2947 -- Check if the file name is already recorded for another
2948 -- language or another kind.
2950 if Source.Language /= Lang_Id then
2954 "the same file cannot be a source of two languages",
2957 elsif Source.Kind /= Kind then
2961 "the same file cannot be a source and a template",
2965 -- If the file is already recorded for the same
2966 -- language and the same kind, it means that the file
2967 -- name appears several times in the *_Exceptions
2968 -- attribute; so there is nothing to do.
2971 Element_Id := Element.Next;
2974 end Process_Exceptions_File_Based;
2976 -----------------------------------
2977 -- Process_Exceptions_Unit_Based --
2978 -----------------------------------
2980 procedure Process_Exceptions_Unit_Based
2981 (Lang_Id : Language_Ptr;
2984 Lang : constant Name_Id := Lang_Id.Name;
2985 Exceptions : Array_Element_Id;
2986 Element : Array_Element;
2989 File_Name : File_Name_Type;
2991 Source_To_Replace : Source_Id := No_Source;
2992 Other_Project : Project_Id;
2993 Iter : Source_Iterator;
2998 Exceptions := Value_Of
3000 In_Arrays => Naming.Decl.Arrays,
3001 In_Tree => In_Tree);
3003 if Exceptions = No_Array_Element then
3006 (Name_Implementation,
3007 In_Arrays => Naming.Decl.Arrays,
3008 In_Tree => In_Tree);
3015 In_Arrays => Naming.Decl.Arrays,
3016 In_Tree => In_Tree);
3018 if Exceptions = No_Array_Element then
3019 Exceptions := Value_Of
3021 In_Arrays => Naming.Decl.Arrays,
3022 In_Tree => In_Tree);
3026 while Exceptions /= No_Array_Element loop
3027 Element := In_Tree.Array_Elements.Table (Exceptions);
3028 File_Name := Canonical_Case_File_Name (Element.Value.Value);
3030 Get_Name_String (Element.Index);
3031 To_Lower (Name_Buffer (1 .. Name_Len));
3033 Index := Element.Value.Index;
3035 -- For Ada, check if it is a valid unit name
3037 if Lang = Name_Ada then
3038 Get_Name_String (Element.Index);
3039 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
3041 if Unit = No_Name then
3042 Err_Vars.Error_Msg_Name_1 := Element.Index;
3045 "%% is not a valid unit name.",
3046 Element.Value.Location);
3050 if Unit /= No_Name then
3052 -- Check if the source already exists
3053 -- ??? In Ada_Only mode (Record_Unit), we use a htable for
3056 Source_To_Replace := No_Source;
3057 Iter := For_Each_Source (In_Tree);
3060 Source := Prj.Element (Iter);
3061 exit when Source = No_Source
3062 or else (Source.Unit /= null
3063 and then Source.Unit.Name = Unit
3064 and then Source.Index = Index);
3068 if Source /= No_Source then
3069 if Source.Kind /= Kind then
3072 Source := Prj.Element (Iter);
3074 exit when Source = No_Source
3075 or else (Source.Unit /= null
3076 and then Source.Unit.Name = Unit
3077 and then Source.Index = Index);
3081 if Source /= No_Source then
3082 Other_Project := Source.Project;
3084 if Is_Extending (Project, Other_Project) then
3085 Source_To_Replace := Source;
3086 Source := No_Source;
3089 Error_Msg_Name_1 := Unit;
3090 Error_Msg_Name_2 := Other_Project.Name;
3094 "%% is already a source of project %%",
3095 Element.Value.Location);
3100 if Source = No_Source then
3107 File_Name => File_Name,
3108 Display_File => File_Name_Type (Element.Value.Value),
3111 Naming_Exception => True,
3112 Source_To_Replace => Source_To_Replace);
3116 Exceptions := Element.Next;
3118 end Process_Exceptions_Unit_Based;
3120 ---------------------------
3121 -- Check_Naming_Ada_Only --
3122 ---------------------------
3124 procedure Check_Naming_Ada_Only is
3125 Casing_Defined : Boolean;
3126 Spec_Suffix : File_Name_Type;
3127 Body_Suffix : File_Name_Type;
3128 Sep_Suffix_Loc : Source_Ptr;
3130 Ada_Spec_Suffix : constant Variable_Value :=
3134 In_Array => Project.Naming.Spec_Suffix,
3135 In_Tree => In_Tree);
3137 Ada_Body_Suffix : constant Variable_Value :=
3141 In_Array => Project.Naming.Body_Suffix,
3142 In_Tree => In_Tree);
3145 -- The default value of separate suffix should be the same as the
3146 -- body suffix, so we need to compute that first.
3148 if Ada_Body_Suffix.Kind = Single
3149 and then Length_Of_Name (Ada_Body_Suffix.Value) /= 0
3151 Body_Suffix := Canonical_Case_File_Name (Ada_Body_Suffix.Value);
3152 Project.Naming.Separate_Suffix := Body_Suffix;
3153 Set_Body_Suffix (In_Tree, "ada", Project.Naming, Body_Suffix);
3156 Body_Suffix := Default_Ada_Body_Suffix;
3157 Project.Naming.Separate_Suffix := Body_Suffix;
3158 Set_Body_Suffix (In_Tree, "ada", Project.Naming, Body_Suffix);
3161 Write_Attr ("Body_Suffix", Get_Name_String (Body_Suffix));
3163 -- We'll need the dot replacement below, so compute it now
3166 (Dot_Replacement => Project.Naming.Dot_Replacement,
3167 Casing => Project.Naming.Casing,
3168 Casing_Defined => Casing_Defined,
3169 Separate_Suffix => Project.Naming.Separate_Suffix,
3170 Sep_Suffix_Loc => Sep_Suffix_Loc);
3172 Bodies := Util.Value_Of (Name_Body, Naming.Decl.Arrays, In_Tree);
3174 if Bodies /= No_Array_Element then
3175 Check_And_Normalize_Unit_Names
3176 (Project, In_Tree, Bodies, "Naming.Bodies");
3179 Specs := Util.Value_Of (Name_Spec, Naming.Decl.Arrays, In_Tree);
3181 if Specs /= No_Array_Element then
3182 Check_And_Normalize_Unit_Names
3183 (Project, In_Tree, Specs, "Naming.Specs");
3186 -- Check Spec_Suffix
3188 if Ada_Spec_Suffix.Kind = Single
3189 and then Length_Of_Name (Ada_Spec_Suffix.Value) /= 0
3191 Spec_Suffix := Canonical_Case_File_Name (Ada_Spec_Suffix.Value);
3192 Set_Spec_Suffix (In_Tree, "ada", Project.Naming, Spec_Suffix);
3194 if Is_Illegal_Suffix
3195 (Spec_Suffix, Project.Naming.Dot_Replacement)
3197 Err_Vars.Error_Msg_File_1 := Spec_Suffix;
3200 "{ is illegal for Spec_Suffix",
3201 Ada_Spec_Suffix.Location);
3205 Spec_Suffix := Default_Ada_Spec_Suffix;
3206 Set_Spec_Suffix (In_Tree, "ada", Project.Naming, Spec_Suffix);
3209 Write_Attr ("Spec_Suffix", Get_Name_String (Spec_Suffix));
3211 -- Check Body_Suffix
3213 if Is_Illegal_Suffix
3214 (Body_Suffix, Project.Naming.Dot_Replacement)
3216 Err_Vars.Error_Msg_File_1 := Body_Suffix;
3219 "{ is illegal for Body_Suffix",
3220 Ada_Body_Suffix.Location);
3223 -- Spec_Suffix cannot be equal to Body_Suffix or Separate_Suffix,
3224 -- since that would cause a clear ambiguity. Note that we do allow a
3225 -- Spec_Suffix to have the same termination as one of these, which
3226 -- causes a potential ambiguity, but we resolve that my matching the
3227 -- longest possible suffix.
3229 if Spec_Suffix = Body_Suffix then
3233 Get_Name_String (Body_Suffix) &
3234 """) cannot be the same as Spec_Suffix.",
3235 Ada_Body_Suffix.Location);
3238 if Body_Suffix /= Project.Naming.Separate_Suffix
3239 and then Spec_Suffix = Project.Naming.Separate_Suffix
3243 "Separate_Suffix (""" &
3244 Get_Name_String (Project.Naming.Separate_Suffix) &
3245 """) cannot be the same as Spec_Suffix.",
3248 end Check_Naming_Ada_Only;
3250 -----------------------------
3251 -- Check_Naming_Multi_Lang --
3252 -----------------------------
3254 procedure Check_Naming_Multi_Lang is
3255 Dot_Replacement : File_Name_Type := No_File;
3256 Separate_Suffix : File_Name_Type := No_File;
3257 Casing : Casing_Type := All_Lower_Case;
3258 Casing_Defined : Boolean;
3259 Lang_Id : Language_Ptr;
3260 Sep_Suffix_Loc : Source_Ptr;
3261 Suffix : Variable_Value;
3266 (Dot_Replacement => Dot_Replacement,
3268 Casing_Defined => Casing_Defined,
3269 Separate_Suffix => Separate_Suffix,
3270 Sep_Suffix_Loc => Sep_Suffix_Loc);
3272 -- For all unit based languages, if any, set the specified
3273 -- value of Dot_Replacement, Casing and/or Separate_Suffix. Do not
3274 -- systematically overwrite, since the defaults come from the
3275 -- configuration file
3277 if Dot_Replacement /= No_File
3278 or else Casing_Defined
3279 or else Separate_Suffix /= No_File
3281 Lang_Id := Project.Languages;
3282 while Lang_Id /= No_Language_Index loop
3283 if Lang_Id.Config.Kind = Unit_Based then
3284 if Dot_Replacement /= No_File then
3285 Lang_Id.Config.Naming_Data.Dot_Replacement :=
3289 if Casing_Defined then
3290 Lang_Id.Config.Naming_Data.Casing := Casing;
3293 if Separate_Suffix /= No_File then
3294 Lang_Id.Config.Naming_Data.Separate_Suffix :=
3299 Lang_Id := Lang_Id.Next;
3303 -- Next, get the spec and body suffixes
3305 Lang_Id := Project.Languages;
3306 while Lang_Id /= No_Language_Index loop
3307 Lang := Lang_Id.Name;
3313 Attribute_Or_Array_Name => Name_Spec_Suffix,
3314 In_Package => Naming_Id,
3315 In_Tree => In_Tree);
3317 if Suffix = Nil_Variable_Value then
3320 Attribute_Or_Array_Name => Name_Spec_Suffix,
3321 In_Package => Naming_Id,
3322 In_Tree => In_Tree);
3325 if Suffix /= Nil_Variable_Value then
3326 Lang_Id.Config.Naming_Data.Spec_Suffix :=
3327 File_Name_Type (Suffix.Value);
3334 Attribute_Or_Array_Name => Name_Body_Suffix,
3335 In_Package => Naming_Id,
3336 In_Tree => In_Tree);
3338 if Suffix = Nil_Variable_Value then
3341 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3342 In_Package => Naming_Id,
3343 In_Tree => In_Tree);
3346 if Suffix /= Nil_Variable_Value then
3347 Lang_Id.Config.Naming_Data.Body_Suffix :=
3348 File_Name_Type (Suffix.Value);
3351 -- ??? As opposed to what is done in Check_Naming_Ada_Only,
3352 -- we do not check whether spec_suffix=body_suffix, which
3353 -- should be illegal. Best would be to share this code into
3354 -- Check_Common, but we access the attributes from the project
3355 -- files slightly differently apparently.
3357 Lang_Id := Lang_Id.Next;
3360 -- Get the naming exceptions for all languages
3362 for Kind in Spec .. Impl loop
3363 Lang_Id := Project.Languages;
3364 while Lang_Id /= No_Language_Index loop
3365 case Lang_Id.Config.Kind is
3367 Process_Exceptions_File_Based (Lang_Id, Kind);
3370 Process_Exceptions_Unit_Based (Lang_Id, Kind);
3373 Lang_Id := Lang_Id.Next;
3376 end Check_Naming_Multi_Lang;
3378 -- Start of processing for Check_Naming_Schemes
3381 Specs := No_Array_Element;
3382 Bodies := No_Array_Element;
3384 -- No Naming package or parsing a configuration file? nothing to do
3386 if Naming_Id /= No_Package and not Is_Config_File then
3387 Naming := In_Tree.Packages.Table (Naming_Id);
3389 if Current_Verbosity = High then
3390 Write_Line ("Checking package Naming.");
3395 Check_Naming_Ada_Only;
3396 when Multi_Language =>
3397 Check_Naming_Multi_Lang;
3400 end Check_Naming_Schemes;
3402 ------------------------------
3403 -- Check_Library_Attributes --
3404 ------------------------------
3406 procedure Check_Library_Attributes
3407 (Project : Project_Id;
3408 In_Tree : Project_Tree_Ref)
3410 Attributes : constant Prj.Variable_Id := Project.Decl.Attributes;
3412 Lib_Dir : constant Prj.Variable_Value :=
3414 (Snames.Name_Library_Dir, Attributes, In_Tree);
3416 Lib_Name : constant Prj.Variable_Value :=
3418 (Snames.Name_Library_Name, Attributes, In_Tree);
3420 Lib_Version : constant Prj.Variable_Value :=
3422 (Snames.Name_Library_Version, Attributes, In_Tree);
3424 Lib_ALI_Dir : constant Prj.Variable_Value :=
3426 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3428 Lib_GCC : constant Prj.Variable_Value :=
3430 (Snames.Name_Library_GCC, Attributes, In_Tree);
3432 The_Lib_Kind : constant Prj.Variable_Value :=
3434 (Snames.Name_Library_Kind, Attributes, In_Tree);
3436 Imported_Project_List : Project_List;
3438 Continuation : String_Access := No_Continuation_String'Access;
3440 Support_For_Libraries : Library_Support;
3442 Library_Directory_Present : Boolean;
3444 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3445 -- Check if an imported or extended project if also a library project
3451 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3453 Iter : Source_Iterator;
3456 if Proj /= No_Project then
3457 if not Proj.Library then
3459 -- The only not library projects that are OK are those that
3460 -- have no sources. However, header files from non-Ada
3461 -- languages are OK, as there is nothing to compile.
3463 Iter := For_Each_Source (In_Tree, Proj);
3465 Src_Id := Prj.Element (Iter);
3466 exit when Src_Id = No_Source
3467 or else Src_Id.Language.Config.Kind /= File_Based
3468 or else Src_Id.Kind /= Spec;
3472 if Src_Id /= No_Source then
3473 Error_Msg_Name_1 := Project.Name;
3474 Error_Msg_Name_2 := Proj.Name;
3477 if Project.Library_Kind /= Static then
3481 "shared library project %% cannot extend " &
3482 "project %% that is not a library project",
3484 Continuation := Continuation_String'Access;
3487 elsif (not Unchecked_Shared_Lib_Imports)
3488 and then Project.Library_Kind /= Static
3493 "shared library project %% cannot import project %% " &
3494 "that is not a shared library project",
3496 Continuation := Continuation_String'Access;
3500 elsif Project.Library_Kind /= Static and then
3501 Proj.Library_Kind = Static
3503 Error_Msg_Name_1 := Project.Name;
3504 Error_Msg_Name_2 := Proj.Name;
3510 "shared library project %% cannot extend static " &
3511 "library project %%",
3513 Continuation := Continuation_String'Access;
3515 elsif not Unchecked_Shared_Lib_Imports then
3519 "shared library project %% cannot import static " &
3520 "library project %%",
3522 Continuation := Continuation_String'Access;
3529 Dir_Exists : Boolean;
3531 -- Start of processing for Check_Library_Attributes
3534 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3536 -- Special case of extending project
3538 if Project.Extends /= No_Project then
3540 -- If the project extended is a library project, we inherit the
3541 -- library name, if it is not redefined; we check that the library
3542 -- directory is specified.
3544 if Project.Extends.Library then
3545 if Project.Qualifier = Standard then
3548 "a standard project cannot extend a library project",
3552 if Lib_Name.Default then
3553 Project.Library_Name := Project.Extends.Library_Name;
3556 if Lib_Dir.Default then
3557 if not Project.Virtual then
3560 "a project extending a library project must " &
3561 "specify an attribute Library_Dir",
3565 -- For a virtual project extending a library project,
3566 -- inherit library directory.
3568 Project.Library_Dir := Project.Extends.Library_Dir;
3569 Library_Directory_Present := True;
3576 pragma Assert (Lib_Name.Kind = Single);
3578 if Lib_Name.Value = Empty_String then
3579 if Current_Verbosity = High
3580 and then Project.Library_Name = No_Name
3582 Write_Line ("No library name");
3586 -- There is no restriction on the syntax of library names
3588 Project.Library_Name := Lib_Name.Value;
3591 if Project.Library_Name /= No_Name then
3592 if Current_Verbosity = High then
3594 ("Library name", Get_Name_String (Project.Library_Name));
3597 pragma Assert (Lib_Dir.Kind = Single);
3599 if not Library_Directory_Present then
3600 if Current_Verbosity = High then
3601 Write_Line ("No library directory");
3605 -- Find path name (unless inherited), check that it is a directory
3607 if Project.Library_Dir = No_Path_Information then
3611 File_Name_Type (Lib_Dir.Value),
3612 Path => Project.Library_Dir,
3613 Dir_Exists => Dir_Exists,
3614 Create => "library",
3615 Must_Exist => False,
3616 Location => Lib_Dir.Location,
3617 Externally_Built => Project.Externally_Built);
3623 (Project.Library_Dir.Display_Name));
3626 if not Dir_Exists then
3627 -- Get the absolute name of the library directory that
3628 -- does not exist, to report an error.
3630 Err_Vars.Error_Msg_File_1 :=
3631 File_Name_Type (Project.Library_Dir.Display_Name);
3634 "library directory { does not exist",
3637 -- The library directory cannot be the same as the Object
3640 elsif Project.Library_Dir.Name = Project.Object_Directory.Name then
3643 "library directory cannot be the same " &
3644 "as object directory",
3646 Project.Library_Dir := No_Path_Information;
3650 OK : Boolean := True;
3651 Dirs_Id : String_List_Id;
3652 Dir_Elem : String_Element;
3656 -- The library directory cannot be the same as a source
3657 -- directory of the current project.
3659 Dirs_Id := Project.Source_Dirs;
3660 while Dirs_Id /= Nil_String loop
3661 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3662 Dirs_Id := Dir_Elem.Next;
3664 if Project.Library_Dir.Name =
3665 Path_Name_Type (Dir_Elem.Value)
3667 Err_Vars.Error_Msg_File_1 :=
3668 File_Name_Type (Dir_Elem.Value);
3671 "library directory cannot be the same " &
3672 "as source directory {",
3681 -- The library directory cannot be the same as a source
3682 -- directory of another project either.
3684 Pid := In_Tree.Projects;
3686 exit Project_Loop when Pid = null;
3688 if Pid.Project /= Project then
3689 Dirs_Id := Pid.Project.Source_Dirs;
3691 Dir_Loop : while Dirs_Id /= Nil_String loop
3693 In_Tree.String_Elements.Table (Dirs_Id);
3694 Dirs_Id := Dir_Elem.Next;
3696 if Project.Library_Dir.Name =
3697 Path_Name_Type (Dir_Elem.Value)
3699 Err_Vars.Error_Msg_File_1 :=
3700 File_Name_Type (Dir_Elem.Value);
3701 Err_Vars.Error_Msg_Name_1 := Pid.Project.Name;
3705 "library directory cannot be the same " &
3706 "as source directory { of project %%",
3715 end loop Project_Loop;
3719 Project.Library_Dir := No_Path_Information;
3721 elsif Current_Verbosity = High then
3723 -- Display the Library directory in high verbosity
3726 ("Library directory",
3727 Get_Name_String (Project.Library_Dir.Display_Name));
3736 Project.Library_Dir /= No_Path_Information
3737 and then Project.Library_Name /= No_Name;
3739 if Project.Extends = No_Project then
3740 case Project.Qualifier is
3742 if Project.Library then
3745 "a standard project cannot be a library project",
3750 if not Project.Library then
3751 if Project.Library_Dir = No_Path_Information then
3754 "\attribute Library_Dir not declared",
3758 if Project.Library_Name = No_Name then
3761 "\attribute Library_Name not declared",
3772 if Project.Library then
3773 if Get_Mode = Multi_Language then
3774 Support_For_Libraries := Project.Config.Lib_Support;
3777 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3780 if Support_For_Libraries = Prj.None then
3783 "?libraries are not supported on this platform",
3785 Project.Library := False;
3788 if Lib_ALI_Dir.Value = Empty_String then
3789 if Current_Verbosity = High then
3790 Write_Line ("No library ALI directory specified");
3793 Project.Library_ALI_Dir := Project.Library_Dir;
3796 -- Find path name, check that it is a directory
3801 File_Name_Type (Lib_ALI_Dir.Value),
3802 Path => Project.Library_ALI_Dir,
3803 Create => "library ALI",
3804 Dir_Exists => Dir_Exists,
3805 Must_Exist => False,
3806 Location => Lib_ALI_Dir.Location,
3807 Externally_Built => Project.Externally_Built);
3809 if not Dir_Exists then
3810 -- Get the absolute name of the library ALI directory that
3811 -- does not exist, to report an error.
3813 Err_Vars.Error_Msg_File_1 :=
3814 File_Name_Type (Project.Library_ALI_Dir.Display_Name);
3817 "library 'A'L'I directory { does not exist",
3818 Lib_ALI_Dir.Location);
3821 if Project.Library_ALI_Dir /= Project.Library_Dir then
3823 -- The library ALI directory cannot be the same as the
3824 -- Object directory.
3826 if Project.Library_ALI_Dir = Project.Object_Directory then
3829 "library 'A'L'I directory cannot be the same " &
3830 "as object directory",
3831 Lib_ALI_Dir.Location);
3832 Project.Library_ALI_Dir := No_Path_Information;
3836 OK : Boolean := True;
3837 Dirs_Id : String_List_Id;
3838 Dir_Elem : String_Element;
3842 -- The library ALI directory cannot be the same as
3843 -- a source directory of the current project.
3845 Dirs_Id := Project.Source_Dirs;
3846 while Dirs_Id /= Nil_String loop
3847 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3848 Dirs_Id := Dir_Elem.Next;
3850 if Project.Library_ALI_Dir.Name =
3851 Path_Name_Type (Dir_Elem.Value)
3853 Err_Vars.Error_Msg_File_1 :=
3854 File_Name_Type (Dir_Elem.Value);
3857 "library 'A'L'I directory cannot be " &
3858 "the same as source directory {",
3859 Lib_ALI_Dir.Location);
3867 -- The library ALI directory cannot be the same as
3868 -- a source directory of another project either.
3870 Pid := In_Tree.Projects;
3871 ALI_Project_Loop : loop
3872 exit ALI_Project_Loop when Pid = null;
3874 if Pid.Project /= Project then
3875 Dirs_Id := Pid.Project.Source_Dirs;
3878 while Dirs_Id /= Nil_String loop
3880 In_Tree.String_Elements.Table (Dirs_Id);
3881 Dirs_Id := Dir_Elem.Next;
3883 if Project.Library_ALI_Dir.Name =
3884 Path_Name_Type (Dir_Elem.Value)
3886 Err_Vars.Error_Msg_File_1 :=
3887 File_Name_Type (Dir_Elem.Value);
3888 Err_Vars.Error_Msg_Name_1 :=
3893 "library 'A'L'I directory cannot " &
3894 "be the same as source directory " &
3896 Lib_ALI_Dir.Location);
3898 exit ALI_Project_Loop;
3900 end loop ALI_Dir_Loop;
3903 end loop ALI_Project_Loop;
3907 Project.Library_ALI_Dir := No_Path_Information;
3909 elsif Current_Verbosity = High then
3911 -- Display the Library ALI directory in high
3917 (Project.Library_ALI_Dir.Display_Name));
3924 pragma Assert (Lib_Version.Kind = Single);
3926 if Lib_Version.Value = Empty_String then
3927 if Current_Verbosity = High then
3928 Write_Line ("No library version specified");
3932 Project.Lib_Internal_Name := Lib_Version.Value;
3935 pragma Assert (The_Lib_Kind.Kind = Single);
3937 if The_Lib_Kind.Value = Empty_String then
3938 if Current_Verbosity = High then
3939 Write_Line ("No library kind specified");
3943 Get_Name_String (The_Lib_Kind.Value);
3946 Kind_Name : constant String :=
3947 To_Lower (Name_Buffer (1 .. Name_Len));
3949 OK : Boolean := True;
3952 if Kind_Name = "static" then
3953 Project.Library_Kind := Static;
3955 elsif Kind_Name = "dynamic" then
3956 Project.Library_Kind := Dynamic;
3958 elsif Kind_Name = "relocatable" then
3959 Project.Library_Kind := Relocatable;
3964 "illegal value for Library_Kind",
3965 The_Lib_Kind.Location);
3969 if Current_Verbosity = High and then OK then
3970 Write_Attr ("Library kind", Kind_Name);
3973 if Project.Library_Kind /= Static then
3974 if Support_For_Libraries = Prj.Static_Only then
3977 "only static libraries are supported " &
3979 The_Lib_Kind.Location);
3980 Project.Library := False;
3983 -- Check if (obsolescent) attribute Library_GCC or
3984 -- Linker'Driver is declared.
3986 if Lib_GCC.Value /= Empty_String then
3990 "?Library_'G'C'C is an obsolescent attribute, " &
3991 "use Linker''Driver instead",
3993 Project.Config.Shared_Lib_Driver :=
3994 File_Name_Type (Lib_GCC.Value);
3998 Linker : constant Package_Id :=
4001 Project.Decl.Packages,
4003 Driver : constant Variable_Value :=
4006 Attribute_Or_Array_Name =>
4008 In_Package => Linker,
4013 if Driver /= Nil_Variable_Value
4014 and then Driver.Value /= Empty_String
4016 Project.Config.Shared_Lib_Driver :=
4017 File_Name_Type (Driver.Value);
4026 if Project.Library then
4027 if Current_Verbosity = High then
4028 Write_Line ("This is a library project file");
4031 if Get_Mode = Multi_Language then
4032 Check_Library (Project.Extends, Extends => True);
4034 Imported_Project_List := Project.Imported_Projects;
4035 while Imported_Project_List /= null loop
4037 (Imported_Project_List.Project,
4039 Imported_Project_List := Imported_Project_List.Next;
4047 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4048 -- Warn if they are declared, as it is a common error to think that
4049 -- library are "linked" with Linker switches.
4051 if Project.Library then
4053 Linker_Package_Id : constant Package_Id :=
4056 Project.Decl.Packages, In_Tree);
4057 Linker_Package : Package_Element;
4058 Switches : Array_Element_Id := No_Array_Element;
4061 if Linker_Package_Id /= No_Package then
4062 Linker_Package := In_Tree.Packages.Table (Linker_Package_Id);
4066 (Name => Name_Switches,
4067 In_Arrays => Linker_Package.Decl.Arrays,
4068 In_Tree => In_Tree);
4070 if Switches = No_Array_Element then
4073 (Name => Name_Default_Switches,
4074 In_Arrays => Linker_Package.Decl.Arrays,
4075 In_Tree => In_Tree);
4078 if Switches /= No_Array_Element then
4081 "?Linker switches not taken into account in library " &
4089 if Project.Extends /= No_Project then
4090 Project.Extends.Library := False;
4092 end Check_Library_Attributes;
4094 --------------------------
4095 -- Check_Package_Naming --
4096 --------------------------
4098 procedure Check_Package_Naming
4099 (Project : Project_Id;
4100 In_Tree : Project_Tree_Ref)
4102 Naming_Id : constant Package_Id :=
4103 Util.Value_Of (Name_Naming, Project.Decl.Packages, In_Tree);
4105 Naming : Package_Element;
4108 -- If there is a package Naming, we will put in Data.Naming
4109 -- what is in this package Naming.
4111 if Naming_Id /= No_Package then
4112 Naming := In_Tree.Packages.Table (Naming_Id);
4114 if Current_Verbosity = High then
4115 Write_Line ("Checking ""Naming"".");
4118 -- Check Spec_Suffix
4121 Spec_Suffixs : Array_Element_Id :=
4127 Suffix : Array_Element_Id;
4128 Element : Array_Element;
4129 Suffix2 : Array_Element_Id;
4132 -- If some suffixes have been specified, we make sure that
4133 -- for each language for which a default suffix has been
4134 -- specified, there is a suffix specified, either the one
4135 -- in the project file or if there were none, the default.
4137 if Spec_Suffixs /= No_Array_Element then
4138 Suffix := Project.Naming.Spec_Suffix;
4140 while Suffix /= No_Array_Element loop
4142 In_Tree.Array_Elements.Table (Suffix);
4143 Suffix2 := Spec_Suffixs;
4145 while Suffix2 /= No_Array_Element loop
4146 exit when In_Tree.Array_Elements.Table
4147 (Suffix2).Index = Element.Index;
4148 Suffix2 := In_Tree.Array_Elements.Table
4152 -- There is a registered default suffix, but no
4153 -- suffix specified in the project file.
4154 -- Add the default to the array.
4156 if Suffix2 = No_Array_Element then
4157 Array_Element_Table.Increment_Last
4158 (In_Tree.Array_Elements);
4159 In_Tree.Array_Elements.Table
4160 (Array_Element_Table.Last
4161 (In_Tree.Array_Elements)) :=
4162 (Index => Element.Index,
4163 Src_Index => Element.Src_Index,
4164 Index_Case_Sensitive => False,
4165 Value => Element.Value,
4166 Next => Spec_Suffixs);
4167 Spec_Suffixs := Array_Element_Table.Last
4168 (In_Tree.Array_Elements);
4171 Suffix := Element.Next;
4174 -- Put the resulting array as the Spec suffixes
4176 Project.Naming.Spec_Suffix := Spec_Suffixs;
4180 -- Check Body_Suffix
4183 Impl_Suffixs : Array_Element_Id :=
4189 Suffix : Array_Element_Id;
4190 Element : Array_Element;
4191 Suffix2 : Array_Element_Id;
4194 -- If some suffixes have been specified, we make sure that
4195 -- for each language for which a default suffix has been
4196 -- specified, there is a suffix specified, either the one
4197 -- in the project file or if there were none, the default.
4199 if Impl_Suffixs /= No_Array_Element then
4200 Suffix := Project.Naming.Body_Suffix;
4201 while Suffix /= No_Array_Element loop
4203 In_Tree.Array_Elements.Table (Suffix);
4205 Suffix2 := Impl_Suffixs;
4206 while Suffix2 /= No_Array_Element loop
4207 exit when In_Tree.Array_Elements.Table
4208 (Suffix2).Index = Element.Index;
4209 Suffix2 := In_Tree.Array_Elements.Table
4213 -- There is a registered default suffix, but no suffix was
4214 -- specified in the project file. Add default to the array.
4216 if Suffix2 = No_Array_Element then
4217 Array_Element_Table.Increment_Last
4218 (In_Tree.Array_Elements);
4219 In_Tree.Array_Elements.Table
4220 (Array_Element_Table.Last
4221 (In_Tree.Array_Elements)) :=
4222 (Index => Element.Index,
4223 Src_Index => Element.Src_Index,
4224 Index_Case_Sensitive => False,
4225 Value => Element.Value,
4226 Next => Impl_Suffixs);
4227 Impl_Suffixs := Array_Element_Table.Last
4228 (In_Tree.Array_Elements);
4231 Suffix := Element.Next;
4234 -- Put the resulting array as the implementation suffixes
4236 Project.Naming.Body_Suffix := Impl_Suffixs;
4240 end Check_Package_Naming;
4242 ---------------------------------
4243 -- Check_Programming_Languages --
4244 ---------------------------------
4246 procedure Check_Programming_Languages
4247 (In_Tree : Project_Tree_Ref;
4248 Project : Project_Id)
4250 Languages : Variable_Value := Nil_Variable_Value;
4251 Def_Lang : Variable_Value := Nil_Variable_Value;
4252 Def_Lang_Id : Name_Id;
4255 Project.Languages := No_Language_Index;
4257 Prj.Util.Value_Of (Name_Languages, Project.Decl.Attributes, In_Tree);
4260 (Name_Default_Language, Project.Decl.Attributes, In_Tree);
4262 -- Shouldn't these be set to False by default, and only set to True when
4263 -- we actually find some source file???
4265 if Project.Source_Dirs /= Nil_String then
4267 -- Check if languages are specified in this project
4269 if Languages.Default then
4271 -- In Ada_Only mode, the default language is Ada
4273 if Get_Mode = Ada_Only then
4274 Def_Lang_Id := Name_Ada;
4277 -- Fail if there is no default language defined
4279 if Def_Lang.Default then
4280 if not Default_Language_Is_Ada then
4284 "no languages defined for this project",
4286 Def_Lang_Id := No_Name;
4288 Def_Lang_Id := Name_Ada;
4292 Get_Name_String (Def_Lang.Value);
4293 To_Lower (Name_Buffer (1 .. Name_Len));
4294 Def_Lang_Id := Name_Find;
4298 if Def_Lang_Id /= No_Name then
4299 Project.Languages := new Language_Data'(No_Language_Data);
4300 Project.Languages.Name := Def_Lang_Id;
4301 Get_Name_String (Def_Lang_Id);
4302 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4303 Project.Languages.Display_Name := Name_Find;
4305 if Def_Lang_Id = Name_Ada then
4306 Project.Languages.Config.Kind := Unit_Based;
4307 Project.Languages.Config.Dependency_Kind := ALI_File;
4309 Project.Languages.Config.Kind := File_Based;
4315 Current : String_List_Id := Languages.Values;
4316 Element : String_Element;
4317 Lang_Name : Name_Id;
4318 Index : Language_Ptr;
4319 NL_Id : Language_Ptr;
4322 -- If there are no languages declared, there are no sources
4324 if Current = Nil_String then
4325 Project.Source_Dirs := Nil_String;
4327 if Project.Qualifier = Standard then
4331 "a standard project must have at least one language",
4332 Languages.Location);
4336 -- Look through all the languages specified in attribute
4339 while Current /= Nil_String loop
4340 Element := In_Tree.String_Elements.Table (Current);
4341 Get_Name_String (Element.Value);
4342 To_Lower (Name_Buffer (1 .. Name_Len));
4343 Lang_Name := Name_Find;
4345 -- If the language was not already specified (duplicates
4346 -- are simply ignored).
4348 NL_Id := Project.Languages;
4349 while NL_Id /= No_Language_Index loop
4350 exit when Lang_Name = NL_Id.Name;
4351 NL_Id := NL_Id.Next;
4354 if NL_Id = No_Language_Index then
4355 Index := new Language_Data'(No_Language_Data);
4356 Index.Name := Lang_Name;
4357 Index.Display_Name := Element.Value;
4358 Index.Next := Project.Languages;
4360 if Lang_Name = Name_Ada then
4361 Index.Config.Kind := Unit_Based;
4362 Index.Config.Dependency_Kind := ALI_File;
4365 Index.Config.Kind := File_Based;
4366 Index.Config.Dependency_Kind := None;
4369 Project.Languages := Index;
4372 Current := Element.Next;
4378 end Check_Programming_Languages;
4384 function Check_Project
4386 Root_Project : Project_Id;
4387 Extending : Boolean) return Boolean
4391 if P = Root_Project then
4394 elsif Extending then
4395 Prj := Root_Project;
4396 while Prj.Extends /= No_Project loop
4397 if P = Prj.Extends then
4408 -------------------------------
4409 -- Check_Stand_Alone_Library --
4410 -------------------------------
4412 procedure Check_Stand_Alone_Library
4413 (Project : Project_Id;
4414 In_Tree : Project_Tree_Ref;
4415 Current_Dir : String;
4416 Extending : Boolean)
4418 Lib_Interfaces : constant Prj.Variable_Value :=
4420 (Snames.Name_Library_Interface,
4421 Project.Decl.Attributes,
4424 Lib_Auto_Init : constant Prj.Variable_Value :=
4426 (Snames.Name_Library_Auto_Init,
4427 Project.Decl.Attributes,
4430 Lib_Src_Dir : constant Prj.Variable_Value :=
4432 (Snames.Name_Library_Src_Dir,
4433 Project.Decl.Attributes,
4436 Lib_Symbol_File : constant Prj.Variable_Value :=
4438 (Snames.Name_Library_Symbol_File,
4439 Project.Decl.Attributes,
4442 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4444 (Snames.Name_Library_Symbol_Policy,
4445 Project.Decl.Attributes,
4448 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4450 (Snames.Name_Library_Reference_Symbol_File,
4451 Project.Decl.Attributes,
4454 Auto_Init_Supported : Boolean;
4455 OK : Boolean := True;
4457 Next_Proj : Project_Id;
4458 Iter : Source_Iterator;
4461 if Get_Mode = Multi_Language then
4462 Auto_Init_Supported := Project.Config.Auto_Init_Supported;
4464 Auto_Init_Supported :=
4465 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4468 pragma Assert (Lib_Interfaces.Kind = List);
4470 -- It is a stand-alone library project file if attribute
4471 -- Library_Interface is defined.
4473 if not Lib_Interfaces.Default then
4474 SAL_Library : declare
4475 Interfaces : String_List_Id := Lib_Interfaces.Values;
4476 Interface_ALIs : String_List_Id := Nil_String;
4480 procedure Add_ALI_For (Source : File_Name_Type);
4481 -- Add an ALI file name to the list of Interface ALIs
4487 procedure Add_ALI_For (Source : File_Name_Type) is
4489 Get_Name_String (Source);
4492 ALI : constant String :=
4493 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4494 ALI_Name_Id : Name_Id;
4497 Name_Len := ALI'Length;
4498 Name_Buffer (1 .. Name_Len) := ALI;
4499 ALI_Name_Id := Name_Find;
4501 String_Element_Table.Increment_Last
4502 (In_Tree.String_Elements);
4503 In_Tree.String_Elements.Table
4504 (String_Element_Table.Last
4505 (In_Tree.String_Elements)) :=
4506 (Value => ALI_Name_Id,
4508 Display_Value => ALI_Name_Id,
4510 In_Tree.String_Elements.Table
4511 (Interfaces).Location,
4513 Next => Interface_ALIs);
4514 Interface_ALIs := String_Element_Table.Last
4515 (In_Tree.String_Elements);
4519 -- Start of processing for SAL_Library
4522 Project.Standalone_Library := True;
4524 -- Library_Interface cannot be an empty list
4526 if Interfaces = Nil_String then
4529 "Library_Interface cannot be an empty list",
4530 Lib_Interfaces.Location);
4533 -- Process each unit name specified in the attribute
4534 -- Library_Interface.
4536 while Interfaces /= Nil_String loop
4538 (In_Tree.String_Elements.Table (Interfaces).Value);
4539 To_Lower (Name_Buffer (1 .. Name_Len));
4541 if Name_Len = 0 then
4544 "an interface cannot be an empty string",
4545 In_Tree.String_Elements.Table (Interfaces).Location);
4549 Error_Msg_Name_1 := Unit;
4551 if Get_Mode = Ada_Only then
4552 UData := Units_Htable.Get (In_Tree.Units_HT, Unit);
4554 if UData = No_Unit_Index then
4558 In_Tree.String_Elements.Table
4559 (Interfaces).Location);
4562 -- Check that the unit is part of the project
4564 if UData.File_Names (Impl) /= null
4565 and then not UData.File_Names (Impl).Locally_Removed
4568 (UData.File_Names (Impl).Project,
4571 -- There is a body for this unit. If there is
4572 -- no spec, we need to check that it is not a
4575 if UData.File_Names (Spec) = null then
4577 Src_Ind : Source_File_Index;
4581 Sinput.P.Load_Project_File
4582 (Get_Name_String (UData.File_Names
4585 if Sinput.P.Source_File_Is_Subunit
4590 "%% is a subunit; " &
4591 "it cannot be an interface",
4593 String_Elements.Table
4594 (Interfaces).Location);
4599 -- The unit is not a subunit, so we add the
4600 -- ALI file for its body to the Interface ALIs.
4603 (UData.File_Names (Impl).File);
4608 "%% is not an unit of this project",
4609 In_Tree.String_Elements.Table
4610 (Interfaces).Location);
4613 elsif UData.File_Names (Spec) /= null
4614 and then not UData.File_Names (Spec).Locally_Removed
4615 and then Check_Project
4616 (UData.File_Names (Spec).Project,
4620 -- The unit is part of the project, it has a spec,
4621 -- but no body. We add the ALI for its spec to the
4625 (UData.File_Names (Spec).File);
4630 "%% is not an unit of this project",
4631 In_Tree.String_Elements.Table
4632 (Interfaces).Location);
4637 -- Multi_Language mode
4639 Next_Proj := Project.Extends;
4640 Iter := For_Each_Source (In_Tree, Project);
4642 while Prj.Element (Iter) /= No_Source
4644 (Prj.Element (Iter).Unit = null
4645 or else Prj.Element (Iter).Unit.Name /= Unit)
4650 Source := Prj.Element (Iter);
4651 exit when Source /= No_Source
4652 or else Next_Proj = No_Project;
4654 Iter := For_Each_Source (In_Tree, Next_Proj);
4655 Next_Proj := Next_Proj.Extends;
4658 if Source /= No_Source then
4659 if Source.Kind = Sep then
4660 Source := No_Source;
4661 elsif Source.Kind = Spec
4662 and then Other_Part (Source) /= No_Source
4664 Source := Other_Part (Source);
4668 if Source /= No_Source then
4669 if Source.Project /= Project
4670 and then not Is_Extending (Project, Source.Project)
4672 Source := No_Source;
4676 if Source = No_Source then
4679 "%% is not an unit of this project",
4680 In_Tree.String_Elements.Table
4681 (Interfaces).Location);
4684 if Source.Kind = Spec
4685 and then Other_Part (Source) /= No_Source
4687 Source := Other_Part (Source);
4690 String_Element_Table.Increment_Last
4691 (In_Tree.String_Elements);
4693 In_Tree.String_Elements.Table
4694 (String_Element_Table.Last
4695 (In_Tree.String_Elements)) :=
4696 (Value => Name_Id (Source.Dep_Name),
4698 Display_Value => Name_Id (Source.Dep_Name),
4700 In_Tree.String_Elements.Table
4701 (Interfaces).Location,
4703 Next => Interface_ALIs);
4706 String_Element_Table.Last (In_Tree.String_Elements);
4714 In_Tree.String_Elements.Table (Interfaces).Next;
4717 -- Put the list of Interface ALIs in the project data
4719 Project.Lib_Interface_ALIs := Interface_ALIs;
4721 -- Check value of attribute Library_Auto_Init and set
4722 -- Lib_Auto_Init accordingly.
4724 if Lib_Auto_Init.Default then
4726 -- If no attribute Library_Auto_Init is declared, then set auto
4727 -- init only if it is supported.
4729 Project.Lib_Auto_Init := Auto_Init_Supported;
4732 Get_Name_String (Lib_Auto_Init.Value);
4733 To_Lower (Name_Buffer (1 .. Name_Len));
4735 if Name_Buffer (1 .. Name_Len) = "false" then
4736 Project.Lib_Auto_Init := False;
4738 elsif Name_Buffer (1 .. Name_Len) = "true" then
4739 if Auto_Init_Supported then
4740 Project.Lib_Auto_Init := True;
4743 -- Library_Auto_Init cannot be "true" if auto init is not
4748 "library auto init not supported " &
4750 Lib_Auto_Init.Location);
4756 "invalid value for attribute Library_Auto_Init",
4757 Lib_Auto_Init.Location);
4762 -- If attribute Library_Src_Dir is defined and not the empty string,
4763 -- check if the directory exist and is not the object directory or
4764 -- one of the source directories. This is the directory where copies
4765 -- of the interface sources will be copied. Note that this directory
4766 -- may be the library directory.
4768 if Lib_Src_Dir.Value /= Empty_String then
4770 Dir_Id : constant File_Name_Type :=
4771 File_Name_Type (Lib_Src_Dir.Value);
4772 Dir_Exists : Boolean;
4779 Path => Project.Library_Src_Dir,
4780 Dir_Exists => Dir_Exists,
4781 Must_Exist => False,
4782 Create => "library source copy",
4783 Location => Lib_Src_Dir.Location,
4784 Externally_Built => Project.Externally_Built);
4786 -- If directory does not exist, report an error
4788 if not Dir_Exists then
4789 -- Get the absolute name of the library directory that does
4790 -- not exist, to report an error.
4792 Err_Vars.Error_Msg_File_1 :=
4793 File_Name_Type (Project.Library_Src_Dir.Display_Name);
4796 "Directory { does not exist",
4797 Lib_Src_Dir.Location);
4799 -- Report error if it is the same as the object directory
4801 elsif Project.Library_Src_Dir = Project.Object_Directory then
4804 "directory to copy interfaces cannot be " &
4805 "the object directory",
4806 Lib_Src_Dir.Location);
4807 Project.Library_Src_Dir := No_Path_Information;
4811 Src_Dirs : String_List_Id;
4812 Src_Dir : String_Element;
4816 -- Interface copy directory cannot be one of the source
4817 -- directory of the current project.
4819 Src_Dirs := Project.Source_Dirs;
4820 while Src_Dirs /= Nil_String loop
4821 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
4823 -- Report error if it is one of the source directories
4825 if Project.Library_Src_Dir.Name =
4826 Path_Name_Type (Src_Dir.Value)
4830 "directory to copy interfaces cannot " &
4831 "be one of the source directories",
4832 Lib_Src_Dir.Location);
4833 Project.Library_Src_Dir := No_Path_Information;
4837 Src_Dirs := Src_Dir.Next;
4840 if Project.Library_Src_Dir /= No_Path_Information then
4842 -- It cannot be a source directory of any other
4845 Pid := In_Tree.Projects;
4847 exit Project_Loop when Pid = null;
4849 Src_Dirs := Pid.Project.Source_Dirs;
4850 Dir_Loop : while Src_Dirs /= Nil_String loop
4852 In_Tree.String_Elements.Table (Src_Dirs);
4854 -- Report error if it is one of the source
4857 if Project.Library_Src_Dir.Name =
4858 Path_Name_Type (Src_Dir.Value)
4861 File_Name_Type (Src_Dir.Value);
4862 Error_Msg_Name_1 := Pid.Project.Name;
4865 "directory to copy interfaces cannot " &
4866 "be the same as source directory { of " &
4868 Lib_Src_Dir.Location);
4869 Project.Library_Src_Dir :=
4870 No_Path_Information;
4874 Src_Dirs := Src_Dir.Next;
4878 end loop Project_Loop;
4882 -- In high verbosity, if there is a valid Library_Src_Dir,
4883 -- display its path name.
4885 if Project.Library_Src_Dir /= No_Path_Information
4886 and then Current_Verbosity = High
4889 ("Directory to copy interfaces",
4890 Get_Name_String (Project.Library_Src_Dir.Name));
4896 -- Check the symbol related attributes
4898 -- First, the symbol policy
4900 if not Lib_Symbol_Policy.Default then
4902 Value : constant String :=
4904 (Get_Name_String (Lib_Symbol_Policy.Value));
4907 -- Symbol policy must hove one of a limited number of values
4909 if Value = "autonomous" or else Value = "default" then
4910 Project.Symbol_Data.Symbol_Policy := Autonomous;
4912 elsif Value = "compliant" then
4913 Project.Symbol_Data.Symbol_Policy := Compliant;
4915 elsif Value = "controlled" then
4916 Project.Symbol_Data.Symbol_Policy := Controlled;
4918 elsif Value = "restricted" then
4919 Project.Symbol_Data.Symbol_Policy := Restricted;
4921 elsif Value = "direct" then
4922 Project.Symbol_Data.Symbol_Policy := Direct;
4927 "illegal value for Library_Symbol_Policy",
4928 Lib_Symbol_Policy.Location);
4933 -- If attribute Library_Symbol_File is not specified, symbol policy
4934 -- cannot be Restricted.
4936 if Lib_Symbol_File.Default then
4937 if Project.Symbol_Data.Symbol_Policy = Restricted then
4940 "Library_Symbol_File needs to be defined when " &
4941 "symbol policy is Restricted",
4942 Lib_Symbol_Policy.Location);
4946 -- Library_Symbol_File is defined
4948 Project.Symbol_Data.Symbol_File :=
4949 Path_Name_Type (Lib_Symbol_File.Value);
4951 Get_Name_String (Lib_Symbol_File.Value);
4953 if Name_Len = 0 then
4956 "symbol file name cannot be an empty string",
4957 Lib_Symbol_File.Location);
4960 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
4963 for J in 1 .. Name_Len loop
4964 if Name_Buffer (J) = '/'
4965 or else Name_Buffer (J) = Directory_Separator
4974 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
4977 "symbol file name { is illegal. " &
4978 "Name cannot include directory info.",
4979 Lib_Symbol_File.Location);
4984 -- If attribute Library_Reference_Symbol_File is not defined,
4985 -- symbol policy cannot be Compliant or Controlled.
4987 if Lib_Ref_Symbol_File.Default then
4988 if Project.Symbol_Data.Symbol_Policy = Compliant
4989 or else Project.Symbol_Data.Symbol_Policy = Controlled
4993 "a reference symbol file needs to be defined",
4994 Lib_Symbol_Policy.Location);
4998 -- Library_Reference_Symbol_File is defined, check file exists
5000 Project.Symbol_Data.Reference :=
5001 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5003 Get_Name_String (Lib_Ref_Symbol_File.Value);
5005 if Name_Len = 0 then
5008 "reference symbol file name cannot be an empty string",
5009 Lib_Symbol_File.Location);
5012 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5014 Add_Str_To_Name_Buffer
5015 (Get_Name_String (Project.Directory.Name));
5016 Add_Char_To_Name_Buffer (Directory_Separator);
5017 Add_Str_To_Name_Buffer
5018 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5019 Project.Symbol_Data.Reference := Name_Find;
5022 if not Is_Regular_File
5023 (Get_Name_String (Project.Symbol_Data.Reference))
5026 File_Name_Type (Lib_Ref_Symbol_File.Value);
5028 -- For controlled and direct symbol policies, it is an error
5029 -- if the reference symbol file does not exist. For other
5030 -- symbol policies, this is just a warning
5033 Project.Symbol_Data.Symbol_Policy /= Controlled
5034 and then Project.Symbol_Data.Symbol_Policy /= Direct;
5038 "<library reference symbol file { does not exist",
5039 Lib_Ref_Symbol_File.Location);
5041 -- In addition in the non-controlled case, if symbol policy
5042 -- is Compliant, it is changed to Autonomous, because there
5043 -- is no reference to check against, and we don't want to
5044 -- fail in this case.
5046 if Project.Symbol_Data.Symbol_Policy /= Controlled then
5047 if Project.Symbol_Data.Symbol_Policy = Compliant then
5048 Project.Symbol_Data.Symbol_Policy := Autonomous;
5053 -- If both the reference symbol file and the symbol file are
5054 -- defined, then check that they are not the same file.
5056 if Project.Symbol_Data.Symbol_File /= No_Path then
5057 Get_Name_String (Project.Symbol_Data.Symbol_File);
5059 if Name_Len > 0 then
5061 Symb_Path : constant String :=
5064 (Project.Object_Directory.Name) &
5065 Directory_Separator &
5066 Name_Buffer (1 .. Name_Len),
5067 Directory => Current_Dir,
5069 Opt.Follow_Links_For_Files);
5070 Ref_Path : constant String :=
5073 (Project.Symbol_Data.Reference),
5074 Directory => Current_Dir,
5076 Opt.Follow_Links_For_Files);
5078 if Symb_Path = Ref_Path then
5081 "library reference symbol file and library" &
5082 " symbol file cannot be the same file",
5083 Lib_Ref_Symbol_File.Location);
5091 end Check_Stand_Alone_Library;
5093 ----------------------------
5094 -- Compute_Directory_Last --
5095 ----------------------------
5097 function Compute_Directory_Last (Dir : String) return Natural is
5100 and then (Dir (Dir'Last - 1) = Directory_Separator
5101 or else Dir (Dir'Last - 1) = '/')
5103 return Dir'Last - 1;
5107 end Compute_Directory_Last;
5114 (Project : Project_Id;
5115 In_Tree : Project_Tree_Ref;
5117 Flag_Location : Source_Ptr)
5119 Real_Location : Source_Ptr := Flag_Location;
5120 Error_Buffer : String (1 .. 5_000);
5121 Error_Last : Natural := 0;
5122 Name_Number : Natural := 0;
5123 File_Number : Natural := 0;
5124 First : Positive := Msg'First;
5127 procedure Add (C : Character);
5128 -- Add a character to the buffer
5130 procedure Add (S : String);
5131 -- Add a string to the buffer
5134 -- Add a name to the buffer
5137 -- Add a file name to the buffer
5143 procedure Add (C : Character) is
5145 Error_Last := Error_Last + 1;
5146 Error_Buffer (Error_Last) := C;
5149 procedure Add (S : String) is
5151 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5152 Error_Last := Error_Last + S'Length;
5159 procedure Add_File is
5160 File : File_Name_Type;
5164 File_Number := File_Number + 1;
5168 File := Err_Vars.Error_Msg_File_1;
5170 File := Err_Vars.Error_Msg_File_2;
5172 File := Err_Vars.Error_Msg_File_3;
5177 Get_Name_String (File);
5178 Add (Name_Buffer (1 .. Name_Len));
5186 procedure Add_Name is
5191 Name_Number := Name_Number + 1;
5195 Name := Err_Vars.Error_Msg_Name_1;
5197 Name := Err_Vars.Error_Msg_Name_2;
5199 Name := Err_Vars.Error_Msg_Name_3;
5204 Get_Name_String (Name);
5205 Add (Name_Buffer (1 .. Name_Len));
5209 -- Start of processing for Error_Msg
5212 -- If location of error is unknown, use the location of the project
5214 if Real_Location = No_Location then
5215 Real_Location := Project.Location;
5218 if Error_Report = null then
5219 Prj.Err.Error_Msg (Msg, Real_Location);
5223 -- Ignore continuation character
5225 if Msg (First) = '\' then
5229 -- Warning character is always the first one in this package
5230 -- this is an undocumented kludge???
5232 if Msg (First) = '?' then
5236 elsif Msg (First) = '<' then
5239 if Err_Vars.Error_Msg_Warn then
5245 while Index <= Msg'Last loop
5246 if Msg (Index) = '{' then
5249 elsif Msg (Index) = '%' then
5250 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5262 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5265 --------------------------------
5266 -- Free_Ada_Naming_Exceptions --
5267 --------------------------------
5269 procedure Free_Ada_Naming_Exceptions is
5271 Ada_Naming_Exception_Table.Set_Last (0);
5272 Ada_Naming_Exceptions.Reset;
5273 Reverse_Ada_Naming_Exceptions.Reset;
5274 end Free_Ada_Naming_Exceptions;
5276 ---------------------
5277 -- Get_Directories --
5278 ---------------------
5280 procedure Get_Directories
5281 (Project : Project_Id;
5282 In_Tree : Project_Tree_Ref;
5283 Current_Dir : String)
5285 Object_Dir : constant Variable_Value :=
5287 (Name_Object_Dir, Project.Decl.Attributes, In_Tree);
5289 Exec_Dir : constant Variable_Value :=
5291 (Name_Exec_Dir, Project.Decl.Attributes, In_Tree);
5293 Source_Dirs : constant Variable_Value :=
5295 (Name_Source_Dirs, Project.Decl.Attributes, In_Tree);
5297 Excluded_Source_Dirs : constant Variable_Value :=
5299 (Name_Excluded_Source_Dirs,
5300 Project.Decl.Attributes,
5303 Source_Files : constant Variable_Value :=
5305 (Name_Source_Files, Project.Decl.Attributes, In_Tree);
5307 Last_Source_Dir : String_List_Id := Nil_String;
5309 Languages : constant Variable_Value :=
5311 (Name_Languages, Project.Decl.Attributes, In_Tree);
5313 procedure Find_Source_Dirs
5314 (From : File_Name_Type;
5315 Location : Source_Ptr;
5316 Removed : Boolean := False);
5317 -- Find one or several source directories, and add (or remove, if
5318 -- Removed is True) them to list of source directories of the project.
5320 ----------------------
5321 -- Find_Source_Dirs --
5322 ----------------------
5324 procedure Find_Source_Dirs
5325 (From : File_Name_Type;
5326 Location : Source_Ptr;
5327 Removed : Boolean := False)
5329 Directory : constant String := Get_Name_String (From);
5330 Element : String_Element;
5332 procedure Recursive_Find_Dirs (Path : Name_Id);
5333 -- Find all the subdirectories (recursively) of Path and add them
5334 -- to the list of source directories of the project.
5336 -------------------------
5337 -- Recursive_Find_Dirs --
5338 -------------------------
5340 procedure Recursive_Find_Dirs (Path : Name_Id) is
5342 Name : String (1 .. 250);
5344 List : String_List_Id;
5345 Prev : String_List_Id;
5346 Element : String_Element;
5347 Found : Boolean := False;
5349 Non_Canonical_Path : Name_Id := No_Name;
5350 Canonical_Path : Name_Id := No_Name;
5352 The_Path : constant String :=
5354 (Get_Name_String (Path),
5355 Directory => Current_Dir,
5356 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5357 Directory_Separator;
5359 The_Path_Last : constant Natural :=
5360 Compute_Directory_Last (The_Path);
5363 Name_Len := The_Path_Last - The_Path'First + 1;
5364 Name_Buffer (1 .. Name_Len) :=
5365 The_Path (The_Path'First .. The_Path_Last);
5366 Non_Canonical_Path := Name_Find;
5368 Name_Id (Canonical_Case_File_Name (Non_Canonical_Path));
5370 -- To avoid processing the same directory several times, check
5371 -- if the directory is already in Recursive_Dirs. If it is, then
5372 -- there is nothing to do, just return. If it is not, put it there
5373 -- and continue recursive processing.
5376 if Recursive_Dirs.Get (Canonical_Path) then
5379 Recursive_Dirs.Set (Canonical_Path, True);
5383 -- Check if directory is already in list
5385 List := Project.Source_Dirs;
5387 while List /= Nil_String loop
5388 Element := In_Tree.String_Elements.Table (List);
5390 if Element.Value /= No_Name then
5391 Found := Element.Value = Canonical_Path;
5396 List := Element.Next;
5399 -- If directory is not already in list, put it there
5401 if (not Removed) and (not Found) then
5402 if Current_Verbosity = High then
5404 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5407 String_Element_Table.Increment_Last
5408 (In_Tree.String_Elements);
5410 (Value => Canonical_Path,
5411 Display_Value => Non_Canonical_Path,
5412 Location => No_Location,
5417 -- Case of first source directory
5419 if Last_Source_Dir = Nil_String then
5420 Project.Source_Dirs := String_Element_Table.Last
5421 (In_Tree.String_Elements);
5423 -- Here we already have source directories
5426 -- Link the previous last to the new one
5428 In_Tree.String_Elements.Table
5429 (Last_Source_Dir).Next :=
5430 String_Element_Table.Last
5431 (In_Tree.String_Elements);
5434 -- And register this source directory as the new last
5436 Last_Source_Dir := String_Element_Table.Last
5437 (In_Tree.String_Elements);
5438 In_Tree.String_Elements.Table (Last_Source_Dir) :=
5441 elsif Removed and Found then
5442 if Prev = Nil_String then
5443 Project.Source_Dirs :=
5444 In_Tree.String_Elements.Table (List).Next;
5446 In_Tree.String_Elements.Table (Prev).Next :=
5447 In_Tree.String_Elements.Table (List).Next;
5451 -- Now look for subdirectories. We do that even when this
5452 -- directory is already in the list, because some of its
5453 -- subdirectories may not be in the list yet.
5455 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5458 Read (Dir, Name, Last);
5461 if Name (1 .. Last) /= "."
5462 and then Name (1 .. Last) /= ".."
5464 -- Avoid . and .. directories
5466 if Current_Verbosity = High then
5467 Write_Str (" Checking ");
5468 Write_Line (Name (1 .. Last));
5472 Path_Name : constant String :=
5474 (Name => Name (1 .. Last),
5476 The_Path (The_Path'First .. The_Path_Last),
5477 Resolve_Links => Opt.Follow_Links_For_Dirs,
5478 Case_Sensitive => True);
5481 if Is_Directory (Path_Name) then
5482 -- We have found a new subdirectory, call self
5484 Name_Len := Path_Name'Length;
5485 Name_Buffer (1 .. Name_Len) := Path_Name;
5486 Recursive_Find_Dirs (Name_Find);
5495 when Directory_Error =>
5497 end Recursive_Find_Dirs;
5499 -- Start of processing for Find_Source_Dirs
5502 if Current_Verbosity = High and then not Removed then
5503 Write_Str ("Find_Source_Dirs (""");
5504 Write_Str (Directory);
5508 -- First, check if we are looking for a directory tree, indicated
5509 -- by "/**" at the end.
5511 if Directory'Length >= 3
5512 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5513 and then (Directory (Directory'Last - 2) = '/'
5515 Directory (Directory'Last - 2) = Directory_Separator)
5518 Project.Known_Order_Of_Source_Dirs := False;
5521 Name_Len := Directory'Length - 3;
5523 if Name_Len = 0 then
5525 -- Case of "/**": all directories in file system
5528 Name_Buffer (1) := Directory (Directory'First);
5531 Name_Buffer (1 .. Name_Len) :=
5532 Directory (Directory'First .. Directory'Last - 3);
5535 if Current_Verbosity = High then
5536 Write_Str ("Looking for all subdirectories of """);
5537 Write_Str (Name_Buffer (1 .. Name_Len));
5542 Base_Dir : constant File_Name_Type := Name_Find;
5543 Root_Dir : constant String :=
5545 (Name => Get_Name_String (Base_Dir),
5548 (Project.Directory.Display_Name),
5549 Resolve_Links => False,
5550 Case_Sensitive => True);
5553 if Root_Dir'Length = 0 then
5554 Err_Vars.Error_Msg_File_1 := Base_Dir;
5556 if Location = No_Location then
5559 "{ is not a valid directory.",
5564 "{ is not a valid directory.",
5569 -- We have an existing directory, we register it and all of
5570 -- its subdirectories.
5572 if Current_Verbosity = High then
5573 Write_Line ("Looking for source directories:");
5576 Name_Len := Root_Dir'Length;
5577 Name_Buffer (1 .. Name_Len) := Root_Dir;
5578 Recursive_Find_Dirs (Name_Find);
5580 if Current_Verbosity = High then
5581 Write_Line ("End of looking for source directories.");
5586 -- We have a single directory
5590 Path_Name : Path_Information;
5591 List : String_List_Id;
5592 Prev : String_List_Id;
5593 Dir_Exists : Boolean;
5597 (Project => Project,
5601 Dir_Exists => Dir_Exists,
5602 Must_Exist => False);
5604 if not Dir_Exists then
5605 Err_Vars.Error_Msg_File_1 := From;
5607 if Location = No_Location then
5610 "{ is not a valid directory",
5615 "{ is not a valid directory",
5621 Path : constant String :=
5622 Get_Name_String (Path_Name.Name) &
5623 Directory_Separator;
5624 Last_Path : constant Natural :=
5625 Compute_Directory_Last (Path);
5627 Display_Path : constant String :=
5629 (Path_Name.Display_Name) &
5630 Directory_Separator;
5631 Last_Display_Path : constant Natural :=
5632 Compute_Directory_Last
5634 Display_Path_Id : Name_Id;
5638 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
5639 Path_Id := Name_Find;
5641 Add_Str_To_Name_Buffer
5643 (Display_Path'First .. Last_Display_Path));
5644 Display_Path_Id := Name_Find;
5648 -- As it is an existing directory, we add it to the
5649 -- list of directories.
5651 String_Element_Table.Increment_Last
5652 (In_Tree.String_Elements);
5656 Display_Value => Display_Path_Id,
5657 Location => No_Location,
5659 Next => Nil_String);
5661 if Last_Source_Dir = Nil_String then
5663 -- This is the first source directory
5665 Project.Source_Dirs := String_Element_Table.Last
5666 (In_Tree.String_Elements);
5669 -- We already have source directories, link the
5670 -- previous last to the new one.
5672 In_Tree.String_Elements.Table
5673 (Last_Source_Dir).Next :=
5674 String_Element_Table.Last
5675 (In_Tree.String_Elements);
5678 -- And register this source directory as the new last
5680 Last_Source_Dir := String_Element_Table.Last
5681 (In_Tree.String_Elements);
5682 In_Tree.String_Elements.Table
5683 (Last_Source_Dir) := Element;
5686 -- Remove source dir, if present
5690 -- Look for source dir in current list
5692 List := Project.Source_Dirs;
5693 while List /= Nil_String loop
5694 Element := In_Tree.String_Elements.Table (List);
5695 exit when Element.Value = Path_Id;
5697 List := Element.Next;
5700 if List /= Nil_String then
5701 -- Source dir was found, remove it from the list
5703 if Prev = Nil_String then
5704 Project.Source_Dirs :=
5705 In_Tree.String_Elements.Table (List).Next;
5708 In_Tree.String_Elements.Table (Prev).Next :=
5709 In_Tree.String_Elements.Table (List).Next;
5717 end Find_Source_Dirs;
5719 -- Start of processing for Get_Directories
5721 Dir_Exists : Boolean;
5724 if Current_Verbosity = High then
5725 Write_Line ("Starting to look for directories");
5728 -- Set the object directory to its default which may be nil, if there
5729 -- is no sources in the project.
5731 if (((not Source_Files.Default)
5732 and then Source_Files.Values = Nil_String)
5734 ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
5736 ((not Languages.Default) and then Languages.Values = Nil_String))
5737 and then Project.Extends = No_Project
5739 Project.Object_Directory := No_Path_Information;
5741 Project.Object_Directory := Project.Directory;
5744 -- Check the object directory
5746 if Object_Dir.Value /= Empty_String then
5747 Get_Name_String (Object_Dir.Value);
5749 if Name_Len = 0 then
5752 "Object_Dir cannot be empty",
5753 Object_Dir.Location);
5756 -- We check that the specified object directory does exist.
5757 -- However, even when it doesn't exist, we set it to a default
5758 -- value. This is for the benefit of tools that recover from
5759 -- errors; for example, these tools could create the non existent
5761 -- We always return an absolute directory name though
5766 File_Name_Type (Object_Dir.Value),
5767 Path => Project.Object_Directory,
5769 Dir_Exists => Dir_Exists,
5770 Location => Object_Dir.Location,
5771 Must_Exist => False,
5772 Externally_Built => Project.Externally_Built);
5775 and then not Project.Externally_Built
5777 -- The object directory does not exist, report an error if
5778 -- the project is not externally built.
5780 Err_Vars.Error_Msg_File_1 :=
5781 File_Name_Type (Object_Dir.Value);
5784 "object directory { not found",
5789 elsif Project.Object_Directory /= No_Path_Information
5790 and then Subdirs /= null
5793 Name_Buffer (1) := '.';
5798 Path => Project.Object_Directory,
5800 Dir_Exists => Dir_Exists,
5801 Location => Object_Dir.Location,
5802 Externally_Built => Project.Externally_Built);
5805 if Current_Verbosity = High then
5806 if Project.Object_Directory = No_Path_Information then
5807 Write_Line ("No object directory");
5810 ("Object directory",
5811 Get_Name_String (Project.Object_Directory.Display_Name));
5815 -- Check the exec directory
5817 -- We set the object directory to its default
5819 Project.Exec_Directory := Project.Object_Directory;
5821 if Exec_Dir.Value /= Empty_String then
5822 Get_Name_String (Exec_Dir.Value);
5824 if Name_Len = 0 then
5827 "Exec_Dir cannot be empty",
5831 -- We check that the specified exec directory does exist
5836 File_Name_Type (Exec_Dir.Value),
5837 Path => Project.Exec_Directory,
5838 Dir_Exists => Dir_Exists,
5840 Location => Exec_Dir.Location,
5841 Externally_Built => Project.Externally_Built);
5843 if not Dir_Exists then
5844 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
5847 "exec directory { not found",
5853 if Current_Verbosity = High then
5854 if Project.Exec_Directory = No_Path_Information then
5855 Write_Line ("No exec directory");
5857 Write_Str ("Exec directory: """);
5858 Write_Str (Get_Name_String (Project.Exec_Directory.Display_Name));
5863 -- Look for the source directories
5865 if Current_Verbosity = High then
5866 Write_Line ("Starting to look for source directories");
5869 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
5871 if (not Source_Files.Default) and then
5872 Source_Files.Values = Nil_String
5874 Project.Source_Dirs := Nil_String;
5876 if Project.Qualifier = Standard then
5880 "a standard project cannot have no sources",
5881 Source_Files.Location);
5884 elsif Source_Dirs.Default then
5886 -- No Source_Dirs specified: the single source directory is the one
5887 -- containing the project file
5889 String_Element_Table.Append (In_Tree.String_Elements,
5890 (Value => Name_Id (Project.Directory.Name),
5891 Display_Value => Name_Id (Project.Directory.Display_Name),
5892 Location => No_Location,
5896 Project.Source_Dirs := String_Element_Table.Last
5897 (In_Tree.String_Elements);
5899 if Current_Verbosity = High then
5901 ("Default source directory",
5902 Get_Name_String (Project.Directory.Display_Name));
5905 elsif Source_Dirs.Values = Nil_String then
5906 if Project.Qualifier = Standard then
5910 "a standard project cannot have no source directories",
5911 Source_Dirs.Location);
5914 Project.Source_Dirs := Nil_String;
5918 Source_Dir : String_List_Id;
5919 Element : String_Element;
5922 -- Process the source directories for each element of the list
5924 Source_Dir := Source_Dirs.Values;
5925 while Source_Dir /= Nil_String loop
5926 Element := In_Tree.String_Elements.Table (Source_Dir);
5928 (File_Name_Type (Element.Value), Element.Location);
5929 Source_Dir := Element.Next;
5934 if not Excluded_Source_Dirs.Default
5935 and then Excluded_Source_Dirs.Values /= Nil_String
5938 Source_Dir : String_List_Id;
5939 Element : String_Element;
5942 -- Process the source directories for each element of the list
5944 Source_Dir := Excluded_Source_Dirs.Values;
5945 while Source_Dir /= Nil_String loop
5946 Element := In_Tree.String_Elements.Table (Source_Dir);
5948 (File_Name_Type (Element.Value),
5951 Source_Dir := Element.Next;
5956 if Current_Verbosity = High then
5957 Write_Line ("Putting source directories in canonical cases");
5961 Current : String_List_Id := Project.Source_Dirs;
5962 Element : String_Element;
5965 while Current /= Nil_String loop
5966 Element := In_Tree.String_Elements.Table (Current);
5967 if Element.Value /= No_Name then
5969 Name_Id (Canonical_Case_File_Name (Name_Id (Element.Value)));
5970 In_Tree.String_Elements.Table (Current) := Element;
5973 Current := Element.Next;
5976 end Get_Directories;
5983 (Project : Project_Id;
5984 In_Tree : Project_Tree_Ref)
5986 Mains : constant Variable_Value :=
5987 Prj.Util.Value_Of (Name_Main, Project.Decl.Attributes, In_Tree);
5988 List : String_List_Id;
5989 Elem : String_Element;
5992 Project.Mains := Mains.Values;
5994 -- If no Mains were specified, and if we are an extending project,
5995 -- inherit the Mains from the project we are extending.
5997 if Mains.Default then
5998 if not Project.Library and then Project.Extends /= No_Project then
5999 Project.Mains := Project.Extends.Mains;
6002 -- In a library project file, Main cannot be specified
6004 elsif Project.Library then
6007 "a library project file cannot have Main specified",
6011 List := Mains.Values;
6012 while List /= Nil_String loop
6013 Elem := In_Tree.String_Elements.Table (List);
6015 if Length_Of_Name (Elem.Value) = 0 then
6018 "?a main cannot have an empty name",
6028 ---------------------------
6029 -- Get_Sources_From_File --
6030 ---------------------------
6032 procedure Get_Sources_From_File
6034 Location : Source_Ptr;
6035 Project : Project_Id;
6036 In_Tree : Project_Tree_Ref)
6038 File : Prj.Util.Text_File;
6039 Line : String (1 .. 250);
6041 Source_Name : File_Name_Type;
6042 Name_Loc : Name_Location;
6045 if Get_Mode = Ada_Only then
6049 if Current_Verbosity = High then
6050 Write_Str ("Opening """);
6057 Prj.Util.Open (File, Path);
6059 if not Prj.Util.Is_Valid (File) then
6060 Error_Msg (Project, In_Tree, "file does not exist", Location);
6063 -- Read the lines one by one
6065 while not Prj.Util.End_Of_File (File) loop
6066 Prj.Util.Get_Line (File, Line, Last);
6068 -- A non empty, non comment line should contain a file name
6071 and then (Last = 1 or else Line (1 .. 2) /= "--")
6074 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6075 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6076 Source_Name := Name_Find;
6078 -- Check that there is no directory information
6080 for J in 1 .. Last loop
6081 if Line (J) = '/' or else Line (J) = Directory_Separator then
6082 Error_Msg_File_1 := Source_Name;
6086 "file name cannot include directory information ({)",
6092 Name_Loc := Source_Names.Get (Source_Name);
6094 if Name_Loc = No_Name_Location then
6096 (Name => Source_Name,
6097 Location => Location,
6098 Source => No_Source,
6103 Source_Names.Set (Source_Name, Name_Loc);
6107 Prj.Util.Close (File);
6110 end Get_Sources_From_File;
6112 -----------------------
6113 -- Compute_Unit_Name --
6114 -----------------------
6116 procedure Compute_Unit_Name
6117 (File_Name : File_Name_Type;
6118 Dot_Replacement : File_Name_Type;
6119 Separate_Suffix : File_Name_Type;
6120 Body_Suffix : File_Name_Type;
6121 Spec_Suffix : File_Name_Type;
6122 Casing : Casing_Type;
6123 Kind : out Source_Kind;
6125 In_Tree : Project_Tree_Ref)
6127 Filename : constant String := Get_Name_String (File_Name);
6128 Last : Integer := Filename'Last;
6129 Sep_Len : constant Integer :=
6130 Integer (Length_Of_Name (Separate_Suffix));
6131 Body_Len : constant Integer :=
6132 Integer (Length_Of_Name (Body_Suffix));
6133 Spec_Len : constant Integer :=
6134 Integer (Length_Of_Name (Spec_Suffix));
6136 Standard_GNAT : constant Boolean :=
6137 Spec_Suffix = Default_Ada_Spec_Suffix
6139 Body_Suffix = Default_Ada_Body_Suffix;
6141 Unit_Except : Unit_Exception;
6142 Masked : Boolean := False;
6147 if Dot_Replacement = No_File then
6148 if Current_Verbosity = High then
6149 Write_Line (" No dot_replacement specified");
6154 -- Choose the longest suffix that matches. If there are several matches,
6155 -- give priority to specs, then bodies, then separates.
6157 if Separate_Suffix /= Body_Suffix
6158 and then Suffix_Matches (Filename, Separate_Suffix)
6160 Last := Filename'Last - Sep_Len;
6164 if Filename'Last - Body_Len <= Last
6165 and then Suffix_Matches (Filename, Body_Suffix)
6167 Last := Natural'Min (Last, Filename'Last - Body_Len);
6171 if Filename'Last - Spec_Len <= Last
6172 and then Suffix_Matches (Filename, Spec_Suffix)
6174 Last := Natural'Min (Last, Filename'Last - Spec_Len);
6178 if Last = Filename'Last then
6179 if Current_Verbosity = High then
6180 Write_Line (" No matching suffix");
6185 -- Check that the casing matches
6187 if File_Names_Case_Sensitive then
6189 when All_Lower_Case =>
6190 for J in Filename'First .. Last loop
6191 if Is_Letter (Filename (J))
6192 and then not Is_Lower (Filename (J))
6194 if Current_Verbosity = High then
6195 Write_Line (" Invalid casing");
6201 when All_Upper_Case =>
6202 for J in Filename'First .. Last loop
6203 if Is_Letter (Filename (J))
6204 and then not Is_Upper (Filename (J))
6206 if Current_Verbosity = High then
6207 Write_Line (" Invalid casing");
6213 when Mixed_Case | Unknown =>
6218 -- If Dot_Replacement is not a single dot, then there should not
6219 -- be any dot in the name.
6222 Dot_Repl : constant String := Get_Name_String (Dot_Replacement);
6225 if Dot_Repl /= "." then
6226 for Index in Filename'First .. Last loop
6227 if Filename (Index) = '.' then
6228 if Current_Verbosity = High then
6229 Write_Line (" Invalid name, contains dot");
6235 Replace_Into_Name_Buffer
6236 (Filename (Filename'First .. Last), Dot_Repl, '.');
6238 Name_Len := Last - Filename'First + 1;
6239 Name_Buffer (1 .. Name_Len) := Filename (Filename'First .. Last);
6241 (Source => Name_Buffer (1 .. Name_Len),
6242 Mapping => Lower_Case_Map);
6246 -- In the standard GNAT naming scheme, check for special cases: children
6247 -- or separates of A, G, I or S, and run time sources.
6249 if Standard_GNAT and then Name_Len >= 3 then
6251 S1 : constant Character := Name_Buffer (1);
6252 S2 : constant Character := Name_Buffer (2);
6253 S3 : constant Character := Name_Buffer (3);
6261 -- Children or separates of packages A, G, I or S. These names
6262 -- are x__ ... or x~... (where x is a, g, i, or s). Both
6263 -- versions (x__... and x~...) are allowed in all platforms,
6264 -- because it is not possible to know the platform before
6265 -- processing of the project files.
6267 if S2 = '_' and then S3 = '_' then
6268 Name_Buffer (2) := '.';
6269 Name_Buffer (3 .. Name_Len - 1) :=
6270 Name_Buffer (4 .. Name_Len);
6271 Name_Len := Name_Len - 1;
6274 Name_Buffer (2) := '.';
6278 -- If it is potentially a run time source, disable filling
6279 -- of the mapping file to avoid warnings.
6281 Set_Mapping_File_Initial_State_To_Empty (In_Tree);
6287 -- Name_Buffer contains the name of the the unit in lower-cases. Check
6288 -- that this is a valid unit name
6290 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
6292 -- If there is a naming exception for the same unit, the file is not
6293 -- a source for the unit. Currently, this only applies in multi_lang
6294 -- mode, since Unit_Exceptions is no set in ada_only mode.
6296 if Unit /= No_Name then
6297 Unit_Except := Unit_Exceptions.Get (Unit);
6300 Masked := Unit_Except.Spec /= No_File
6302 Unit_Except.Spec /= File_Name;
6304 Masked := Unit_Except.Impl /= No_File
6306 Unit_Except.Impl /= File_Name;
6310 if Current_Verbosity = High then
6311 Write_Str (" """ & Filename & """ contains the ");
6314 Write_Str ("spec of a unit found in """);
6315 Write_Str (Get_Name_String (Unit_Except.Spec));
6317 Write_Str ("body of a unit found in """);
6318 Write_Str (Get_Name_String (Unit_Except.Impl));
6321 Write_Line (""" (ignored)");
6329 and then Current_Verbosity = High
6332 when Spec => Write_Str (" spec of ");
6333 when Impl => Write_Str (" body of ");
6334 when Sep => Write_Str (" sep of ");
6337 Write_Line (Get_Name_String (Unit));
6339 end Compute_Unit_Name;
6346 (In_Tree : Project_Tree_Ref;
6347 Canonical_File_Name : File_Name_Type;
6348 Naming : Naming_Data;
6349 Exception_Id : out Ada_Naming_Exception_Id;
6350 Unit_Name : out Name_Id;
6351 Unit_Kind : out Spec_Or_Body)
6353 Info_Id : Ada_Naming_Exception_Id :=
6354 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6355 VMS_Name : File_Name_Type;
6359 if Info_Id = No_Ada_Naming_Exception
6360 and then Hostparm.OpenVMS
6362 VMS_Name := Canonical_File_Name;
6363 Get_Name_String (VMS_Name);
6365 if Name_Buffer (Name_Len) = '.' then
6366 Name_Len := Name_Len - 1;
6367 VMS_Name := Name_Find;
6370 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6373 if Info_Id /= No_Ada_Naming_Exception then
6374 Exception_Id := Info_Id;
6375 Unit_Name := No_Name;
6379 Exception_Id := No_Ada_Naming_Exception;
6381 (File_Name => Canonical_File_Name,
6382 Dot_Replacement => Naming.Dot_Replacement,
6383 Separate_Suffix => Naming.Separate_Suffix,
6384 Body_Suffix => Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming),
6385 Spec_Suffix => Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming),
6386 Casing => Naming.Casing,
6389 In_Tree => In_Tree);
6392 when Spec => Unit_Kind := Spec;
6393 when Impl | Sep => Unit_Kind := Impl;
6402 function Hash (Unit : Unit_Info) return Header_Num is
6404 return Header_Num (Unit.Unit mod 2048);
6407 -----------------------
6408 -- Is_Illegal_Suffix --
6409 -----------------------
6411 function Is_Illegal_Suffix
6412 (Suffix : File_Name_Type;
6413 Dot_Replacement : File_Name_Type) return Boolean
6415 Suffix_Str : constant String := Get_Name_String (Suffix);
6418 if Suffix_Str'Length = 0 then
6420 elsif Index (Suffix_Str, ".") = 0 then
6424 -- Case of dot replacement is a single dot, and first character of
6425 -- suffix is also a dot.
6427 if Get_Name_String (Dot_Replacement) = "."
6428 and then Suffix_Str (Suffix_Str'First) = '.'
6430 for Index in Suffix_Str'First + 1 .. Suffix_Str'Last loop
6432 -- Case of following dot
6434 if Suffix_Str (Index) = '.' then
6436 -- It is illegal to have a letter following the initial dot
6438 return Is_Letter (Suffix_Str (Suffix_Str'First + 1));
6444 end Is_Illegal_Suffix;
6446 ----------------------
6447 -- Locate_Directory --
6448 ----------------------
6450 procedure Locate_Directory
6451 (Project : Project_Id;
6452 In_Tree : Project_Tree_Ref;
6453 Name : File_Name_Type;
6454 Path : out Path_Information;
6455 Dir_Exists : out Boolean;
6456 Create : String := "";
6457 Location : Source_Ptr := No_Location;
6458 Must_Exist : Boolean := True;
6459 Externally_Built : Boolean := False)
6461 Parent : constant Path_Name_Type :=
6462 Project.Directory.Display_Name;
6463 The_Parent : constant String :=
6464 Get_Name_String (Parent) & Directory_Separator;
6465 The_Parent_Last : constant Natural :=
6466 Compute_Directory_Last (The_Parent);
6467 Full_Name : File_Name_Type;
6468 The_Name : File_Name_Type;
6471 Get_Name_String (Name);
6473 -- Add Subdirs.all if it is a directory that may be created and
6474 -- Subdirs is not null;
6476 if Create /= "" and then Subdirs /= null then
6477 if Name_Buffer (Name_Len) /= Directory_Separator then
6478 Add_Char_To_Name_Buffer (Directory_Separator);
6481 Add_Str_To_Name_Buffer (Subdirs.all);
6484 -- Convert '/' to directory separator (for Windows)
6486 for J in 1 .. Name_Len loop
6487 if Name_Buffer (J) = '/' then
6488 Name_Buffer (J) := Directory_Separator;
6492 The_Name := Name_Find;
6494 if Current_Verbosity = High then
6495 Write_Str ("Locate_Directory (""");
6496 Write_Str (Get_Name_String (The_Name));
6497 Write_Str (""", """);
6498 Write_Str (The_Parent);
6502 Path := No_Path_Information;
6503 Dir_Exists := False;
6505 if Is_Absolute_Path (Get_Name_String (The_Name)) then
6506 Full_Name := The_Name;
6510 Add_Str_To_Name_Buffer
6511 (The_Parent (The_Parent'First .. The_Parent_Last));
6512 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
6513 Full_Name := Name_Find;
6517 Full_Path_Name : String_Access :=
6518 new String'(Get_Name_String (Full_Name));
6521 if (Setup_Projects or else Subdirs /= null)
6522 and then Create'Length > 0
6524 if not Is_Directory (Full_Path_Name.all) then
6526 -- If project is externally built, do not create a subdir,
6527 -- use the specified directory, without the subdir.
6529 if Externally_Built then
6530 if Is_Absolute_Path (Get_Name_String (Name)) then
6531 Get_Name_String (Name);
6535 Add_Str_To_Name_Buffer
6536 (The_Parent (The_Parent'First .. The_Parent_Last));
6537 Add_Str_To_Name_Buffer (Get_Name_String (Name));
6540 Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
6544 Create_Path (Full_Path_Name.all);
6546 if not Quiet_Output then
6548 Write_Str (" directory """);
6549 Write_Str (Full_Path_Name.all);
6550 Write_Str (""" created for project ");
6551 Write_Line (Get_Name_String (Project.Name));
6558 "could not create " & Create &
6559 " directory " & Full_Path_Name.all,
6566 Dir_Exists := Is_Directory (Full_Path_Name.all);
6568 if not Must_Exist or else Dir_Exists then
6570 Normed : constant String :=
6572 (Full_Path_Name.all,
6574 The_Parent (The_Parent'First .. The_Parent_Last),
6575 Resolve_Links => False,
6576 Case_Sensitive => True);
6578 Canonical_Path : constant String :=
6583 (The_Parent'First .. The_Parent_Last),
6585 Opt.Follow_Links_For_Dirs,
6586 Case_Sensitive => False);
6589 Name_Len := Normed'Length;
6590 Name_Buffer (1 .. Name_Len) := Normed;
6591 Path.Display_Name := Name_Find;
6593 Name_Len := Canonical_Path'Length;
6594 Name_Buffer (1 .. Name_Len) := Canonical_Path;
6595 Path.Name := Name_Find;
6599 Free (Full_Path_Name);
6601 end Locate_Directory;
6603 ---------------------------
6604 -- Find_Excluded_Sources --
6605 ---------------------------
6607 procedure Find_Excluded_Sources
6608 (Project : Project_Id;
6609 In_Tree : Project_Tree_Ref)
6611 Excluded_Source_List_File : constant Variable_Value :=
6613 (Name_Excluded_Source_List_File,
6614 Project.Decl.Attributes,
6617 Excluded_Sources : Variable_Value := Util.Value_Of
6618 (Name_Excluded_Source_Files,
6619 Project.Decl.Attributes,
6622 Current : String_List_Id;
6623 Element : String_Element;
6624 Location : Source_Ptr;
6625 Name : File_Name_Type;
6626 File : Prj.Util.Text_File;
6627 Line : String (1 .. 300);
6629 Locally_Removed : Boolean := False;
6632 -- If Excluded_Source_Files is not declared, check
6633 -- Locally_Removed_Files.
6635 if Excluded_Sources.Default then
6636 Locally_Removed := True;
6639 (Name_Locally_Removed_Files, Project.Decl.Attributes, In_Tree);
6642 Excluded_Sources_Htable.Reset;
6644 -- If there are excluded sources, put them in the table
6646 if not Excluded_Sources.Default then
6647 if not Excluded_Source_List_File.Default then
6648 if Locally_Removed then
6651 "?both attributes Locally_Removed_Files and " &
6652 "Excluded_Source_List_File are present",
6653 Excluded_Source_List_File.Location);
6657 "?both attributes Excluded_Source_Files and " &
6658 "Excluded_Source_List_File are present",
6659 Excluded_Source_List_File.Location);
6663 Current := Excluded_Sources.Values;
6664 while Current /= Nil_String loop
6665 Element := In_Tree.String_Elements.Table (Current);
6666 Name := Canonical_Case_File_Name (Element.Value);
6668 -- If the element has no location, then use the location of
6669 -- Excluded_Sources to report possible errors.
6671 if Element.Location = No_Location then
6672 Location := Excluded_Sources.Location;
6674 Location := Element.Location;
6677 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
6678 Current := Element.Next;
6681 elsif not Excluded_Source_List_File.Default then
6682 Location := Excluded_Source_List_File.Location;
6685 Source_File_Path_Name : constant String :=
6688 (Excluded_Source_List_File.Value),
6689 Project.Directory.Name);
6692 if Source_File_Path_Name'Length = 0 then
6693 Err_Vars.Error_Msg_File_1 :=
6694 File_Name_Type (Excluded_Source_List_File.Value);
6697 "file with excluded sources { does not exist",
6698 Excluded_Source_List_File.Location);
6703 Prj.Util.Open (File, Source_File_Path_Name);
6705 if not Prj.Util.Is_Valid (File) then
6707 (Project, In_Tree, "file does not exist", Location);
6709 -- Read the lines one by one
6711 while not Prj.Util.End_Of_File (File) loop
6712 Prj.Util.Get_Line (File, Line, Last);
6714 -- Non empty, non comment line should contain a file name
6717 and then (Last = 1 or else Line (1 .. 2) /= "--")
6720 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6721 Canonical_Case_File_Name
6722 (Name_Buffer (1 .. Name_Len));
6725 -- Check that there is no directory information
6727 for J in 1 .. Last loop
6729 or else Line (J) = Directory_Separator
6731 Error_Msg_File_1 := Name;
6735 "file name cannot include " &
6736 "directory information ({)",
6742 Excluded_Sources_Htable.Set
6743 (Name, (Name, False, Location));
6747 Prj.Util.Close (File);
6752 end Find_Excluded_Sources;
6758 procedure Find_Sources
6759 (Project : Project_Id;
6760 In_Tree : Project_Tree_Ref;
6761 Proc_Data : in out Processing_Data;
6762 Allow_Duplicate_Basenames : Boolean)
6764 Sources : constant Variable_Value :=
6767 Project.Decl.Attributes,
6769 Source_List_File : constant Variable_Value :=
6771 (Name_Source_List_File,
6772 Project.Decl.Attributes,
6774 Name_Loc : Name_Location;
6776 Has_Explicit_Sources : Boolean;
6779 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
6781 (Source_List_File.Kind = Single,
6782 "Source_List_File is not a single string");
6784 -- If the user has specified a Source_Files attribute
6786 if not Sources.Default then
6787 if not Source_List_File.Default then
6790 "?both attributes source_files and " &
6791 "source_list_file are present",
6792 Source_List_File.Location);
6795 -- Sources is a list of file names
6798 Current : String_List_Id := Sources.Values;
6799 Element : String_Element;
6800 Location : Source_Ptr;
6801 Name : File_Name_Type;
6804 if Get_Mode = Multi_Language then
6805 if Current = Nil_String then
6806 Project.Languages := No_Language_Index;
6808 -- This project contains no source. For projects that don't
6809 -- extend other projects, this also means that there is no
6810 -- need for an object directory, if not specified.
6812 if Project.Extends = No_Project
6813 and then Project.Object_Directory = Project.Directory
6815 Project.Object_Directory := No_Path_Information;
6820 while Current /= Nil_String loop
6821 Element := In_Tree.String_Elements.Table (Current);
6822 Name := Canonical_Case_File_Name (Element.Value);
6823 Get_Name_String (Element.Value);
6825 -- If the element has no location, then use the location of
6826 -- Sources to report possible errors.
6828 if Element.Location = No_Location then
6829 Location := Sources.Location;
6831 Location := Element.Location;
6834 -- Check that there is no directory information
6836 for J in 1 .. Name_Len loop
6837 if Name_Buffer (J) = '/'
6838 or else Name_Buffer (J) = Directory_Separator
6840 Error_Msg_File_1 := Name;
6844 "file name cannot include directory " &
6851 -- In Multi_Language mode, check whether the file is already
6852 -- there: the same file name may be in the list. If the source
6853 -- is missing, the error will be on the first mention of the
6854 -- source file name.
6858 Name_Loc := No_Name_Location;
6859 when Multi_Language =>
6860 Name_Loc := Source_Names.Get (Name);
6863 if Name_Loc = No_Name_Location then
6866 Location => Location,
6867 Source => No_Source,
6870 Source_Names.Set (Name, Name_Loc);
6873 Current := Element.Next;
6876 Has_Explicit_Sources := True;
6879 -- If we have no Source_Files attribute, check the Source_List_File
6882 elsif not Source_List_File.Default then
6884 -- Source_List_File is the name of the file that contains the source
6888 Source_File_Path_Name : constant String :=
6890 (File_Name_Type (Source_List_File.Value),
6891 Project.Directory.Name);
6894 Has_Explicit_Sources := True;
6896 if Source_File_Path_Name'Length = 0 then
6897 Err_Vars.Error_Msg_File_1 :=
6898 File_Name_Type (Source_List_File.Value);
6901 "file with sources { does not exist",
6902 Source_List_File.Location);
6905 Get_Sources_From_File
6906 (Source_File_Path_Name, Source_List_File.Location,
6912 -- Neither Source_Files nor Source_List_File has been specified. Find
6913 -- all the files that satisfy the naming scheme in all the source
6916 Has_Explicit_Sources := False;
6919 if Get_Mode = Ada_Only then
6922 Explicit_Sources_Only => Has_Explicit_Sources,
6923 Proc_Data => Proc_Data);
6929 Sources.Default and then Source_List_File.Default,
6930 Allow_Duplicate_Basenames => Allow_Duplicate_Basenames);
6933 -- Check if all exceptions have been found. For Ada, it is an error if
6934 -- an exception is not found. For other language, the source is simply
6939 Iter : Source_Iterator;
6942 Iter := For_Each_Source (In_Tree, Project);
6944 Source := Prj.Element (Iter);
6945 exit when Source = No_Source;
6947 if Source.Naming_Exception
6948 and then Source.Path = No_Path_Information
6950 if Source.Unit /= No_Unit_Index then
6951 Error_Msg_Name_1 := Name_Id (Source.Display_File);
6952 Error_Msg_Name_2 := Name_Id (Source.Unit.Name);
6955 "source file %% for unit %% not found",
6959 Remove_Source (Source, No_Source);
6966 -- It is an error if a source file name in a source list or in a source
6967 -- list file is not found.
6969 if Has_Explicit_Sources then
6972 First_Error : Boolean;
6975 NL := Source_Names.Get_First;
6976 First_Error := True;
6977 while NL /= No_Name_Location loop
6978 if not NL.Found then
6979 Err_Vars.Error_Msg_File_1 := NL.Name;
6984 "source file { not found",
6986 First_Error := False;
6991 "\source file { not found",
6996 NL := Source_Names.Get_Next;
7001 if Get_Mode = Ada_Only
7002 and then Project.Extends = No_Project
7004 -- We should have found at least one source, if not report an error
7006 if not Has_Ada_Sources (Project) then
7008 (Project, "Ada", In_Tree, Source_List_File.Location);
7017 procedure Initialize (Proc_Data : in out Processing_Data) is
7019 Files_Htable.Reset (Proc_Data.Units);
7026 procedure Free (Proc_Data : in out Processing_Data) is
7028 Files_Htable.Reset (Proc_Data.Units);
7031 ----------------------
7032 -- Find_Ada_Sources --
7033 ----------------------
7035 procedure Find_Ada_Sources
7036 (Project : Project_Id;
7037 In_Tree : Project_Tree_Ref;
7038 Explicit_Sources_Only : Boolean;
7039 Proc_Data : in out Processing_Data)
7041 Source_Dir : String_List_Id;
7042 Element : String_Element;
7044 Dir_Has_Source : Boolean := False;
7046 Ada_Language : Language_Ptr;
7049 if Current_Verbosity = High then
7050 Write_Line ("Looking for Ada sources:");
7053 Ada_Language := Project.Languages;
7054 while Ada_Language /= No_Language_Index
7055 and then Ada_Language.Name /= Name_Ada
7057 Ada_Language := Ada_Language.Next;
7060 -- We look in all source directories for the file names in the hash
7061 -- table Source_Names.
7063 Source_Dir := Project.Source_Dirs;
7064 while Source_Dir /= Nil_String loop
7065 Dir_Has_Source := False;
7066 Element := In_Tree.String_Elements.Table (Source_Dir);
7069 Dir_Path : constant String :=
7070 Get_Name_String (Element.Display_Value) &
7071 Directory_Separator;
7072 Dir_Last : constant Natural := Compute_Directory_Last (Dir_Path);
7075 if Current_Verbosity = High then
7076 Write_Line ("checking directory """ & Dir_Path & """");
7079 -- Look for all files in the current source directory
7081 Open (Dir, Dir_Path (Dir_Path'First .. Dir_Last));
7084 Read (Dir, Name_Buffer, Name_Len);
7085 exit when Name_Len = 0;
7087 if Current_Verbosity = High then
7088 Write_Line (" Checking " & Name_Buffer (1 .. Name_Len));
7092 Name : constant File_Name_Type := Name_Find;
7093 Canonical_Name : File_Name_Type;
7095 -- ??? We could probably optimize the following call: we
7096 -- need to resolve links only once for the directory itself,
7097 -- and then do a single call to readlink() for each file.
7098 -- Unfortunately that would require a change in
7099 -- Normalize_Pathname so that it has the option of not
7100 -- resolving links for its Directory parameter, only for
7103 Path : constant String :=
7105 (Name => Name_Buffer (1 .. Name_Len),
7106 Directory => Dir_Path (Dir_Path'First .. Dir_Last),
7107 Resolve_Links => Opt.Follow_Links_For_Files,
7108 Case_Sensitive => True); -- no case folding
7110 Path_Name : Path_Name_Type;
7111 To_Record : Boolean := False;
7112 Location : Source_Ptr;
7115 -- If the file was listed in the explicit list of sources,
7116 -- mark it as such (since we'll need to report an error when
7117 -- an explicit source was not found)
7119 if Explicit_Sources_Only then
7121 Canonical_Case_File_Name (Name_Id (Name));
7122 NL := Source_Names.Get (Canonical_Name);
7123 To_Record := NL /= No_Name_Location and then not NL.Found;
7127 Location := NL.Location;
7128 Source_Names.Set (Canonical_Name, NL);
7133 Location := No_Location;
7137 Name_Len := Path'Length;
7138 Name_Buffer (1 .. Name_Len) := Path;
7139 Path_Name := Name_Find;
7141 if Current_Verbosity = High then
7142 Write_Line (" recording " & Get_Name_String (Name));
7145 -- Register the source if it is an Ada compilation unit
7149 Path_Name => Path_Name,
7152 Proc_Data => Proc_Data,
7153 Ada_Language => Ada_Language,
7154 Location => Location,
7155 Source_Recorded => Dir_Has_Source);
7168 if Dir_Has_Source then
7169 In_Tree.String_Elements.Table (Source_Dir).Flag := True;
7172 Source_Dir := Element.Next;
7175 if Current_Verbosity = High then
7176 Write_Line ("End looking for sources");
7178 end Find_Ada_Sources;
7180 -------------------------------
7181 -- Check_File_Naming_Schemes --
7182 -------------------------------
7184 procedure Check_File_Naming_Schemes
7185 (In_Tree : Project_Tree_Ref;
7186 Project : Project_Id;
7187 File_Name : File_Name_Type;
7188 Alternate_Languages : out Language_List;
7189 Language : out Language_Ptr;
7190 Display_Language_Name : out Name_Id;
7192 Lang_Kind : out Language_Kind;
7193 Kind : out Source_Kind)
7195 Filename : constant String := Get_Name_String (File_Name);
7196 Config : Language_Config;
7197 Tmp_Lang : Language_Ptr;
7199 Header_File : Boolean := False;
7200 -- True if we found at least one language for which the file is a header
7201 -- In such a case, we search for all possible languages where this is
7202 -- also a header (C and C++ for instance), since the file might be used
7203 -- for several such languages.
7205 procedure Check_File_Based_Lang;
7206 -- Does the naming scheme test for file-based languages. For those,
7207 -- there is no Unit. Just check if the file name has the implementation
7208 -- or, if it is specified, the template suffix of the language.
7210 -- Returns True if the file belongs to the current language and we
7211 -- should stop searching for matching languages. Not that a given header
7212 -- file could belong to several languages (C and C++ for instance). Thus
7213 -- if we found a header we'll check whether it matches other languages.
7215 ---------------------------
7216 -- Check_File_Based_Lang --
7217 ---------------------------
7219 procedure Check_File_Based_Lang is
7222 and then Suffix_Matches (Filename, Config.Naming_Data.Body_Suffix)
7226 Language := Tmp_Lang;
7228 if Current_Verbosity = High then
7229 Write_Str (" implementation of language ");
7230 Write_Line (Get_Name_String (Display_Language_Name));
7233 elsif Suffix_Matches (Filename, Config.Naming_Data.Spec_Suffix) then
7234 if Current_Verbosity = High then
7235 Write_Str (" header of language ");
7236 Write_Line (Get_Name_String (Display_Language_Name));
7240 Alternate_Languages := new Language_List_Element'
7241 (Language => Language,
7242 Next => Alternate_Languages);
7245 Header_File := True;
7248 Language := Tmp_Lang;
7251 end Check_File_Based_Lang;
7253 -- Start of processing for Check_File_Naming_Schemes
7256 Language := No_Language_Index;
7257 Alternate_Languages := null;
7258 Display_Language_Name := No_Name;
7260 Lang_Kind := File_Based;
7263 Tmp_Lang := Project.Languages;
7264 while Tmp_Lang /= No_Language_Index loop
7265 if Current_Verbosity = High then
7267 (" Testing language "
7268 & Get_Name_String (Tmp_Lang.Name)
7269 & " Header_File=" & Header_File'Img);
7272 Display_Language_Name := Tmp_Lang.Display_Name;
7273 Config := Tmp_Lang.Config;
7274 Lang_Kind := Config.Kind;
7278 Check_File_Based_Lang;
7279 exit when Kind = Impl;
7283 -- We know it belongs to a least a file_based language, no
7284 -- need to check unit-based ones.
7286 if not Header_File then
7288 (File_Name => File_Name,
7289 Dot_Replacement => Config.Naming_Data.Dot_Replacement,
7290 Separate_Suffix => Config.Naming_Data.Separate_Suffix,
7291 Body_Suffix => Config.Naming_Data.Body_Suffix,
7292 Spec_Suffix => Config.Naming_Data.Spec_Suffix,
7293 Casing => Config.Naming_Data.Casing,
7296 In_Tree => In_Tree);
7298 if Unit /= No_Name then
7299 Language := Tmp_Lang;
7305 Tmp_Lang := Tmp_Lang.Next;
7308 if Language = No_Language_Index
7309 and then Current_Verbosity = High
7311 Write_Line (" not a source of any language");
7313 end Check_File_Naming_Schemes;
7319 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind) is
7321 -- If the file was previously already associated with a unit, change it
7323 if Source.Unit /= null
7324 and then Source.Kind in Spec_Or_Body
7325 and then Source.Unit.File_Names (Source.Kind) /= null
7327 -- If we had another file referencing the same unit (for instance it
7328 -- was in an extended project), that source file is in fact invisible
7329 -- from now on, and in particular doesn't belong to the same unit.
7331 if Source.Unit.File_Names (Source.Kind) /= Source then
7332 Source.Unit.File_Names (Source.Kind).Unit := No_Unit_Index;
7335 Source.Unit.File_Names (Source.Kind) := null;
7338 Source.Kind := Kind;
7340 if Source.Kind in Spec_Or_Body and then Source.Unit /= null then
7341 Source.Unit.File_Names (Source.Kind) := Source;
7349 procedure Check_File
7350 (Project : Project_Id;
7351 In_Tree : Project_Tree_Ref;
7352 Path : Path_Name_Type;
7353 File_Name : File_Name_Type;
7354 Display_File_Name : File_Name_Type;
7355 For_All_Sources : Boolean;
7356 Allow_Duplicate_Basenames : Boolean)
7358 Canonical_Path : constant Path_Name_Type :=
7360 (Canonical_Case_File_Name (Name_Id (Path)));
7362 Name_Loc : Name_Location := Source_Names.Get (File_Name);
7363 Check_Name : Boolean := False;
7364 Alternate_Languages : Language_List;
7365 Language : Language_Ptr;
7368 Src_Ind : Source_File_Index;
7370 Source_To_Replace : Source_Id := No_Source;
7371 Display_Language_Name : Name_Id;
7372 Lang_Kind : Language_Kind;
7373 Kind : Source_Kind := Spec;
7374 Iter : Source_Iterator;
7377 if Name_Loc = No_Name_Location then
7378 Check_Name := For_All_Sources;
7381 if Name_Loc.Found then
7383 -- Check if it is OK to have the same file name in several
7384 -- source directories.
7386 if not Project.Known_Order_Of_Source_Dirs then
7387 Error_Msg_File_1 := File_Name;
7390 "{ is found in several source directories",
7395 Name_Loc.Found := True;
7397 Source_Names.Set (File_Name, Name_Loc);
7399 if Name_Loc.Source = No_Source then
7403 Name_Loc.Source.Path := (Canonical_Path, Path);
7405 Source_Paths_Htable.Set
7406 (In_Tree.Source_Paths_HT,
7410 -- Check if this is a subunit
7412 if Name_Loc.Source.Unit /= No_Unit_Index
7413 and then Name_Loc.Source.Kind = Impl
7415 Src_Ind := Sinput.P.Load_Project_File
7416 (Get_Name_String (Canonical_Path));
7418 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7419 Override_Kind (Name_Loc.Source, Sep);
7427 Check_File_Naming_Schemes
7428 (In_Tree => In_Tree,
7430 File_Name => File_Name,
7431 Alternate_Languages => Alternate_Languages,
7432 Language => Language,
7433 Display_Language_Name => Display_Language_Name,
7435 Lang_Kind => Lang_Kind,
7438 if Language = No_Language_Index then
7440 -- A file name in a list must be a source of a language
7442 if Name_Loc.Found then
7443 Error_Msg_File_1 := File_Name;
7447 "language unknown for {",
7452 -- Check if the same file name or unit is used in the prj tree
7454 Iter := For_Each_Source (In_Tree);
7457 Source := Prj.Element (Iter);
7458 exit when Source = No_Source;
7461 and then Source.Unit /= No_Unit_Index
7462 and then Source.Unit.Name = Unit
7464 ((Source.Kind = Spec and then Kind = Impl)
7466 (Source.Kind = Impl and then Kind = Spec))
7468 -- We found the "other_part (source)"
7472 elsif (Unit /= No_Name
7473 and then Source.Unit /= No_Unit_Index
7474 and then Source.Unit.Name = Unit
7478 (Source.Kind = Sep and then Kind = Impl)
7480 (Source.Kind = Impl and then Kind = Sep)))
7482 (Unit = No_Name and then Source.File = File_Name)
7484 -- Duplication of file/unit in same project is only
7485 -- allowed if order of source directories is known.
7487 if Project = Source.Project then
7488 if Unit = No_Name then
7489 if Allow_Duplicate_Basenames then
7491 elsif Project.Known_Order_Of_Source_Dirs then
7494 Error_Msg_File_1 := File_Name;
7496 (Project, In_Tree, "duplicate source file name {",
7502 if Project.Known_Order_Of_Source_Dirs then
7505 Error_Msg_Name_1 := Unit;
7507 (Project, In_Tree, "duplicate unit %%",
7513 -- Do not allow the same unit name in different projects,
7514 -- except if one is extending the other.
7516 -- For a file based language, the same file name replaces
7517 -- a file in a project being extended, but it is allowed
7518 -- to have the same file name in unrelated projects.
7520 elsif Is_Extending (Project, Source.Project) then
7521 Source_To_Replace := Source;
7523 elsif Unit /= No_Name
7524 and then not Source.Locally_Removed
7526 Error_Msg_Name_1 := Unit;
7529 "unit %% cannot belong to several projects",
7532 Error_Msg_Name_1 := Project.Name;
7533 Error_Msg_Name_2 := Name_Id (Path);
7535 (Project, In_Tree, "\ project %%, %%", No_Location);
7537 Error_Msg_Name_1 := Source.Project.Name;
7538 Error_Msg_Name_2 := Name_Id (Source.Path.Display_Name);
7540 (Project, In_Tree, "\ project %%, %%", No_Location);
7554 Lang_Id => Language,
7556 Alternate_Languages => Alternate_Languages,
7557 File_Name => File_Name,
7558 Display_File => Display_File_Name,
7560 Path => (Canonical_Path, Path),
7561 Source_To_Replace => Source_To_Replace);
7567 ------------------------
7568 -- Search_Directories --
7569 ------------------------
7571 procedure Search_Directories
7572 (Project : Project_Id;
7573 In_Tree : Project_Tree_Ref;
7574 For_All_Sources : Boolean;
7575 Allow_Duplicate_Basenames : Boolean)
7577 Source_Dir : String_List_Id;
7578 Element : String_Element;
7580 Name : String (1 .. 1_000);
7582 File_Name : File_Name_Type;
7583 Display_File_Name : File_Name_Type;
7586 if Current_Verbosity = High then
7587 Write_Line ("Looking for sources:");
7590 -- Loop through subdirectories
7592 Source_Dir := Project.Source_Dirs;
7593 while Source_Dir /= Nil_String loop
7595 Element := In_Tree.String_Elements.Table (Source_Dir);
7596 if Element.Value /= No_Name then
7597 Get_Name_String (Element.Display_Value);
7600 Source_Directory : constant String :=
7601 Name_Buffer (1 .. Name_Len) &
7602 Directory_Separator;
7604 Dir_Last : constant Natural :=
7605 Compute_Directory_Last
7609 if Current_Verbosity = High then
7610 Write_Attr ("Source_Dir", Source_Directory);
7613 -- We look to every entry in the source directory
7615 Open (Dir, Source_Directory);
7618 Read (Dir, Name, Last);
7622 -- ??? Duplicate system call here, we just did a
7623 -- a similar one. Maybe Ada.Directories would be more
7627 (Source_Directory & Name (1 .. Last))
7629 if Current_Verbosity = High then
7630 Write_Str (" Checking ");
7631 Write_Line (Name (1 .. Last));
7635 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
7636 Display_File_Name := Name_Find;
7638 if Osint.File_Names_Case_Sensitive then
7639 File_Name := Display_File_Name;
7641 Canonical_Case_File_Name
7642 (Name_Buffer (1 .. Name_Len));
7643 File_Name := Name_Find;
7647 Path_Name : constant String :=
7652 (Source_Directory'First ..
7655 Opt.Follow_Links_For_Files,
7656 Case_Sensitive => True);
7657 -- Case_Sensitive set True (no folding)
7659 Path : Path_Name_Type;
7661 Excluded_Sources_Htable.Get (File_Name);
7664 Name_Len := Path_Name'Length;
7665 Name_Buffer (1 .. Name_Len) := Path_Name;
7668 if FF /= No_File_Found then
7669 if not FF.Found then
7671 Excluded_Sources_Htable.Set (File_Name, FF);
7673 if Current_Verbosity = High then
7674 Write_Str (" excluded source """);
7675 Write_Str (Get_Name_String (File_Name));
7682 (Project => Project,
7685 File_Name => File_Name,
7686 Display_File_Name =>
7688 For_All_Sources => For_All_Sources,
7689 Allow_Duplicate_Basenames =>
7690 Allow_Duplicate_Basenames);
7701 when Directory_Error =>
7705 Source_Dir := Element.Next;
7708 if Current_Verbosity = High then
7709 Write_Line ("end Looking for sources.");
7711 end Search_Directories;
7713 ----------------------------
7714 -- Load_Naming_Exceptions --
7715 ----------------------------
7717 procedure Load_Naming_Exceptions
7718 (Project : Project_Id;
7719 In_Tree : Project_Tree_Ref)
7722 Iter : Source_Iterator;
7725 Unit_Exceptions.Reset;
7727 Iter := For_Each_Source (In_Tree, Project);
7729 Source := Prj.Element (Iter);
7730 exit when Source = No_Source;
7732 -- An excluded file cannot also be an exception file name
7734 if Excluded_Sources_Htable.Get (Source.File) /= No_File_Found then
7735 Error_Msg_File_1 := Source.File;
7738 "{ cannot be both excluded and an exception file name",
7742 if Current_Verbosity = High then
7743 Write_Str ("Naming exception: Putting source file ");
7744 Write_Str (Get_Name_String (Source.File));
7745 Write_Line (" in Source_Names");
7751 (Name => Source.File,
7752 Location => No_Location,
7754 Except => Source.Unit /= No_Unit_Index,
7757 -- If this is an Ada exception, record in table Unit_Exceptions
7759 if Source.Unit /= No_Unit_Index then
7761 Unit_Except : Unit_Exception :=
7762 Unit_Exceptions.Get (Source.Unit.Name);
7765 Unit_Except.Name := Source.Unit.Name;
7767 if Source.Kind = Spec then
7768 Unit_Except.Spec := Source.File;
7770 Unit_Except.Impl := Source.File;
7773 Unit_Exceptions.Set (Source.Unit.Name, Unit_Except);
7779 end Load_Naming_Exceptions;
7781 ----------------------
7782 -- Look_For_Sources --
7783 ----------------------
7785 procedure Look_For_Sources
7786 (Project : Project_Id;
7787 In_Tree : Project_Tree_Ref;
7788 Proc_Data : in out Processing_Data;
7789 Allow_Duplicate_Basenames : Boolean)
7791 Iter : Source_Iterator;
7793 procedure Process_Sources_In_Multi_Language_Mode;
7794 -- Find all source files when in multi language mode
7796 procedure Mark_Excluded_Sources;
7797 -- Mark as such the sources that are declared as excluded
7799 ---------------------------
7800 -- Mark_Excluded_Sources --
7801 ---------------------------
7803 procedure Mark_Excluded_Sources is
7804 Source : Source_Id := No_Source;
7806 Excluded : File_Found;
7809 Excluded := Excluded_Sources_Htable.Get_First;
7810 while Excluded /= No_File_Found loop
7813 -- ??? Don't we have a hash table to map files to Source_Id?
7815 Iter := For_Each_Source (In_Tree);
7817 Source := Prj.Element (Iter);
7818 exit when Source = No_Source;
7820 if Source.File = Excluded.File then
7821 if Source.Project = Project
7822 or else Is_Extending (Project, Source.Project)
7825 Source.Locally_Removed := True;
7826 Source.In_Interfaces := False;
7828 if Current_Verbosity = High then
7829 Write_Str ("Removing file ");
7830 Write_Line (Get_Name_String (Excluded.File));
7836 "cannot remove a source from another project",
7846 OK := OK or Excluded.Found;
7849 Err_Vars.Error_Msg_File_1 := Excluded.File;
7851 (Project, In_Tree, "unknown file {", Excluded.Location);
7854 Excluded := Excluded_Sources_Htable.Get_Next;
7856 end Mark_Excluded_Sources;
7858 --------------------------------------------
7859 -- Process_Sources_In_Multi_Language_Mode --
7860 --------------------------------------------
7862 procedure Process_Sources_In_Multi_Language_Mode is
7863 Iter : Source_Iterator;
7866 -- Check that two sources of this project do not have the same object
7869 Check_Object_File_Names : declare
7871 Source_Name : File_Name_Type;
7873 procedure Check_Object (Src : Source_Id);
7874 -- Check if object file name of the current source is already in
7875 -- hash table Object_File_Names. If it is, report an error. If it
7876 -- is not, put it there with the file name of the current source.
7882 procedure Check_Object (Src : Source_Id) is
7884 Source_Name := Object_File_Names.Get (Src.Object);
7886 if Source_Name /= No_File then
7887 Error_Msg_File_1 := Src.File;
7888 Error_Msg_File_2 := Source_Name;
7892 "{ and { have the same object file name",
7896 Object_File_Names.Set (Src.Object, Src.File);
7900 -- Start of processing for Check_Object_File_Names
7903 Object_File_Names.Reset;
7904 Iter := For_Each_Source (In_Tree);
7906 Src_Id := Prj.Element (Iter);
7907 exit when Src_Id = No_Source;
7909 if Is_Compilable (Src_Id)
7910 and then Src_Id.Language.Config.Object_Generated
7911 and then Is_Extending (Project, Src_Id.Project)
7913 if Src_Id.Unit = No_Unit_Index then
7914 if Src_Id.Kind = Impl then
7915 Check_Object (Src_Id);
7921 if Other_Part (Src_Id) = No_Source then
7922 Check_Object (Src_Id);
7929 if Other_Part (Src_Id) /= No_Source then
7930 Check_Object (Src_Id);
7933 -- Check if it is a subunit
7936 Src_Ind : constant Source_File_Index :=
7937 Sinput.P.Load_Project_File
7939 (Src_Id.Path.Name));
7941 if Sinput.P.Source_File_Is_Subunit
7944 Override_Kind (Src_Id, Sep);
7946 Check_Object (Src_Id);
7956 end Check_Object_File_Names;
7957 end Process_Sources_In_Multi_Language_Mode;
7959 -- Start of processing for Look_For_Sources
7963 Find_Excluded_Sources (Project, In_Tree);
7965 if (Get_Mode = Ada_Only and then Is_A_Language (Project, Name_Ada))
7966 or else (Get_Mode = Multi_Language
7967 and then Project.Languages /= No_Language_Index)
7969 if Get_Mode = Multi_Language then
7970 Load_Naming_Exceptions (Project, In_Tree);
7973 Find_Sources (Project, In_Tree, Proc_Data, Allow_Duplicate_Basenames);
7974 Mark_Excluded_Sources;
7976 if Get_Mode = Multi_Language then
7977 Process_Sources_In_Multi_Language_Mode;
7980 end Look_For_Sources;
7986 function Path_Name_Of
7987 (File_Name : File_Name_Type;
7988 Directory : Path_Name_Type) return String
7990 Result : String_Access;
7991 The_Directory : constant String := Get_Name_String (Directory);
7994 Get_Name_String (File_Name);
7997 (File_Name => Name_Buffer (1 .. Name_Len),
7998 Path => The_Directory);
8000 if Result = null then
8004 R : String := Result.all;
8007 Canonical_Case_File_Name (R);
8013 -----------------------------------
8014 -- Prepare_Ada_Naming_Exceptions --
8015 -----------------------------------
8017 procedure Prepare_Ada_Naming_Exceptions
8018 (List : Array_Element_Id;
8019 In_Tree : Project_Tree_Ref;
8020 Kind : Spec_Or_Body)
8022 Current : Array_Element_Id;
8023 Element : Array_Element;
8027 -- Traverse the list
8030 while Current /= No_Array_Element loop
8031 Element := In_Tree.Array_Elements.Table (Current);
8033 if Element.Index /= No_Name then
8036 Unit => Element.Index,
8037 Next => No_Ada_Naming_Exception);
8038 Reverse_Ada_Naming_Exceptions.Set
8039 (Unit, (Element.Value.Value, Element.Value.Index));
8041 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8042 Ada_Naming_Exception_Table.Increment_Last;
8043 Ada_Naming_Exception_Table.Table
8044 (Ada_Naming_Exception_Table.Last) := Unit;
8045 Ada_Naming_Exceptions.Set
8046 (File_Name_Type (Element.Value.Value),
8047 Ada_Naming_Exception_Table.Last);
8050 Current := Element.Next;
8052 end Prepare_Ada_Naming_Exceptions;
8054 -----------------------
8055 -- Record_Ada_Source --
8056 -----------------------
8058 procedure Record_Ada_Source
8059 (File_Name : File_Name_Type;
8060 Path_Name : Path_Name_Type;
8061 Project : Project_Id;
8062 In_Tree : Project_Tree_Ref;
8063 Proc_Data : in out Processing_Data;
8064 Ada_Language : Language_Ptr;
8065 Location : Source_Ptr;
8066 Source_Recorded : in out Boolean)
8068 Canonical_File : File_Name_Type;
8069 Canonical_Path : Path_Name_Type;
8071 File_Recorded : Boolean := False;
8072 -- True when at least one file has been recorded
8074 procedure Record_Unit
8075 (Unit_Name : Name_Id;
8076 Unit_Ind : Int := 0;
8077 Unit_Kind : Spec_Or_Body;
8078 Needs_Pragma : Boolean);
8079 -- Register of the units contained in the source file (there is in
8080 -- general a single such unit except when exceptions to the naming
8081 -- scheme indicate there are several such units)
8087 procedure Record_Unit
8088 (Unit_Name : Name_Id;
8089 Unit_Ind : Int := 0;
8090 Unit_Kind : Spec_Or_Body;
8091 Needs_Pragma : Boolean)
8093 UData : constant Unit_Index :=
8094 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
8095 -- ??? Add_Source will look it up again, can we do that only once ?
8098 To_Record : Boolean := False;
8099 The_Location : Source_Ptr := Location;
8100 Unit_Prj : Project_Id;
8103 if Current_Verbosity = High then
8104 Write_Str (" Putting ");
8105 Write_Str (Get_Name_String (Unit_Name));
8106 Write_Line (" in the unit list.");
8109 -- The unit is already in the list, but may be it is only the other
8110 -- unit kind (spec or body), or what is in the unit list is a unit of
8111 -- a project we are extending.
8113 if UData /= No_Unit_Index then
8114 if UData.File_Names (Unit_Kind) = null
8116 (UData.File_Names (Unit_Kind).File = Canonical_File
8117 and then UData.File_Names (Unit_Kind).Locally_Removed)
8118 or else Is_Extending
8119 (Project.Extends, UData.File_Names (Unit_Kind).Project)
8123 -- If the same file is already in the list, do not add it again
8125 elsif UData.File_Names (Unit_Kind).Project = Project
8127 (Project.Known_Order_Of_Source_Dirs
8129 UData.File_Names (Unit_Kind).Path.Name = Canonical_Path)
8133 -- Else, same unit but not same file => It is an error to have two
8134 -- units with the same name and the same kind (spec or body).
8137 if The_Location = No_Location then
8138 The_Location := Project.Location;
8141 Err_Vars.Error_Msg_Name_1 := Unit_Name;
8143 (Project, In_Tree, "duplicate unit %%", The_Location);
8145 Err_Vars.Error_Msg_Name_1 :=
8146 UData.File_Names (Unit_Kind).Project.Name;
8147 Err_Vars.Error_Msg_File_1 :=
8148 File_Name_Type (UData.File_Names (Unit_Kind).Path.Name);
8151 "\ project file %%, {", The_Location);
8153 Err_Vars.Error_Msg_Name_1 := Project.Name;
8154 Err_Vars.Error_Msg_File_1 := File_Name_Type (Canonical_Path);
8156 (Project, In_Tree, "\ project file %%, {", The_Location);
8161 -- It is a new unit, create a new record
8164 -- First, check if there is no other unit with this file name in
8165 -- another project. If it is, report error but note we do that
8166 -- only for the first unit in the source file.
8168 Unit_Prj := Files_Htable.Get (Proc_Data.Units, Canonical_File);
8170 if not File_Recorded
8171 and then Unit_Prj /= No_Project
8173 Error_Msg_File_1 := File_Name;
8174 Error_Msg_Name_1 := Unit_Prj.Name;
8177 "{ is already a source of project %%",
8186 Files_Htable.Set (Proc_Data.Units, Canonical_File, Project);
8191 Lang_Id => Ada_Language,
8192 File_Name => Canonical_File,
8193 Display_File => File_Name,
8195 Path => (Canonical_Path, Path_Name),
8196 Naming_Exception => Needs_Pragma,
8199 Source_Recorded := True;
8203 Exception_Id : Ada_Naming_Exception_Id;
8204 Unit_Name : Name_Id;
8205 Unit_Kind : Spec_Or_Body;
8206 Unit_Ind : Int := 0;
8208 Name_Index : Name_And_Index;
8209 Except_Name : Name_And_Index := No_Name_And_Index;
8210 Needs_Pragma : Boolean;
8213 Canonical_File := Canonical_Case_File_Name (Name_Id (File_Name));
8215 Path_Name_Type (Canonical_Case_File_Name (Name_Id (Path_Name)));
8217 -- Check the naming scheme to get extra file properties
8220 (In_Tree => In_Tree,
8221 Canonical_File_Name => Canonical_File,
8222 Naming => Project.Naming,
8223 Exception_Id => Exception_Id,
8224 Unit_Name => Unit_Name,
8225 Unit_Kind => Unit_Kind);
8227 Needs_Pragma := Exception_Id /= No_Ada_Naming_Exception;
8229 if Exception_Id = No_Ada_Naming_Exception
8230 and then Unit_Name = No_Name
8232 if Current_Verbosity = High then
8234 Write_Str (Get_Name_String (Canonical_File));
8235 Write_Line (""" is not a valid source file name (ignored).");
8240 -- Check to see if the source has been hidden by an exception,
8241 -- but only if it is not an exception.
8243 if not Needs_Pragma then
8245 Reverse_Ada_Naming_Exceptions.Get
8246 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
8248 if Except_Name /= No_Name_And_Index then
8249 if Current_Verbosity = High then
8251 Write_Str (Get_Name_String (Canonical_File));
8252 Write_Str (""" contains a unit that is found in """);
8253 Write_Str (Get_Name_String (Except_Name.Name));
8254 Write_Line (""" (ignored).");
8257 -- The file is not included in the source of the project since it
8258 -- is hidden by the exception. So, nothing else to do.
8264 -- The following loop registers the unit in the appropriate table. It
8265 -- will be executed multiple times when the file is a multi-unit file,
8266 -- in which case Exception_Id initially points to the first file and
8267 -- then to each other unit in the file.
8270 if Exception_Id /= No_Ada_Naming_Exception then
8271 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
8272 Exception_Id := Info.Next;
8273 Info.Next := No_Ada_Naming_Exception;
8274 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
8276 Unit_Name := Info.Unit;
8277 Unit_Ind := Name_Index.Index;
8278 Unit_Kind := Info.Kind;
8281 Record_Unit (Unit_Name, Unit_Ind, Unit_Kind, Needs_Pragma);
8282 File_Recorded := True;
8284 exit when Exception_Id = No_Ada_Naming_Exception;
8286 end Record_Ada_Source;
8292 procedure Remove_Source
8294 Replaced_By : Source_Id)
8299 if Current_Verbosity = High then
8300 Write_Str ("Removing source ");
8301 Write_Line (Get_Name_String (Id.File));
8304 if Replaced_By /= No_Source then
8305 Id.Replaced_By := Replaced_By;
8306 Replaced_By.Declared_In_Interfaces := Id.Declared_In_Interfaces;
8309 Source := Id.Language.First_Source;
8312 Id.Language.First_Source := Id.Next_In_Lang;
8315 while Source.Next_In_Lang /= Id loop
8316 Source := Source.Next_In_Lang;
8319 Source.Next_In_Lang := Id.Next_In_Lang;
8323 -----------------------
8324 -- Report_No_Sources --
8325 -----------------------
8327 procedure Report_No_Sources
8328 (Project : Project_Id;
8330 In_Tree : Project_Tree_Ref;
8331 Location : Source_Ptr;
8332 Continuation : Boolean := False)
8335 case When_No_Sources is
8339 when Warning | Error =>
8341 Msg : constant String :=
8344 " sources in this project";
8347 Error_Msg_Warn := When_No_Sources = Warning;
8349 if Continuation then
8350 Error_Msg (Project, In_Tree, "\" & Msg, Location);
8352 Error_Msg (Project, In_Tree, Msg, Location);
8356 end Report_No_Sources;
8358 ----------------------
8359 -- Show_Source_Dirs --
8360 ----------------------
8362 procedure Show_Source_Dirs
8363 (Project : Project_Id;
8364 In_Tree : Project_Tree_Ref)
8366 Current : String_List_Id;
8367 Element : String_Element;
8370 Write_Line ("Source_Dirs:");
8372 Current := Project.Source_Dirs;
8373 while Current /= Nil_String loop
8374 Element := In_Tree.String_Elements.Table (Current);
8376 Write_Line (Get_Name_String (Element.Value));
8377 Current := Element.Next;
8380 Write_Line ("end Source_Dirs.");
8381 end Show_Source_Dirs;
8383 -------------------------
8384 -- Warn_If_Not_Sources --
8385 -------------------------
8387 -- comments needed in this body ???
8389 procedure Warn_If_Not_Sources
8390 (Project : Project_Id;
8391 In_Tree : Project_Tree_Ref;
8392 Conventions : Array_Element_Id;
8394 Extending : Boolean)
8396 Conv : Array_Element_Id;
8398 The_Unit_Data : Unit_Index;
8399 Location : Source_Ptr;
8402 Conv := Conventions;
8403 while Conv /= No_Array_Element loop
8404 Unit := In_Tree.Array_Elements.Table (Conv).Index;
8405 Error_Msg_Name_1 := Unit;
8406 Get_Name_String (Unit);
8407 To_Lower (Name_Buffer (1 .. Name_Len));
8409 The_Unit_Data := Units_Htable.Get (In_Tree.Units_HT, Unit);
8410 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
8412 if The_Unit_Data = No_Unit_Index then
8413 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
8417 In_Tree.Array_Elements.Table (Conv).Value.Value;
8420 if not Check_Project
8421 (The_Unit_Data.File_Names (Spec).Project,
8426 "?source of spec of unit %% (%%)" &
8427 " not found in this project",
8432 if The_Unit_Data.File_Names (Impl) = null
8433 or else not Check_Project
8434 (The_Unit_Data.File_Names (Impl).Project,
8439 "?source of body of unit %% (%%)" &
8440 " not found in this project",
8446 Conv := In_Tree.Array_Elements.Table (Conv).Next;
8448 end Warn_If_Not_Sources;