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;
35 with Osint; use Osint;
36 with Output; use Output;
37 with Prj.Env; use Prj.Env;
39 with Prj.Util; use Prj.Util;
41 with Snames; use Snames;
42 with Table; use Table;
43 with Targparm; use Targparm;
45 with Ada.Characters.Handling; use Ada.Characters.Handling;
46 with Ada.Directories; use Ada.Directories;
47 with Ada.Strings; use Ada.Strings;
48 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
49 with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants;
51 package body Prj.Nmsc is
53 No_Continuation_String : aliased String := "";
54 Continuation_String : aliased String := "\";
55 -- Used in Check_Library for continuation error messages at the same
58 Error_Report : Put_Line_Access := null;
59 -- Set to point to error reporting procedure
61 When_No_Sources : Error_Warning := Error;
62 -- Indicates what should be done when there is no Ada sources in a non
63 -- extending Ada project.
65 ALI_Suffix : constant String := ".ali";
66 -- File suffix for ali files
68 type Name_Location is record
69 Name : File_Name_Type;
70 Location : Source_Ptr;
71 Source : Source_Id := No_Source;
72 Except : Boolean := False;
73 Found : Boolean := False;
75 -- Information about file names found in string list attribute:
76 -- Source_Files or in a source list file, stored in hash table.
77 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
78 -- Except is set to True if source is a naming exception in the project.
80 No_Name_Location : constant Name_Location :=
82 Location => No_Location,
87 package Source_Names is new GNAT.HTable.Simple_HTable
88 (Header_Num => Header_Num,
89 Element => Name_Location,
90 No_Element => No_Name_Location,
91 Key => File_Name_Type,
94 -- Hash table to store file names found in string list attribute
95 -- Source_Files or in a source list file, stored in hash table
96 -- Source_Names, used by procedure Get_Path_Names_And_Record_Sources.
98 -- More documentation needed on what unit exceptions are about ???
100 type Unit_Exception is record
102 Spec : File_Name_Type;
103 Impl : File_Name_Type;
105 -- Record special naming schemes for Ada units (name of spec file and name
106 -- of implementation file).
108 No_Unit_Exception : constant Unit_Exception :=
113 package Unit_Exceptions is new GNAT.HTable.Simple_HTable
114 (Header_Num => Header_Num,
115 Element => Unit_Exception,
116 No_Element => No_Unit_Exception,
120 -- Hash table to store the unit exceptions.
121 -- ??? Seems to be used only by the multi_lang mode
122 -- ??? Should not be a global array, but stored in the project_data
124 package Recursive_Dirs is new GNAT.HTable.Simple_HTable
125 (Header_Num => Header_Num,
131 -- Hash table to store recursive source directories, to avoid looking
132 -- several times, and to avoid cycles that may be introduced by symbolic
135 type Ada_Naming_Exception_Id is new Nat;
136 No_Ada_Naming_Exception : constant Ada_Naming_Exception_Id := 0;
138 type Unit_Info is record
141 Next : Ada_Naming_Exception_Id := No_Ada_Naming_Exception;
145 package Ada_Naming_Exception_Table is new Table.Table
146 (Table_Component_Type => Unit_Info,
147 Table_Index_Type => Ada_Naming_Exception_Id,
148 Table_Low_Bound => 1,
150 Table_Increment => 100,
151 Table_Name => "Prj.Nmsc.Ada_Naming_Exception_Table");
153 package Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
154 (Header_Num => Header_Num,
155 Element => Ada_Naming_Exception_Id,
156 No_Element => No_Ada_Naming_Exception,
157 Key => File_Name_Type,
160 -- A hash table to store naming exceptions for Ada. For each file name
161 -- there is one or several unit in table Ada_Naming_Exception_Table.
162 -- ??? This is for ada_only mode, we should be able to merge with
163 -- Unit_Exceptions table, used by multi_lang mode.
165 package Object_File_Names is new GNAT.HTable.Simple_HTable
166 (Header_Num => Header_Num,
167 Element => File_Name_Type,
168 No_Element => No_File,
169 Key => File_Name_Type,
172 -- A hash table to store the object file names for a project, to check that
173 -- two different sources have different object file names.
175 type File_Found is record
176 File : File_Name_Type := No_File;
177 Found : Boolean := False;
178 Location : Source_Ptr := No_Location;
180 No_File_Found : constant File_Found := (No_File, False, No_Location);
181 -- Comments needed ???
183 package Excluded_Sources_Htable is new GNAT.HTable.Simple_HTable
184 (Header_Num => Header_Num,
185 Element => File_Found,
186 No_Element => No_File_Found,
187 Key => File_Name_Type,
190 -- A hash table to store the excluded files, if any. This is filled by
191 -- Find_Excluded_Sources below.
193 procedure Find_Excluded_Sources
194 (Project : Project_Id;
195 In_Tree : Project_Tree_Ref);
196 -- Find the list of files that should not be considered as source files
197 -- for this project. Sets the list in the Excluded_Sources_Htable.
199 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind);
200 -- Override the reference kind for a source file. This properly updates
201 -- the unit data if necessary.
203 function Hash (Unit : Unit_Info) return Header_Num;
205 type Name_And_Index is record
206 Name : Name_Id := No_Name;
209 No_Name_And_Index : constant Name_And_Index :=
210 (Name => No_Name, Index => 0);
211 -- Name of a unit, and its index inside the source file. The first unit has
212 -- index 1 (see doc for pragma Source_File_Name), but the index might be
213 -- set to 0 when the source file contains a single unit.
215 package Reverse_Ada_Naming_Exceptions is new GNAT.HTable.Simple_HTable
216 (Header_Num => Header_Num,
217 Element => Name_And_Index,
218 No_Element => No_Name_And_Index,
222 -- A table to check if a unit with an exceptional name will hide a source
223 -- with a file name following the naming convention.
225 procedure Load_Naming_Exceptions
226 (Project : Project_Id;
227 In_Tree : Project_Tree_Ref);
228 -- All source files in Data.First_Source are considered as naming
229 -- exceptions, and copied into the Source_Names and Unit_Exceptions tables
234 In_Tree : Project_Tree_Ref;
235 Project : Project_Id;
236 Lang_Id : Language_Ptr;
238 File_Name : File_Name_Type;
239 Display_File : File_Name_Type;
240 Naming_Exception : Boolean := False;
241 Path : Path_Information := No_Path_Information;
242 Alternate_Languages : Language_List := null;
243 Unit : Name_Id := No_Name;
245 Source_To_Replace : Source_Id := No_Source);
246 -- Add a new source to the different lists: list of all sources in the
247 -- project tree, list of source of a project and list of sources of a
250 -- If Path is specified, the file is also added to Source_Paths_HT.
251 -- If Source_To_Replace is specified, it points to the source in the
252 -- extended project that the new file is overriding.
254 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type;
255 -- Same as Osint.Canonical_Case_File_Name but applies to Name_Id.
256 -- This alters Name_Buffer
258 function Suffix_Matches
260 Suffix : File_Name_Type) return Boolean;
261 -- True if the file name ends with the given suffix. Always returns False
262 -- if Suffix is No_Name.
264 procedure Replace_Into_Name_Buffer
267 Replacement : Character);
268 -- Copy Str into Name_Buffer, replacing Pattern with Replacement. Str is
269 -- converted to lower-case at the same time.
271 function ALI_File_Name (Source : String) return String;
272 -- Return the ALI file name corresponding to a source
274 procedure Check_Ada_Name (Name : String; Unit : out Name_Id);
275 -- Check that a name is a valid Ada unit name
277 procedure Check_Naming_Schemes
278 (Project : Project_Id;
279 In_Tree : Project_Tree_Ref;
280 Is_Config_File : Boolean);
281 -- Check the naming scheme part of Data.
282 -- Is_Config_File should be True if Project is a config file (.cgpr)
284 procedure Check_Configuration
285 (Project : Project_Id;
286 In_Tree : Project_Tree_Ref;
287 Compiler_Driver_Mandatory : Boolean);
288 -- Check the configuration attributes for the project
289 -- If Compiler_Driver_Mandatory is true, then a Compiler.Driver attribute
290 -- for each language must be defined, or we will not look for its source
293 procedure Check_If_Externally_Built
294 (Project : Project_Id;
295 In_Tree : Project_Tree_Ref);
296 -- Check attribute Externally_Built of project Project in project tree
297 -- In_Tree and modify its data Data if it has the value "true".
299 procedure Check_Interfaces
300 (Project : Project_Id;
301 In_Tree : Project_Tree_Ref);
302 -- If a list of sources is specified in attribute Interfaces, set
303 -- In_Interfaces only for the sources specified in the list.
305 procedure Check_Library_Attributes
306 (Project : Project_Id;
307 In_Tree : Project_Tree_Ref);
308 -- Check the library attributes of project Project in project tree In_Tree
309 -- and modify its data Data accordingly.
310 -- Current_Dir should represent the current directory, and is passed for
311 -- efficiency to avoid system calls to recompute it.
313 procedure Check_Package_Naming
314 (Project : Project_Id;
315 In_Tree : Project_Tree_Ref);
316 -- Check package Naming of project Project in project tree In_Tree and
317 -- modify its data Data accordingly.
319 procedure Check_Programming_Languages
320 (In_Tree : Project_Tree_Ref;
321 Project : Project_Id);
322 -- Check attribute Languages for the project with data Data in project
323 -- tree In_Tree and set the components of Data for all the programming
324 -- languages indicated in attribute Languages, if any.
326 function Check_Project
328 Root_Project : Project_Id;
329 Extending : Boolean) return Boolean;
330 -- Returns True if P is Root_Project or, if Extending is True, a project
331 -- extended by Root_Project.
333 procedure Check_Stand_Alone_Library
334 (Project : Project_Id;
335 In_Tree : Project_Tree_Ref;
336 Current_Dir : String;
337 Extending : Boolean);
338 -- Check if project Project in project tree In_Tree is a Stand-Alone
339 -- Library project, and modify its data Data accordingly if it is one.
340 -- Current_Dir should represent the current directory, and is passed for
341 -- efficiency to avoid system calls to recompute it.
343 procedure Check_And_Normalize_Unit_Names
344 (Project : Project_Id;
345 In_Tree : Project_Tree_Ref;
346 List : Array_Element_Id;
347 Debug_Name : String);
348 -- Check that a list of unit names contains only valid names. Casing
349 -- is normalized where appropriate.
350 -- Debug_Name is the name representing the list, and is used for debug
353 procedure Find_Ada_Sources
354 (Project : Project_Id;
355 In_Tree : Project_Tree_Ref;
356 Explicit_Sources_Only : Boolean;
357 Proc_Data : in out Processing_Data);
358 -- Find all Ada sources by traversing all source directories. If
359 -- Explicit_Sources_Only is True, then the sources found must belong to
360 -- the list of sources specified explicitly in the project file. If
361 -- Explicit_Sources_Only is False, then all sources matching the naming
362 -- scheme are recorded.
364 function Compute_Directory_Last (Dir : String) return Natural;
365 -- Return the index of the last significant character in Dir. This is used
366 -- to avoid duplicate '/' (slash) characters at the end of directory names.
369 (Project : Project_Id;
370 In_Tree : Project_Tree_Ref;
372 Flag_Location : Source_Ptr);
373 -- Output an error message. If Error_Report is null, simply call
374 -- Prj.Err.Error_Msg. Otherwise, disregard Flag_Location and use
377 procedure Search_Directories
378 (Project : Project_Id;
379 In_Tree : Project_Tree_Ref;
380 For_All_Sources : Boolean;
381 Allow_Duplicate_Basenames : Boolean);
382 -- Search the source directories to find the sources. If For_All_Sources is
383 -- True, check each regular file name against the naming schemes of the
384 -- different languages. Otherwise consider only the file names in the hash
385 -- table Source_Names. If Allow_Duplicate_Basenames, then files with the
386 -- same base names are authorized within a project for source-based
387 -- languages (never for unit based languages)
390 (Project : Project_Id;
391 In_Tree : Project_Tree_Ref;
392 Path : Path_Name_Type;
393 File_Name : File_Name_Type;
394 Display_File_Name : File_Name_Type;
395 For_All_Sources : Boolean;
396 Allow_Duplicate_Basenames : Boolean);
397 -- Check if file File_Name is a valid source of the project. This is used
398 -- in multi-language mode only. When the file matches one of the naming
399 -- schemes, it is added to various htables through Add_Source and to
400 -- Source_Paths_Htable.
402 -- Name is the name of the candidate file. It hasn't been normalized yet
403 -- and is the direct result of readdir().
405 -- File_Name is the same as Name, but has been normalized.
406 -- Display_File_Name, however, has not been normalized.
408 -- Source_Directory is the directory in which the file
409 -- was found. It hasn't been normalized (nor has had links resolved).
410 -- It should not end with a directory separator, to avoid duplicates
413 -- If For_All_Sources is True, then all possible file names are analyzed
414 -- otherwise only those currently set in the Source_Names htable.
416 -- If Allow_Duplicate_Basenames, then files with the same base names are
417 -- authorized within a project for source-based languages (never for unit
420 procedure Check_File_Naming_Schemes
421 (In_Tree : Project_Tree_Ref;
422 Project : Project_Id;
423 File_Name : File_Name_Type;
424 Alternate_Languages : out Language_List;
425 Language : out Language_Ptr;
426 Display_Language_Name : out Name_Id;
428 Lang_Kind : out Language_Kind;
429 Kind : out Source_Kind);
430 -- Check if the file name File_Name conforms to one of the naming
431 -- schemes of the project.
433 -- If the file does not match one of the naming schemes, set Language
434 -- to No_Language_Index.
436 -- Filename is the name of the file being investigated. It has been
437 -- normalized (case-folded). File_Name is the same value.
439 procedure Free_Ada_Naming_Exceptions;
440 -- Free the internal hash tables used for checking naming exceptions
442 procedure Get_Directories
443 (Project : Project_Id;
444 In_Tree : Project_Tree_Ref;
445 Current_Dir : String);
446 -- Get the object directory, the exec directory and the source directories
449 -- Current_Dir should represent the current directory, and is passed for
450 -- efficiency to avoid system calls to recompute it.
453 (Project : Project_Id;
454 In_Tree : Project_Tree_Ref);
455 -- Get the mains of a project from attribute Main, if it exists, and put
456 -- them in the project data.
458 procedure Get_Sources_From_File
460 Location : Source_Ptr;
461 Project : Project_Id;
462 In_Tree : Project_Tree_Ref);
463 -- Get the list of sources from a text file and put them in hash table
466 procedure Find_Sources
467 (Project : Project_Id;
468 In_Tree : Project_Tree_Ref;
469 Proc_Data : in out Processing_Data;
470 Allow_Duplicate_Basenames : Boolean);
471 -- Process the Source_Files and Source_List_File attributes, and store
472 -- the list of source files into the Source_Names htable.
473 -- When these attributes are not defined, find all files matching the
474 -- naming schemes in the source directories.
475 -- If Allow_Duplicate_Basenames, then files with the same base names are
476 -- authorized within a project for source-based languages (never for unit
479 procedure Compute_Unit_Name
480 (File_Name : File_Name_Type;
481 Dot_Replacement : File_Name_Type;
482 Separate_Suffix : File_Name_Type;
483 Body_Suffix : File_Name_Type;
484 Spec_Suffix : File_Name_Type;
485 Casing : Casing_Type;
486 Kind : out Source_Kind;
488 In_Tree : Project_Tree_Ref);
489 -- Check whether the file matches the naming scheme. If it does,
490 -- compute its unit name. If Unit is set to No_Name on exit, none of the
491 -- other out parameters are relevant.
494 (In_Tree : Project_Tree_Ref;
495 Canonical_File_Name : File_Name_Type;
496 Naming : Naming_Data;
497 Exception_Id : out Ada_Naming_Exception_Id;
498 Unit_Name : out Name_Id;
499 Unit_Kind : out Spec_Or_Body);
500 -- Find out, from a file name, the unit name, the unit kind and if a
501 -- specific SFN pragma is needed. If the file name corresponds to no unit,
502 -- then Unit_Name will be No_Name. If the file is a multi-unit source or an
503 -- exception to the naming scheme, then Exception_Id is set to the unit or
504 -- units that the source contains, and the other information are not set.
506 function Is_Illegal_Suffix
507 (Suffix : File_Name_Type;
508 Dot_Replacement : File_Name_Type) return Boolean;
509 -- Returns True if the string Suffix cannot be used as a spec suffix, a
510 -- body suffix or a separate suffix.
512 procedure Locate_Directory
513 (Project : Project_Id;
514 In_Tree : Project_Tree_Ref;
515 Name : File_Name_Type;
516 Path : out Path_Information;
517 Dir_Exists : out Boolean;
518 Create : String := "";
519 Location : Source_Ptr := No_Location;
520 Must_Exist : Boolean := True;
521 Externally_Built : Boolean := False);
522 -- Locate a directory. Name is the directory name.
523 -- Relative paths are resolved relative to the project's directory.
524 -- If the directory does not exist and Setup_Projects
525 -- is True and Create is a non null string, an attempt is made to create
527 -- If the directory does not exist, it is either created if Setup_Projects
528 -- is False (and then returned), or simply returned without checking for
529 -- its existence (if Must_Exist is False) or No_Path_Information is
530 -- returned. In all cases, Dir_Exists indicates whether the directory now
533 -- Create is also used for debugging traces to show which path we are
536 procedure Look_For_Sources
537 (Project : Project_Id;
538 In_Tree : Project_Tree_Ref;
539 Proc_Data : in out Processing_Data;
540 Allow_Duplicate_Basenames : Boolean);
541 -- Find all the sources of project Project in project tree In_Tree and
542 -- update its Data accordingly. This assumes that Data.First_Source has
543 -- been initialized with the list of excluded sources and special naming
544 -- exceptions. If Allow_Duplicate_Basenames, then files with the same base
545 -- names are authorized within a project for source-based languages (never
546 -- for unit based languages)
548 function Path_Name_Of
549 (File_Name : File_Name_Type;
550 Directory : Path_Name_Type) return String;
551 -- Returns the path name of a (non project) file. Returns an empty string
552 -- if file cannot be found.
554 procedure Prepare_Ada_Naming_Exceptions
555 (List : Array_Element_Id;
556 In_Tree : Project_Tree_Ref;
557 Kind : Spec_Or_Body);
558 -- Prepare the internal hash tables used for checking naming exceptions
559 -- for Ada. Insert all elements of List in the tables.
561 procedure Record_Ada_Source
562 (File_Name : File_Name_Type;
563 Path_Name : Path_Name_Type;
564 Project : Project_Id;
565 In_Tree : Project_Tree_Ref;
566 Proc_Data : in out Processing_Data;
567 Ada_Language : Language_Ptr;
568 Location : Source_Ptr;
569 Source_Recorded : in out Boolean);
570 -- Put a unit in the list of units of a project, if the file name
571 -- corresponds to a valid unit name. Ada_Language is a pointer to the
572 -- Language_Data for "Ada" in Project.
574 procedure Remove_Source
576 Replaced_By : Source_Id);
579 procedure Report_No_Sources
580 (Project : Project_Id;
582 In_Tree : Project_Tree_Ref;
583 Location : Source_Ptr;
584 Continuation : Boolean := False);
585 -- Report an error or a warning depending on the value of When_No_Sources
586 -- when there are no sources for language Lang_Name.
588 procedure Show_Source_Dirs
589 (Project : Project_Id; In_Tree : Project_Tree_Ref);
590 -- List all the source directories of a project
592 procedure Warn_If_Not_Sources
593 (Project : Project_Id;
594 In_Tree : Project_Tree_Ref;
595 Conventions : Array_Element_Id;
597 Extending : Boolean);
598 -- Check that individual naming conventions apply to immediate sources of
599 -- the project. If not, issue a warning.
601 procedure Write_Attr (Name, Value : String);
602 -- Debug print a value for a specific property. Does nothing when not in
605 ------------------------------
606 -- Replace_Into_Name_Buffer --
607 ------------------------------
609 procedure Replace_Into_Name_Buffer
612 Replacement : Character)
614 Max : constant Integer := Str'Last - Pattern'Length + 1;
621 while J <= Str'Last loop
622 Name_Len := Name_Len + 1;
625 and then Str (J .. J + Pattern'Length - 1) = Pattern
627 Name_Buffer (Name_Len) := Replacement;
628 J := J + Pattern'Length;
631 Name_Buffer (Name_Len) := GNAT.Case_Util.To_Lower (Str (J));
635 end Replace_Into_Name_Buffer;
641 function Suffix_Matches
643 Suffix : File_Name_Type) return Boolean
645 Min_Prefix_Length : Natural := 0;
647 if Suffix = No_File or else Suffix = Empty_File then
652 Suf : constant String := Get_Name_String (Suffix);
655 -- The file name must end with the suffix (which is not an extension)
656 -- For instance a suffix "configure.in" must match a file with the
657 -- same name. To avoid dummy cases, though, a suffix starting with
658 -- '.' requires a file that is at least one character longer ('.cpp'
659 -- should not match a file with the same name)
661 if Suf (Suf'First) = '.' then
662 Min_Prefix_Length := 1;
665 return Filename'Length >= Suf'Length + Min_Prefix_Length
667 (Filename'Last - Suf'Length + 1 .. Filename'Last) = Suf;
675 procedure Write_Attr (Name, Value : String) is
677 if Current_Verbosity = High then
678 Write_Str (" " & Name & " = """);
691 In_Tree : Project_Tree_Ref;
692 Project : Project_Id;
693 Lang_Id : Language_Ptr;
695 File_Name : File_Name_Type;
696 Display_File : File_Name_Type;
697 Naming_Exception : Boolean := False;
698 Path : Path_Information := No_Path_Information;
699 Alternate_Languages : Language_List := null;
700 Unit : Name_Id := No_Name;
702 Source_To_Replace : Source_Id := No_Source)
704 Config : constant Language_Config := Lang_Id.Config;
708 Id := new Source_Data;
710 if Current_Verbosity = High then
711 Write_Str ("Adding source File: ");
712 Write_Str (Get_Name_String (File_Name));
714 if Lang_Id.Config.Kind = Unit_Based then
715 Write_Str (" Unit: ");
716 -- ??? in gprclean, it seems we sometimes pass an empty Unit name
717 -- (see test extended_projects)
718 if Unit /= No_Name then
719 Write_Str (Get_Name_String (Unit));
721 Write_Str (" Kind: ");
722 Write_Str (Source_Kind'Image (Kind));
728 Id.Project := Project;
729 Id.Language := Lang_Id;
731 Id.Alternate_Languages := Alternate_Languages;
733 -- Add the source id to the Unit_Sources_HT hash table, if the unit name
736 if Unit /= No_Name then
737 Unit_Sources_Htable.Set (In_Tree.Unit_Sources_HT, Unit, Id);
739 -- ??? Record_Unit has already fetched that earlier, so this isn't
740 -- the most efficient way. But we can't really pass a parameter since
741 -- Process_Exceptions_Unit_Based and Check_File haven't looked it up.
743 UData := Units_Htable.Get (In_Tree.Units_HT, Unit);
745 if UData = No_Unit_Index then
746 UData := new Unit_Data;
748 Units_Htable.Set (In_Tree.Units_HT, Unit, UData);
753 -- Note that this updates Unit information as well
755 Override_Kind (Id, Kind);
759 Id.File := File_Name;
760 Id.Display_File := Display_File;
761 Id.Dep_Name := Dependency_Name
762 (File_Name, Lang_Id.Config.Dependency_Kind);
763 Id.Naming_Exception := Naming_Exception;
765 if Is_Compilable (Id) and then Config.Object_Generated then
766 Id.Object := Object_Name (File_Name, Config.Object_File_Suffix);
767 Id.Switches := Switches_Name (File_Name);
770 if Path /= No_Path_Information then
772 Source_Paths_Htable.Set (In_Tree.Source_Paths_HT, Path.Name, Id);
775 -- Add the source to the language list
777 Id.Next_In_Lang := Lang_Id.First_Source;
778 Lang_Id.First_Source := Id;
780 if Source_To_Replace /= No_Source then
781 Remove_Source (Source_To_Replace, Id);
789 function ALI_File_Name (Source : String) return String is
791 -- If the source name has extension, replace it with the ALI suffix
793 for Index in reverse Source'First + 1 .. Source'Last loop
794 if Source (Index) = '.' then
795 return Source (Source'First .. Index - 1) & ALI_Suffix;
799 -- If no dot, or if it is the first character, just add the ALI suffix
801 return Source & ALI_Suffix;
804 ------------------------------
805 -- Canonical_Case_File_Name --
806 ------------------------------
808 function Canonical_Case_File_Name (Name : Name_Id) return File_Name_Type is
810 if Osint.File_Names_Case_Sensitive then
811 return File_Name_Type (Name);
813 Get_Name_String (Name);
814 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
817 end Canonical_Case_File_Name;
824 (Project : Project_Id;
825 In_Tree : Project_Tree_Ref;
826 Report_Error : Put_Line_Access;
827 When_No_Sources : Error_Warning;
828 Current_Dir : String;
829 Proc_Data : in out Processing_Data;
830 Is_Config_File : Boolean;
831 Compiler_Driver_Mandatory : Boolean;
832 Allow_Duplicate_Basenames : Boolean)
834 Extending : Boolean := False;
837 Nmsc.When_No_Sources := When_No_Sources;
838 Error_Report := Report_Error;
840 Recursive_Dirs.Reset;
842 Check_If_Externally_Built (Project, In_Tree);
844 -- Object, exec and source directories
846 Get_Directories (Project, In_Tree, Current_Dir);
848 -- Get the programming languages
850 Check_Programming_Languages (In_Tree, Project);
852 if Project.Qualifier = Dry
853 and then Project.Source_Dirs /= Nil_String
856 Source_Dirs : constant Variable_Value :=
859 Project.Decl.Attributes, In_Tree);
860 Source_Files : constant Variable_Value :=
863 Project.Decl.Attributes, In_Tree);
864 Source_List_File : constant Variable_Value :=
866 (Name_Source_List_File,
867 Project.Decl.Attributes, In_Tree);
868 Languages : constant Variable_Value :=
871 Project.Decl.Attributes, In_Tree);
874 if Source_Dirs.Values = Nil_String
875 and then Source_Files.Values = Nil_String
876 and then Languages.Values = Nil_String
877 and then Source_List_File.Default
879 Project.Source_Dirs := Nil_String;
884 "at least one of Source_Files, Source_Dirs or Languages " &
885 "must be declared empty for an abstract project",
891 -- Check configuration in multi language mode
893 if Must_Check_Configuration then
896 Compiler_Driver_Mandatory => Compiler_Driver_Mandatory);
899 -- Library attributes
901 Check_Library_Attributes (Project, In_Tree);
903 if Current_Verbosity = High then
904 Show_Source_Dirs (Project, In_Tree);
907 Check_Package_Naming (Project, In_Tree);
909 Extending := Project.Extends /= No_Project;
911 Check_Naming_Schemes (Project, In_Tree, Is_Config_File);
913 if Get_Mode = Ada_Only then
914 Prepare_Ada_Naming_Exceptions
915 (Project.Naming.Bodies, In_Tree, Impl);
916 Prepare_Ada_Naming_Exceptions
917 (Project.Naming.Specs, In_Tree, Spec);
922 if Project.Source_Dirs /= Nil_String then
924 (Project, In_Tree, Proc_Data, Allow_Duplicate_Basenames);
926 if Get_Mode = Ada_Only then
928 -- Check that all individual naming conventions apply to sources
929 -- of this project file.
932 (Project, In_Tree, Project.Naming.Bodies,
934 Extending => Extending);
936 (Project, In_Tree, Project.Naming.Specs,
938 Extending => Extending);
940 elsif Get_Mode = Multi_Language and then
941 (not Project.Externally_Built) and then
945 Language : Language_Ptr;
947 Alt_Lang : Language_List;
948 Continuation : Boolean := False;
949 Iter : Source_Iterator;
952 Language := Project.Languages;
953 while Language /= No_Language_Index loop
955 -- If there are no sources for this language, check whether
956 -- there are sources for which this is an alternate
959 if Language.First_Source = No_Source then
960 Iter := For_Each_Source (In_Tree => In_Tree,
963 Source := Element (Iter);
964 exit Source_Loop when Source = No_Source
965 or else Source.Language = Language;
967 Alt_Lang := Source.Alternate_Languages;
968 while Alt_Lang /= null loop
969 exit Source_Loop when Alt_Lang.Language = Language;
970 Alt_Lang := Alt_Lang.Next;
974 end loop Source_Loop;
976 if Source = No_Source then
979 Get_Name_String (Language.Display_Name),
983 Continuation := True;
987 Language := Language.Next;
993 if Get_Mode = Multi_Language then
995 -- If a list of sources is specified in attribute Interfaces, set
996 -- In_Interfaces only for the sources specified in the list.
998 Check_Interfaces (Project, In_Tree);
1001 -- If it is a library project file, check if it is a standalone library
1003 if Project.Library then
1004 Check_Stand_Alone_Library
1005 (Project, In_Tree, Current_Dir, Extending);
1008 -- Put the list of Mains, if any, in the project data
1010 Get_Mains (Project, In_Tree);
1012 Free_Ada_Naming_Exceptions;
1015 --------------------
1016 -- Check_Ada_Name --
1017 --------------------
1019 procedure Check_Ada_Name (Name : String; Unit : out Name_Id) is
1020 The_Name : String := Name;
1021 Real_Name : Name_Id;
1022 Need_Letter : Boolean := True;
1023 Last_Underscore : Boolean := False;
1024 OK : Boolean := The_Name'Length > 0;
1027 function Is_Reserved (Name : Name_Id) return Boolean;
1028 function Is_Reserved (S : String) return Boolean;
1029 -- Check that the given name is not an Ada 95 reserved word. The reason
1030 -- for the Ada 95 here is that we do not want to exclude the case of an
1031 -- Ada 95 unit called Interface (for example). In Ada 2005, such a unit
1032 -- name would be rejected anyway by the compiler. That means there is no
1033 -- requirement that the project file parser reject this.
1039 function Is_Reserved (S : String) return Boolean is
1042 Add_Str_To_Name_Buffer (S);
1043 return Is_Reserved (Name_Find);
1050 function Is_Reserved (Name : Name_Id) return Boolean is
1052 if Get_Name_Table_Byte (Name) /= 0
1053 and then Name /= Name_Project
1054 and then Name /= Name_Extends
1055 and then Name /= Name_External
1056 and then Name not in Ada_2005_Reserved_Words
1060 if Current_Verbosity = High then
1061 Write_Str (The_Name);
1062 Write_Line (" is an Ada reserved word.");
1072 -- Start of processing for Check_Ada_Name
1075 To_Lower (The_Name);
1077 Name_Len := The_Name'Length;
1078 Name_Buffer (1 .. Name_Len) := The_Name;
1080 -- Special cases of children of packages A, G, I and S on VMS
1082 if OpenVMS_On_Target
1083 and then Name_Len > 3
1084 and then Name_Buffer (2 .. 3) = "__"
1086 ((Name_Buffer (1) = 'a') or else
1087 (Name_Buffer (1) = 'g') or else
1088 (Name_Buffer (1) = 'i') or else
1089 (Name_Buffer (1) = 's'))
1091 Name_Buffer (2) := '.';
1092 Name_Buffer (3 .. Name_Len - 1) := Name_Buffer (4 .. Name_Len);
1093 Name_Len := Name_Len - 1;
1096 Real_Name := Name_Find;
1098 if Is_Reserved (Real_Name) then
1102 First := The_Name'First;
1104 for Index in The_Name'Range loop
1107 -- We need a letter (at the beginning, and following a dot),
1108 -- but we don't have one.
1110 if Is_Letter (The_Name (Index)) then
1111 Need_Letter := False;
1116 if Current_Verbosity = High then
1117 Write_Int (Types.Int (Index));
1119 Write_Char (The_Name (Index));
1120 Write_Line ("' is not a letter.");
1126 elsif Last_Underscore
1127 and then (The_Name (Index) = '_' or else The_Name (Index) = '.')
1129 -- Two underscores are illegal, and a dot cannot follow
1134 if Current_Verbosity = High then
1135 Write_Int (Types.Int (Index));
1137 Write_Char (The_Name (Index));
1138 Write_Line ("' is illegal here.");
1143 elsif The_Name (Index) = '.' then
1145 -- First, check if the name before the dot is not a reserved word
1146 if Is_Reserved (The_Name (First .. Index - 1)) then
1152 -- We need a letter after a dot
1154 Need_Letter := True;
1156 elsif The_Name (Index) = '_' then
1157 Last_Underscore := True;
1160 -- We need an letter or a digit
1162 Last_Underscore := False;
1164 if not Is_Alphanumeric (The_Name (Index)) then
1167 if Current_Verbosity = High then
1168 Write_Int (Types.Int (Index));
1170 Write_Char (The_Name (Index));
1171 Write_Line ("' is not alphanumeric.");
1179 -- Cannot end with an underscore or a dot
1181 OK := OK and then not Need_Letter and then not Last_Underscore;
1184 if First /= Name'First and then
1185 Is_Reserved (The_Name (First .. The_Name'Last))
1193 -- Signal a problem with No_Name
1199 -------------------------
1200 -- Check_Configuration --
1201 -------------------------
1203 procedure Check_Configuration
1204 (Project : Project_Id;
1205 In_Tree : Project_Tree_Ref;
1206 Compiler_Driver_Mandatory : Boolean)
1208 Dot_Replacement : File_Name_Type := No_File;
1209 Casing : Casing_Type := All_Lower_Case;
1210 Separate_Suffix : File_Name_Type := No_File;
1212 Lang_Index : Language_Ptr := No_Language_Index;
1213 -- The index of the language data being checked
1215 Prev_Index : Language_Ptr := No_Language_Index;
1216 -- The index of the previous language
1218 procedure Process_Project_Level_Simple_Attributes;
1219 -- Process the simple attributes at the project level
1221 procedure Process_Project_Level_Array_Attributes;
1222 -- Process the associate array attributes at the project level
1224 procedure Process_Packages;
1225 -- Read the packages of the project
1227 ----------------------
1228 -- Process_Packages --
1229 ----------------------
1231 procedure Process_Packages is
1232 Packages : Package_Id;
1233 Element : Package_Element;
1235 procedure Process_Binder (Arrays : Array_Id);
1236 -- Process the associate array attributes of package Binder
1238 procedure Process_Builder (Attributes : Variable_Id);
1239 -- Process the simple attributes of package Builder
1241 procedure Process_Compiler (Arrays : Array_Id);
1242 -- Process the associate array attributes of package Compiler
1244 procedure Process_Naming (Attributes : Variable_Id);
1245 -- Process the simple attributes of package Naming
1247 procedure Process_Naming (Arrays : Array_Id);
1248 -- Process the associate array attributes of package Naming
1250 procedure Process_Linker (Attributes : Variable_Id);
1251 -- Process the simple attributes of package Linker of a
1252 -- configuration project.
1254 --------------------
1255 -- Process_Binder --
1256 --------------------
1258 procedure Process_Binder (Arrays : Array_Id) is
1259 Current_Array_Id : Array_Id;
1260 Current_Array : Array_Data;
1261 Element_Id : Array_Element_Id;
1262 Element : Array_Element;
1265 -- Process the associative array attribute of package Binder
1267 Current_Array_Id := Arrays;
1268 while Current_Array_Id /= No_Array loop
1269 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1271 Element_Id := Current_Array.Value;
1272 while Element_Id /= No_Array_Element loop
1273 Element := In_Tree.Array_Elements.Table (Element_Id);
1275 if Element.Index /= All_Other_Names then
1277 -- Get the name of the language
1280 Get_Language_From_Name
1281 (Project, Get_Name_String (Element.Index));
1283 if Lang_Index /= No_Language_Index then
1284 case Current_Array.Name is
1287 -- Attribute Driver (<language>)
1289 Lang_Index.Config.Binder_Driver :=
1290 File_Name_Type (Element.Value.Value);
1292 when Name_Required_Switches =>
1295 Lang_Index.Config.Binder_Required_Switches,
1296 From_List => Element.Value.Values,
1297 In_Tree => In_Tree);
1301 -- Attribute Prefix (<language>)
1303 Lang_Index.Config.Binder_Prefix :=
1304 Element.Value.Value;
1306 when Name_Objects_Path =>
1308 -- Attribute Objects_Path (<language>)
1310 Lang_Index.Config.Objects_Path :=
1311 Element.Value.Value;
1313 when Name_Objects_Path_File =>
1315 -- Attribute Objects_Path (<language>)
1317 Lang_Index.Config.Objects_Path_File :=
1318 Element.Value.Value;
1326 Element_Id := Element.Next;
1329 Current_Array_Id := Current_Array.Next;
1333 ---------------------
1334 -- Process_Builder --
1335 ---------------------
1337 procedure Process_Builder (Attributes : Variable_Id) is
1338 Attribute_Id : Variable_Id;
1339 Attribute : Variable;
1342 -- Process non associated array attribute from package Builder
1344 Attribute_Id := Attributes;
1345 while Attribute_Id /= No_Variable loop
1347 In_Tree.Variable_Elements.Table (Attribute_Id);
1349 if not Attribute.Value.Default then
1350 if Attribute.Name = Name_Executable_Suffix then
1352 -- Attribute Executable_Suffix: the suffix of the
1355 Project.Config.Executable_Suffix :=
1356 Attribute.Value.Value;
1360 Attribute_Id := Attribute.Next;
1362 end Process_Builder;
1364 ----------------------
1365 -- Process_Compiler --
1366 ----------------------
1368 procedure Process_Compiler (Arrays : Array_Id) is
1369 Current_Array_Id : Array_Id;
1370 Current_Array : Array_Data;
1371 Element_Id : Array_Element_Id;
1372 Element : Array_Element;
1373 List : String_List_Id;
1376 -- Process the associative array attribute of package Compiler
1378 Current_Array_Id := Arrays;
1379 while Current_Array_Id /= No_Array loop
1380 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1382 Element_Id := Current_Array.Value;
1383 while Element_Id /= No_Array_Element loop
1384 Element := In_Tree.Array_Elements.Table (Element_Id);
1386 if Element.Index /= All_Other_Names then
1388 -- Get the name of the language
1390 Lang_Index := Get_Language_From_Name
1391 (Project, Get_Name_String (Element.Index));
1393 if Lang_Index /= No_Language_Index then
1394 case Current_Array.Name is
1395 when Name_Dependency_Switches =>
1397 -- Attribute Dependency_Switches (<language>)
1399 if Lang_Index.Config.Dependency_Kind = None then
1400 Lang_Index.Config.Dependency_Kind := Makefile;
1403 List := Element.Value.Values;
1405 if List /= Nil_String then
1407 Lang_Index.Config.Dependency_Option,
1409 In_Tree => In_Tree);
1412 when Name_Dependency_Driver =>
1414 -- Attribute Dependency_Driver (<language>)
1416 if Lang_Index.Config.Dependency_Kind = None then
1417 Lang_Index.Config.Dependency_Kind := Makefile;
1420 List := Element.Value.Values;
1422 if List /= Nil_String then
1424 Lang_Index.Config.Compute_Dependency,
1426 In_Tree => In_Tree);
1429 when Name_Include_Switches =>
1431 -- Attribute Include_Switches (<language>)
1433 List := Element.Value.Values;
1435 if List = Nil_String then
1439 "include option cannot be null",
1440 Element.Value.Location);
1444 Lang_Index.Config.Include_Option,
1446 In_Tree => In_Tree);
1448 when Name_Include_Path =>
1450 -- Attribute Include_Path (<language>)
1452 Lang_Index.Config.Include_Path :=
1453 Element.Value.Value;
1455 when Name_Include_Path_File =>
1457 -- Attribute Include_Path_File (<language>)
1459 Lang_Index.Config.Include_Path_File :=
1460 Element.Value.Value;
1464 -- Attribute Driver (<language>)
1466 Lang_Index.Config.Compiler_Driver :=
1467 File_Name_Type (Element.Value.Value);
1469 when Name_Required_Switches |
1470 Name_Leading_Required_Switches =>
1473 Compiler_Leading_Required_Switches,
1474 From_List => Element.Value.Values,
1475 In_Tree => In_Tree);
1477 when Name_Trailing_Required_Switches =>
1480 Compiler_Trailing_Required_Switches,
1481 From_List => Element.Value.Values,
1482 In_Tree => In_Tree);
1484 when Name_Path_Syntax =>
1486 Lang_Index.Config.Path_Syntax :=
1487 Path_Syntax_Kind'Value
1488 (Get_Name_String (Element.Value.Value));
1491 when Constraint_Error =>
1495 "invalid value for Path_Syntax",
1496 Element.Value.Location);
1499 when Name_Object_File_Suffix =>
1500 if Get_Name_String (Element.Value.Value) = "" then
1503 "object file suffix cannot be empty",
1504 Element.Value.Location);
1507 Lang_Index.Config.Object_File_Suffix :=
1508 Element.Value.Value;
1511 when Name_Object_File_Switches =>
1513 Lang_Index.Config.Object_File_Switches,
1514 From_List => Element.Value.Values,
1515 In_Tree => In_Tree);
1517 when Name_Pic_Option =>
1519 -- Attribute Compiler_Pic_Option (<language>)
1521 List := Element.Value.Values;
1523 if List = Nil_String then
1527 "compiler PIC option cannot be null",
1528 Element.Value.Location);
1532 Lang_Index.Config.Compilation_PIC_Option,
1534 In_Tree => In_Tree);
1536 when Name_Mapping_File_Switches =>
1538 -- Attribute Mapping_File_Switches (<language>)
1540 List := Element.Value.Values;
1542 if List = Nil_String then
1546 "mapping file switches cannot be null",
1547 Element.Value.Location);
1551 Lang_Index.Config.Mapping_File_Switches,
1553 In_Tree => In_Tree);
1555 when Name_Mapping_Spec_Suffix =>
1557 -- Attribute Mapping_Spec_Suffix (<language>)
1559 Lang_Index.Config.Mapping_Spec_Suffix :=
1560 File_Name_Type (Element.Value.Value);
1562 when Name_Mapping_Body_Suffix =>
1564 -- Attribute Mapping_Body_Suffix (<language>)
1566 Lang_Index.Config.Mapping_Body_Suffix :=
1567 File_Name_Type (Element.Value.Value);
1569 when Name_Config_File_Switches =>
1571 -- Attribute Config_File_Switches (<language>)
1573 List := Element.Value.Values;
1575 if List = Nil_String then
1579 "config file switches cannot be null",
1580 Element.Value.Location);
1584 Lang_Index.Config.Config_File_Switches,
1586 In_Tree => In_Tree);
1588 when Name_Objects_Path =>
1590 -- Attribute Objects_Path (<language>)
1592 Lang_Index.Config.Objects_Path :=
1593 Element.Value.Value;
1595 when Name_Objects_Path_File =>
1597 -- Attribute Objects_Path_File (<language>)
1599 Lang_Index.Config.Objects_Path_File :=
1600 Element.Value.Value;
1602 when Name_Config_Body_File_Name =>
1604 -- Attribute Config_Body_File_Name (<language>)
1606 Lang_Index.Config.Config_Body :=
1607 Element.Value.Value;
1609 when Name_Config_Body_File_Name_Pattern =>
1611 -- Attribute Config_Body_File_Name_Pattern
1614 Lang_Index.Config.Config_Body_Pattern :=
1615 Element.Value.Value;
1617 when Name_Config_Spec_File_Name =>
1619 -- Attribute Config_Spec_File_Name (<language>)
1621 Lang_Index.Config.Config_Spec :=
1622 Element.Value.Value;
1624 when Name_Config_Spec_File_Name_Pattern =>
1626 -- Attribute Config_Spec_File_Name_Pattern
1629 Lang_Index.Config.Config_Spec_Pattern :=
1630 Element.Value.Value;
1632 when Name_Config_File_Unique =>
1634 -- Attribute Config_File_Unique (<language>)
1637 Lang_Index.Config.Config_File_Unique :=
1639 (Get_Name_String (Element.Value.Value));
1641 when Constraint_Error =>
1645 "illegal value for Config_File_Unique",
1646 Element.Value.Location);
1655 Element_Id := Element.Next;
1658 Current_Array_Id := Current_Array.Next;
1660 end Process_Compiler;
1662 --------------------
1663 -- Process_Naming --
1664 --------------------
1666 procedure Process_Naming (Attributes : Variable_Id) is
1667 Attribute_Id : Variable_Id;
1668 Attribute : Variable;
1671 -- Process non associated array attribute from package Naming
1673 Attribute_Id := Attributes;
1674 while Attribute_Id /= No_Variable loop
1675 Attribute := In_Tree.Variable_Elements.Table (Attribute_Id);
1677 if not Attribute.Value.Default then
1678 if Attribute.Name = Name_Separate_Suffix then
1680 -- Attribute Separate_Suffix
1682 Separate_Suffix := File_Name_Type (Attribute.Value.Value);
1684 elsif Attribute.Name = Name_Casing then
1690 Value (Get_Name_String (Attribute.Value.Value));
1693 when Constraint_Error =>
1697 "invalid value for Casing",
1698 Attribute.Value.Location);
1701 elsif Attribute.Name = Name_Dot_Replacement then
1703 -- Attribute Dot_Replacement
1705 Dot_Replacement := File_Name_Type (Attribute.Value.Value);
1710 Attribute_Id := Attribute.Next;
1714 procedure Process_Naming (Arrays : Array_Id) is
1715 Current_Array_Id : Array_Id;
1716 Current_Array : Array_Data;
1717 Element_Id : Array_Element_Id;
1718 Element : Array_Element;
1720 -- Process the associative array attribute of package Naming
1722 Current_Array_Id := Arrays;
1723 while Current_Array_Id /= No_Array loop
1724 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
1726 Element_Id := Current_Array.Value;
1727 while Element_Id /= No_Array_Element loop
1728 Element := In_Tree.Array_Elements.Table (Element_Id);
1730 -- Get the name of the language
1732 Lang_Index := Get_Language_From_Name
1733 (Project, Get_Name_String (Element.Index));
1735 if Lang_Index /= No_Language_Index then
1736 case Current_Array.Name is
1737 when Name_Spec_Suffix | Name_Specification_Suffix =>
1739 -- Attribute Spec_Suffix (<language>)
1741 Lang_Index.Config.Naming_Data.Spec_Suffix :=
1742 File_Name_Type (Element.Value.Value);
1744 when Name_Implementation_Suffix | Name_Body_Suffix =>
1746 -- Attribute Body_Suffix (<language>)
1748 Lang_Index.Config.Naming_Data.Body_Suffix :=
1749 File_Name_Type (Element.Value.Value);
1751 Lang_Index.Config.Naming_Data.Separate_Suffix :=
1752 File_Name_Type (Element.Value.Value);
1759 Element_Id := Element.Next;
1762 Current_Array_Id := Current_Array.Next;
1766 --------------------
1767 -- Process_Linker --
1768 --------------------
1770 procedure Process_Linker (Attributes : Variable_Id) is
1771 Attribute_Id : Variable_Id;
1772 Attribute : Variable;
1775 -- Process non associated array attribute from package Linker
1777 Attribute_Id := Attributes;
1778 while Attribute_Id /= No_Variable loop
1780 In_Tree.Variable_Elements.Table (Attribute_Id);
1782 if not Attribute.Value.Default then
1783 if Attribute.Name = Name_Driver then
1785 -- Attribute Linker'Driver: the default linker to use
1787 Project.Config.Linker :=
1788 Path_Name_Type (Attribute.Value.Value);
1790 -- Linker'Driver is also used to link shared libraries
1791 -- if the obsolescent attribute Library_GCC has not been
1794 if Project.Config.Shared_Lib_Driver = No_File then
1795 Project.Config.Shared_Lib_Driver :=
1796 File_Name_Type (Attribute.Value.Value);
1799 elsif Attribute.Name = Name_Required_Switches then
1801 -- Attribute Required_Switches: the minimum
1802 -- options to use when invoking the linker
1804 Put (Into_List => Project.Config.Minimum_Linker_Options,
1805 From_List => Attribute.Value.Values,
1806 In_Tree => In_Tree);
1808 elsif Attribute.Name = Name_Map_File_Option then
1809 Project.Config.Map_File_Option := Attribute.Value.Value;
1811 elsif Attribute.Name = Name_Max_Command_Line_Length then
1813 Project.Config.Max_Command_Line_Length :=
1814 Natural'Value (Get_Name_String
1815 (Attribute.Value.Value));
1818 when Constraint_Error =>
1822 "value must be positive or equal to 0",
1823 Attribute.Value.Location);
1826 elsif Attribute.Name = Name_Response_File_Format then
1831 Get_Name_String (Attribute.Value.Value);
1832 To_Lower (Name_Buffer (1 .. Name_Len));
1835 if Name = Name_None then
1836 Project.Config.Resp_File_Format := None;
1838 elsif Name = Name_Gnu then
1839 Project.Config.Resp_File_Format := GNU;
1841 elsif Name = Name_Object_List then
1842 Project.Config.Resp_File_Format := Object_List;
1844 elsif Name = Name_Option_List then
1845 Project.Config.Resp_File_Format := Option_List;
1851 "illegal response file format",
1852 Attribute.Value.Location);
1856 elsif Attribute.Name = Name_Response_File_Switches then
1857 Put (Into_List => Project.Config.Resp_File_Options,
1858 From_List => Attribute.Value.Values,
1859 In_Tree => In_Tree);
1863 Attribute_Id := Attribute.Next;
1867 -- Start of processing for Process_Packages
1870 Packages := Project.Decl.Packages;
1871 while Packages /= No_Package loop
1872 Element := In_Tree.Packages.Table (Packages);
1874 case Element.Name is
1877 -- Process attributes of package Binder
1879 Process_Binder (Element.Decl.Arrays);
1881 when Name_Builder =>
1883 -- Process attributes of package Builder
1885 Process_Builder (Element.Decl.Attributes);
1887 when Name_Compiler =>
1889 -- Process attributes of package Compiler
1891 Process_Compiler (Element.Decl.Arrays);
1895 -- Process attributes of package Linker
1897 Process_Linker (Element.Decl.Attributes);
1901 -- Process attributes of package Naming
1903 Process_Naming (Element.Decl.Attributes);
1904 Process_Naming (Element.Decl.Arrays);
1910 Packages := Element.Next;
1912 end Process_Packages;
1914 ---------------------------------------------
1915 -- Process_Project_Level_Simple_Attributes --
1916 ---------------------------------------------
1918 procedure Process_Project_Level_Simple_Attributes is
1919 Attribute_Id : Variable_Id;
1920 Attribute : Variable;
1921 List : String_List_Id;
1924 -- Process non associated array attribute at project level
1926 Attribute_Id := Project.Decl.Attributes;
1927 while Attribute_Id /= No_Variable loop
1929 In_Tree.Variable_Elements.Table (Attribute_Id);
1931 if not Attribute.Value.Default then
1932 if Attribute.Name = Name_Target then
1934 -- Attribute Target: the target specified
1936 Project.Config.Target := Attribute.Value.Value;
1938 elsif Attribute.Name = Name_Library_Builder then
1940 -- Attribute Library_Builder: the application to invoke
1941 -- to build libraries.
1943 Project.Config.Library_Builder :=
1944 Path_Name_Type (Attribute.Value.Value);
1946 elsif Attribute.Name = Name_Archive_Builder then
1948 -- Attribute Archive_Builder: the archive builder
1949 -- (usually "ar") and its minimum options (usually "cr").
1951 List := Attribute.Value.Values;
1953 if List = Nil_String then
1957 "archive builder cannot be null",
1958 Attribute.Value.Location);
1961 Put (Into_List => Project.Config.Archive_Builder,
1963 In_Tree => In_Tree);
1965 elsif Attribute.Name = Name_Archive_Builder_Append_Option then
1967 -- Attribute Archive_Builder: the archive builder
1968 -- (usually "ar") and its minimum options (usually "cr").
1970 List := Attribute.Value.Values;
1972 if List /= Nil_String then
1975 Project.Config.Archive_Builder_Append_Option,
1977 In_Tree => In_Tree);
1980 elsif Attribute.Name = Name_Archive_Indexer then
1982 -- Attribute Archive_Indexer: the optional archive
1983 -- indexer (usually "ranlib") with its minimum options
1986 List := Attribute.Value.Values;
1988 if List = Nil_String then
1992 "archive indexer cannot be null",
1993 Attribute.Value.Location);
1996 Put (Into_List => Project.Config.Archive_Indexer,
1998 In_Tree => In_Tree);
2000 elsif Attribute.Name = Name_Library_Partial_Linker then
2002 -- Attribute Library_Partial_Linker: the optional linker
2003 -- driver with its minimum options, to partially link
2006 List := Attribute.Value.Values;
2008 if List = Nil_String then
2012 "partial linker cannot be null",
2013 Attribute.Value.Location);
2016 Put (Into_List => Project.Config.Lib_Partial_Linker,
2018 In_Tree => In_Tree);
2020 elsif Attribute.Name = Name_Library_GCC then
2021 Project.Config.Shared_Lib_Driver :=
2022 File_Name_Type (Attribute.Value.Value);
2026 "?Library_'G'C'C is an obsolescent attribute, " &
2027 "use Linker''Driver instead",
2028 Attribute.Value.Location);
2030 elsif Attribute.Name = Name_Archive_Suffix then
2031 Project.Config.Archive_Suffix :=
2032 File_Name_Type (Attribute.Value.Value);
2034 elsif Attribute.Name = Name_Linker_Executable_Option then
2036 -- Attribute Linker_Executable_Option: optional options
2037 -- to specify an executable name. Defaults to "-o".
2039 List := Attribute.Value.Values;
2041 if List = Nil_String then
2045 "linker executable option cannot be null",
2046 Attribute.Value.Location);
2049 Put (Into_List => Project.Config.Linker_Executable_Option,
2051 In_Tree => In_Tree);
2053 elsif Attribute.Name = Name_Linker_Lib_Dir_Option then
2055 -- Attribute Linker_Lib_Dir_Option: optional options
2056 -- to specify a library search directory. Defaults to
2059 Get_Name_String (Attribute.Value.Value);
2061 if Name_Len = 0 then
2065 "linker library directory option cannot be empty",
2066 Attribute.Value.Location);
2069 Project.Config.Linker_Lib_Dir_Option :=
2070 Attribute.Value.Value;
2072 elsif Attribute.Name = Name_Linker_Lib_Name_Option then
2074 -- Attribute Linker_Lib_Name_Option: optional options
2075 -- to specify the name of a library to be linked in.
2076 -- Defaults to "-l".
2078 Get_Name_String (Attribute.Value.Value);
2080 if Name_Len = 0 then
2084 "linker library name option cannot be empty",
2085 Attribute.Value.Location);
2088 Project.Config.Linker_Lib_Name_Option :=
2089 Attribute.Value.Value;
2091 elsif Attribute.Name = Name_Run_Path_Option then
2093 -- Attribute Run_Path_Option: optional options to
2094 -- specify a path for libraries.
2096 List := Attribute.Value.Values;
2098 if List /= Nil_String then
2099 Put (Into_List => Project.Config.Run_Path_Option,
2101 In_Tree => In_Tree);
2104 elsif Attribute.Name = Name_Separate_Run_Path_Options then
2106 pragma Unsuppress (All_Checks);
2108 Project.Config.Separate_Run_Path_Options :=
2109 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2111 when Constraint_Error =>
2115 "invalid value """ &
2116 Get_Name_String (Attribute.Value.Value) &
2117 """ for Separate_Run_Path_Options",
2118 Attribute.Value.Location);
2121 elsif Attribute.Name = Name_Library_Support then
2123 pragma Unsuppress (All_Checks);
2125 Project.Config.Lib_Support :=
2126 Library_Support'Value (Get_Name_String
2127 (Attribute.Value.Value));
2129 when Constraint_Error =>
2133 "invalid value """ &
2134 Get_Name_String (Attribute.Value.Value) &
2135 """ for Library_Support",
2136 Attribute.Value.Location);
2139 elsif Attribute.Name = Name_Shared_Library_Prefix then
2140 Project.Config.Shared_Lib_Prefix :=
2141 File_Name_Type (Attribute.Value.Value);
2143 elsif Attribute.Name = Name_Shared_Library_Suffix then
2144 Project.Config.Shared_Lib_Suffix :=
2145 File_Name_Type (Attribute.Value.Value);
2147 elsif Attribute.Name = Name_Symbolic_Link_Supported then
2149 pragma Unsuppress (All_Checks);
2151 Project.Config.Symbolic_Link_Supported :=
2152 Boolean'Value (Get_Name_String
2153 (Attribute.Value.Value));
2155 when Constraint_Error =>
2160 & Get_Name_String (Attribute.Value.Value)
2161 & """ for Symbolic_Link_Supported",
2162 Attribute.Value.Location);
2166 Attribute.Name = Name_Library_Major_Minor_Id_Supported
2169 pragma Unsuppress (All_Checks);
2171 Project.Config.Lib_Maj_Min_Id_Supported :=
2172 Boolean'Value (Get_Name_String
2173 (Attribute.Value.Value));
2175 when Constraint_Error =>
2179 "invalid value """ &
2180 Get_Name_String (Attribute.Value.Value) &
2181 """ for Library_Major_Minor_Id_Supported",
2182 Attribute.Value.Location);
2185 elsif Attribute.Name = Name_Library_Auto_Init_Supported then
2187 pragma Unsuppress (All_Checks);
2189 Project.Config.Auto_Init_Supported :=
2190 Boolean'Value (Get_Name_String (Attribute.Value.Value));
2192 when Constraint_Error =>
2197 & Get_Name_String (Attribute.Value.Value)
2198 & """ for Library_Auto_Init_Supported",
2199 Attribute.Value.Location);
2202 elsif Attribute.Name = Name_Shared_Library_Minimum_Switches then
2203 List := Attribute.Value.Values;
2205 if List /= Nil_String then
2206 Put (Into_List => Project.Config.Shared_Lib_Min_Options,
2208 In_Tree => In_Tree);
2211 elsif Attribute.Name = Name_Library_Version_Switches then
2212 List := Attribute.Value.Values;
2214 if List /= Nil_String then
2215 Put (Into_List => Project.Config.Lib_Version_Options,
2217 In_Tree => In_Tree);
2222 Attribute_Id := Attribute.Next;
2224 end Process_Project_Level_Simple_Attributes;
2226 --------------------------------------------
2227 -- Process_Project_Level_Array_Attributes --
2228 --------------------------------------------
2230 procedure Process_Project_Level_Array_Attributes is
2231 Current_Array_Id : Array_Id;
2232 Current_Array : Array_Data;
2233 Element_Id : Array_Element_Id;
2234 Element : Array_Element;
2235 List : String_List_Id;
2238 -- Process the associative array attributes at project level
2240 Current_Array_Id := Project.Decl.Arrays;
2241 while Current_Array_Id /= No_Array loop
2242 Current_Array := In_Tree.Arrays.Table (Current_Array_Id);
2244 Element_Id := Current_Array.Value;
2245 while Element_Id /= No_Array_Element loop
2246 Element := In_Tree.Array_Elements.Table (Element_Id);
2248 -- Get the name of the language
2251 Get_Language_From_Name
2252 (Project, Get_Name_String (Element.Index));
2254 if Lang_Index /= No_Language_Index then
2255 case Current_Array.Name is
2256 when Name_Inherit_Source_Path =>
2257 List := Element.Value.Values;
2259 if List /= Nil_String then
2262 Lang_Index.Config.Include_Compatible_Languages,
2265 Lower_Case => True);
2268 when Name_Toolchain_Description =>
2270 -- Attribute Toolchain_Description (<language>)
2272 Lang_Index.Config.Toolchain_Description :=
2273 Element.Value.Value;
2275 when Name_Toolchain_Version =>
2277 -- Attribute Toolchain_Version (<language>)
2279 Lang_Index.Config.Toolchain_Version :=
2280 Element.Value.Value;
2282 when Name_Runtime_Library_Dir =>
2284 -- Attribute Runtime_Library_Dir (<language>)
2286 Lang_Index.Config.Runtime_Library_Dir :=
2287 Element.Value.Value;
2289 when Name_Runtime_Source_Dir =>
2291 -- Attribute Runtime_Library_Dir (<language>)
2293 Lang_Index.Config.Runtime_Source_Dir :=
2294 Element.Value.Value;
2296 when Name_Object_Generated =>
2298 pragma Unsuppress (All_Checks);
2304 (Get_Name_String (Element.Value.Value));
2306 Lang_Index.Config.Object_Generated := Value;
2308 -- If no object is generated, no object may be
2312 Lang_Index.Config.Objects_Linked := False;
2316 when Constraint_Error =>
2321 & Get_Name_String (Element.Value.Value)
2322 & """ for Object_Generated",
2323 Element.Value.Location);
2326 when Name_Objects_Linked =>
2328 pragma Unsuppress (All_Checks);
2334 (Get_Name_String (Element.Value.Value));
2336 -- No change if Object_Generated is False, as this
2337 -- forces Objects_Linked to be False too.
2339 if Lang_Index.Config.Object_Generated then
2340 Lang_Index.Config.Objects_Linked := Value;
2344 when Constraint_Error =>
2349 & Get_Name_String (Element.Value.Value)
2350 & """ for Objects_Linked",
2351 Element.Value.Location);
2358 Element_Id := Element.Next;
2361 Current_Array_Id := Current_Array.Next;
2363 end Process_Project_Level_Array_Attributes;
2366 Process_Project_Level_Simple_Attributes;
2367 Process_Project_Level_Array_Attributes;
2370 -- For unit based languages, set Casing, Dot_Replacement and
2371 -- Separate_Suffix in Naming_Data.
2373 Lang_Index := Project.Languages;
2374 while Lang_Index /= No_Language_Index loop
2375 if Lang_Index.Name = Name_Ada then
2376 Lang_Index.Config.Naming_Data.Casing := Casing;
2377 Lang_Index.Config.Naming_Data.Dot_Replacement := Dot_Replacement;
2379 if Separate_Suffix /= No_File then
2380 Lang_Index.Config.Naming_Data.Separate_Suffix :=
2387 Lang_Index := Lang_Index.Next;
2390 -- Give empty names to various prefixes/suffixes, if they have not
2391 -- been specified in the configuration.
2393 if Project.Config.Archive_Suffix = No_File then
2394 Project.Config.Archive_Suffix := Empty_File;
2397 if Project.Config.Shared_Lib_Prefix = No_File then
2398 Project.Config.Shared_Lib_Prefix := Empty_File;
2401 if Project.Config.Shared_Lib_Suffix = No_File then
2402 Project.Config.Shared_Lib_Suffix := Empty_File;
2405 Lang_Index := Project.Languages;
2406 while Lang_Index /= No_Language_Index loop
2407 -- For all languages, Compiler_Driver needs to be specified. This is
2408 -- only necessary if we do intend to compiler (not in GPS for
2411 if Compiler_Driver_Mandatory
2412 and then Lang_Index.Config.Compiler_Driver = No_File
2414 Error_Msg_Name_1 := Lang_Index.Display_Name;
2418 "?no compiler specified for language %%" &
2419 ", ignoring all its sources",
2422 if Lang_Index = Project.Languages then
2423 Project.Languages := Lang_Index.Next;
2425 Prev_Index.Next := Lang_Index.Next;
2428 elsif Lang_Index.Name = Name_Ada then
2429 Prev_Index := Lang_Index;
2431 -- For unit based languages, Dot_Replacement, Spec_Suffix and
2432 -- Body_Suffix need to be specified.
2434 if Lang_Index.Config.Naming_Data.Dot_Replacement = No_File then
2438 "Dot_Replacement not specified for Ada",
2442 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File then
2446 "Spec_Suffix not specified for Ada",
2450 if Lang_Index.Config.Naming_Data.Body_Suffix = No_File then
2454 "Body_Suffix not specified for Ada",
2459 Prev_Index := Lang_Index;
2461 -- For file based languages, either Spec_Suffix or Body_Suffix
2462 -- need to be specified.
2464 if Lang_Index.Config.Naming_Data.Spec_Suffix = No_File and then
2465 Lang_Index.Config.Naming_Data.Body_Suffix = No_File
2467 Error_Msg_Name_1 := Lang_Index.Display_Name;
2471 "no suffixes specified for %%",
2476 Lang_Index := Lang_Index.Next;
2478 end Check_Configuration;
2480 -------------------------------
2481 -- Check_If_Externally_Built --
2482 -------------------------------
2484 procedure Check_If_Externally_Built
2485 (Project : Project_Id;
2486 In_Tree : Project_Tree_Ref)
2488 Externally_Built : constant Variable_Value :=
2490 (Name_Externally_Built,
2491 Project.Decl.Attributes, In_Tree);
2494 if not Externally_Built.Default then
2495 Get_Name_String (Externally_Built.Value);
2496 To_Lower (Name_Buffer (1 .. Name_Len));
2498 if Name_Buffer (1 .. Name_Len) = "true" then
2499 Project.Externally_Built := True;
2501 elsif Name_Buffer (1 .. Name_Len) /= "false" then
2502 Error_Msg (Project, In_Tree,
2503 "Externally_Built may only be true or false",
2504 Externally_Built.Location);
2508 -- A virtual project extending an externally built project is itself
2509 -- externally built.
2511 if Project.Virtual and then Project.Extends /= No_Project then
2512 Project.Externally_Built := Project.Extends.Externally_Built;
2515 if Current_Verbosity = High then
2516 Write_Str ("Project is ");
2518 if not Project.Externally_Built then
2522 Write_Line ("externally built.");
2524 end Check_If_Externally_Built;
2526 ----------------------
2527 -- Check_Interfaces --
2528 ----------------------
2530 procedure Check_Interfaces
2531 (Project : Project_Id;
2532 In_Tree : Project_Tree_Ref)
2534 Interfaces : constant Prj.Variable_Value :=
2536 (Snames.Name_Interfaces,
2537 Project.Decl.Attributes,
2540 List : String_List_Id;
2541 Element : String_Element;
2542 Name : File_Name_Type;
2543 Iter : Source_Iterator;
2545 Project_2 : Project_Id;
2549 if not Interfaces.Default then
2551 -- Set In_Interfaces to False for all sources. It will be set to True
2552 -- later for the sources in the Interfaces list.
2554 Project_2 := Project;
2555 while Project_2 /= No_Project loop
2556 Iter := For_Each_Source (In_Tree, Project_2);
2559 Source := Prj.Element (Iter);
2560 exit when Source = No_Source;
2561 Source.In_Interfaces := False;
2565 Project_2 := Project_2.Extends;
2568 List := Interfaces.Values;
2569 while List /= Nil_String loop
2570 Element := In_Tree.String_Elements.Table (List);
2571 Name := Canonical_Case_File_Name (Element.Value);
2573 Project_2 := Project;
2575 while Project_2 /= No_Project loop
2576 Iter := For_Each_Source (In_Tree, Project_2);
2579 Source := Prj.Element (Iter);
2580 exit when Source = No_Source;
2582 if Source.File = Name then
2583 if not Source.Locally_Removed then
2584 Source.In_Interfaces := True;
2585 Source.Declared_In_Interfaces := True;
2587 Other := Other_Part (Source);
2589 if Other /= No_Source then
2590 Other.In_Interfaces := True;
2591 Other.Declared_In_Interfaces := True;
2594 if Current_Verbosity = High then
2595 Write_Str (" interface: ");
2596 Write_Line (Get_Name_String (Source.Path.Name));
2606 Project_2 := Project_2.Extends;
2609 if Source = No_Source then
2610 Error_Msg_File_1 := File_Name_Type (Element.Value);
2611 Error_Msg_Name_1 := Project.Name;
2616 "{ cannot be an interface of project %% "
2617 & "as it is not one of its sources",
2621 List := Element.Next;
2624 Project.Interfaces_Defined := True;
2626 elsif Project.Extends /= No_Project then
2627 Project.Interfaces_Defined := Project.Extends.Interfaces_Defined;
2629 if Project.Interfaces_Defined then
2630 Iter := For_Each_Source (In_Tree, Project);
2632 Source := Prj.Element (Iter);
2633 exit when Source = No_Source;
2635 if not Source.Declared_In_Interfaces then
2636 Source.In_Interfaces := False;
2643 end Check_Interfaces;
2645 ------------------------------------
2646 -- Check_And_Normalize_Unit_Names --
2647 ------------------------------------
2649 procedure Check_And_Normalize_Unit_Names
2650 (Project : Project_Id;
2651 In_Tree : Project_Tree_Ref;
2652 List : Array_Element_Id;
2653 Debug_Name : String)
2655 Current : Array_Element_Id;
2656 Element : Array_Element;
2657 Unit_Name : Name_Id;
2660 if Current_Verbosity = High then
2661 Write_Line (" Checking unit names in " & Debug_Name);
2665 while Current /= No_Array_Element loop
2666 Element := In_Tree.Array_Elements.Table (Current);
2667 Element.Value.Value :=
2668 Name_Id (Canonical_Case_File_Name (Element.Value.Value));
2670 -- Check that it contains a valid unit name
2672 Get_Name_String (Element.Index);
2673 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit_Name);
2675 if Unit_Name = No_Name then
2676 Err_Vars.Error_Msg_Name_1 := Element.Index;
2679 "%% is not a valid unit name.",
2680 Element.Value.Location);
2683 if Current_Verbosity = High then
2684 Write_Str (" for unit: ");
2685 Write_Line (Get_Name_String (Unit_Name));
2688 Element.Index := Unit_Name;
2689 In_Tree.Array_Elements.Table (Current) := Element;
2692 Current := Element.Next;
2694 end Check_And_Normalize_Unit_Names;
2696 --------------------------
2697 -- Check_Naming_Schemes --
2698 --------------------------
2700 procedure Check_Naming_Schemes
2701 (Project : Project_Id;
2702 In_Tree : Project_Tree_Ref;
2703 Is_Config_File : Boolean)
2705 Naming_Id : constant Package_Id :=
2706 Util.Value_Of (Name_Naming, Project.Decl.Packages, In_Tree);
2707 Naming : Package_Element;
2709 procedure Check_Naming_Ada_Only;
2710 -- Does Check_Naming_Schemes processing in Ada_Only mode.
2711 -- If there is a package Naming, puts in Data.Naming the contents of
2714 procedure Check_Naming_Multi_Lang;
2715 -- Does Check_Naming_Schemes processing for Multi_Language mode
2717 procedure Check_Common
2718 (Dot_Replacement : in out File_Name_Type;
2719 Casing : in out Casing_Type;
2720 Casing_Defined : out Boolean;
2721 Separate_Suffix : in out File_Name_Type;
2722 Sep_Suffix_Loc : out Source_Ptr);
2723 -- Check attributes common to Ada_Only and Multi_Lang modes
2725 procedure Process_Exceptions_File_Based
2726 (Lang_Id : Language_Ptr;
2727 Kind : Source_Kind);
2728 procedure Process_Exceptions_Unit_Based
2729 (Lang_Id : Language_Ptr;
2730 Kind : Source_Kind);
2731 -- In Multi_Lang mode, process the naming exceptions for the two types
2732 -- of languages we can have.
2738 procedure Check_Common
2739 (Dot_Replacement : in out File_Name_Type;
2740 Casing : in out Casing_Type;
2741 Casing_Defined : out Boolean;
2742 Separate_Suffix : in out File_Name_Type;
2743 Sep_Suffix_Loc : out Source_Ptr)
2745 Dot_Repl : constant Variable_Value :=
2747 (Name_Dot_Replacement,
2748 Naming.Decl.Attributes,
2750 Casing_String : constant Variable_Value :=
2753 Naming.Decl.Attributes,
2755 Sep_Suffix : constant Variable_Value :=
2757 (Name_Separate_Suffix,
2758 Naming.Decl.Attributes,
2760 Dot_Repl_Loc : Source_Ptr;
2763 Sep_Suffix_Loc := No_Location;
2765 if not Dot_Repl.Default then
2767 (Dot_Repl.Kind = Single, "Dot_Replacement is not a string");
2769 if Length_Of_Name (Dot_Repl.Value) = 0 then
2772 "Dot_Replacement cannot be empty",
2776 Dot_Replacement := Canonical_Case_File_Name (Dot_Repl.Value);
2777 Dot_Repl_Loc := Dot_Repl.Location;
2780 Repl : constant String := Get_Name_String (Dot_Replacement);
2783 -- Dot_Replacement cannot
2785 -- - start or end with an alphanumeric
2786 -- - be a single '_'
2787 -- - start with an '_' followed by an alphanumeric
2788 -- - contain a '.' except if it is "."
2791 or else Is_Alphanumeric (Repl (Repl'First))
2792 or else Is_Alphanumeric (Repl (Repl'Last))
2793 or else (Repl (Repl'First) = '_'
2797 Is_Alphanumeric (Repl (Repl'First + 1))))
2798 or else (Repl'Length > 1
2800 Index (Source => Repl, Pattern => ".") /= 0)
2805 """ is illegal for Dot_Replacement.",
2811 if Dot_Replacement /= No_File then
2813 ("Dot_Replacement", Get_Name_String (Dot_Replacement));
2816 Casing_Defined := False;
2818 if not Casing_String.Default then
2820 (Casing_String.Kind = Single, "Casing is not a string");
2823 Casing_Image : constant String :=
2824 Get_Name_String (Casing_String.Value);
2826 if Casing_Image'Length = 0 then
2829 "Casing cannot be an empty string",
2830 Casing_String.Location);
2833 Casing := Value (Casing_Image);
2834 Casing_Defined := True;
2837 when Constraint_Error =>
2838 Name_Len := Casing_Image'Length;
2839 Name_Buffer (1 .. Name_Len) := Casing_Image;
2840 Err_Vars.Error_Msg_Name_1 := Name_Find;
2843 "%% is not a correct Casing",
2844 Casing_String.Location);
2848 Write_Attr ("Casing", Image (Casing));
2850 if not Sep_Suffix.Default then
2851 if Length_Of_Name (Sep_Suffix.Value) = 0 then
2854 "Separate_Suffix cannot be empty",
2855 Sep_Suffix.Location);
2858 Separate_Suffix := Canonical_Case_File_Name (Sep_Suffix.Value);
2859 Sep_Suffix_Loc := Sep_Suffix.Location;
2861 if Is_Illegal_Suffix (Separate_Suffix, Dot_Replacement) then
2862 Err_Vars.Error_Msg_File_1 := Separate_Suffix;
2865 "{ is illegal for Separate_Suffix",
2866 Sep_Suffix.Location);
2871 if Separate_Suffix /= No_File then
2873 ("Separate_Suffix", Get_Name_String (Separate_Suffix));
2877 -----------------------------------
2878 -- Process_Exceptions_File_Based --
2879 -----------------------------------
2881 procedure Process_Exceptions_File_Based
2882 (Lang_Id : Language_Ptr;
2885 Lang : constant Name_Id := Lang_Id.Name;
2886 Exceptions : Array_Element_Id;
2887 Exception_List : Variable_Value;
2888 Element_Id : String_List_Id;
2889 Element : String_Element;
2890 File_Name : File_Name_Type;
2892 Iter : Source_Iterator;
2899 (Name_Implementation_Exceptions,
2900 In_Arrays => Naming.Decl.Arrays,
2901 In_Tree => In_Tree);
2906 (Name_Specification_Exceptions,
2907 In_Arrays => Naming.Decl.Arrays,
2908 In_Tree => In_Tree);
2911 Exception_List := Value_Of
2913 In_Array => Exceptions,
2914 In_Tree => In_Tree);
2916 if Exception_List /= Nil_Variable_Value then
2917 Element_Id := Exception_List.Values;
2918 while Element_Id /= Nil_String loop
2919 Element := In_Tree.String_Elements.Table (Element_Id);
2920 File_Name := Canonical_Case_File_Name (Element.Value);
2922 Iter := For_Each_Source (In_Tree, Project);
2924 Source := Prj.Element (Iter);
2925 exit when Source = No_Source or else Source.File = File_Name;
2929 if Source = No_Source then
2936 File_Name => File_Name,
2937 Display_File => File_Name_Type (Element.Value),
2938 Naming_Exception => True);
2941 -- Check if the file name is already recorded for another
2942 -- language or another kind.
2944 if Source.Language /= Lang_Id then
2948 "the same file cannot be a source of two languages",
2951 elsif Source.Kind /= Kind then
2955 "the same file cannot be a source and a template",
2959 -- If the file is already recorded for the same
2960 -- language and the same kind, it means that the file
2961 -- name appears several times in the *_Exceptions
2962 -- attribute; so there is nothing to do.
2965 Element_Id := Element.Next;
2968 end Process_Exceptions_File_Based;
2970 -----------------------------------
2971 -- Process_Exceptions_Unit_Based --
2972 -----------------------------------
2974 procedure Process_Exceptions_Unit_Based
2975 (Lang_Id : Language_Ptr;
2978 Lang : constant Name_Id := Lang_Id.Name;
2979 Exceptions : Array_Element_Id;
2980 Element : Array_Element;
2983 File_Name : File_Name_Type;
2985 Source_To_Replace : Source_Id := No_Source;
2986 Other_Project : Project_Id;
2987 Iter : Source_Iterator;
2992 Exceptions := Value_Of
2994 In_Arrays => Naming.Decl.Arrays,
2995 In_Tree => In_Tree);
2997 if Exceptions = No_Array_Element then
3000 (Name_Implementation,
3001 In_Arrays => Naming.Decl.Arrays,
3002 In_Tree => In_Tree);
3009 In_Arrays => Naming.Decl.Arrays,
3010 In_Tree => In_Tree);
3012 if Exceptions = No_Array_Element then
3013 Exceptions := Value_Of
3015 In_Arrays => Naming.Decl.Arrays,
3016 In_Tree => In_Tree);
3020 while Exceptions /= No_Array_Element loop
3021 Element := In_Tree.Array_Elements.Table (Exceptions);
3022 File_Name := Canonical_Case_File_Name (Element.Value.Value);
3024 Get_Name_String (Element.Index);
3025 To_Lower (Name_Buffer (1 .. Name_Len));
3027 Index := Element.Value.Index;
3029 -- For Ada, check if it is a valid unit name
3031 if Lang = Name_Ada then
3032 Get_Name_String (Element.Index);
3033 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
3035 if Unit = No_Name then
3036 Err_Vars.Error_Msg_Name_1 := Element.Index;
3039 "%% is not a valid unit name.",
3040 Element.Value.Location);
3044 if Unit /= No_Name then
3046 -- Check if the source already exists
3047 -- ??? In Ada_Only mode (Record_Unit), we use a htable for
3050 Source_To_Replace := No_Source;
3051 Iter := For_Each_Source (In_Tree);
3054 Source := Prj.Element (Iter);
3055 exit when Source = No_Source
3056 or else (Source.Unit /= null
3057 and then Source.Unit.Name = Unit
3058 and then Source.Index = Index);
3062 if Source /= No_Source then
3063 if Source.Kind /= Kind then
3066 Source := Prj.Element (Iter);
3068 exit when Source = No_Source
3069 or else (Source.Unit /= null
3070 and then Source.Unit.Name = Unit
3071 and then Source.Index = Index);
3075 if Source /= No_Source then
3076 Other_Project := Source.Project;
3078 if Is_Extending (Project, Other_Project) then
3079 Source_To_Replace := Source;
3080 Source := No_Source;
3083 Error_Msg_Name_1 := Unit;
3084 Error_Msg_Name_2 := Other_Project.Name;
3088 "%% is already a source of project %%",
3089 Element.Value.Location);
3094 if Source = No_Source then
3101 File_Name => File_Name,
3102 Display_File => File_Name_Type (Element.Value.Value),
3105 Naming_Exception => True,
3106 Source_To_Replace => Source_To_Replace);
3110 Exceptions := Element.Next;
3112 end Process_Exceptions_Unit_Based;
3114 ---------------------------
3115 -- Check_Naming_Ada_Only --
3116 ---------------------------
3118 procedure Check_Naming_Ada_Only is
3119 Casing_Defined : Boolean;
3120 Spec_Suffix : File_Name_Type;
3121 Body_Suffix : File_Name_Type;
3122 Sep_Suffix_Loc : Source_Ptr;
3124 Ada_Spec_Suffix : constant Variable_Value :=
3128 In_Array => Project.Naming.Spec_Suffix,
3129 In_Tree => In_Tree);
3131 Ada_Body_Suffix : constant Variable_Value :=
3135 In_Array => Project.Naming.Body_Suffix,
3136 In_Tree => In_Tree);
3139 -- The default value of separate suffix should be the same as the
3140 -- body suffix, so we need to compute that first.
3142 if Ada_Body_Suffix.Kind = Single
3143 and then Length_Of_Name (Ada_Body_Suffix.Value) /= 0
3145 Body_Suffix := Canonical_Case_File_Name (Ada_Body_Suffix.Value);
3146 Project.Naming.Separate_Suffix := Body_Suffix;
3147 Set_Body_Suffix (In_Tree, "ada", Project.Naming, Body_Suffix);
3150 Body_Suffix := Default_Ada_Body_Suffix;
3151 Project.Naming.Separate_Suffix := Body_Suffix;
3152 Set_Body_Suffix (In_Tree, "ada", Project.Naming, Body_Suffix);
3155 Write_Attr ("Body_Suffix", Get_Name_String (Body_Suffix));
3157 -- We'll need the dot replacement below, so compute it now
3160 (Dot_Replacement => Project.Naming.Dot_Replacement,
3161 Casing => Project.Naming.Casing,
3162 Casing_Defined => Casing_Defined,
3163 Separate_Suffix => Project.Naming.Separate_Suffix,
3164 Sep_Suffix_Loc => Sep_Suffix_Loc);
3166 Project.Naming.Bodies :=
3167 Util.Value_Of (Name_Body, Naming.Decl.Arrays, In_Tree);
3169 if Project.Naming.Bodies /= No_Array_Element then
3170 Check_And_Normalize_Unit_Names
3171 (Project, In_Tree, Project.Naming.Bodies, "Naming.Bodies");
3174 Project.Naming.Specs :=
3175 Util.Value_Of (Name_Spec, Naming.Decl.Arrays, In_Tree);
3177 if Project.Naming.Specs /= No_Array_Element then
3178 Check_And_Normalize_Unit_Names
3179 (Project, In_Tree, Project.Naming.Specs, "Naming.Specs");
3182 -- Check Spec_Suffix
3184 if Ada_Spec_Suffix.Kind = Single
3185 and then Length_Of_Name (Ada_Spec_Suffix.Value) /= 0
3187 Spec_Suffix := Canonical_Case_File_Name (Ada_Spec_Suffix.Value);
3188 Set_Spec_Suffix (In_Tree, "ada", Project.Naming, Spec_Suffix);
3190 if Is_Illegal_Suffix
3191 (Spec_Suffix, Project.Naming.Dot_Replacement)
3193 Err_Vars.Error_Msg_File_1 := Spec_Suffix;
3196 "{ is illegal for Spec_Suffix",
3197 Ada_Spec_Suffix.Location);
3201 Spec_Suffix := Default_Ada_Spec_Suffix;
3202 Set_Spec_Suffix (In_Tree, "ada", Project.Naming, Spec_Suffix);
3205 Write_Attr ("Spec_Suffix", Get_Name_String (Spec_Suffix));
3207 -- Check Body_Suffix
3209 if Is_Illegal_Suffix
3210 (Body_Suffix, Project.Naming.Dot_Replacement)
3212 Err_Vars.Error_Msg_File_1 := Body_Suffix;
3215 "{ is illegal for Body_Suffix",
3216 Ada_Body_Suffix.Location);
3219 -- Spec_Suffix cannot be equal to Body_Suffix or Separate_Suffix,
3220 -- since that would cause a clear ambiguity. Note that we do allow a
3221 -- Spec_Suffix to have the same termination as one of these, which
3222 -- causes a potential ambiguity, but we resolve that my matching the
3223 -- longest possible suffix.
3225 if Spec_Suffix = Body_Suffix then
3229 Get_Name_String (Body_Suffix) &
3230 """) cannot be the same as Spec_Suffix.",
3231 Ada_Body_Suffix.Location);
3234 if Body_Suffix /= Project.Naming.Separate_Suffix
3235 and then Spec_Suffix = Project.Naming.Separate_Suffix
3239 "Separate_Suffix (""" &
3240 Get_Name_String (Project.Naming.Separate_Suffix) &
3241 """) cannot be the same as Spec_Suffix.",
3244 end Check_Naming_Ada_Only;
3246 -----------------------------
3247 -- Check_Naming_Multi_Lang --
3248 -----------------------------
3250 procedure Check_Naming_Multi_Lang is
3251 Dot_Replacement : File_Name_Type := No_File;
3252 Separate_Suffix : File_Name_Type := No_File;
3253 Casing : Casing_Type := All_Lower_Case;
3254 Casing_Defined : Boolean;
3255 Lang_Id : Language_Ptr;
3256 Sep_Suffix_Loc : Source_Ptr;
3257 Suffix : Variable_Value;
3262 (Dot_Replacement => Dot_Replacement,
3264 Casing_Defined => Casing_Defined,
3265 Separate_Suffix => Separate_Suffix,
3266 Sep_Suffix_Loc => Sep_Suffix_Loc);
3268 -- For all unit based languages, if any, set the specified
3269 -- value of Dot_Replacement, Casing and/or Separate_Suffix. Do not
3270 -- systematically overwrite, since the defaults come from the
3271 -- configuration file
3273 if Dot_Replacement /= No_File
3274 or else Casing_Defined
3275 or else Separate_Suffix /= No_File
3277 Lang_Id := Project.Languages;
3278 while Lang_Id /= No_Language_Index loop
3279 if Lang_Id.Config.Kind = Unit_Based then
3280 if Dot_Replacement /= No_File then
3281 Lang_Id.Config.Naming_Data.Dot_Replacement :=
3285 if Casing_Defined then
3286 Lang_Id.Config.Naming_Data.Casing := Casing;
3289 if Separate_Suffix /= No_File then
3290 Lang_Id.Config.Naming_Data.Separate_Suffix :=
3295 Lang_Id := Lang_Id.Next;
3299 -- Next, get the spec and body suffixes
3301 Lang_Id := Project.Languages;
3302 while Lang_Id /= No_Language_Index loop
3303 Lang := Lang_Id.Name;
3309 Attribute_Or_Array_Name => Name_Spec_Suffix,
3310 In_Package => Naming_Id,
3311 In_Tree => In_Tree);
3313 if Suffix = Nil_Variable_Value then
3316 Attribute_Or_Array_Name => Name_Spec_Suffix,
3317 In_Package => Naming_Id,
3318 In_Tree => In_Tree);
3321 if Suffix /= Nil_Variable_Value then
3322 Lang_Id.Config.Naming_Data.Spec_Suffix :=
3323 File_Name_Type (Suffix.Value);
3330 Attribute_Or_Array_Name => Name_Body_Suffix,
3331 In_Package => Naming_Id,
3332 In_Tree => In_Tree);
3334 if Suffix = Nil_Variable_Value then
3337 Attribute_Or_Array_Name => Name_Implementation_Suffix,
3338 In_Package => Naming_Id,
3339 In_Tree => In_Tree);
3342 if Suffix /= Nil_Variable_Value then
3343 Lang_Id.Config.Naming_Data.Body_Suffix :=
3344 File_Name_Type (Suffix.Value);
3347 -- ??? As opposed to what is done in Check_Naming_Ada_Only,
3348 -- we do not check whether spec_suffix=body_suffix, which
3349 -- should be illegal. Best would be to share this code into
3350 -- Check_Common, but we access the attributes from the project
3351 -- files slightly differently apparently.
3353 Lang_Id := Lang_Id.Next;
3356 -- Get the naming exceptions for all languages
3358 for Kind in Spec .. Impl loop
3359 Lang_Id := Project.Languages;
3360 while Lang_Id /= No_Language_Index loop
3361 case Lang_Id.Config.Kind is
3363 Process_Exceptions_File_Based (Lang_Id, Kind);
3366 Process_Exceptions_Unit_Based (Lang_Id, Kind);
3369 Lang_Id := Lang_Id.Next;
3372 end Check_Naming_Multi_Lang;
3374 -- Start of processing for Check_Naming_Schemes
3377 -- No Naming package or parsing a configuration file? nothing to do
3379 if Naming_Id /= No_Package and not Is_Config_File then
3380 Naming := In_Tree.Packages.Table (Naming_Id);
3382 if Current_Verbosity = High then
3383 Write_Line ("Checking package Naming.");
3388 Check_Naming_Ada_Only;
3389 when Multi_Language =>
3390 Check_Naming_Multi_Lang;
3393 end Check_Naming_Schemes;
3395 ------------------------------
3396 -- Check_Library_Attributes --
3397 ------------------------------
3399 procedure Check_Library_Attributes
3400 (Project : Project_Id;
3401 In_Tree : Project_Tree_Ref)
3403 Attributes : constant Prj.Variable_Id := Project.Decl.Attributes;
3405 Lib_Dir : constant Prj.Variable_Value :=
3407 (Snames.Name_Library_Dir, Attributes, In_Tree);
3409 Lib_Name : constant Prj.Variable_Value :=
3411 (Snames.Name_Library_Name, Attributes, In_Tree);
3413 Lib_Version : constant Prj.Variable_Value :=
3415 (Snames.Name_Library_Version, Attributes, In_Tree);
3417 Lib_ALI_Dir : constant Prj.Variable_Value :=
3419 (Snames.Name_Library_Ali_Dir, Attributes, In_Tree);
3421 Lib_GCC : constant Prj.Variable_Value :=
3423 (Snames.Name_Library_GCC, Attributes, In_Tree);
3425 The_Lib_Kind : constant Prj.Variable_Value :=
3427 (Snames.Name_Library_Kind, Attributes, In_Tree);
3429 Imported_Project_List : Project_List;
3431 Continuation : String_Access := No_Continuation_String'Access;
3433 Support_For_Libraries : Library_Support;
3435 Library_Directory_Present : Boolean;
3437 procedure Check_Library (Proj : Project_Id; Extends : Boolean);
3438 -- Check if an imported or extended project if also a library project
3444 procedure Check_Library (Proj : Project_Id; Extends : Boolean) is
3446 Iter : Source_Iterator;
3449 if Proj /= No_Project then
3450 if not Proj.Library then
3452 -- The only not library projects that are OK are those that
3453 -- have no sources. However, header files from non-Ada
3454 -- languages are OK, as there is nothing to compile.
3456 Iter := For_Each_Source (In_Tree, Proj);
3458 Src_Id := Prj.Element (Iter);
3459 exit when Src_Id = No_Source
3460 or else Src_Id.Language.Config.Kind /= File_Based
3461 or else Src_Id.Kind /= Spec;
3465 if Src_Id /= No_Source then
3466 Error_Msg_Name_1 := Project.Name;
3467 Error_Msg_Name_2 := Proj.Name;
3470 if Project.Library_Kind /= Static then
3474 "shared library project %% cannot extend " &
3475 "project %% that is not a library project",
3477 Continuation := Continuation_String'Access;
3480 elsif (not Unchecked_Shared_Lib_Imports)
3481 and then Project.Library_Kind /= Static
3486 "shared library project %% cannot import project %% " &
3487 "that is not a shared library project",
3489 Continuation := Continuation_String'Access;
3493 elsif Project.Library_Kind /= Static and then
3494 Proj.Library_Kind = Static
3496 Error_Msg_Name_1 := Project.Name;
3497 Error_Msg_Name_2 := Proj.Name;
3503 "shared library project %% cannot extend static " &
3504 "library project %%",
3506 Continuation := Continuation_String'Access;
3508 elsif not Unchecked_Shared_Lib_Imports then
3512 "shared library project %% cannot import static " &
3513 "library project %%",
3515 Continuation := Continuation_String'Access;
3522 Dir_Exists : Boolean;
3524 -- Start of processing for Check_Library_Attributes
3527 Library_Directory_Present := Lib_Dir.Value /= Empty_String;
3529 -- Special case of extending project
3531 if Project.Extends /= No_Project then
3533 -- If the project extended is a library project, we inherit the
3534 -- library name, if it is not redefined; we check that the library
3535 -- directory is specified.
3537 if Project.Extends.Library then
3538 if Project.Qualifier = Standard then
3541 "a standard project cannot extend a library project",
3545 if Lib_Name.Default then
3546 Project.Library_Name := Project.Extends.Library_Name;
3549 if Lib_Dir.Default then
3550 if not Project.Virtual then
3553 "a project extending a library project must " &
3554 "specify an attribute Library_Dir",
3558 -- For a virtual project extending a library project,
3559 -- inherit library directory.
3561 Project.Library_Dir := Project.Extends.Library_Dir;
3562 Library_Directory_Present := True;
3569 pragma Assert (Lib_Name.Kind = Single);
3571 if Lib_Name.Value = Empty_String then
3572 if Current_Verbosity = High
3573 and then Project.Library_Name = No_Name
3575 Write_Line ("No library name");
3579 -- There is no restriction on the syntax of library names
3581 Project.Library_Name := Lib_Name.Value;
3584 if Project.Library_Name /= No_Name then
3585 if Current_Verbosity = High then
3587 ("Library name", Get_Name_String (Project.Library_Name));
3590 pragma Assert (Lib_Dir.Kind = Single);
3592 if not Library_Directory_Present then
3593 if Current_Verbosity = High then
3594 Write_Line ("No library directory");
3598 -- Find path name (unless inherited), check that it is a directory
3600 if Project.Library_Dir = No_Path_Information then
3604 File_Name_Type (Lib_Dir.Value),
3605 Path => Project.Library_Dir,
3606 Dir_Exists => Dir_Exists,
3607 Create => "library",
3608 Must_Exist => False,
3609 Location => Lib_Dir.Location,
3610 Externally_Built => Project.Externally_Built);
3616 (Project.Library_Dir.Display_Name));
3619 if not Dir_Exists then
3620 -- Get the absolute name of the library directory that
3621 -- does not exist, to report an error.
3623 Err_Vars.Error_Msg_File_1 :=
3624 File_Name_Type (Project.Library_Dir.Display_Name);
3627 "library directory { does not exist",
3630 -- The library directory cannot be the same as the Object
3633 elsif Project.Library_Dir.Name = Project.Object_Directory.Name then
3636 "library directory cannot be the same " &
3637 "as object directory",
3639 Project.Library_Dir := No_Path_Information;
3643 OK : Boolean := True;
3644 Dirs_Id : String_List_Id;
3645 Dir_Elem : String_Element;
3649 -- The library directory cannot be the same as a source
3650 -- directory of the current project.
3652 Dirs_Id := Project.Source_Dirs;
3653 while Dirs_Id /= Nil_String loop
3654 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3655 Dirs_Id := Dir_Elem.Next;
3657 if Project.Library_Dir.Name =
3658 Path_Name_Type (Dir_Elem.Value)
3660 Err_Vars.Error_Msg_File_1 :=
3661 File_Name_Type (Dir_Elem.Value);
3664 "library directory cannot be the same " &
3665 "as source directory {",
3674 -- The library directory cannot be the same as a source
3675 -- directory of another project either.
3677 Pid := In_Tree.Projects;
3679 exit Project_Loop when Pid = null;
3681 if Pid.Project /= Project then
3682 Dirs_Id := Pid.Project.Source_Dirs;
3684 Dir_Loop : while Dirs_Id /= Nil_String loop
3686 In_Tree.String_Elements.Table (Dirs_Id);
3687 Dirs_Id := Dir_Elem.Next;
3689 if Project.Library_Dir.Name =
3690 Path_Name_Type (Dir_Elem.Value)
3692 Err_Vars.Error_Msg_File_1 :=
3693 File_Name_Type (Dir_Elem.Value);
3694 Err_Vars.Error_Msg_Name_1 := Pid.Project.Name;
3698 "library directory cannot be the same " &
3699 "as source directory { of project %%",
3708 end loop Project_Loop;
3712 Project.Library_Dir := No_Path_Information;
3714 elsif Current_Verbosity = High then
3716 -- Display the Library directory in high verbosity
3719 ("Library directory",
3720 Get_Name_String (Project.Library_Dir.Display_Name));
3729 Project.Library_Dir /= No_Path_Information
3730 and then Project.Library_Name /= No_Name;
3732 if Project.Extends = No_Project then
3733 case Project.Qualifier is
3735 if Project.Library then
3738 "a standard project cannot be a library project",
3743 if not Project.Library then
3744 if Project.Library_Dir = No_Path_Information then
3747 "\attribute Library_Dir not declared",
3751 if Project.Library_Name = No_Name then
3754 "\attribute Library_Name not declared",
3765 if Project.Library then
3766 if Get_Mode = Multi_Language then
3767 Support_For_Libraries := Project.Config.Lib_Support;
3770 Support_For_Libraries := MLib.Tgt.Support_For_Libraries;
3773 if Support_For_Libraries = Prj.None then
3776 "?libraries are not supported on this platform",
3778 Project.Library := False;
3781 if Lib_ALI_Dir.Value = Empty_String then
3782 if Current_Verbosity = High then
3783 Write_Line ("No library ALI directory specified");
3786 Project.Library_ALI_Dir := Project.Library_Dir;
3789 -- Find path name, check that it is a directory
3794 File_Name_Type (Lib_ALI_Dir.Value),
3795 Path => Project.Library_ALI_Dir,
3796 Create => "library ALI",
3797 Dir_Exists => Dir_Exists,
3798 Must_Exist => False,
3799 Location => Lib_ALI_Dir.Location,
3800 Externally_Built => Project.Externally_Built);
3802 if not Dir_Exists then
3803 -- Get the absolute name of the library ALI directory that
3804 -- does not exist, to report an error.
3806 Err_Vars.Error_Msg_File_1 :=
3807 File_Name_Type (Project.Library_ALI_Dir.Display_Name);
3810 "library 'A'L'I directory { does not exist",
3811 Lib_ALI_Dir.Location);
3814 if Project.Library_ALI_Dir /= Project.Library_Dir then
3816 -- The library ALI directory cannot be the same as the
3817 -- Object directory.
3819 if Project.Library_ALI_Dir = Project.Object_Directory then
3822 "library 'A'L'I directory cannot be the same " &
3823 "as object directory",
3824 Lib_ALI_Dir.Location);
3825 Project.Library_ALI_Dir := No_Path_Information;
3829 OK : Boolean := True;
3830 Dirs_Id : String_List_Id;
3831 Dir_Elem : String_Element;
3835 -- The library ALI directory cannot be the same as
3836 -- a source directory of the current project.
3838 Dirs_Id := Project.Source_Dirs;
3839 while Dirs_Id /= Nil_String loop
3840 Dir_Elem := In_Tree.String_Elements.Table (Dirs_Id);
3841 Dirs_Id := Dir_Elem.Next;
3843 if Project.Library_ALI_Dir.Name =
3844 Path_Name_Type (Dir_Elem.Value)
3846 Err_Vars.Error_Msg_File_1 :=
3847 File_Name_Type (Dir_Elem.Value);
3850 "library 'A'L'I directory cannot be " &
3851 "the same as source directory {",
3852 Lib_ALI_Dir.Location);
3860 -- The library ALI directory cannot be the same as
3861 -- a source directory of another project either.
3863 Pid := In_Tree.Projects;
3864 ALI_Project_Loop : loop
3865 exit ALI_Project_Loop when Pid = null;
3867 if Pid.Project /= Project then
3868 Dirs_Id := Pid.Project.Source_Dirs;
3871 while Dirs_Id /= Nil_String loop
3873 In_Tree.String_Elements.Table (Dirs_Id);
3874 Dirs_Id := Dir_Elem.Next;
3876 if Project.Library_ALI_Dir.Name =
3877 Path_Name_Type (Dir_Elem.Value)
3879 Err_Vars.Error_Msg_File_1 :=
3880 File_Name_Type (Dir_Elem.Value);
3881 Err_Vars.Error_Msg_Name_1 :=
3886 "library 'A'L'I directory cannot " &
3887 "be the same as source directory " &
3889 Lib_ALI_Dir.Location);
3891 exit ALI_Project_Loop;
3893 end loop ALI_Dir_Loop;
3896 end loop ALI_Project_Loop;
3900 Project.Library_ALI_Dir := No_Path_Information;
3902 elsif Current_Verbosity = High then
3904 -- Display the Library ALI directory in high
3910 (Project.Library_ALI_Dir.Display_Name));
3917 pragma Assert (Lib_Version.Kind = Single);
3919 if Lib_Version.Value = Empty_String then
3920 if Current_Verbosity = High then
3921 Write_Line ("No library version specified");
3925 Project.Lib_Internal_Name := Lib_Version.Value;
3928 pragma Assert (The_Lib_Kind.Kind = Single);
3930 if The_Lib_Kind.Value = Empty_String then
3931 if Current_Verbosity = High then
3932 Write_Line ("No library kind specified");
3936 Get_Name_String (The_Lib_Kind.Value);
3939 Kind_Name : constant String :=
3940 To_Lower (Name_Buffer (1 .. Name_Len));
3942 OK : Boolean := True;
3945 if Kind_Name = "static" then
3946 Project.Library_Kind := Static;
3948 elsif Kind_Name = "dynamic" then
3949 Project.Library_Kind := Dynamic;
3951 elsif Kind_Name = "relocatable" then
3952 Project.Library_Kind := Relocatable;
3957 "illegal value for Library_Kind",
3958 The_Lib_Kind.Location);
3962 if Current_Verbosity = High and then OK then
3963 Write_Attr ("Library kind", Kind_Name);
3966 if Project.Library_Kind /= Static then
3967 if Support_For_Libraries = Prj.Static_Only then
3970 "only static libraries are supported " &
3972 The_Lib_Kind.Location);
3973 Project.Library := False;
3976 -- Check if (obsolescent) attribute Library_GCC or
3977 -- Linker'Driver is declared.
3979 if Lib_GCC.Value /= Empty_String then
3983 "?Library_'G'C'C is an obsolescent attribute, " &
3984 "use Linker''Driver instead",
3986 Project.Config.Shared_Lib_Driver :=
3987 File_Name_Type (Lib_GCC.Value);
3991 Linker : constant Package_Id :=
3994 Project.Decl.Packages,
3996 Driver : constant Variable_Value :=
3999 Attribute_Or_Array_Name =>
4001 In_Package => Linker,
4006 if Driver /= Nil_Variable_Value
4007 and then Driver.Value /= Empty_String
4009 Project.Config.Shared_Lib_Driver :=
4010 File_Name_Type (Driver.Value);
4019 if Project.Library then
4020 if Current_Verbosity = High then
4021 Write_Line ("This is a library project file");
4024 if Get_Mode = Multi_Language then
4025 Check_Library (Project.Extends, Extends => True);
4027 Imported_Project_List := Project.Imported_Projects;
4028 while Imported_Project_List /= null loop
4030 (Imported_Project_List.Project,
4032 Imported_Project_List := Imported_Project_List.Next;
4040 -- Check if Linker'Switches or Linker'Default_Switches are declared.
4041 -- Warn if they are declared, as it is a common error to think that
4042 -- library are "linked" with Linker switches.
4044 if Project.Library then
4046 Linker_Package_Id : constant Package_Id :=
4049 Project.Decl.Packages, In_Tree);
4050 Linker_Package : Package_Element;
4051 Switches : Array_Element_Id := No_Array_Element;
4054 if Linker_Package_Id /= No_Package then
4055 Linker_Package := In_Tree.Packages.Table (Linker_Package_Id);
4059 (Name => Name_Switches,
4060 In_Arrays => Linker_Package.Decl.Arrays,
4061 In_Tree => In_Tree);
4063 if Switches = No_Array_Element then
4066 (Name => Name_Default_Switches,
4067 In_Arrays => Linker_Package.Decl.Arrays,
4068 In_Tree => In_Tree);
4071 if Switches /= No_Array_Element then
4074 "?Linker switches not taken into account in library " &
4082 if Project.Extends /= No_Project then
4083 Project.Extends.Library := False;
4085 end Check_Library_Attributes;
4087 --------------------------
4088 -- Check_Package_Naming --
4089 --------------------------
4091 procedure Check_Package_Naming
4092 (Project : Project_Id;
4093 In_Tree : Project_Tree_Ref)
4095 Naming_Id : constant Package_Id :=
4096 Util.Value_Of (Name_Naming, Project.Decl.Packages, In_Tree);
4098 Naming : Package_Element;
4101 -- If there is a package Naming, we will put in Data.Naming
4102 -- what is in this package Naming.
4104 if Naming_Id /= No_Package then
4105 Naming := In_Tree.Packages.Table (Naming_Id);
4107 if Current_Verbosity = High then
4108 Write_Line ("Checking ""Naming"".");
4111 -- Check Spec_Suffix
4114 Spec_Suffixs : Array_Element_Id :=
4120 Suffix : Array_Element_Id;
4121 Element : Array_Element;
4122 Suffix2 : Array_Element_Id;
4125 -- If some suffixes have been specified, we make sure that
4126 -- for each language for which a default suffix has been
4127 -- specified, there is a suffix specified, either the one
4128 -- in the project file or if there were none, the default.
4130 if Spec_Suffixs /= No_Array_Element then
4131 Suffix := Project.Naming.Spec_Suffix;
4133 while Suffix /= No_Array_Element loop
4135 In_Tree.Array_Elements.Table (Suffix);
4136 Suffix2 := Spec_Suffixs;
4138 while Suffix2 /= No_Array_Element loop
4139 exit when In_Tree.Array_Elements.Table
4140 (Suffix2).Index = Element.Index;
4141 Suffix2 := In_Tree.Array_Elements.Table
4145 -- There is a registered default suffix, but no
4146 -- suffix specified in the project file.
4147 -- Add the default to the array.
4149 if Suffix2 = No_Array_Element then
4150 Array_Element_Table.Increment_Last
4151 (In_Tree.Array_Elements);
4152 In_Tree.Array_Elements.Table
4153 (Array_Element_Table.Last
4154 (In_Tree.Array_Elements)) :=
4155 (Index => Element.Index,
4156 Src_Index => Element.Src_Index,
4157 Index_Case_Sensitive => False,
4158 Value => Element.Value,
4159 Next => Spec_Suffixs);
4160 Spec_Suffixs := Array_Element_Table.Last
4161 (In_Tree.Array_Elements);
4164 Suffix := Element.Next;
4167 -- Put the resulting array as the Spec suffixes
4169 Project.Naming.Spec_Suffix := Spec_Suffixs;
4173 -- Check Body_Suffix
4176 Impl_Suffixs : Array_Element_Id :=
4182 Suffix : Array_Element_Id;
4183 Element : Array_Element;
4184 Suffix2 : Array_Element_Id;
4187 -- If some suffixes have been specified, we make sure that
4188 -- for each language for which a default suffix has been
4189 -- specified, there is a suffix specified, either the one
4190 -- in the project file or if there were none, the default.
4192 if Impl_Suffixs /= No_Array_Element then
4193 Suffix := Project.Naming.Body_Suffix;
4194 while Suffix /= No_Array_Element loop
4196 In_Tree.Array_Elements.Table (Suffix);
4198 Suffix2 := Impl_Suffixs;
4199 while Suffix2 /= No_Array_Element loop
4200 exit when In_Tree.Array_Elements.Table
4201 (Suffix2).Index = Element.Index;
4202 Suffix2 := In_Tree.Array_Elements.Table
4206 -- There is a registered default suffix, but no suffix was
4207 -- specified in the project file. Add default to the array.
4209 if Suffix2 = No_Array_Element then
4210 Array_Element_Table.Increment_Last
4211 (In_Tree.Array_Elements);
4212 In_Tree.Array_Elements.Table
4213 (Array_Element_Table.Last
4214 (In_Tree.Array_Elements)) :=
4215 (Index => Element.Index,
4216 Src_Index => Element.Src_Index,
4217 Index_Case_Sensitive => False,
4218 Value => Element.Value,
4219 Next => Impl_Suffixs);
4220 Impl_Suffixs := Array_Element_Table.Last
4221 (In_Tree.Array_Elements);
4224 Suffix := Element.Next;
4227 -- Put the resulting array as the implementation suffixes
4229 Project.Naming.Body_Suffix := Impl_Suffixs;
4233 -- Get the exceptions, if any
4235 Project.Naming.Specification_Exceptions :=
4237 (Name_Specification_Exceptions,
4238 In_Arrays => Naming.Decl.Arrays,
4239 In_Tree => In_Tree);
4241 Project.Naming.Implementation_Exceptions :=
4243 (Name_Implementation_Exceptions,
4244 In_Arrays => Naming.Decl.Arrays,
4245 In_Tree => In_Tree);
4247 end Check_Package_Naming;
4249 ---------------------------------
4250 -- Check_Programming_Languages --
4251 ---------------------------------
4253 procedure Check_Programming_Languages
4254 (In_Tree : Project_Tree_Ref;
4255 Project : Project_Id)
4257 Languages : Variable_Value := Nil_Variable_Value;
4258 Def_Lang : Variable_Value := Nil_Variable_Value;
4259 Def_Lang_Id : Name_Id;
4262 Project.Languages := No_Language_Index;
4264 Prj.Util.Value_Of (Name_Languages, Project.Decl.Attributes, In_Tree);
4267 (Name_Default_Language, Project.Decl.Attributes, In_Tree);
4269 -- Shouldn't these be set to False by default, and only set to True when
4270 -- we actually find some source file???
4272 if Project.Source_Dirs /= Nil_String then
4274 -- Check if languages are specified in this project
4276 if Languages.Default then
4278 -- In Ada_Only mode, the default language is Ada
4280 if Get_Mode = Ada_Only then
4281 Def_Lang_Id := Name_Ada;
4284 -- Fail if there is no default language defined
4286 if Def_Lang.Default then
4287 if not Default_Language_Is_Ada then
4291 "no languages defined for this project",
4293 Def_Lang_Id := No_Name;
4295 Def_Lang_Id := Name_Ada;
4299 Get_Name_String (Def_Lang.Value);
4300 To_Lower (Name_Buffer (1 .. Name_Len));
4301 Def_Lang_Id := Name_Find;
4305 if Def_Lang_Id /= No_Name then
4306 Project.Languages := new Language_Data'(No_Language_Data);
4307 Project.Languages.Name := Def_Lang_Id;
4308 Get_Name_String (Def_Lang_Id);
4309 Name_Buffer (1) := GNAT.Case_Util.To_Upper (Name_Buffer (1));
4310 Project.Languages.Display_Name := Name_Find;
4312 if Def_Lang_Id = Name_Ada then
4313 Project.Languages.Config.Kind := Unit_Based;
4314 Project.Languages.Config.Dependency_Kind := ALI_File;
4316 Project.Languages.Config.Kind := File_Based;
4322 Current : String_List_Id := Languages.Values;
4323 Element : String_Element;
4324 Lang_Name : Name_Id;
4325 Index : Language_Ptr;
4326 NL_Id : Language_Ptr;
4329 -- If there are no languages declared, there are no sources
4331 if Current = Nil_String then
4332 Project.Source_Dirs := Nil_String;
4334 if Project.Qualifier = Standard then
4338 "a standard project must have at least one language",
4339 Languages.Location);
4343 -- Look through all the languages specified in attribute
4346 while Current /= Nil_String loop
4347 Element := In_Tree.String_Elements.Table (Current);
4348 Get_Name_String (Element.Value);
4349 To_Lower (Name_Buffer (1 .. Name_Len));
4350 Lang_Name := Name_Find;
4352 -- If the language was not already specified (duplicates
4353 -- are simply ignored).
4355 NL_Id := Project.Languages;
4356 while NL_Id /= No_Language_Index loop
4357 exit when Lang_Name = NL_Id.Name;
4358 NL_Id := NL_Id.Next;
4361 if NL_Id = No_Language_Index then
4362 Index := new Language_Data'(No_Language_Data);
4363 Index.Name := Lang_Name;
4364 Index.Display_Name := Element.Value;
4365 Index.Next := Project.Languages;
4367 if Lang_Name = Name_Ada then
4368 Index.Config.Kind := Unit_Based;
4369 Index.Config.Dependency_Kind := ALI_File;
4372 Index.Config.Kind := File_Based;
4373 Index.Config.Dependency_Kind := None;
4376 Project.Languages := Index;
4379 Current := Element.Next;
4385 end Check_Programming_Languages;
4391 function Check_Project
4393 Root_Project : Project_Id;
4394 Extending : Boolean) return Boolean
4398 if P = Root_Project then
4401 elsif Extending then
4402 Prj := Root_Project;
4403 while Prj.Extends /= No_Project loop
4404 if P = Prj.Extends then
4415 -------------------------------
4416 -- Check_Stand_Alone_Library --
4417 -------------------------------
4419 procedure Check_Stand_Alone_Library
4420 (Project : Project_Id;
4421 In_Tree : Project_Tree_Ref;
4422 Current_Dir : String;
4423 Extending : Boolean)
4425 Lib_Interfaces : constant Prj.Variable_Value :=
4427 (Snames.Name_Library_Interface,
4428 Project.Decl.Attributes,
4431 Lib_Auto_Init : constant Prj.Variable_Value :=
4433 (Snames.Name_Library_Auto_Init,
4434 Project.Decl.Attributes,
4437 Lib_Src_Dir : constant Prj.Variable_Value :=
4439 (Snames.Name_Library_Src_Dir,
4440 Project.Decl.Attributes,
4443 Lib_Symbol_File : constant Prj.Variable_Value :=
4445 (Snames.Name_Library_Symbol_File,
4446 Project.Decl.Attributes,
4449 Lib_Symbol_Policy : constant Prj.Variable_Value :=
4451 (Snames.Name_Library_Symbol_Policy,
4452 Project.Decl.Attributes,
4455 Lib_Ref_Symbol_File : constant Prj.Variable_Value :=
4457 (Snames.Name_Library_Reference_Symbol_File,
4458 Project.Decl.Attributes,
4461 Auto_Init_Supported : Boolean;
4462 OK : Boolean := True;
4464 Next_Proj : Project_Id;
4465 Iter : Source_Iterator;
4468 if Get_Mode = Multi_Language then
4469 Auto_Init_Supported := Project.Config.Auto_Init_Supported;
4471 Auto_Init_Supported :=
4472 MLib.Tgt.Standalone_Library_Auto_Init_Is_Supported;
4475 pragma Assert (Lib_Interfaces.Kind = List);
4477 -- It is a stand-alone library project file if attribute
4478 -- Library_Interface is defined.
4480 if not Lib_Interfaces.Default then
4481 SAL_Library : declare
4482 Interfaces : String_List_Id := Lib_Interfaces.Values;
4483 Interface_ALIs : String_List_Id := Nil_String;
4487 procedure Add_ALI_For (Source : File_Name_Type);
4488 -- Add an ALI file name to the list of Interface ALIs
4494 procedure Add_ALI_For (Source : File_Name_Type) is
4496 Get_Name_String (Source);
4499 ALI : constant String :=
4500 ALI_File_Name (Name_Buffer (1 .. Name_Len));
4501 ALI_Name_Id : Name_Id;
4504 Name_Len := ALI'Length;
4505 Name_Buffer (1 .. Name_Len) := ALI;
4506 ALI_Name_Id := Name_Find;
4508 String_Element_Table.Increment_Last
4509 (In_Tree.String_Elements);
4510 In_Tree.String_Elements.Table
4511 (String_Element_Table.Last
4512 (In_Tree.String_Elements)) :=
4513 (Value => ALI_Name_Id,
4515 Display_Value => ALI_Name_Id,
4517 In_Tree.String_Elements.Table
4518 (Interfaces).Location,
4520 Next => Interface_ALIs);
4521 Interface_ALIs := String_Element_Table.Last
4522 (In_Tree.String_Elements);
4526 -- Start of processing for SAL_Library
4529 Project.Standalone_Library := True;
4531 -- Library_Interface cannot be an empty list
4533 if Interfaces = Nil_String then
4536 "Library_Interface cannot be an empty list",
4537 Lib_Interfaces.Location);
4540 -- Process each unit name specified in the attribute
4541 -- Library_Interface.
4543 while Interfaces /= Nil_String loop
4545 (In_Tree.String_Elements.Table (Interfaces).Value);
4546 To_Lower (Name_Buffer (1 .. Name_Len));
4548 if Name_Len = 0 then
4551 "an interface cannot be an empty string",
4552 In_Tree.String_Elements.Table (Interfaces).Location);
4556 Error_Msg_Name_1 := Unit;
4558 if Get_Mode = Ada_Only then
4559 UData := Units_Htable.Get (In_Tree.Units_HT, Unit);
4561 if UData = No_Unit_Index then
4565 In_Tree.String_Elements.Table
4566 (Interfaces).Location);
4569 -- Check that the unit is part of the project
4571 if UData.File_Names (Impl) /= null
4572 and then not UData.File_Names (Impl).Locally_Removed
4575 (UData.File_Names (Impl).Project,
4578 -- There is a body for this unit.
4579 -- If there is no spec, we need to check that it
4580 -- is not a subunit.
4582 if UData.File_Names (Spec) = null then
4584 Src_Ind : Source_File_Index;
4588 Sinput.P.Load_Project_File
4589 (Get_Name_String (UData.File_Names
4592 if Sinput.P.Source_File_Is_Subunit
4597 "%% is a subunit; " &
4598 "it cannot be an interface",
4600 String_Elements.Table
4601 (Interfaces).Location);
4606 -- The unit is not a subunit, so we add the
4607 -- ALI file for its body to the Interface ALIs.
4610 (UData.File_Names (Impl).File);
4615 "%% is not an unit of this project",
4616 In_Tree.String_Elements.Table
4617 (Interfaces).Location);
4620 elsif UData.File_Names (Spec) /= null
4621 and then not UData.File_Names (Spec).Locally_Removed
4622 and then Check_Project
4623 (UData.File_Names (Spec).Project,
4627 -- The unit is part of the project, it has a spec,
4628 -- but no body. We add the ALI for its spec to the
4632 (UData.File_Names (Spec).File);
4637 "%% is not an unit of this project",
4638 In_Tree.String_Elements.Table
4639 (Interfaces).Location);
4644 -- Multi_Language mode
4646 Next_Proj := Project.Extends;
4647 Iter := For_Each_Source (In_Tree, Project);
4649 while Prj.Element (Iter) /= No_Source
4651 (Prj.Element (Iter).Unit = null
4652 or else Prj.Element (Iter).Unit.Name /= Unit)
4657 Source := Prj.Element (Iter);
4658 exit when Source /= No_Source
4659 or else Next_Proj = No_Project;
4661 Iter := For_Each_Source (In_Tree, Next_Proj);
4662 Next_Proj := Next_Proj.Extends;
4665 if Source /= No_Source then
4666 if Source.Kind = Sep then
4667 Source := No_Source;
4668 elsif Source.Kind = Spec
4669 and then Other_Part (Source) /= No_Source
4671 Source := Other_Part (Source);
4675 if Source /= No_Source then
4676 if Source.Project /= Project
4677 and then not Is_Extending (Project, Source.Project)
4679 Source := No_Source;
4683 if Source = No_Source then
4686 "%% is not an unit of this project",
4687 In_Tree.String_Elements.Table
4688 (Interfaces).Location);
4691 if Source.Kind = Spec
4692 and then Other_Part (Source) /= No_Source
4694 Source := Other_Part (Source);
4697 String_Element_Table.Increment_Last
4698 (In_Tree.String_Elements);
4700 In_Tree.String_Elements.Table
4701 (String_Element_Table.Last
4702 (In_Tree.String_Elements)) :=
4703 (Value => Name_Id (Source.Dep_Name),
4705 Display_Value => Name_Id (Source.Dep_Name),
4707 In_Tree.String_Elements.Table
4708 (Interfaces).Location,
4710 Next => Interface_ALIs);
4713 String_Element_Table.Last (In_Tree.String_Elements);
4721 In_Tree.String_Elements.Table (Interfaces).Next;
4724 -- Put the list of Interface ALIs in the project data
4726 Project.Lib_Interface_ALIs := Interface_ALIs;
4728 -- Check value of attribute Library_Auto_Init and set
4729 -- Lib_Auto_Init accordingly.
4731 if Lib_Auto_Init.Default then
4733 -- If no attribute Library_Auto_Init is declared, then set auto
4734 -- init only if it is supported.
4736 Project.Lib_Auto_Init := Auto_Init_Supported;
4739 Get_Name_String (Lib_Auto_Init.Value);
4740 To_Lower (Name_Buffer (1 .. Name_Len));
4742 if Name_Buffer (1 .. Name_Len) = "false" then
4743 Project.Lib_Auto_Init := False;
4745 elsif Name_Buffer (1 .. Name_Len) = "true" then
4746 if Auto_Init_Supported then
4747 Project.Lib_Auto_Init := True;
4750 -- Library_Auto_Init cannot be "true" if auto init is not
4755 "library auto init not supported " &
4757 Lib_Auto_Init.Location);
4763 "invalid value for attribute Library_Auto_Init",
4764 Lib_Auto_Init.Location);
4769 -- If attribute Library_Src_Dir is defined and not the empty string,
4770 -- check if the directory exist and is not the object directory or
4771 -- one of the source directories. This is the directory where copies
4772 -- of the interface sources will be copied. Note that this directory
4773 -- may be the library directory.
4775 if Lib_Src_Dir.Value /= Empty_String then
4777 Dir_Id : constant File_Name_Type :=
4778 File_Name_Type (Lib_Src_Dir.Value);
4779 Dir_Exists : Boolean;
4786 Path => Project.Library_Src_Dir,
4787 Dir_Exists => Dir_Exists,
4788 Must_Exist => False,
4789 Create => "library source copy",
4790 Location => Lib_Src_Dir.Location,
4791 Externally_Built => Project.Externally_Built);
4793 -- If directory does not exist, report an error
4795 if not Dir_Exists then
4796 -- Get the absolute name of the library directory that does
4797 -- not exist, to report an error.
4799 Err_Vars.Error_Msg_File_1 :=
4800 File_Name_Type (Project.Library_Src_Dir.Display_Name);
4803 "Directory { does not exist",
4804 Lib_Src_Dir.Location);
4806 -- Report error if it is the same as the object directory
4808 elsif Project.Library_Src_Dir = Project.Object_Directory then
4811 "directory to copy interfaces cannot be " &
4812 "the object directory",
4813 Lib_Src_Dir.Location);
4814 Project.Library_Src_Dir := No_Path_Information;
4818 Src_Dirs : String_List_Id;
4819 Src_Dir : String_Element;
4823 -- Interface copy directory cannot be one of the source
4824 -- directory of the current project.
4826 Src_Dirs := Project.Source_Dirs;
4827 while Src_Dirs /= Nil_String loop
4828 Src_Dir := In_Tree.String_Elements.Table (Src_Dirs);
4830 -- Report error if it is one of the source directories
4832 if Project.Library_Src_Dir.Name =
4833 Path_Name_Type (Src_Dir.Value)
4837 "directory to copy interfaces cannot " &
4838 "be one of the source directories",
4839 Lib_Src_Dir.Location);
4840 Project.Library_Src_Dir := No_Path_Information;
4844 Src_Dirs := Src_Dir.Next;
4847 if Project.Library_Src_Dir /= No_Path_Information then
4849 -- It cannot be a source directory of any other
4852 Pid := In_Tree.Projects;
4854 exit Project_Loop when Pid = null;
4856 Src_Dirs := Pid.Project.Source_Dirs;
4857 Dir_Loop : while Src_Dirs /= Nil_String loop
4859 In_Tree.String_Elements.Table (Src_Dirs);
4861 -- Report error if it is one of the source
4864 if Project.Library_Src_Dir.Name =
4865 Path_Name_Type (Src_Dir.Value)
4868 File_Name_Type (Src_Dir.Value);
4869 Error_Msg_Name_1 := Pid.Project.Name;
4872 "directory to copy interfaces cannot " &
4873 "be the same as source directory { of " &
4875 Lib_Src_Dir.Location);
4876 Project.Library_Src_Dir :=
4877 No_Path_Information;
4881 Src_Dirs := Src_Dir.Next;
4885 end loop Project_Loop;
4889 -- In high verbosity, if there is a valid Library_Src_Dir,
4890 -- display its path name.
4892 if Project.Library_Src_Dir /= No_Path_Information
4893 and then Current_Verbosity = High
4896 ("Directory to copy interfaces",
4897 Get_Name_String (Project.Library_Src_Dir.Name));
4903 -- Check the symbol related attributes
4905 -- First, the symbol policy
4907 if not Lib_Symbol_Policy.Default then
4909 Value : constant String :=
4911 (Get_Name_String (Lib_Symbol_Policy.Value));
4914 -- Symbol policy must hove one of a limited number of values
4916 if Value = "autonomous" or else Value = "default" then
4917 Project.Symbol_Data.Symbol_Policy := Autonomous;
4919 elsif Value = "compliant" then
4920 Project.Symbol_Data.Symbol_Policy := Compliant;
4922 elsif Value = "controlled" then
4923 Project.Symbol_Data.Symbol_Policy := Controlled;
4925 elsif Value = "restricted" then
4926 Project.Symbol_Data.Symbol_Policy := Restricted;
4928 elsif Value = "direct" then
4929 Project.Symbol_Data.Symbol_Policy := Direct;
4934 "illegal value for Library_Symbol_Policy",
4935 Lib_Symbol_Policy.Location);
4940 -- If attribute Library_Symbol_File is not specified, symbol policy
4941 -- cannot be Restricted.
4943 if Lib_Symbol_File.Default then
4944 if Project.Symbol_Data.Symbol_Policy = Restricted then
4947 "Library_Symbol_File needs to be defined when " &
4948 "symbol policy is Restricted",
4949 Lib_Symbol_Policy.Location);
4953 -- Library_Symbol_File is defined
4955 Project.Symbol_Data.Symbol_File :=
4956 Path_Name_Type (Lib_Symbol_File.Value);
4958 Get_Name_String (Lib_Symbol_File.Value);
4960 if Name_Len = 0 then
4963 "symbol file name cannot be an empty string",
4964 Lib_Symbol_File.Location);
4967 OK := not Is_Absolute_Path (Name_Buffer (1 .. Name_Len));
4970 for J in 1 .. Name_Len loop
4971 if Name_Buffer (J) = '/'
4972 or else Name_Buffer (J) = Directory_Separator
4981 Error_Msg_File_1 := File_Name_Type (Lib_Symbol_File.Value);
4984 "symbol file name { is illegal. " &
4985 "Name cannot include directory info.",
4986 Lib_Symbol_File.Location);
4991 -- If attribute Library_Reference_Symbol_File is not defined,
4992 -- symbol policy cannot be Compliant or Controlled.
4994 if Lib_Ref_Symbol_File.Default then
4995 if Project.Symbol_Data.Symbol_Policy = Compliant
4996 or else Project.Symbol_Data.Symbol_Policy = Controlled
5000 "a reference symbol file needs to be defined",
5001 Lib_Symbol_Policy.Location);
5005 -- Library_Reference_Symbol_File is defined, check file exists
5007 Project.Symbol_Data.Reference :=
5008 Path_Name_Type (Lib_Ref_Symbol_File.Value);
5010 Get_Name_String (Lib_Ref_Symbol_File.Value);
5012 if Name_Len = 0 then
5015 "reference symbol file name cannot be an empty string",
5016 Lib_Symbol_File.Location);
5019 if not Is_Absolute_Path (Name_Buffer (1 .. Name_Len)) then
5021 Add_Str_To_Name_Buffer
5022 (Get_Name_String (Project.Directory.Name));
5023 Add_Char_To_Name_Buffer (Directory_Separator);
5024 Add_Str_To_Name_Buffer
5025 (Get_Name_String (Lib_Ref_Symbol_File.Value));
5026 Project.Symbol_Data.Reference := Name_Find;
5029 if not Is_Regular_File
5030 (Get_Name_String (Project.Symbol_Data.Reference))
5033 File_Name_Type (Lib_Ref_Symbol_File.Value);
5035 -- For controlled and direct symbol policies, it is an error
5036 -- if the reference symbol file does not exist. For other
5037 -- symbol policies, this is just a warning
5040 Project.Symbol_Data.Symbol_Policy /= Controlled
5041 and then Project.Symbol_Data.Symbol_Policy /= Direct;
5045 "<library reference symbol file { does not exist",
5046 Lib_Ref_Symbol_File.Location);
5048 -- In addition in the non-controlled case, if symbol policy
5049 -- is Compliant, it is changed to Autonomous, because there
5050 -- is no reference to check against, and we don't want to
5051 -- fail in this case.
5053 if Project.Symbol_Data.Symbol_Policy /= Controlled then
5054 if Project.Symbol_Data.Symbol_Policy = Compliant then
5055 Project.Symbol_Data.Symbol_Policy := Autonomous;
5060 -- If both the reference symbol file and the symbol file are
5061 -- defined, then check that they are not the same file.
5063 if Project.Symbol_Data.Symbol_File /= No_Path then
5064 Get_Name_String (Project.Symbol_Data.Symbol_File);
5066 if Name_Len > 0 then
5068 Symb_Path : constant String :=
5071 (Project.Object_Directory.Name) &
5072 Directory_Separator &
5073 Name_Buffer (1 .. Name_Len),
5074 Directory => Current_Dir,
5076 Opt.Follow_Links_For_Files);
5077 Ref_Path : constant String :=
5080 (Project.Symbol_Data.Reference),
5081 Directory => Current_Dir,
5083 Opt.Follow_Links_For_Files);
5085 if Symb_Path = Ref_Path then
5088 "library reference symbol file and library" &
5089 " symbol file cannot be the same file",
5090 Lib_Ref_Symbol_File.Location);
5098 end Check_Stand_Alone_Library;
5100 ----------------------------
5101 -- Compute_Directory_Last --
5102 ----------------------------
5104 function Compute_Directory_Last (Dir : String) return Natural is
5107 and then (Dir (Dir'Last - 1) = Directory_Separator
5108 or else Dir (Dir'Last - 1) = '/')
5110 return Dir'Last - 1;
5114 end Compute_Directory_Last;
5121 (Project : Project_Id;
5122 In_Tree : Project_Tree_Ref;
5124 Flag_Location : Source_Ptr)
5126 Real_Location : Source_Ptr := Flag_Location;
5127 Error_Buffer : String (1 .. 5_000);
5128 Error_Last : Natural := 0;
5129 Name_Number : Natural := 0;
5130 File_Number : Natural := 0;
5131 First : Positive := Msg'First;
5134 procedure Add (C : Character);
5135 -- Add a character to the buffer
5137 procedure Add (S : String);
5138 -- Add a string to the buffer
5141 -- Add a name to the buffer
5144 -- Add a file name to the buffer
5150 procedure Add (C : Character) is
5152 Error_Last := Error_Last + 1;
5153 Error_Buffer (Error_Last) := C;
5156 procedure Add (S : String) is
5158 Error_Buffer (Error_Last + 1 .. Error_Last + S'Length) := S;
5159 Error_Last := Error_Last + S'Length;
5166 procedure Add_File is
5167 File : File_Name_Type;
5171 File_Number := File_Number + 1;
5175 File := Err_Vars.Error_Msg_File_1;
5177 File := Err_Vars.Error_Msg_File_2;
5179 File := Err_Vars.Error_Msg_File_3;
5184 Get_Name_String (File);
5185 Add (Name_Buffer (1 .. Name_Len));
5193 procedure Add_Name is
5198 Name_Number := Name_Number + 1;
5202 Name := Err_Vars.Error_Msg_Name_1;
5204 Name := Err_Vars.Error_Msg_Name_2;
5206 Name := Err_Vars.Error_Msg_Name_3;
5211 Get_Name_String (Name);
5212 Add (Name_Buffer (1 .. Name_Len));
5216 -- Start of processing for Error_Msg
5219 -- If location of error is unknown, use the location of the project
5221 if Real_Location = No_Location then
5222 Real_Location := Project.Location;
5225 if Error_Report = null then
5226 Prj.Err.Error_Msg (Msg, Real_Location);
5230 -- Ignore continuation character
5232 if Msg (First) = '\' then
5236 -- Warning character is always the first one in this package
5237 -- this is an undocumented kludge???
5239 if Msg (First) = '?' then
5243 elsif Msg (First) = '<' then
5246 if Err_Vars.Error_Msg_Warn then
5252 while Index <= Msg'Last loop
5253 if Msg (Index) = '{' then
5256 elsif Msg (Index) = '%' then
5257 if Index < Msg'Last and then Msg (Index + 1) = '%' then
5269 Error_Report (Error_Buffer (1 .. Error_Last), Project, In_Tree);
5272 --------------------------------
5273 -- Free_Ada_Naming_Exceptions --
5274 --------------------------------
5276 procedure Free_Ada_Naming_Exceptions is
5278 Ada_Naming_Exception_Table.Set_Last (0);
5279 Ada_Naming_Exceptions.Reset;
5280 Reverse_Ada_Naming_Exceptions.Reset;
5281 end Free_Ada_Naming_Exceptions;
5283 ---------------------
5284 -- Get_Directories --
5285 ---------------------
5287 procedure Get_Directories
5288 (Project : Project_Id;
5289 In_Tree : Project_Tree_Ref;
5290 Current_Dir : String)
5292 Object_Dir : constant Variable_Value :=
5294 (Name_Object_Dir, Project.Decl.Attributes, In_Tree);
5296 Exec_Dir : constant Variable_Value :=
5298 (Name_Exec_Dir, Project.Decl.Attributes, In_Tree);
5300 Source_Dirs : constant Variable_Value :=
5302 (Name_Source_Dirs, Project.Decl.Attributes, In_Tree);
5304 Excluded_Source_Dirs : constant Variable_Value :=
5306 (Name_Excluded_Source_Dirs,
5307 Project.Decl.Attributes,
5310 Source_Files : constant Variable_Value :=
5312 (Name_Source_Files, Project.Decl.Attributes, In_Tree);
5314 Last_Source_Dir : String_List_Id := Nil_String;
5316 Languages : constant Variable_Value :=
5318 (Name_Languages, Project.Decl.Attributes, In_Tree);
5320 procedure Find_Source_Dirs
5321 (From : File_Name_Type;
5322 Location : Source_Ptr;
5323 Removed : Boolean := False);
5324 -- Find one or several source directories, and add (or remove, if
5325 -- Removed is True) them to list of source directories of the project.
5327 ----------------------
5328 -- Find_Source_Dirs --
5329 ----------------------
5331 procedure Find_Source_Dirs
5332 (From : File_Name_Type;
5333 Location : Source_Ptr;
5334 Removed : Boolean := False)
5336 Directory : constant String := Get_Name_String (From);
5337 Element : String_Element;
5339 procedure Recursive_Find_Dirs (Path : Name_Id);
5340 -- Find all the subdirectories (recursively) of Path and add them
5341 -- to the list of source directories of the project.
5343 -------------------------
5344 -- Recursive_Find_Dirs --
5345 -------------------------
5347 procedure Recursive_Find_Dirs (Path : Name_Id) is
5349 Name : String (1 .. 250);
5351 List : String_List_Id;
5352 Prev : String_List_Id;
5353 Element : String_Element;
5354 Found : Boolean := False;
5356 Non_Canonical_Path : Name_Id := No_Name;
5357 Canonical_Path : Name_Id := No_Name;
5359 The_Path : constant String :=
5361 (Get_Name_String (Path),
5362 Directory => Current_Dir,
5363 Resolve_Links => Opt.Follow_Links_For_Dirs) &
5364 Directory_Separator;
5366 The_Path_Last : constant Natural :=
5367 Compute_Directory_Last (The_Path);
5370 Name_Len := The_Path_Last - The_Path'First + 1;
5371 Name_Buffer (1 .. Name_Len) :=
5372 The_Path (The_Path'First .. The_Path_Last);
5373 Non_Canonical_Path := Name_Find;
5375 Name_Id (Canonical_Case_File_Name (Non_Canonical_Path));
5377 -- To avoid processing the same directory several times, check
5378 -- if the directory is already in Recursive_Dirs. If it is, then
5379 -- there is nothing to do, just return. If it is not, put it there
5380 -- and continue recursive processing.
5383 if Recursive_Dirs.Get (Canonical_Path) then
5386 Recursive_Dirs.Set (Canonical_Path, True);
5390 -- Check if directory is already in list
5392 List := Project.Source_Dirs;
5394 while List /= Nil_String loop
5395 Element := In_Tree.String_Elements.Table (List);
5397 if Element.Value /= No_Name then
5398 Found := Element.Value = Canonical_Path;
5403 List := Element.Next;
5406 -- If directory is not already in list, put it there
5408 if (not Removed) and (not Found) then
5409 if Current_Verbosity = High then
5411 Write_Line (The_Path (The_Path'First .. The_Path_Last));
5414 String_Element_Table.Increment_Last
5415 (In_Tree.String_Elements);
5417 (Value => Canonical_Path,
5418 Display_Value => Non_Canonical_Path,
5419 Location => No_Location,
5424 -- Case of first source directory
5426 if Last_Source_Dir = Nil_String then
5427 Project.Source_Dirs := String_Element_Table.Last
5428 (In_Tree.String_Elements);
5430 -- Here we already have source directories
5433 -- Link the previous last to the new one
5435 In_Tree.String_Elements.Table
5436 (Last_Source_Dir).Next :=
5437 String_Element_Table.Last
5438 (In_Tree.String_Elements);
5441 -- And register this source directory as the new last
5443 Last_Source_Dir := String_Element_Table.Last
5444 (In_Tree.String_Elements);
5445 In_Tree.String_Elements.Table (Last_Source_Dir) :=
5448 elsif Removed and Found then
5449 if Prev = Nil_String then
5450 Project.Source_Dirs :=
5451 In_Tree.String_Elements.Table (List).Next;
5453 In_Tree.String_Elements.Table (Prev).Next :=
5454 In_Tree.String_Elements.Table (List).Next;
5458 -- Now look for subdirectories. We do that even when this
5459 -- directory is already in the list, because some of its
5460 -- subdirectories may not be in the list yet.
5462 Open (Dir, The_Path (The_Path'First .. The_Path_Last));
5465 Read (Dir, Name, Last);
5468 if Name (1 .. Last) /= "."
5469 and then Name (1 .. Last) /= ".."
5471 -- Avoid . and .. directories
5473 if Current_Verbosity = High then
5474 Write_Str (" Checking ");
5475 Write_Line (Name (1 .. Last));
5479 Path_Name : constant String :=
5481 (Name => Name (1 .. Last),
5483 The_Path (The_Path'First .. The_Path_Last),
5484 Resolve_Links => Opt.Follow_Links_For_Dirs,
5485 Case_Sensitive => True);
5488 if Is_Directory (Path_Name) then
5489 -- We have found a new subdirectory, call self
5491 Name_Len := Path_Name'Length;
5492 Name_Buffer (1 .. Name_Len) := Path_Name;
5493 Recursive_Find_Dirs (Name_Find);
5502 when Directory_Error =>
5504 end Recursive_Find_Dirs;
5506 -- Start of processing for Find_Source_Dirs
5509 if Current_Verbosity = High and then not Removed then
5510 Write_Str ("Find_Source_Dirs (""");
5511 Write_Str (Directory);
5515 -- First, check if we are looking for a directory tree, indicated
5516 -- by "/**" at the end.
5518 if Directory'Length >= 3
5519 and then Directory (Directory'Last - 1 .. Directory'Last) = "**"
5520 and then (Directory (Directory'Last - 2) = '/'
5522 Directory (Directory'Last - 2) = Directory_Separator)
5525 Project.Known_Order_Of_Source_Dirs := False;
5528 Name_Len := Directory'Length - 3;
5530 if Name_Len = 0 then
5532 -- Case of "/**": all directories in file system
5535 Name_Buffer (1) := Directory (Directory'First);
5538 Name_Buffer (1 .. Name_Len) :=
5539 Directory (Directory'First .. Directory'Last - 3);
5542 if Current_Verbosity = High then
5543 Write_Str ("Looking for all subdirectories of """);
5544 Write_Str (Name_Buffer (1 .. Name_Len));
5549 Base_Dir : constant File_Name_Type := Name_Find;
5550 Root_Dir : constant String :=
5552 (Name => Get_Name_String (Base_Dir),
5555 (Project.Directory.Display_Name),
5556 Resolve_Links => False,
5557 Case_Sensitive => True);
5560 if Root_Dir'Length = 0 then
5561 Err_Vars.Error_Msg_File_1 := Base_Dir;
5563 if Location = No_Location then
5566 "{ is not a valid directory.",
5571 "{ is not a valid directory.",
5576 -- We have an existing directory, we register it and all of
5577 -- its subdirectories.
5579 if Current_Verbosity = High then
5580 Write_Line ("Looking for source directories:");
5583 Name_Len := Root_Dir'Length;
5584 Name_Buffer (1 .. Name_Len) := Root_Dir;
5585 Recursive_Find_Dirs (Name_Find);
5587 if Current_Verbosity = High then
5588 Write_Line ("End of looking for source directories.");
5593 -- We have a single directory
5597 Path_Name : Path_Information;
5598 List : String_List_Id;
5599 Prev : String_List_Id;
5600 Dir_Exists : Boolean;
5604 (Project => Project,
5608 Dir_Exists => Dir_Exists,
5609 Must_Exist => False);
5611 if not Dir_Exists then
5612 Err_Vars.Error_Msg_File_1 := From;
5614 if Location = No_Location then
5617 "{ is not a valid directory",
5622 "{ is not a valid directory",
5628 Path : constant String :=
5629 Get_Name_String (Path_Name.Name) &
5630 Directory_Separator;
5631 Last_Path : constant Natural :=
5632 Compute_Directory_Last (Path);
5634 Display_Path : constant String :=
5636 (Path_Name.Display_Name) &
5637 Directory_Separator;
5638 Last_Display_Path : constant Natural :=
5639 Compute_Directory_Last
5641 Display_Path_Id : Name_Id;
5645 Add_Str_To_Name_Buffer (Path (Path'First .. Last_Path));
5646 Path_Id := Name_Find;
5648 Add_Str_To_Name_Buffer
5650 (Display_Path'First .. Last_Display_Path));
5651 Display_Path_Id := Name_Find;
5655 -- As it is an existing directory, we add it to the
5656 -- list of directories.
5658 String_Element_Table.Increment_Last
5659 (In_Tree.String_Elements);
5663 Display_Value => Display_Path_Id,
5664 Location => No_Location,
5666 Next => Nil_String);
5668 if Last_Source_Dir = Nil_String then
5670 -- This is the first source directory
5672 Project.Source_Dirs := String_Element_Table.Last
5673 (In_Tree.String_Elements);
5676 -- We already have source directories, link the
5677 -- previous last to the new one.
5679 In_Tree.String_Elements.Table
5680 (Last_Source_Dir).Next :=
5681 String_Element_Table.Last
5682 (In_Tree.String_Elements);
5685 -- And register this source directory as the new last
5687 Last_Source_Dir := String_Element_Table.Last
5688 (In_Tree.String_Elements);
5689 In_Tree.String_Elements.Table
5690 (Last_Source_Dir) := Element;
5693 -- Remove source dir, if present
5697 -- Look for source dir in current list
5699 List := Project.Source_Dirs;
5700 while List /= Nil_String loop
5701 Element := In_Tree.String_Elements.Table (List);
5702 exit when Element.Value = Path_Id;
5704 List := Element.Next;
5707 if List /= Nil_String then
5708 -- Source dir was found, remove it from the list
5710 if Prev = Nil_String then
5711 Project.Source_Dirs :=
5712 In_Tree.String_Elements.Table (List).Next;
5715 In_Tree.String_Elements.Table (Prev).Next :=
5716 In_Tree.String_Elements.Table (List).Next;
5724 end Find_Source_Dirs;
5726 -- Start of processing for Get_Directories
5728 Dir_Exists : Boolean;
5731 if Current_Verbosity = High then
5732 Write_Line ("Starting to look for directories");
5735 -- Set the object directory to its default which may be nil, if there
5736 -- is no sources in the project.
5738 if (((not Source_Files.Default)
5739 and then Source_Files.Values = Nil_String)
5741 ((not Source_Dirs.Default) and then Source_Dirs.Values = Nil_String)
5743 ((not Languages.Default) and then Languages.Values = Nil_String))
5744 and then Project.Extends = No_Project
5746 Project.Object_Directory := No_Path_Information;
5748 Project.Object_Directory := Project.Directory;
5751 -- Check the object directory
5753 if Object_Dir.Value /= Empty_String then
5754 Get_Name_String (Object_Dir.Value);
5756 if Name_Len = 0 then
5759 "Object_Dir cannot be empty",
5760 Object_Dir.Location);
5763 -- We check that the specified object directory does exist.
5764 -- However, even when it doesn't exist, we set it to a default
5765 -- value. This is for the benefit of tools that recover from
5766 -- errors; for example, these tools could create the non existent
5768 -- We always return an absolute directory name though
5773 File_Name_Type (Object_Dir.Value),
5774 Path => Project.Object_Directory,
5776 Dir_Exists => Dir_Exists,
5777 Location => Object_Dir.Location,
5778 Must_Exist => False,
5779 Externally_Built => Project.Externally_Built);
5782 and then not Project.Externally_Built
5784 -- The object directory does not exist, report an error if
5785 -- the project is not externally built.
5787 Err_Vars.Error_Msg_File_1 :=
5788 File_Name_Type (Object_Dir.Value);
5791 "object directory { not found",
5796 elsif Project.Object_Directory /= No_Path_Information
5797 and then Subdirs /= null
5800 Name_Buffer (1) := '.';
5805 Path => Project.Object_Directory,
5807 Dir_Exists => Dir_Exists,
5808 Location => Object_Dir.Location,
5809 Externally_Built => Project.Externally_Built);
5812 if Current_Verbosity = High then
5813 if Project.Object_Directory = No_Path_Information then
5814 Write_Line ("No object directory");
5817 ("Object directory",
5818 Get_Name_String (Project.Object_Directory.Display_Name));
5822 -- Check the exec directory
5824 -- We set the object directory to its default
5826 Project.Exec_Directory := Project.Object_Directory;
5828 if Exec_Dir.Value /= Empty_String then
5829 Get_Name_String (Exec_Dir.Value);
5831 if Name_Len = 0 then
5834 "Exec_Dir cannot be empty",
5838 -- We check that the specified exec directory does exist
5843 File_Name_Type (Exec_Dir.Value),
5844 Path => Project.Exec_Directory,
5845 Dir_Exists => Dir_Exists,
5847 Location => Exec_Dir.Location,
5848 Externally_Built => Project.Externally_Built);
5850 if not Dir_Exists then
5851 Err_Vars.Error_Msg_File_1 := File_Name_Type (Exec_Dir.Value);
5854 "exec directory { not found",
5860 if Current_Verbosity = High then
5861 if Project.Exec_Directory = No_Path_Information then
5862 Write_Line ("No exec directory");
5864 Write_Str ("Exec directory: """);
5865 Write_Str (Get_Name_String (Project.Exec_Directory.Display_Name));
5870 -- Look for the source directories
5872 if Current_Verbosity = High then
5873 Write_Line ("Starting to look for source directories");
5876 pragma Assert (Source_Dirs.Kind = List, "Source_Dirs is not a list");
5878 if (not Source_Files.Default) and then
5879 Source_Files.Values = Nil_String
5881 Project.Source_Dirs := Nil_String;
5883 if Project.Qualifier = Standard then
5887 "a standard project cannot have no sources",
5888 Source_Files.Location);
5891 elsif Source_Dirs.Default then
5893 -- No Source_Dirs specified: the single source directory is the one
5894 -- containing the project file
5896 String_Element_Table.Append (In_Tree.String_Elements,
5897 (Value => Name_Id (Project.Directory.Name),
5898 Display_Value => Name_Id (Project.Directory.Display_Name),
5899 Location => No_Location,
5903 Project.Source_Dirs := String_Element_Table.Last
5904 (In_Tree.String_Elements);
5906 if Current_Verbosity = High then
5908 ("Default source directory",
5909 Get_Name_String (Project.Directory.Display_Name));
5912 elsif Source_Dirs.Values = Nil_String then
5913 if Project.Qualifier = Standard then
5917 "a standard project cannot have no source directories",
5918 Source_Dirs.Location);
5921 Project.Source_Dirs := Nil_String;
5925 Source_Dir : String_List_Id;
5926 Element : String_Element;
5929 -- Process the source directories for each element of the list
5931 Source_Dir := Source_Dirs.Values;
5932 while Source_Dir /= Nil_String loop
5933 Element := In_Tree.String_Elements.Table (Source_Dir);
5935 (File_Name_Type (Element.Value), Element.Location);
5936 Source_Dir := Element.Next;
5941 if not Excluded_Source_Dirs.Default
5942 and then Excluded_Source_Dirs.Values /= Nil_String
5945 Source_Dir : String_List_Id;
5946 Element : String_Element;
5949 -- Process the source directories for each element of the list
5951 Source_Dir := Excluded_Source_Dirs.Values;
5952 while Source_Dir /= Nil_String loop
5953 Element := In_Tree.String_Elements.Table (Source_Dir);
5955 (File_Name_Type (Element.Value),
5958 Source_Dir := Element.Next;
5963 if Current_Verbosity = High then
5964 Write_Line ("Putting source directories in canonical cases");
5968 Current : String_List_Id := Project.Source_Dirs;
5969 Element : String_Element;
5972 while Current /= Nil_String loop
5973 Element := In_Tree.String_Elements.Table (Current);
5974 if Element.Value /= No_Name then
5976 Name_Id (Canonical_Case_File_Name (Name_Id (Element.Value)));
5977 In_Tree.String_Elements.Table (Current) := Element;
5980 Current := Element.Next;
5983 end Get_Directories;
5990 (Project : Project_Id;
5991 In_Tree : Project_Tree_Ref)
5993 Mains : constant Variable_Value :=
5994 Prj.Util.Value_Of (Name_Main, Project.Decl.Attributes, In_Tree);
5995 List : String_List_Id;
5996 Elem : String_Element;
5999 Project.Mains := Mains.Values;
6001 -- If no Mains were specified, and if we are an extending project,
6002 -- inherit the Mains from the project we are extending.
6004 if Mains.Default then
6005 if not Project.Library and then Project.Extends /= No_Project then
6006 Project.Mains := Project.Extends.Mains;
6009 -- In a library project file, Main cannot be specified
6011 elsif Project.Library then
6014 "a library project file cannot have Main specified",
6018 List := Mains.Values;
6019 while List /= Nil_String loop
6020 Elem := In_Tree.String_Elements.Table (List);
6022 if Length_Of_Name (Elem.Value) = 0 then
6025 "?a main cannot have an empty name",
6035 ---------------------------
6036 -- Get_Sources_From_File --
6037 ---------------------------
6039 procedure Get_Sources_From_File
6041 Location : Source_Ptr;
6042 Project : Project_Id;
6043 In_Tree : Project_Tree_Ref)
6045 File : Prj.Util.Text_File;
6046 Line : String (1 .. 250);
6048 Source_Name : File_Name_Type;
6049 Name_Loc : Name_Location;
6052 if Get_Mode = Ada_Only then
6056 if Current_Verbosity = High then
6057 Write_Str ("Opening """);
6064 Prj.Util.Open (File, Path);
6066 if not Prj.Util.Is_Valid (File) then
6067 Error_Msg (Project, In_Tree, "file does not exist", Location);
6070 -- Read the lines one by one
6072 while not Prj.Util.End_Of_File (File) loop
6073 Prj.Util.Get_Line (File, Line, Last);
6075 -- A non empty, non comment line should contain a file name
6078 and then (Last = 1 or else Line (1 .. 2) /= "--")
6081 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6082 Canonical_Case_File_Name (Name_Buffer (1 .. Name_Len));
6083 Source_Name := Name_Find;
6085 -- Check that there is no directory information
6087 for J in 1 .. Last loop
6088 if Line (J) = '/' or else Line (J) = Directory_Separator then
6089 Error_Msg_File_1 := Source_Name;
6093 "file name cannot include directory information ({)",
6099 Name_Loc := Source_Names.Get (Source_Name);
6101 if Name_Loc = No_Name_Location then
6103 (Name => Source_Name,
6104 Location => Location,
6105 Source => No_Source,
6110 Source_Names.Set (Source_Name, Name_Loc);
6114 Prj.Util.Close (File);
6117 end Get_Sources_From_File;
6119 -----------------------
6120 -- Compute_Unit_Name --
6121 -----------------------
6123 procedure Compute_Unit_Name
6124 (File_Name : File_Name_Type;
6125 Dot_Replacement : File_Name_Type;
6126 Separate_Suffix : File_Name_Type;
6127 Body_Suffix : File_Name_Type;
6128 Spec_Suffix : File_Name_Type;
6129 Casing : Casing_Type;
6130 Kind : out Source_Kind;
6132 In_Tree : Project_Tree_Ref)
6134 Filename : constant String := Get_Name_String (File_Name);
6135 Last : Integer := Filename'Last;
6136 Sep_Len : constant Integer :=
6137 Integer (Length_Of_Name (Separate_Suffix));
6138 Body_Len : constant Integer :=
6139 Integer (Length_Of_Name (Body_Suffix));
6140 Spec_Len : constant Integer :=
6141 Integer (Length_Of_Name (Spec_Suffix));
6143 Standard_GNAT : constant Boolean :=
6144 Spec_Suffix = Default_Ada_Spec_Suffix
6146 Body_Suffix = Default_Ada_Body_Suffix;
6148 Unit_Except : Unit_Exception;
6149 Masked : Boolean := False;
6154 if Dot_Replacement = No_File then
6155 if Current_Verbosity = High then
6156 Write_Line (" No dot_replacement specified");
6161 -- Choose the longest suffix that matches. If there are several matches,
6162 -- give priority to specs, then bodies, then separates.
6164 if Separate_Suffix /= Body_Suffix
6165 and then Suffix_Matches (Filename, Separate_Suffix)
6167 Last := Filename'Last - Sep_Len;
6171 if Filename'Last - Body_Len <= Last
6172 and then Suffix_Matches (Filename, Body_Suffix)
6174 Last := Natural'Min (Last, Filename'Last - Body_Len);
6178 if Filename'Last - Spec_Len <= Last
6179 and then Suffix_Matches (Filename, Spec_Suffix)
6181 Last := Natural'Min (Last, Filename'Last - Spec_Len);
6185 if Last = Filename'Last then
6186 if Current_Verbosity = High then
6187 Write_Line (" No matching suffix");
6192 -- Check that the casing matches
6194 if File_Names_Case_Sensitive then
6196 when All_Lower_Case =>
6197 for J in Filename'First .. Last loop
6198 if Is_Letter (Filename (J))
6199 and then not Is_Lower (Filename (J))
6201 if Current_Verbosity = High then
6202 Write_Line (" Invalid casing");
6208 when All_Upper_Case =>
6209 for J in Filename'First .. Last loop
6210 if Is_Letter (Filename (J))
6211 and then not Is_Upper (Filename (J))
6213 if Current_Verbosity = High then
6214 Write_Line (" Invalid casing");
6220 when Mixed_Case | Unknown =>
6225 -- If Dot_Replacement is not a single dot, then there should not
6226 -- be any dot in the name.
6229 Dot_Repl : constant String := Get_Name_String (Dot_Replacement);
6232 if Dot_Repl /= "." then
6233 for Index in Filename'First .. Last loop
6234 if Filename (Index) = '.' then
6235 if Current_Verbosity = High then
6236 Write_Line (" Invalid name, contains dot");
6242 Replace_Into_Name_Buffer
6243 (Filename (Filename'First .. Last), Dot_Repl, '.');
6245 Name_Len := Last - Filename'First + 1;
6246 Name_Buffer (1 .. Name_Len) := Filename (Filename'First .. Last);
6248 (Source => Name_Buffer (1 .. Name_Len),
6249 Mapping => Lower_Case_Map);
6253 -- In the standard GNAT naming scheme, check for special cases: children
6254 -- or separates of A, G, I or S, and run time sources.
6256 if Standard_GNAT and then Name_Len >= 3 then
6258 S1 : constant Character := Name_Buffer (1);
6259 S2 : constant Character := Name_Buffer (2);
6260 S3 : constant Character := Name_Buffer (3);
6268 -- Children or separates of packages A, G, I or S. These names
6269 -- are x__ ... or x~... (where x is a, g, i, or s). Both
6270 -- versions (x__... and x~...) are allowed in all platforms,
6271 -- because it is not possible to know the platform before
6272 -- processing of the project files.
6274 if S2 = '_' and then S3 = '_' then
6275 Name_Buffer (2) := '.';
6276 Name_Buffer (3 .. Name_Len - 1) :=
6277 Name_Buffer (4 .. Name_Len);
6278 Name_Len := Name_Len - 1;
6281 Name_Buffer (2) := '.';
6285 -- If it is potentially a run time source, disable filling
6286 -- of the mapping file to avoid warnings.
6288 Set_Mapping_File_Initial_State_To_Empty (In_Tree);
6294 -- Name_Buffer contains the name of the the unit in lower-cases. Check
6295 -- that this is a valid unit name
6297 Check_Ada_Name (Name_Buffer (1 .. Name_Len), Unit);
6299 -- If there is a naming exception for the same unit, the file is not
6300 -- a source for the unit. Currently, this only applies in multi_lang
6301 -- mode, since Unit_Exceptions is no set in ada_only mode.
6303 if Unit /= No_Name then
6304 Unit_Except := Unit_Exceptions.Get (Unit);
6307 Masked := Unit_Except.Spec /= No_File
6309 Unit_Except.Spec /= File_Name;
6311 Masked := Unit_Except.Impl /= No_File
6313 Unit_Except.Impl /= File_Name;
6317 if Current_Verbosity = High then
6318 Write_Str (" """ & Filename & """ contains the ");
6321 Write_Str ("spec of a unit found in """);
6322 Write_Str (Get_Name_String (Unit_Except.Spec));
6324 Write_Str ("body of a unit found in """);
6325 Write_Str (Get_Name_String (Unit_Except.Impl));
6328 Write_Line (""" (ignored)");
6336 and then Current_Verbosity = High
6339 when Spec => Write_Str (" spec of ");
6340 when Impl => Write_Str (" body of ");
6341 when Sep => Write_Str (" sep of ");
6344 Write_Line (Get_Name_String (Unit));
6346 end Compute_Unit_Name;
6353 (In_Tree : Project_Tree_Ref;
6354 Canonical_File_Name : File_Name_Type;
6355 Naming : Naming_Data;
6356 Exception_Id : out Ada_Naming_Exception_Id;
6357 Unit_Name : out Name_Id;
6358 Unit_Kind : out Spec_Or_Body)
6360 Info_Id : Ada_Naming_Exception_Id :=
6361 Ada_Naming_Exceptions.Get (Canonical_File_Name);
6362 VMS_Name : File_Name_Type;
6366 if Info_Id = No_Ada_Naming_Exception
6367 and then Hostparm.OpenVMS
6369 VMS_Name := Canonical_File_Name;
6370 Get_Name_String (VMS_Name);
6372 if Name_Buffer (Name_Len) = '.' then
6373 Name_Len := Name_Len - 1;
6374 VMS_Name := Name_Find;
6377 Info_Id := Ada_Naming_Exceptions.Get (VMS_Name);
6380 if Info_Id /= No_Ada_Naming_Exception then
6381 Exception_Id := Info_Id;
6382 Unit_Name := No_Name;
6386 Exception_Id := No_Ada_Naming_Exception;
6388 (File_Name => Canonical_File_Name,
6389 Dot_Replacement => Naming.Dot_Replacement,
6390 Separate_Suffix => Naming.Separate_Suffix,
6391 Body_Suffix => Body_Suffix_Id_Of (In_Tree, Name_Ada, Naming),
6392 Spec_Suffix => Spec_Suffix_Id_Of (In_Tree, Name_Ada, Naming),
6393 Casing => Naming.Casing,
6396 In_Tree => In_Tree);
6399 when Spec => Unit_Kind := Spec;
6400 when Impl | Sep => Unit_Kind := Impl;
6409 function Hash (Unit : Unit_Info) return Header_Num is
6411 return Header_Num (Unit.Unit mod 2048);
6414 -----------------------
6415 -- Is_Illegal_Suffix --
6416 -----------------------
6418 function Is_Illegal_Suffix
6419 (Suffix : File_Name_Type;
6420 Dot_Replacement : File_Name_Type) return Boolean
6422 Suffix_Str : constant String := Get_Name_String (Suffix);
6425 if Suffix_Str'Length = 0 then
6427 elsif Index (Suffix_Str, ".") = 0 then
6431 -- Case of dot replacement is a single dot, and first character of
6432 -- suffix is also a dot.
6434 if Get_Name_String (Dot_Replacement) = "."
6435 and then Suffix_Str (Suffix_Str'First) = '.'
6437 for Index in Suffix_Str'First + 1 .. Suffix_Str'Last loop
6439 -- Case of following dot
6441 if Suffix_Str (Index) = '.' then
6443 -- It is illegal to have a letter following the initial dot
6445 return Is_Letter (Suffix_Str (Suffix_Str'First + 1));
6451 end Is_Illegal_Suffix;
6453 ----------------------
6454 -- Locate_Directory --
6455 ----------------------
6457 procedure Locate_Directory
6458 (Project : Project_Id;
6459 In_Tree : Project_Tree_Ref;
6460 Name : File_Name_Type;
6461 Path : out Path_Information;
6462 Dir_Exists : out Boolean;
6463 Create : String := "";
6464 Location : Source_Ptr := No_Location;
6465 Must_Exist : Boolean := True;
6466 Externally_Built : Boolean := False)
6468 Parent : constant Path_Name_Type :=
6469 Project.Directory.Display_Name;
6470 The_Parent : constant String :=
6471 Get_Name_String (Parent) & Directory_Separator;
6472 The_Parent_Last : constant Natural :=
6473 Compute_Directory_Last (The_Parent);
6474 Full_Name : File_Name_Type;
6475 The_Name : File_Name_Type;
6478 Get_Name_String (Name);
6480 -- Add Subdirs.all if it is a directory that may be created and
6481 -- Subdirs is not null;
6483 if Create /= "" and then Subdirs /= null then
6484 if Name_Buffer (Name_Len) /= Directory_Separator then
6485 Add_Char_To_Name_Buffer (Directory_Separator);
6488 Add_Str_To_Name_Buffer (Subdirs.all);
6491 -- Convert '/' to directory separator (for Windows)
6493 for J in 1 .. Name_Len loop
6494 if Name_Buffer (J) = '/' then
6495 Name_Buffer (J) := Directory_Separator;
6499 The_Name := Name_Find;
6501 if Current_Verbosity = High then
6502 Write_Str ("Locate_Directory (""");
6503 Write_Str (Get_Name_String (The_Name));
6504 Write_Str (""", """);
6505 Write_Str (The_Parent);
6509 Path := No_Path_Information;
6510 Dir_Exists := False;
6512 if Is_Absolute_Path (Get_Name_String (The_Name)) then
6513 Full_Name := The_Name;
6517 Add_Str_To_Name_Buffer
6518 (The_Parent (The_Parent'First .. The_Parent_Last));
6519 Add_Str_To_Name_Buffer (Get_Name_String (The_Name));
6520 Full_Name := Name_Find;
6524 Full_Path_Name : String_Access :=
6525 new String'(Get_Name_String (Full_Name));
6528 if (Setup_Projects or else Subdirs /= null)
6529 and then Create'Length > 0
6531 if not Is_Directory (Full_Path_Name.all) then
6533 -- If project is externally built, do not create a subdir,
6534 -- use the specified directory, without the subdir.
6536 if Externally_Built then
6537 if Is_Absolute_Path (Get_Name_String (Name)) then
6538 Get_Name_String (Name);
6542 Add_Str_To_Name_Buffer
6543 (The_Parent (The_Parent'First .. The_Parent_Last));
6544 Add_Str_To_Name_Buffer (Get_Name_String (Name));
6547 Full_Path_Name := new String'(Name_Buffer (1 .. Name_Len));
6551 Create_Path (Full_Path_Name.all);
6553 if not Quiet_Output then
6555 Write_Str (" directory """);
6556 Write_Str (Full_Path_Name.all);
6557 Write_Str (""" created for project ");
6558 Write_Line (Get_Name_String (Project.Name));
6565 "could not create " & Create &
6566 " directory " & Full_Path_Name.all,
6573 Dir_Exists := Is_Directory (Full_Path_Name.all);
6575 if not Must_Exist or else Dir_Exists then
6577 Normed : constant String :=
6579 (Full_Path_Name.all,
6581 The_Parent (The_Parent'First .. The_Parent_Last),
6582 Resolve_Links => False,
6583 Case_Sensitive => True);
6585 Canonical_Path : constant String :=
6590 (The_Parent'First .. The_Parent_Last),
6592 Opt.Follow_Links_For_Dirs,
6593 Case_Sensitive => False);
6596 Name_Len := Normed'Length;
6597 Name_Buffer (1 .. Name_Len) := Normed;
6598 Path.Display_Name := Name_Find;
6600 Name_Len := Canonical_Path'Length;
6601 Name_Buffer (1 .. Name_Len) := Canonical_Path;
6602 Path.Name := Name_Find;
6606 Free (Full_Path_Name);
6608 end Locate_Directory;
6610 ---------------------------
6611 -- Find_Excluded_Sources --
6612 ---------------------------
6614 procedure Find_Excluded_Sources
6615 (Project : Project_Id;
6616 In_Tree : Project_Tree_Ref)
6618 Excluded_Source_List_File : constant Variable_Value :=
6620 (Name_Excluded_Source_List_File,
6621 Project.Decl.Attributes,
6624 Excluded_Sources : Variable_Value := Util.Value_Of
6625 (Name_Excluded_Source_Files,
6626 Project.Decl.Attributes,
6629 Current : String_List_Id;
6630 Element : String_Element;
6631 Location : Source_Ptr;
6632 Name : File_Name_Type;
6633 File : Prj.Util.Text_File;
6634 Line : String (1 .. 300);
6636 Locally_Removed : Boolean := False;
6639 -- If Excluded_Source_Files is not declared, check
6640 -- Locally_Removed_Files.
6642 if Excluded_Sources.Default then
6643 Locally_Removed := True;
6646 (Name_Locally_Removed_Files, Project.Decl.Attributes, In_Tree);
6649 Excluded_Sources_Htable.Reset;
6651 -- If there are excluded sources, put them in the table
6653 if not Excluded_Sources.Default then
6654 if not Excluded_Source_List_File.Default then
6655 if Locally_Removed then
6658 "?both attributes Locally_Removed_Files and " &
6659 "Excluded_Source_List_File are present",
6660 Excluded_Source_List_File.Location);
6664 "?both attributes Excluded_Source_Files and " &
6665 "Excluded_Source_List_File are present",
6666 Excluded_Source_List_File.Location);
6670 Current := Excluded_Sources.Values;
6671 while Current /= Nil_String loop
6672 Element := In_Tree.String_Elements.Table (Current);
6673 Name := Canonical_Case_File_Name (Element.Value);
6675 -- If the element has no location, then use the location of
6676 -- Excluded_Sources to report possible errors.
6678 if Element.Location = No_Location then
6679 Location := Excluded_Sources.Location;
6681 Location := Element.Location;
6684 Excluded_Sources_Htable.Set (Name, (Name, False, Location));
6685 Current := Element.Next;
6688 elsif not Excluded_Source_List_File.Default then
6689 Location := Excluded_Source_List_File.Location;
6692 Source_File_Path_Name : constant String :=
6695 (Excluded_Source_List_File.Value),
6696 Project.Directory.Name);
6699 if Source_File_Path_Name'Length = 0 then
6700 Err_Vars.Error_Msg_File_1 :=
6701 File_Name_Type (Excluded_Source_List_File.Value);
6704 "file with excluded sources { does not exist",
6705 Excluded_Source_List_File.Location);
6710 Prj.Util.Open (File, Source_File_Path_Name);
6712 if not Prj.Util.Is_Valid (File) then
6714 (Project, In_Tree, "file does not exist", Location);
6716 -- Read the lines one by one
6718 while not Prj.Util.End_Of_File (File) loop
6719 Prj.Util.Get_Line (File, Line, Last);
6721 -- Non empty, non comment line should contain a file name
6724 and then (Last = 1 or else Line (1 .. 2) /= "--")
6727 Name_Buffer (1 .. Name_Len) := Line (1 .. Last);
6728 Canonical_Case_File_Name
6729 (Name_Buffer (1 .. Name_Len));
6732 -- Check that there is no directory information
6734 for J in 1 .. Last loop
6736 or else Line (J) = Directory_Separator
6738 Error_Msg_File_1 := Name;
6742 "file name cannot include " &
6743 "directory information ({)",
6749 Excluded_Sources_Htable.Set
6750 (Name, (Name, False, Location));
6754 Prj.Util.Close (File);
6759 end Find_Excluded_Sources;
6765 procedure Find_Sources
6766 (Project : Project_Id;
6767 In_Tree : Project_Tree_Ref;
6768 Proc_Data : in out Processing_Data;
6769 Allow_Duplicate_Basenames : Boolean)
6771 Sources : constant Variable_Value :=
6774 Project.Decl.Attributes,
6776 Source_List_File : constant Variable_Value :=
6778 (Name_Source_List_File,
6779 Project.Decl.Attributes,
6781 Name_Loc : Name_Location;
6783 Has_Explicit_Sources : Boolean;
6786 pragma Assert (Sources.Kind = List, "Source_Files is not a list");
6788 (Source_List_File.Kind = Single,
6789 "Source_List_File is not a single string");
6791 -- If the user has specified a Source_Files attribute
6793 if not Sources.Default then
6794 if not Source_List_File.Default then
6797 "?both attributes source_files and " &
6798 "source_list_file are present",
6799 Source_List_File.Location);
6802 -- Sources is a list of file names
6805 Current : String_List_Id := Sources.Values;
6806 Element : String_Element;
6807 Location : Source_Ptr;
6808 Name : File_Name_Type;
6811 if Get_Mode = Multi_Language then
6812 if Current = Nil_String then
6813 Project.Languages := No_Language_Index;
6815 -- This project contains no source. For projects that don't
6816 -- extend other projects, this also means that there is no
6817 -- need for an object directory, if not specified.
6819 if Project.Extends = No_Project
6820 and then Project.Object_Directory = Project.Directory
6822 Project.Object_Directory := No_Path_Information;
6827 while Current /= Nil_String loop
6828 Element := In_Tree.String_Elements.Table (Current);
6829 Name := Canonical_Case_File_Name (Element.Value);
6830 Get_Name_String (Element.Value);
6832 -- If the element has no location, then use the location of
6833 -- Sources to report possible errors.
6835 if Element.Location = No_Location then
6836 Location := Sources.Location;
6838 Location := Element.Location;
6841 -- Check that there is no directory information
6843 for J in 1 .. Name_Len loop
6844 if Name_Buffer (J) = '/'
6845 or else Name_Buffer (J) = Directory_Separator
6847 Error_Msg_File_1 := Name;
6851 "file name cannot include directory " &
6858 -- In Multi_Language mode, check whether the file is already
6859 -- there: the same file name may be in the list. If the source
6860 -- is missing, the error will be on the first mention of the
6861 -- source file name.
6865 Name_Loc := No_Name_Location;
6866 when Multi_Language =>
6867 Name_Loc := Source_Names.Get (Name);
6870 if Name_Loc = No_Name_Location then
6873 Location => Location,
6874 Source => No_Source,
6877 Source_Names.Set (Name, Name_Loc);
6880 Current := Element.Next;
6883 Has_Explicit_Sources := True;
6886 -- If we have no Source_Files attribute, check the Source_List_File
6889 elsif not Source_List_File.Default then
6891 -- Source_List_File is the name of the file that contains the source
6895 Source_File_Path_Name : constant String :=
6897 (File_Name_Type (Source_List_File.Value),
6898 Project.Directory.Name);
6901 Has_Explicit_Sources := True;
6903 if Source_File_Path_Name'Length = 0 then
6904 Err_Vars.Error_Msg_File_1 :=
6905 File_Name_Type (Source_List_File.Value);
6908 "file with sources { does not exist",
6909 Source_List_File.Location);
6912 Get_Sources_From_File
6913 (Source_File_Path_Name, Source_List_File.Location,
6919 -- Neither Source_Files nor Source_List_File has been specified. Find
6920 -- all the files that satisfy the naming scheme in all the source
6923 Has_Explicit_Sources := False;
6926 if Get_Mode = Ada_Only then
6929 Explicit_Sources_Only => Has_Explicit_Sources,
6930 Proc_Data => Proc_Data);
6936 Sources.Default and then Source_List_File.Default,
6937 Allow_Duplicate_Basenames => Allow_Duplicate_Basenames);
6940 -- Check if all exceptions have been found. For Ada, it is an error if
6941 -- an exception is not found. For other language, the source is simply
6946 Iter : Source_Iterator;
6949 Iter := For_Each_Source (In_Tree, Project);
6951 Source := Prj.Element (Iter);
6952 exit when Source = No_Source;
6954 if Source.Naming_Exception
6955 and then Source.Path = No_Path_Information
6957 if Source.Unit /= No_Unit_Index then
6958 Error_Msg_Name_1 := Name_Id (Source.Display_File);
6959 Error_Msg_Name_2 := Name_Id (Source.Unit.Name);
6962 "source file %% for unit %% not found",
6966 Remove_Source (Source, No_Source);
6973 -- It is an error if a source file name in a source list or in a source
6974 -- list file is not found.
6976 if Has_Explicit_Sources then
6979 First_Error : Boolean;
6982 NL := Source_Names.Get_First;
6983 First_Error := True;
6984 while NL /= No_Name_Location loop
6985 if not NL.Found then
6986 Err_Vars.Error_Msg_File_1 := NL.Name;
6991 "source file { not found",
6993 First_Error := False;
6998 "\source file { not found",
7003 NL := Source_Names.Get_Next;
7008 if Get_Mode = Ada_Only
7009 and then Project.Extends = No_Project
7011 -- We should have found at least one source, if not report an error
7013 if not Has_Ada_Sources (Project) then
7015 (Project, "Ada", In_Tree, Source_List_File.Location);
7024 procedure Initialize (Proc_Data : in out Processing_Data) is
7026 Files_Htable.Reset (Proc_Data.Units);
7033 procedure Free (Proc_Data : in out Processing_Data) is
7035 Files_Htable.Reset (Proc_Data.Units);
7038 ----------------------
7039 -- Find_Ada_Sources --
7040 ----------------------
7042 procedure Find_Ada_Sources
7043 (Project : Project_Id;
7044 In_Tree : Project_Tree_Ref;
7045 Explicit_Sources_Only : Boolean;
7046 Proc_Data : in out Processing_Data)
7048 Source_Dir : String_List_Id;
7049 Element : String_Element;
7051 Dir_Has_Source : Boolean := False;
7053 Ada_Language : Language_Ptr;
7056 if Current_Verbosity = High then
7057 Write_Line ("Looking for Ada sources:");
7060 Ada_Language := Project.Languages;
7061 while Ada_Language /= No_Language_Index
7062 and then Ada_Language.Name /= Name_Ada
7064 Ada_Language := Ada_Language.Next;
7067 -- We look in all source directories for the file names in the hash
7068 -- table Source_Names.
7070 Source_Dir := Project.Source_Dirs;
7071 while Source_Dir /= Nil_String loop
7072 Dir_Has_Source := False;
7073 Element := In_Tree.String_Elements.Table (Source_Dir);
7076 Dir_Path : constant String :=
7077 Get_Name_String (Element.Display_Value) &
7078 Directory_Separator;
7079 Dir_Last : constant Natural := Compute_Directory_Last (Dir_Path);
7082 if Current_Verbosity = High then
7083 Write_Line ("checking directory """ & Dir_Path & """");
7086 -- Look for all files in the current source directory
7088 Open (Dir, Dir_Path (Dir_Path'First .. Dir_Last));
7091 Read (Dir, Name_Buffer, Name_Len);
7092 exit when Name_Len = 0;
7094 if Current_Verbosity = High then
7095 Write_Line (" Checking " & Name_Buffer (1 .. Name_Len));
7099 Name : constant File_Name_Type := Name_Find;
7100 Canonical_Name : File_Name_Type;
7102 -- ??? We could probably optimize the following call: we
7103 -- need to resolve links only once for the directory itself,
7104 -- and then do a single call to readlink() for each file.
7105 -- Unfortunately that would require a change in
7106 -- Normalize_Pathname so that it has the option of not
7107 -- resolving links for its Directory parameter, only for
7110 Path : constant String :=
7112 (Name => Name_Buffer (1 .. Name_Len),
7113 Directory => Dir_Path (Dir_Path'First .. Dir_Last),
7114 Resolve_Links => Opt.Follow_Links_For_Files,
7115 Case_Sensitive => True); -- no case folding
7117 Path_Name : Path_Name_Type;
7118 To_Record : Boolean := False;
7119 Location : Source_Ptr;
7122 -- If the file was listed in the explicit list of sources,
7123 -- mark it as such (since we'll need to report an error when
7124 -- an explicit source was not found)
7126 if Explicit_Sources_Only then
7128 Canonical_Case_File_Name (Name_Id (Name));
7129 NL := Source_Names.Get (Canonical_Name);
7130 To_Record := NL /= No_Name_Location and then not NL.Found;
7134 Location := NL.Location;
7135 Source_Names.Set (Canonical_Name, NL);
7140 Location := No_Location;
7144 Name_Len := Path'Length;
7145 Name_Buffer (1 .. Name_Len) := Path;
7146 Path_Name := Name_Find;
7148 if Current_Verbosity = High then
7149 Write_Line (" recording " & Get_Name_String (Name));
7152 -- Register the source if it is an Ada compilation unit
7156 Path_Name => Path_Name,
7159 Proc_Data => Proc_Data,
7160 Ada_Language => Ada_Language,
7161 Location => Location,
7162 Source_Recorded => Dir_Has_Source);
7175 if Dir_Has_Source then
7176 In_Tree.String_Elements.Table (Source_Dir).Flag := True;
7179 Source_Dir := Element.Next;
7182 if Current_Verbosity = High then
7183 Write_Line ("End looking for sources");
7185 end Find_Ada_Sources;
7187 -------------------------------
7188 -- Check_File_Naming_Schemes --
7189 -------------------------------
7191 procedure Check_File_Naming_Schemes
7192 (In_Tree : Project_Tree_Ref;
7193 Project : Project_Id;
7194 File_Name : File_Name_Type;
7195 Alternate_Languages : out Language_List;
7196 Language : out Language_Ptr;
7197 Display_Language_Name : out Name_Id;
7199 Lang_Kind : out Language_Kind;
7200 Kind : out Source_Kind)
7202 Filename : constant String := Get_Name_String (File_Name);
7203 Config : Language_Config;
7204 Tmp_Lang : Language_Ptr;
7206 Header_File : Boolean := False;
7207 -- True if we found at least one language for which the file is a header
7208 -- In such a case, we search for all possible languages where this is
7209 -- also a header (C and C++ for instance), since the file might be used
7210 -- for several such languages.
7212 procedure Check_File_Based_Lang;
7213 -- Does the naming scheme test for file-based languages. For those,
7214 -- there is no Unit. Just check if the file name has the implementation
7215 -- or, if it is specified, the template suffix of the language.
7217 -- Returns True if the file belongs to the current language and we
7218 -- should stop searching for matching languages. Not that a given header
7219 -- file could belong to several languages (C and C++ for instance). Thus
7220 -- if we found a header we'll check whether it matches other languages.
7222 ---------------------------
7223 -- Check_File_Based_Lang --
7224 ---------------------------
7226 procedure Check_File_Based_Lang is
7229 and then Suffix_Matches (Filename, Config.Naming_Data.Body_Suffix)
7233 Language := Tmp_Lang;
7235 if Current_Verbosity = High then
7236 Write_Str (" implementation of language ");
7237 Write_Line (Get_Name_String (Display_Language_Name));
7240 elsif Suffix_Matches (Filename, Config.Naming_Data.Spec_Suffix) then
7241 if Current_Verbosity = High then
7242 Write_Str (" header of language ");
7243 Write_Line (Get_Name_String (Display_Language_Name));
7247 Alternate_Languages := new Language_List_Element'
7248 (Language => Language,
7249 Next => Alternate_Languages);
7252 Header_File := True;
7255 Language := Tmp_Lang;
7258 end Check_File_Based_Lang;
7260 -- Start of processing for Check_File_Naming_Schemes
7263 Language := No_Language_Index;
7264 Alternate_Languages := null;
7265 Display_Language_Name := No_Name;
7267 Lang_Kind := File_Based;
7270 Tmp_Lang := Project.Languages;
7271 while Tmp_Lang /= No_Language_Index loop
7272 if Current_Verbosity = High then
7274 (" Testing language "
7275 & Get_Name_String (Tmp_Lang.Name)
7276 & " Header_File=" & Header_File'Img);
7279 Display_Language_Name := Tmp_Lang.Display_Name;
7280 Config := Tmp_Lang.Config;
7281 Lang_Kind := Config.Kind;
7285 Check_File_Based_Lang;
7286 exit when Kind = Impl;
7290 -- We know it belongs to a least a file_based language, no
7291 -- need to check unit-based ones.
7293 if not Header_File then
7295 (File_Name => File_Name,
7296 Dot_Replacement => Config.Naming_Data.Dot_Replacement,
7297 Separate_Suffix => Config.Naming_Data.Separate_Suffix,
7298 Body_Suffix => Config.Naming_Data.Body_Suffix,
7299 Spec_Suffix => Config.Naming_Data.Spec_Suffix,
7300 Casing => Config.Naming_Data.Casing,
7303 In_Tree => In_Tree);
7305 if Unit /= No_Name then
7306 Language := Tmp_Lang;
7312 Tmp_Lang := Tmp_Lang.Next;
7315 if Language = No_Language_Index
7316 and then Current_Verbosity = High
7318 Write_Line (" not a source of any language");
7320 end Check_File_Naming_Schemes;
7326 procedure Override_Kind (Source : Source_Id; Kind : Source_Kind) is
7327 Unit : constant Unit_Index := Source.Unit;
7329 -- Remove reference in the unit, if necessary
7332 and then Source.Kind in Spec_Or_Body
7333 and then Unit.File_Names (Source.Kind) /= null
7335 Unit.File_Names (Source.Kind).Unit := No_Unit_Index;
7336 Unit.File_Names (Source.Kind) := null;
7339 Source.Kind := Kind;
7341 if Source.Kind in Spec_Or_Body and then Source.Unit /= null then
7342 Source.Unit.File_Names (Source.Kind) := Source;
7350 procedure Check_File
7351 (Project : Project_Id;
7352 In_Tree : Project_Tree_Ref;
7353 Path : Path_Name_Type;
7354 File_Name : File_Name_Type;
7355 Display_File_Name : File_Name_Type;
7356 For_All_Sources : Boolean;
7357 Allow_Duplicate_Basenames : Boolean)
7359 Canonical_Path : constant Path_Name_Type :=
7361 (Canonical_Case_File_Name (Name_Id (Path)));
7363 Name_Loc : Name_Location := Source_Names.Get (File_Name);
7364 Check_Name : Boolean := False;
7365 Alternate_Languages : Language_List;
7366 Language : Language_Ptr;
7369 Src_Ind : Source_File_Index;
7371 Source_To_Replace : Source_Id := No_Source;
7372 Display_Language_Name : Name_Id;
7373 Lang_Kind : Language_Kind;
7374 Kind : Source_Kind := Spec;
7375 Iter : Source_Iterator;
7378 if Name_Loc = No_Name_Location then
7379 Check_Name := For_All_Sources;
7382 if Name_Loc.Found then
7384 -- Check if it is OK to have the same file name in several
7385 -- source directories.
7387 if not Project.Known_Order_Of_Source_Dirs then
7388 Error_Msg_File_1 := File_Name;
7391 "{ is found in several source directories",
7396 Name_Loc.Found := True;
7398 Source_Names.Set (File_Name, Name_Loc);
7400 if Name_Loc.Source = No_Source then
7404 Name_Loc.Source.Path := (Canonical_Path, Path);
7406 Source_Paths_Htable.Set
7407 (In_Tree.Source_Paths_HT,
7411 -- Check if this is a subunit
7413 if Name_Loc.Source.Unit /= No_Unit_Index
7414 and then Name_Loc.Source.Kind = Impl
7416 Src_Ind := Sinput.P.Load_Project_File
7417 (Get_Name_String (Canonical_Path));
7419 if Sinput.P.Source_File_Is_Subunit (Src_Ind) then
7420 Override_Kind (Name_Loc.Source, Sep);
7428 Check_File_Naming_Schemes
7429 (In_Tree => In_Tree,
7431 File_Name => File_Name,
7432 Alternate_Languages => Alternate_Languages,
7433 Language => Language,
7434 Display_Language_Name => Display_Language_Name,
7436 Lang_Kind => Lang_Kind,
7439 if Language = No_Language_Index then
7441 -- A file name in a list must be a source of a language
7443 if Name_Loc.Found then
7444 Error_Msg_File_1 := File_Name;
7448 "language unknown for {",
7453 -- Check if the same file name or unit is used in the prj tree
7455 Iter := For_Each_Source (In_Tree);
7458 Source := Prj.Element (Iter);
7459 exit when Source = No_Source;
7462 and then Source.Unit /= No_Unit_Index
7463 and then Source.Unit.Name = Unit
7465 ((Source.Kind = Spec and then Kind = Impl)
7467 (Source.Kind = Impl and then Kind = Spec))
7469 -- We found the "other_part (source)"
7473 elsif (Unit /= No_Name
7474 and then Source.Unit /= No_Unit_Index
7475 and then Source.Unit.Name = Unit
7479 (Source.Kind = Sep and then Kind = Impl)
7481 (Source.Kind = Impl and then Kind = Sep)))
7483 (Unit = No_Name and then Source.File = File_Name)
7485 -- Duplication of file/unit in same project is only
7486 -- allowed if order of source directories is known.
7488 if Project = Source.Project then
7489 if Unit = No_Name then
7490 if Allow_Duplicate_Basenames then
7492 elsif Project.Known_Order_Of_Source_Dirs then
7495 Error_Msg_File_1 := File_Name;
7497 (Project, In_Tree, "duplicate source file name {",
7503 if Project.Known_Order_Of_Source_Dirs then
7506 Error_Msg_Name_1 := Unit;
7508 (Project, In_Tree, "duplicate unit %%",
7514 -- Do not allow the same unit name in different projects,
7515 -- except if one is extending the other.
7517 -- For a file based language, the same file name replaces
7518 -- a file in a project being extended, but it is allowed
7519 -- to have the same file name in unrelated projects.
7521 elsif Is_Extending (Project, Source.Project) then
7522 Source_To_Replace := Source;
7524 elsif Unit /= No_Name
7525 and then not Source.Locally_Removed
7527 Error_Msg_Name_1 := Unit;
7530 "unit %% cannot belong to several projects",
7533 Error_Msg_Name_1 := Project.Name;
7534 Error_Msg_Name_2 := Name_Id (Path);
7536 (Project, In_Tree, "\ project %%, %%", No_Location);
7538 Error_Msg_Name_1 := Source.Project.Name;
7539 Error_Msg_Name_2 := Name_Id (Source.Path.Display_Name);
7541 (Project, In_Tree, "\ project %%, %%", No_Location);
7555 Lang_Id => Language,
7557 Alternate_Languages => Alternate_Languages,
7558 File_Name => File_Name,
7559 Display_File => Display_File_Name,
7561 Path => (Canonical_Path, Path),
7562 Source_To_Replace => Source_To_Replace);
7568 ------------------------
7569 -- Search_Directories --
7570 ------------------------
7572 procedure Search_Directories
7573 (Project : Project_Id;
7574 In_Tree : Project_Tree_Ref;
7575 For_All_Sources : Boolean;
7576 Allow_Duplicate_Basenames : Boolean)
7578 Source_Dir : String_List_Id;
7579 Element : String_Element;
7581 Name : String (1 .. 1_000);
7583 File_Name : File_Name_Type;
7584 Display_File_Name : File_Name_Type;
7587 if Current_Verbosity = High then
7588 Write_Line ("Looking for sources:");
7591 -- Loop through subdirectories
7593 Source_Dir := Project.Source_Dirs;
7594 while Source_Dir /= Nil_String loop
7596 Element := In_Tree.String_Elements.Table (Source_Dir);
7597 if Element.Value /= No_Name then
7598 Get_Name_String (Element.Display_Value);
7601 Source_Directory : constant String :=
7602 Name_Buffer (1 .. Name_Len) &
7603 Directory_Separator;
7605 Dir_Last : constant Natural :=
7606 Compute_Directory_Last
7610 if Current_Verbosity = High then
7611 Write_Attr ("Source_Dir", Source_Directory);
7614 -- We look to every entry in the source directory
7616 Open (Dir, Source_Directory);
7619 Read (Dir, Name, Last);
7623 -- ??? Duplicate system call here, we just did a
7624 -- a similar one. Maybe Ada.Directories would be more
7628 (Source_Directory & Name (1 .. Last))
7630 if Current_Verbosity = High then
7631 Write_Str (" Checking ");
7632 Write_Line (Name (1 .. Last));
7636 Name_Buffer (1 .. Name_Len) := Name (1 .. Last);
7637 Display_File_Name := Name_Find;
7639 if Osint.File_Names_Case_Sensitive then
7640 File_Name := Display_File_Name;
7642 Canonical_Case_File_Name
7643 (Name_Buffer (1 .. Name_Len));
7644 File_Name := Name_Find;
7648 Path_Name : constant String :=
7653 (Source_Directory'First ..
7656 Opt.Follow_Links_For_Files,
7657 Case_Sensitive => True);
7658 -- Case_Sensitive set True (no folding)
7660 Path : Path_Name_Type;
7662 Excluded_Sources_Htable.Get (File_Name);
7665 Name_Len := Path_Name'Length;
7666 Name_Buffer (1 .. Name_Len) := Path_Name;
7669 if FF /= No_File_Found then
7670 if not FF.Found then
7672 Excluded_Sources_Htable.Set (File_Name, FF);
7674 if Current_Verbosity = High then
7675 Write_Str (" excluded source """);
7676 Write_Str (Get_Name_String (File_Name));
7683 (Project => Project,
7686 File_Name => File_Name,
7687 Display_File_Name =>
7689 For_All_Sources => For_All_Sources,
7690 Allow_Duplicate_Basenames =>
7691 Allow_Duplicate_Basenames);
7702 when Directory_Error =>
7706 Source_Dir := Element.Next;
7709 if Current_Verbosity = High then
7710 Write_Line ("end Looking for sources.");
7712 end Search_Directories;
7714 ----------------------------
7715 -- Load_Naming_Exceptions --
7716 ----------------------------
7718 procedure Load_Naming_Exceptions
7719 (Project : Project_Id;
7720 In_Tree : Project_Tree_Ref)
7723 Iter : Source_Iterator;
7726 Unit_Exceptions.Reset;
7728 Iter := For_Each_Source (In_Tree, Project);
7730 Source := Prj.Element (Iter);
7731 exit when Source = No_Source;
7733 -- An excluded file cannot also be an exception file name
7735 if Excluded_Sources_Htable.Get (Source.File) /= No_File_Found then
7736 Error_Msg_File_1 := Source.File;
7739 "{ cannot be both excluded and an exception file name",
7743 if Current_Verbosity = High then
7744 Write_Str ("Naming exception: Putting source file ");
7745 Write_Str (Get_Name_String (Source.File));
7746 Write_Line (" in Source_Names");
7752 (Name => Source.File,
7753 Location => No_Location,
7755 Except => Source.Unit /= No_Unit_Index,
7758 -- If this is an Ada exception, record in table Unit_Exceptions
7760 if Source.Unit /= No_Unit_Index then
7762 Unit_Except : Unit_Exception :=
7763 Unit_Exceptions.Get (Source.Unit.Name);
7766 Unit_Except.Name := Source.Unit.Name;
7768 if Source.Kind = Spec then
7769 Unit_Except.Spec := Source.File;
7771 Unit_Except.Impl := Source.File;
7774 Unit_Exceptions.Set (Source.Unit.Name, Unit_Except);
7780 end Load_Naming_Exceptions;
7782 ----------------------
7783 -- Look_For_Sources --
7784 ----------------------
7786 procedure Look_For_Sources
7787 (Project : Project_Id;
7788 In_Tree : Project_Tree_Ref;
7789 Proc_Data : in out Processing_Data;
7790 Allow_Duplicate_Basenames : Boolean)
7792 Iter : Source_Iterator;
7794 procedure Process_Sources_In_Multi_Language_Mode;
7795 -- Find all source files when in multi language mode
7797 procedure Mark_Excluded_Sources;
7798 -- Mark as such the sources that are declared as excluded
7800 ---------------------------
7801 -- Mark_Excluded_Sources --
7802 ---------------------------
7804 procedure Mark_Excluded_Sources is
7805 Source : Source_Id := No_Source;
7807 Excluded : File_Found;
7810 Excluded := Excluded_Sources_Htable.Get_First;
7811 while Excluded /= No_File_Found loop
7814 -- ??? Don't we have a hash table to map files to Source_Id?
7816 Iter := For_Each_Source (In_Tree);
7818 Source := Prj.Element (Iter);
7819 exit when Source = No_Source;
7821 if Source.File = Excluded.File then
7822 if Source.Project = Project
7823 or else Is_Extending (Project, Source.Project)
7826 Source.Locally_Removed := True;
7827 Source.In_Interfaces := False;
7829 if Current_Verbosity = High then
7830 Write_Str ("Removing file ");
7831 Write_Line (Get_Name_String (Excluded.File));
7834 Add_Forbidden_File_Name (Excluded.File);
7839 "cannot remove a source from another project",
7849 OK := OK or Excluded.Found;
7852 Err_Vars.Error_Msg_File_1 := Excluded.File;
7854 (Project, In_Tree, "unknown file {", Excluded.Location);
7857 Excluded := Excluded_Sources_Htable.Get_Next;
7859 end Mark_Excluded_Sources;
7861 --------------------------------------------
7862 -- Process_Sources_In_Multi_Language_Mode --
7863 --------------------------------------------
7865 procedure Process_Sources_In_Multi_Language_Mode is
7866 Iter : Source_Iterator;
7869 -- Check that two sources of this project do not have the same object
7872 Check_Object_File_Names : declare
7874 Source_Name : File_Name_Type;
7876 procedure Check_Object (Src : Source_Id);
7877 -- Check if object file name of the current source is already in
7878 -- hash table Object_File_Names. If it is, report an error. If it
7879 -- is not, put it there with the file name of the current source.
7885 procedure Check_Object (Src : Source_Id) is
7887 Source_Name := Object_File_Names.Get (Src.Object);
7889 if Source_Name /= No_File then
7890 Error_Msg_File_1 := Src.File;
7891 Error_Msg_File_2 := Source_Name;
7895 "{ and { have the same object file name",
7899 Object_File_Names.Set (Src.Object, Src.File);
7903 -- Start of processing for Check_Object_File_Names
7906 Object_File_Names.Reset;
7907 Iter := For_Each_Source (In_Tree);
7909 Src_Id := Prj.Element (Iter);
7910 exit when Src_Id = No_Source;
7912 if Is_Compilable (Src_Id)
7913 and then Src_Id.Language.Config.Object_Generated
7914 and then Is_Extending (Project, Src_Id.Project)
7916 if Src_Id.Unit = No_Unit_Index then
7917 if Src_Id.Kind = Impl then
7918 Check_Object (Src_Id);
7924 if Other_Part (Src_Id) = No_Source then
7925 Check_Object (Src_Id);
7932 if Other_Part (Src_Id) /= No_Source then
7933 Check_Object (Src_Id);
7936 -- Check if it is a subunit
7939 Src_Ind : constant Source_File_Index :=
7940 Sinput.P.Load_Project_File
7942 (Src_Id.Path.Name));
7944 if Sinput.P.Source_File_Is_Subunit
7947 Override_Kind (Src_Id, Sep);
7949 Check_Object (Src_Id);
7959 end Check_Object_File_Names;
7960 end Process_Sources_In_Multi_Language_Mode;
7962 -- Start of processing for Look_For_Sources
7966 Find_Excluded_Sources (Project, In_Tree);
7968 if (Get_Mode = Ada_Only and then Is_A_Language (Project, Name_Ada))
7969 or else (Get_Mode = Multi_Language
7970 and then Project.Languages /= No_Language_Index)
7972 if Get_Mode = Multi_Language then
7973 Load_Naming_Exceptions (Project, In_Tree);
7976 Find_Sources (Project, In_Tree, Proc_Data, Allow_Duplicate_Basenames);
7977 Mark_Excluded_Sources;
7979 if Get_Mode = Multi_Language then
7980 Process_Sources_In_Multi_Language_Mode;
7983 end Look_For_Sources;
7989 function Path_Name_Of
7990 (File_Name : File_Name_Type;
7991 Directory : Path_Name_Type) return String
7993 Result : String_Access;
7994 The_Directory : constant String := Get_Name_String (Directory);
7997 Get_Name_String (File_Name);
8000 (File_Name => Name_Buffer (1 .. Name_Len),
8001 Path => The_Directory);
8003 if Result = null then
8007 R : String := Result.all;
8010 Canonical_Case_File_Name (R);
8016 -----------------------------------
8017 -- Prepare_Ada_Naming_Exceptions --
8018 -----------------------------------
8020 procedure Prepare_Ada_Naming_Exceptions
8021 (List : Array_Element_Id;
8022 In_Tree : Project_Tree_Ref;
8023 Kind : Spec_Or_Body)
8025 Current : Array_Element_Id;
8026 Element : Array_Element;
8030 -- Traverse the list
8033 while Current /= No_Array_Element loop
8034 Element := In_Tree.Array_Elements.Table (Current);
8036 if Element.Index /= No_Name then
8039 Unit => Element.Index,
8040 Next => No_Ada_Naming_Exception);
8041 Reverse_Ada_Naming_Exceptions.Set
8042 (Unit, (Element.Value.Value, Element.Value.Index));
8044 Ada_Naming_Exceptions.Get (File_Name_Type (Element.Value.Value));
8045 Ada_Naming_Exception_Table.Increment_Last;
8046 Ada_Naming_Exception_Table.Table
8047 (Ada_Naming_Exception_Table.Last) := Unit;
8048 Ada_Naming_Exceptions.Set
8049 (File_Name_Type (Element.Value.Value),
8050 Ada_Naming_Exception_Table.Last);
8053 Current := Element.Next;
8055 end Prepare_Ada_Naming_Exceptions;
8057 -----------------------
8058 -- Record_Ada_Source --
8059 -----------------------
8061 procedure Record_Ada_Source
8062 (File_Name : File_Name_Type;
8063 Path_Name : Path_Name_Type;
8064 Project : Project_Id;
8065 In_Tree : Project_Tree_Ref;
8066 Proc_Data : in out Processing_Data;
8067 Ada_Language : Language_Ptr;
8068 Location : Source_Ptr;
8069 Source_Recorded : in out Boolean)
8071 Canonical_File : File_Name_Type;
8072 Canonical_Path : Path_Name_Type;
8074 File_Recorded : Boolean := False;
8075 -- True when at least one file has been recorded
8077 procedure Record_Unit
8078 (Unit_Name : Name_Id;
8079 Unit_Ind : Int := 0;
8080 Unit_Kind : Spec_Or_Body;
8081 Needs_Pragma : Boolean);
8082 -- Register of the units contained in the source file (there is in
8083 -- general a single such unit except when exceptions to the naming
8084 -- scheme indicate there are several such units)
8090 procedure Record_Unit
8091 (Unit_Name : Name_Id;
8092 Unit_Ind : Int := 0;
8093 Unit_Kind : Spec_Or_Body;
8094 Needs_Pragma : Boolean)
8096 UData : constant Unit_Index :=
8097 Units_Htable.Get (In_Tree.Units_HT, Unit_Name);
8098 -- ??? Add_Source will look it up again, can we do that only once ?
8101 To_Record : Boolean := False;
8102 The_Location : Source_Ptr := Location;
8103 Unit_Prj : Project_Id;
8106 if Current_Verbosity = High then
8107 Write_Str (" Putting ");
8108 Write_Str (Get_Name_String (Unit_Name));
8109 Write_Line (" in the unit list.");
8112 -- The unit is already in the list, but may be it is only the other
8113 -- unit kind (spec or body), or what is in the unit list is a unit of
8114 -- a project we are extending.
8116 if UData /= No_Unit_Index then
8117 if UData.File_Names (Unit_Kind) = null
8119 (UData.File_Names (Unit_Kind).File = Canonical_File
8120 and then UData.File_Names (Unit_Kind).Locally_Removed)
8121 or else Is_Extending
8122 (Project.Extends, UData.File_Names (Unit_Kind).Project)
8124 if UData.File_Names (Unit_Kind) /= null
8125 and then UData.File_Names (Unit_Kind).Locally_Removed
8127 Remove_Forbidden_File_Name
8128 (UData.File_Names (Unit_Kind).File);
8133 -- If the same file is already in the list, do not add it again
8135 elsif UData.File_Names (Unit_Kind).Project = Project
8137 (Project.Known_Order_Of_Source_Dirs
8139 UData.File_Names (Unit_Kind).Path.Name = Canonical_Path)
8143 -- Else, same unit but not same file => It is an error to have two
8144 -- units with the same name and the same kind (spec or body).
8147 if The_Location = No_Location then
8148 The_Location := Project.Location;
8151 Err_Vars.Error_Msg_Name_1 := Unit_Name;
8153 (Project, In_Tree, "duplicate unit %%", The_Location);
8155 Err_Vars.Error_Msg_Name_1 :=
8156 UData.File_Names (Unit_Kind).Project.Name;
8157 Err_Vars.Error_Msg_File_1 :=
8158 File_Name_Type (UData.File_Names (Unit_Kind).Path.Name);
8161 "\ project file %%, {", The_Location);
8163 Err_Vars.Error_Msg_Name_1 := Project.Name;
8164 Err_Vars.Error_Msg_File_1 := File_Name_Type (Canonical_Path);
8166 (Project, In_Tree, "\ project file %%, {", The_Location);
8171 -- It is a new unit, create a new record
8174 -- First, check if there is no other unit with this file name in
8175 -- another project. If it is, report error but note we do that
8176 -- only for the first unit in the source file.
8178 Unit_Prj := Files_Htable.Get (Proc_Data.Units, Canonical_File);
8180 if not File_Recorded
8181 and then Unit_Prj /= No_Project
8183 Error_Msg_File_1 := File_Name;
8184 Error_Msg_Name_1 := Unit_Prj.Name;
8187 "{ is already a source of project %%",
8196 Files_Htable.Set (Proc_Data.Units, Canonical_File, Project);
8201 Lang_Id => Ada_Language,
8202 File_Name => Canonical_File,
8203 Display_File => File_Name,
8205 Path => (Canonical_Path, Path_Name),
8206 Naming_Exception => Needs_Pragma,
8209 Source_Recorded := True;
8213 Exception_Id : Ada_Naming_Exception_Id;
8214 Unit_Name : Name_Id;
8215 Unit_Kind : Spec_Or_Body;
8216 Unit_Ind : Int := 0;
8218 Name_Index : Name_And_Index;
8219 Except_Name : Name_And_Index := No_Name_And_Index;
8220 Needs_Pragma : Boolean;
8223 Canonical_File := Canonical_Case_File_Name (Name_Id (File_Name));
8225 Path_Name_Type (Canonical_Case_File_Name (Name_Id (Path_Name)));
8227 -- Check the naming scheme to get extra file properties
8230 (In_Tree => In_Tree,
8231 Canonical_File_Name => Canonical_File,
8232 Naming => Project.Naming,
8233 Exception_Id => Exception_Id,
8234 Unit_Name => Unit_Name,
8235 Unit_Kind => Unit_Kind);
8237 Needs_Pragma := Exception_Id /= No_Ada_Naming_Exception;
8239 if Exception_Id = No_Ada_Naming_Exception
8240 and then Unit_Name = No_Name
8242 if Current_Verbosity = High then
8244 Write_Str (Get_Name_String (Canonical_File));
8245 Write_Line (""" is not a valid source file name (ignored).");
8250 -- Check to see if the source has been hidden by an exception,
8251 -- but only if it is not an exception.
8253 if not Needs_Pragma then
8255 Reverse_Ada_Naming_Exceptions.Get
8256 ((Unit_Kind, Unit_Name, No_Ada_Naming_Exception));
8258 if Except_Name /= No_Name_And_Index then
8259 if Current_Verbosity = High then
8261 Write_Str (Get_Name_String (Canonical_File));
8262 Write_Str (""" contains a unit that is found in """);
8263 Write_Str (Get_Name_String (Except_Name.Name));
8264 Write_Line (""" (ignored).");
8267 -- The file is not included in the source of the project since it
8268 -- is hidden by the exception. So, nothing else to do.
8274 -- The following loop registers the unit in the appropriate table. It
8275 -- will be executed multiple times when the file is a multi-unit file,
8276 -- in which case Exception_Id initially points to the first file and
8277 -- then to each other unit in the file.
8280 if Exception_Id /= No_Ada_Naming_Exception then
8281 Info := Ada_Naming_Exception_Table.Table (Exception_Id);
8282 Exception_Id := Info.Next;
8283 Info.Next := No_Ada_Naming_Exception;
8284 Name_Index := Reverse_Ada_Naming_Exceptions.Get (Info);
8286 Unit_Name := Info.Unit;
8287 Unit_Ind := Name_Index.Index;
8288 Unit_Kind := Info.Kind;
8291 Record_Unit (Unit_Name, Unit_Ind, Unit_Kind, Needs_Pragma);
8292 File_Recorded := True;
8294 exit when Exception_Id = No_Ada_Naming_Exception;
8296 end Record_Ada_Source;
8302 procedure Remove_Source
8304 Replaced_By : Source_Id)
8309 if Current_Verbosity = High then
8310 Write_Str ("Removing source ");
8311 Write_Line (Get_Name_String (Id.File));
8314 if Replaced_By /= No_Source then
8315 Id.Replaced_By := Replaced_By;
8316 Replaced_By.Declared_In_Interfaces := Id.Declared_In_Interfaces;
8319 Source := Id.Language.First_Source;
8322 Id.Language.First_Source := Id.Next_In_Lang;
8325 while Source.Next_In_Lang /= Id loop
8326 Source := Source.Next_In_Lang;
8329 Source.Next_In_Lang := Id.Next_In_Lang;
8333 -----------------------
8334 -- Report_No_Sources --
8335 -----------------------
8337 procedure Report_No_Sources
8338 (Project : Project_Id;
8340 In_Tree : Project_Tree_Ref;
8341 Location : Source_Ptr;
8342 Continuation : Boolean := False)
8345 case When_No_Sources is
8349 when Warning | Error =>
8351 Msg : constant String :=
8354 " sources in this project";
8357 Error_Msg_Warn := When_No_Sources = Warning;
8359 if Continuation then
8360 Error_Msg (Project, In_Tree, "\" & Msg, Location);
8362 Error_Msg (Project, In_Tree, Msg, Location);
8366 end Report_No_Sources;
8368 ----------------------
8369 -- Show_Source_Dirs --
8370 ----------------------
8372 procedure Show_Source_Dirs
8373 (Project : Project_Id;
8374 In_Tree : Project_Tree_Ref)
8376 Current : String_List_Id;
8377 Element : String_Element;
8380 Write_Line ("Source_Dirs:");
8382 Current := Project.Source_Dirs;
8383 while Current /= Nil_String loop
8384 Element := In_Tree.String_Elements.Table (Current);
8386 Write_Line (Get_Name_String (Element.Value));
8387 Current := Element.Next;
8390 Write_Line ("end Source_Dirs.");
8391 end Show_Source_Dirs;
8393 -------------------------
8394 -- Warn_If_Not_Sources --
8395 -------------------------
8397 -- comments needed in this body ???
8399 procedure Warn_If_Not_Sources
8400 (Project : Project_Id;
8401 In_Tree : Project_Tree_Ref;
8402 Conventions : Array_Element_Id;
8404 Extending : Boolean)
8406 Conv : Array_Element_Id;
8408 The_Unit_Data : Unit_Index;
8409 Location : Source_Ptr;
8412 Conv := Conventions;
8413 while Conv /= No_Array_Element loop
8414 Unit := In_Tree.Array_Elements.Table (Conv).Index;
8415 Error_Msg_Name_1 := Unit;
8416 Get_Name_String (Unit);
8417 To_Lower (Name_Buffer (1 .. Name_Len));
8419 The_Unit_Data := Units_Htable.Get (In_Tree.Units_HT, Unit);
8420 Location := In_Tree.Array_Elements.Table (Conv).Value.Location;
8422 if The_Unit_Data = No_Unit_Index then
8423 Error_Msg (Project, In_Tree, "?unknown unit %%", Location);
8427 In_Tree.Array_Elements.Table (Conv).Value.Value;
8430 if not Check_Project
8431 (The_Unit_Data.File_Names (Spec).Project,
8436 "?source of spec of unit %% (%%)" &
8437 " not found in this project",
8442 if The_Unit_Data.File_Names (Impl) = null
8443 or else not Check_Project
8444 (The_Unit_Data.File_Names (Impl).Project,
8449 "?source of body of unit %% (%%)" &
8450 " not found in this project",
8456 Conv := In_Tree.Array_Elements.Table (Conv).Next;
8458 end Warn_If_Not_Sources;